Skip to content

Commit 4b570ac

Browse files
committed
PR_26171_003 Game Journey friendly descriptions
1 parent 3295288 commit 4b570ac

3 files changed

Lines changed: 125 additions & 53 deletions

File tree

tests/playwright/tools/RootToolsFutureState.spec.mjs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ test("root tools surface links current tool pages without old_* routes", async (
363363
const guestGroupLabels = await page.locator("[data-tools-accordion-list] details[data-tools-accordion]").evaluateAll((groups) => (
364364
groups.map((group) => group.dataset.toolsAccordion)
365365
));
366-
expect(guestGroupLabels).toEqual(["Idea", "Create", "Design", "Graphics", "Objects", "Interface", "Controls", "Progression"]);
366+
expect(guestGroupLabels).toEqual(["Idea", "Design", "Graphics", "Objects", "Interface", "Controls", "Progression"]);
367367
await expect(page.locator("[data-tools-accordion='Admin']")).toHaveCount(0);
368368
await expect(page.getByRole("button", { name: "Progress" })).toHaveCount(0);
369369
await expect(page.locator("[data-tools-accordion-list] .control-card h3", { hasText: /^Progress$/ })).toHaveCount(0);
@@ -432,7 +432,7 @@ test("root tools surface links current tool pages without old_* routes", async (
432432
const adminGroupLabels = await page.locator("[data-tools-accordion-list] details[data-tools-accordion]").evaluateAll((groups) => (
433433
groups.map((group) => group.dataset.toolsAccordion)
434434
));
435-
expect(adminGroupLabels).toEqual(["Idea", "Create", "Design", "Graphics", "Objects", "Interface", "Controls", "Progression"]);
435+
expect(adminGroupLabels).toEqual(["Idea", "Design", "Graphics", "Objects", "Interface", "Controls", "Progression"]);
436436
await expect(page.getByRole("button", { name: "Progress" })).toHaveCount(0);
437437
await page.getByRole("button", { name: "Build Path" }).click();
438438
await expect(page.locator("[data-build-path-table='workflow']")).toBeVisible();
@@ -670,7 +670,6 @@ test("representative active tool pages align center cleanup and registry group c
670670
];
671671
const gameJourneyGroupClasses = [
672672
"tool-group-idea",
673-
"tool-group-game-create",
674673
"tool-group-journey-design",
675674
"tool-group-graphics",
676675
"tool-group-journey-audio",

tests/playwright/tools/ToolboxRoutePages.spec.mjs

Lines changed: 98 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ const STATUS_HELP_TEXT = Object.freeze({
2626

2727
const GAME_JOURNEY_GROUP_ORDER = Object.freeze([
2828
"Idea",
29-
"Create",
3029
"Design",
3130
"Graphics",
3231
"Audio",
@@ -42,25 +41,23 @@ const GAME_JOURNEY_GROUP_ORDER = Object.freeze([
4241
]);
4342

4443
const GAME_JOURNEY_ACCORDION_LABELS = Object.freeze([
45-
"0% - Idea: Dream, brainstorm, and explore (0 of 4 complete, inactive)",
46-
"0% - Create: Set up your game and crew (0 of 5 complete, active)",
47-
"0% - Design: Shape the player experience (0 of 5 complete, active)",
48-
"0% - Graphics: Create the look of your game (0 of 5 complete, active)",
49-
"0% - Audio: Bring your world to life with sound (0 of 4 complete, inactive)",
50-
"0% - Objects: Build things players can interact with (0 of 5 complete, active)",
51-
"0% - Worlds: Design places to explore (0 of 5 complete, active)",
52-
"0% - Interface: Create what players see and use (0 of 5 complete, active)",
53-
"0% - Controls: Define how players play (0 of 4 complete, active)",
54-
"0% - Rules: Make your game come alive (0 of 5 complete, active)",
55-
"0% - Progression: Reward players and keep them engaged (0 of 4 complete, inactive)",
56-
"0% - Play Test: See how your game feels (0 of 5 complete, active)",
57-
"0% - Publish: Prepare your game for launch (0 of 5 complete, active)",
58-
"0% - Share: Grow your community (0 of 5 complete, inactive)",
44+
"0% Complete — Idea: Dream, brainstorm, and explore",
45+
"0% Complete — Design: Shape your game's story and systems",
46+
"0% Complete — Graphics: Create the visual look of your game",
47+
"0% Complete — Audio: Build sounds, music, and voices",
48+
"0% Complete — Objects: Create the things players interact with",
49+
"0% Complete — Worlds: Build levels, maps, and places to explore",
50+
"0% Complete — Interface: Design menus, HUDs, and player screens",
51+
"0% Complete — Controls: Define how players interact with your game",
52+
"0% Complete — Rules: Create gameplay behavior and events",
53+
"0% Complete — Progression: Build rewards, unlocks, and advancement",
54+
"0% Complete — Play Test: Test, debug, and improve your game",
55+
"0% Complete — Publish: Prepare and release your game",
56+
"0% Complete — Share: Grow your audience and community",
5957
]);
6058

6159
const GAME_JOURNEY_GROUP_COLORS = Object.freeze({
6260
"Idea": { hex: "#FF2D2D", rgb: "rgb(255, 45, 45)" },
63-
"Create": { hex: "#F59E0B", rgb: "rgb(245, 158, 11)" },
6461
"Design": { hex: "#FF7A00", rgb: "rgb(255, 122, 0)" },
6562
"Graphics": { hex: "#FFC857", rgb: "rgb(255, 200, 87)" },
6663
"Audio": { hex: "#FACC15", rgb: "rgb(250, 204, 21)" },
@@ -791,8 +788,11 @@ test("toolbox grouped view renders Game Journey order with unique colors while B
791788
labels.map((label) => label.textContent.trim())
792789
));
793790
expect(accordionLabels).toEqual(GAME_JOURNEY_ACCORDION_LABELS);
794-
expect(accordionLabels.every((label) => /^\d+% - .+ \(\d+ of \d+ complete, (active|inactive)\)$/.test(label))).toBe(true);
791+
expect(accordionLabels.every((label) => /^\d+% Complete .+: .+$/.test(label))).toBe(true);
795792
expect(accordionLabels.join(" ")).not.toContain("xxx%");
793+
expect(accordionLabels.join(" ")).not.toMatch(/\(\d+ of \d+ complete/);
794+
expect(accordionLabels.join(" ")).not.toContain("inactive");
795+
expect(accordionLabels.join(" ")).not.toContain("active");
796796
expect(accordionLabels.every((label) => !/[\r\n]/.test(label))).toBe(true);
797797

798798
const groupSwatches = await page.locator("[data-tools-accordion] > summary [data-toolbox-group-label]").evaluateAll((labels) => (
@@ -819,19 +819,21 @@ test("toolbox grouped view renders Game Journey order with unique colors while B
819819
expect(toolboxGroupsByTool["Idea Board"]).toBe("Idea");
820820
expect(toolboxGroupsByTool["Creator Learning"]).toBe("Idea");
821821
expect(toolboxGroupsByTool["AI Command Center"]).toBe("Design");
822-
expect(toolboxGroupsByTool["Game Hub"]).toBe("Create");
823-
expect(toolboxGroupsByTool["Game Configuration"]).toBe("Create");
824-
expect(toolboxGroupsByTool["Game Crew"]).toBe("Create");
825-
expect(toolboxGroupsByTool["Tags"]).toBe("Create");
822+
expect(toolboxGroupsByTool["Game Hub"]).toBe("Design");
823+
expect(toolboxGroupsByTool["Game Configuration"]).toBe("Design");
824+
expect(toolboxGroupsByTool["Game Crew"]).toBe("Design");
825+
expect(toolboxGroupsByTool["Tags"]).toBe("Design");
826826
expect(toolboxGroupsByTool["Game Journey"]).toBe("Progression");
827827
expect(toolboxGroupsByTool["Publish"]).toBe("Publish");
828828
expect(toolboxGroupsByTool["Marketplace"]).toBe("Share");
829829
expect(toolboxGroupsByTool.Users).toBeUndefined();
830830

831-
const createToolOrder = await page.locator("[data-tools-accordion='Create'] [data-toolbox-tool-card]").evaluateAll((cards) => (
831+
const designToolOrder = await page.locator("[data-tools-accordion='Design'] [data-toolbox-tool-card]").evaluateAll((cards) => (
832832
cards.map((card) => card.getAttribute("data-toolbox-tool-card"))
833833
));
834-
expect(createToolOrder).toEqual(["Game Hub", "Game Crew", "Game Configuration", "Tags"]);
834+
const expectedDesignTools = ["Game Hub", "Game Crew", "Game Configuration", "Tags", "Game Design", "AI Command Center"];
835+
expect(designToolOrder).toEqual(expect.arrayContaining(expectedDesignTools));
836+
expect(designToolOrder.filter((title) => expectedDesignTools.includes(title))).toEqual(expectedDesignTools);
835837

836838
const toolLinks = await page.locator("[data-toolbox-tool-name-link]").evaluateAll((links) => (
837839
links.map((link) => ({
@@ -877,6 +879,79 @@ test("toolbox grouped view renders Game Journey order with unique colors while B
877879
}
878880
});
879881

882+
test("toolbox grouped Game Journey accordions keep friendly labels readable on mobile", async ({ page }) => {
883+
const server = await startRepoServer();
884+
const previousApiUrl = process.env.GAMEFOUNDRY_API_URL;
885+
const previousSiteUrl = process.env.GAMEFOUNDRY_SITE_URL;
886+
process.env.GAMEFOUNDRY_API_URL = `${server.baseUrl}/api`;
887+
process.env.GAMEFOUNDRY_SITE_URL = server.baseUrl;
888+
const failedRequests = [];
889+
const pageErrors = [];
890+
const consoleErrors = [];
891+
892+
page.on("response", (response) => {
893+
if (response.status() >= 400) {
894+
failedRequests.push(`${response.status()} ${response.url()}`);
895+
}
896+
});
897+
page.on("requestfailed", (request) => {
898+
failedRequests.push(`FAILED ${request.url()}`);
899+
});
900+
page.on("pageerror", (error) => {
901+
const text = error.stack || error.message;
902+
if (!isBrowserExtensionNoise(text)) {
903+
pageErrors.push(error.message);
904+
}
905+
});
906+
page.on("console", (message) => {
907+
if (message.type() === "error" && !isBrowserExtensionNoise(message.text())) {
908+
consoleErrors.push(message.text());
909+
}
910+
});
911+
912+
try {
913+
await page.setViewportSize({ width: 390, height: 844 });
914+
await workspaceV2CoverageReporter.start(page);
915+
await setServerSession(server, MOCK_DB_KEYS.users.admin);
916+
await page.goto(`${server.baseUrl}/toolbox/index.html?view=group`, { waitUntil: "networkidle" });
917+
const plannedFilter = page.locator("[data-toolbox-status-filter='planned']");
918+
if (await plannedFilter.getAttribute("aria-pressed") !== "true") {
919+
await plannedFilter.click();
920+
}
921+
const deprecatedFilter = page.locator("[data-toolbox-status-filter='deprecated']");
922+
if (await deprecatedFilter.getAttribute("aria-pressed") !== "true") {
923+
await deprecatedFilter.click();
924+
}
925+
926+
const labels = page.locator("[data-tools-accordion] > summary [data-toolbox-group-label]");
927+
await expect(labels).toHaveText(GAME_JOURNEY_ACCORDION_LABELS);
928+
const labelLayout = await labels.evaluateAll((items) => (
929+
items.map((label) => {
930+
const rect = label.getBoundingClientRect();
931+
const viewportWidth = document.documentElement.clientWidth;
932+
return {
933+
fitsViewport: rect.left >= 0 && rect.right <= viewportWidth,
934+
text: label.textContent.trim(),
935+
wraps: getComputedStyle(label).whiteSpace !== "nowrap",
936+
};
937+
})
938+
));
939+
expect(labelLayout.every((item) => item.fitsViewport)).toBe(true);
940+
expect(labelLayout.every((item) => item.wraps)).toBe(true);
941+
expect(labelLayout.map((item) => item.text)).toEqual(GAME_JOURNEY_ACCORDION_LABELS);
942+
await expect(page.locator("style, [style], script:not([src])")).toHaveCount(0);
943+
944+
expect(failedRequests).toEqual([]);
945+
expect(pageErrors).toEqual([]);
946+
expect(consoleErrors).toEqual([]);
947+
} finally {
948+
await workspaceV2CoverageReporter.stop(page);
949+
await server.close();
950+
restoreEnvValue("GAMEFOUNDRY_API_URL", previousApiUrl);
951+
restoreEnvValue("GAMEFOUNDRY_SITE_URL", previousSiteUrl);
952+
}
953+
});
954+
880955
test("Game Crew friendly route resolves while old Users route remains compatible", async ({ page }) => {
881956
const server = await startRepoServer();
882957
const previousApiUrl = process.env.GAMEFOUNDRY_API_URL;

toolbox/tools-page-accordions.js

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ import { getSessionCurrent } from "../src/api/session-api-client.js";
7272
const stateSwatchMap = Object.freeze({ ...(toolboxContract.releaseChannelSwatches || {}) });
7373
const gameJourneyGroupOrder = Object.freeze([
7474
"Idea",
75-
"Create",
7675
"Design",
7776
"Graphics",
7877
"Audio",
@@ -88,23 +87,21 @@ import { getSessionCurrent } from "../src/api/session-api-client.js";
8887
]);
8988
const gameJourneyFriendlyDescriptions = Object.freeze({
9089
"Idea": "Dream, brainstorm, and explore",
91-
"Create": "Set up your game and crew",
92-
"Design": "Shape the player experience",
93-
"Graphics": "Create the look of your game",
94-
"Audio": "Bring your world to life with sound",
95-
"Objects": "Build things players can interact with",
96-
"Worlds": "Design places to explore",
97-
"Interface": "Create what players see and use",
98-
"Controls": "Define how players play",
99-
"Rules": "Make your game come alive",
100-
"Progression": "Reward players and keep them engaged",
101-
"Play Test": "See how your game feels",
102-
"Publish": "Prepare your game for launch",
103-
"Share": "Grow your community"
90+
"Design": "Shape your game's story and systems",
91+
"Graphics": "Create the visual look of your game",
92+
"Audio": "Build sounds, music, and voices",
93+
"Objects": "Create the things players interact with",
94+
"Worlds": "Build levels, maps, and places to explore",
95+
"Interface": "Design menus, HUDs, and player screens",
96+
"Controls": "Define how players interact with your game",
97+
"Rules": "Create gameplay behavior and events",
98+
"Progression": "Build rewards, unlocks, and advancement",
99+
"Play Test": "Test, debug, and improve your game",
100+
"Publish": "Prepare and release your game",
101+
"Share": "Grow your audience and community"
104102
});
105103
const gameJourneyGroupSwatches = Object.freeze({
106104
"Idea": "swatch-red",
107-
"Create": "swatch-amber",
108105
"Design": "swatch-orange",
109106
"Graphics": "swatch-gold",
110107
"Audio": "swatch-yellow",
@@ -120,7 +117,6 @@ import { getSessionCurrent } from "../src/api/session-api-client.js";
120117
});
121118
const gameJourneyGroupClasses = Object.freeze({
122119
"Idea": "tool-group-idea",
123-
"Create": "tool-group-game-create",
124120
"Design": "tool-group-journey-design",
125121
"Graphics": "tool-group-graphics",
126122
"Audio": "tool-group-journey-audio",
@@ -152,12 +148,13 @@ import { getSessionCurrent } from "../src/api/session-api-client.js";
152148
"environments": "Publish",
153149
"events": "Rules",
154150
"fonts": "Interface",
155-
"game-configuration": "Create",
151+
"game-configuration": "Design",
152+
"game-crew": "Design",
156153
"game-design": "Design",
157154
"game-journey": "Progression",
158155
"game-migration": "Publish",
159156
"game-testing": "Play Test",
160-
"game-workspace": "Create",
157+
"game-workspace": "Design",
161158
"hitboxes": "Controls",
162159
"idea-board": "Idea",
163160
"input-mapping-v2": "Controls",
@@ -176,20 +173,23 @@ import { getSessionCurrent } from "../src/api/session-api-client.js";
176173
"saved-data": "Progression",
177174
"speech-to-text": "Audio",
178175
"sprites": "Graphics",
179-
"tags": "Create",
176+
"tags": "Design",
180177
"text-to-speech": "Audio",
181-
"users": "Create",
178+
"users": "Design",
182179
"videos": "Graphics",
183180
"voices": "Audio",
184181
"worlds": "Worlds"
185182
});
186183
const toolboxGroupPositions = new Map(toolboxGroupOrder.map((group, index) => [group, index]));
187184
const workflowToolOrderByGroup = Object.freeze({
188-
"Create": Object.freeze({
185+
"Design": Object.freeze({
189186
"game-workspace": 1,
190187
"users": 2,
188+
"game-crew": 2,
191189
"game-configuration": 3,
192-
"tags": 4
190+
"tags": 4,
191+
"game-design": 5,
192+
"ai-assistant": 6
193193
})
194194
});
195195
toolboxDefaultReleaseChannels.forEach((channel) => {
@@ -238,11 +238,9 @@ import { getSessionCurrent } from "../src/api/session-api-client.js";
238238

239239
function gameJourneyAccordionLabel(groupName) {
240240
const metric = gameJourneyCompletionByGroup.get(groupName);
241-
const description = metric?.friendlyDescription || gameJourneyFriendlyDescriptions[groupName] || groupName;
242-
if (!metric) {
243-
return `0% - ${groupName}: ${description} (0 of 0 complete, inactive)`;
244-
}
245-
return `${metric.percentComplete}% - ${groupName}: ${description} (${metric.completedCount} of ${metric.plannedCount} complete, ${metric.status})`;
241+
const description = gameJourneyFriendlyDescriptions[groupName] || groupName;
242+
const percentComplete = Number.isFinite(metric?.percentComplete) ? metric.percentComplete : 0;
243+
return `${percentComplete}% Complete — ${groupName}: ${description}`;
246244
}
247245

248246
function getGameProgressSummary() {

0 commit comments

Comments
 (0)