전 저장소 리팩터링과 SSOT 정비
This commit is contained in:
parent
14ecbd4e7d
commit
3dfddcac6f
173 changed files with 19679 additions and 6952 deletions
|
|
@ -106,7 +106,7 @@ async function mockSessionDetail(
|
|||
|
||||
test.describe("persona avatar expression rig", () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.route("**/api/auth/me", (route) =>
|
||||
await page.route(/\/(?:api\/)?auth\/me(?:\?.*)?$/, (route) =>
|
||||
route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
|
|
@ -122,7 +122,7 @@ test.describe("persona avatar expression rig", () => {
|
|||
}),
|
||||
);
|
||||
|
||||
await page.route("**/api/personas", (route) =>
|
||||
await page.route(/\/(?:api\/)?personas(?:\?.*)?$/, (route) =>
|
||||
route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
|
|
@ -137,6 +137,34 @@ test.describe("persona avatar expression rig", () => {
|
|||
),
|
||||
}),
|
||||
);
|
||||
|
||||
await page.route(/\/(?:api\/)?voice\/health(?:\?.*)?$/, (route) =>
|
||||
route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify({ available: false, reason: "test fixture" }),
|
||||
}),
|
||||
);
|
||||
|
||||
await page.route(/\/(?:api\/)?sessions\/[^/]+\/live-coach(?:\?.*)?$/, (route) => {
|
||||
if (route.request().method() === "GET") {
|
||||
return route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify({
|
||||
session_id: "avatar-expression-session",
|
||||
events: [],
|
||||
quota: { used: 0, limit: 3, remaining: 3 },
|
||||
source: "database",
|
||||
}),
|
||||
});
|
||||
}
|
||||
return route.fulfill({
|
||||
status: 503,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify({ detail: "live coach is outside this avatar fixture" }),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test("renders every persona with a distinct baseline expression and at least 20 expressions", async ({
|
||||
|
|
@ -158,17 +186,12 @@ test.describe("persona avatar expression rig", () => {
|
|||
live2dMotionFile: el.getAttribute("data-live2d-motion-file"),
|
||||
live2dExpressionCount: Number(el.getAttribute("data-live2d-expression-count")),
|
||||
renderMode: el.getAttribute("data-render-mode"),
|
||||
rasterArtSet: el.querySelector(".vg-raster")?.getAttribute("data-raster-art-set"),
|
||||
rasterMode: el.querySelector(".vg-raster")?.getAttribute("data-raster-mode"),
|
||||
rasterLayerCount: el.querySelectorAll(".vg-raster__layer").length,
|
||||
rasterBox: el.querySelector<HTMLElement>(".vg-raster")?.getBoundingClientRect().toJSON(),
|
||||
rasterCount: el.querySelectorAll(".vg-raster").length,
|
||||
primitiveCount: el.querySelectorAll("svg path, svg ellipse, svg circle, svg line, svg rect")
|
||||
.length,
|
||||
neckBox: el.querySelector<SVGGraphicsElement>('[data-avatar-neck="true"]')?.getBoundingClientRect().toJSON(),
|
||||
svgBox: el.querySelector("svg")?.getBoundingClientRect().toJSON(),
|
||||
}));
|
||||
const expectedArtSet = `${persona.code.toLowerCase()}-live2d-generated`;
|
||||
|
||||
expect(metrics.expressionCount, `${persona.code} expression count`).toBeGreaterThanOrEqual(20);
|
||||
expect(metrics.live2dSchema, `${persona.code} Live2D schema`).toBe("vignette.live2d.v1");
|
||||
expect(metrics.live2dModel, `${persona.code} Live2D model`).toBe(persona.expectedModel);
|
||||
|
|
@ -180,15 +203,12 @@ test.describe("persona avatar expression rig", () => {
|
|||
`expressions/${persona.expectedExpression}.exp3.json`,
|
||||
);
|
||||
expect(metrics.live2dExpressionCount, `${persona.code} Live2D expressions`).toBeGreaterThanOrEqual(20);
|
||||
expect(metrics.renderMode, `${persona.code} render mode`).toBe("raster");
|
||||
expect(metrics.rasterArtSet, `${persona.code} generated art set`).toBe(expectedArtSet);
|
||||
expect(metrics.rasterMode, `${persona.code} raster rig mode`).toBe("psb-detailed");
|
||||
expect(metrics.rasterLayerCount, `${persona.code} raster layers`).toBeGreaterThanOrEqual(20);
|
||||
expect(metrics.rasterBox?.width, `${persona.code} raster width`).toBeGreaterThan(0);
|
||||
expect(metrics.rasterBox?.height, `${persona.code} raster height`).toBeGreaterThan(0);
|
||||
expect(metrics.primitiveCount, `${persona.code} fallback SVG primitives`).toBe(0);
|
||||
expect(metrics.neckBox, `${persona.code} SVG neck fallback`).toBeUndefined();
|
||||
expect(metrics.svgBox, `${persona.code} SVG fallback`).toBeUndefined();
|
||||
expect(metrics.renderMode, `${persona.code} render mode`).toBe("svg");
|
||||
expect(metrics.rasterCount, `${persona.code} raster rig should be disabled`).toBe(0);
|
||||
expect(metrics.primitiveCount, `${persona.code} SVG primitives`).toBeGreaterThan(10);
|
||||
expect(metrics.neckBox?.width, `${persona.code} SVG neck`).toBeGreaterThan(0);
|
||||
expect(metrics.svgBox?.width, `${persona.code} SVG rig`).toBeGreaterThan(0);
|
||||
expect(metrics.svgBox?.height, `${persona.code} SVG rig`).toBeGreaterThan(0);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -221,8 +241,9 @@ test.describe("persona avatar expression rig", () => {
|
|||
|
||||
const activeAvatar = page.locator(".sx-page--active .vg-avatar").first();
|
||||
await expect(activeAvatar).toBeVisible();
|
||||
await expect(activeAvatar).toHaveAttribute("data-render-mode", "raster");
|
||||
await expect(activeAvatar.locator('.vg-raster[data-raster-art-set="p4-live2d-generated"]')).toBeVisible();
|
||||
await expect(activeAvatar).toHaveAttribute("data-render-mode", "svg");
|
||||
await expect(activeAvatar.locator(".vg-raster")).toHaveCount(0);
|
||||
await expect(activeAvatar.locator(".vg-avatar__svg")).toBeVisible();
|
||||
await expect(activeAvatar).toHaveAttribute("data-expression-count", "28");
|
||||
await expect(activeAvatar).toHaveAttribute("data-live2d-expression-count", "28");
|
||||
await expect(activeAvatar).toHaveAttribute("data-live2d-model", "vignette-p4-live2d");
|
||||
|
|
@ -275,8 +296,9 @@ test.describe("persona avatar expression rig", () => {
|
|||
await page.getByRole("button", { name: "회기 시작" }).click();
|
||||
await expect(page.locator(".sx-page--active")).toBeVisible();
|
||||
const activeAvatar = page.locator(".sx-page--active .vg-avatar").first();
|
||||
await expect(activeAvatar).toHaveAttribute("data-render-mode", "raster");
|
||||
await expect(activeAvatar.locator('.vg-raster[data-raster-art-set="p4-live2d-generated"]')).toBeVisible();
|
||||
await expect(activeAvatar).toHaveAttribute("data-render-mode", "svg");
|
||||
await expect(activeAvatar.locator(".vg-raster")).toHaveCount(0);
|
||||
await expect(activeAvatar.locator(".vg-avatar__svg")).toBeVisible();
|
||||
await expect(activeAvatar).toHaveAttribute("data-live2d-motion", "anxious");
|
||||
|
||||
await setLearnerUtterance(page, "조금 안정된 것 같아요.");
|
||||
|
|
@ -295,18 +317,15 @@ test.describe("persona avatar expression rig", () => {
|
|||
await expect(page.locator(".sx-stage__now")).toContainText("온화함");
|
||||
});
|
||||
|
||||
test("uses the PSD v2 crying raster rig for P1 Seoyeon", async ({ page }) => {
|
||||
test("uses the original SVG parameter rig for P1 Seoyeon", async ({ page }) => {
|
||||
await page.goto("/learn/session/P1");
|
||||
|
||||
const avatar = page.locator('.vg-avatar[data-persona-code="P1"]').first();
|
||||
await expect(avatar).toBeVisible();
|
||||
await expect(avatar).toHaveAttribute("data-render-mode", "raster");
|
||||
await expect(avatar).toHaveAttribute("data-render-mode", "svg");
|
||||
await expect(avatar).toHaveAttribute("data-affect", "sad");
|
||||
|
||||
const raster = avatar.locator('.vg-raster[data-raster-art-set="seoyeon-live2d-psd-v2"]');
|
||||
await expect(raster).toBeVisible();
|
||||
await expect(raster).toHaveAttribute("data-raster-variant", "sad");
|
||||
await expect(raster.locator('.vg-raster__layer--tear[src$="/tear-left.png"]')).toHaveCount(1);
|
||||
await expect(raster.locator('.vg-raster__layer--tear[src$="/tear-right.png"]')).toHaveCount(1);
|
||||
await expect(avatar.locator(".vg-raster")).toHaveCount(0);
|
||||
await expect(avatar.locator(".vg-avatar__svg")).toBeVisible();
|
||||
await expect(avatar.locator('[data-avatar-neck="true"]')).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue