Skip to content

Commit f424497

Browse files
committed
Refine Controls controller profile edit mode and input highlighting - PR_26161_029-controls-controller-profile-edit-mode
1 parent 2589276 commit f424497

7 files changed

Lines changed: 785 additions & 522 deletions

File tree

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
docs_build/dev/reports/controls-compact-controller-profile-report.md
2-
docs_build/dev/reports/codex_review.diff
31
docs_build/dev/reports/codex_changed_files.txt
4-
docs_build/dev/reports/playwright_v8_coverage_report.txt
2+
docs_build/dev/reports/codex_review.diff
3+
docs_build/dev/reports/controls-controller-profile-edit-mode-report.md
54
docs_build/dev/reports/coverage_changed_js_guardrail.txt
5+
docs_build/dev/reports/playwright_v8_coverage_report.txt
66
tests/playwright/tools/InputMappingV2Tool.spec.mjs
77
toolbox/controls/controls.js
8-
toolbox/controls/index.html

‎docs_build/dev/reports/codex_review.diff‎

Lines changed: 526 additions & 400 deletions
Large diffs are not rendered by default.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# PR_26161_029 Controls Controller Profile Edit Mode Report
2+
3+
## Scope
4+
- Updated Controls controller profile rows so saved profiles render as compact summaries outside edit mode.
5+
- Moved generated controller input Action dropdowns into profile edit mode only.
6+
- Added edit-mode gamepad input highlighting for matching generated controller inputs.
7+
- Kept Controls status as Wireframe and kept persistence through the shared DB/mock adapter.
8+
9+
## Branch Validation
10+
- PASS: current branch verified as `main` before edits.
11+
12+
## Impacted Lane
13+
- Controls / Input Mapping.
14+
15+
## Playwright Impacted
16+
- Yes.
17+
18+
## Validation Performed
19+
- PASS: `node --check toolbox/controls/controls.js`
20+
- PASS: `node --check tests/playwright/tools/InputMappingV2Tool.spec.mjs`
21+
- PASS: `git diff --check`
22+
- PASS: `npx playwright test tests/playwright/tools/InputMappingV2Tool.spec.mjs`
23+
24+
## Manual Validation Steps
25+
- Open Controls and refresh devices with a detected gamepad.
26+
- Add a controller profile and confirm the saved profile row shows only the compact summary.
27+
- Click Edit and confirm profile row values are text while generated input Action dropdowns appear underneath.
28+
- Press a controller button during edit and confirm the matching generated input row highlights with the selected Action.
29+
- Assign generated input Actions, Save, reload, and confirm assignments persist.
30+
- Edit a profile, change an Action, Cancel, reload, and confirm the unsaved change did not persist.
31+
32+
## Skipped Lanes
33+
- Full samples validation skipped by request because this PR only changes Controls UI behavior and targeted Playwright coverage exercises the impacted lane.
34+
35+
## Runtime Engine Behavior
36+
- Confirmed: no runtime engine behavior changed.
37+
38+
## Completion Check
39+
- PASS: Controller Profile Edit shows profile row values as text, not dropdowns.
40+
- PASS: Generated input Action dropdowns appear only in edit mode.
41+
- PASS: Generated input Action dropdowns are hidden outside edit mode.
42+
- PASS: Controller input press during edit highlights the matching generated input.
43+
- PASS: Selected/assigned Action is visibly shown for the pressed input.
44+
- PASS: Editing one input does not alter other inputs.
45+
- PASS: Save persists generated input action assignments after reload.
46+
- PASS: Cancel does not persist unsaved generated input action changes.

‎docs_build/dev/reports/coverage_changed_js_guardrail.txt‎

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,7 @@ Missing changed runtime JS files are WARN, not FAIL.
66
Source: Playwright/Chromium built-in V8 coverage from the active Playwright run.
77

88
Changed runtime JS files considered:
9-
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
10-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
11-
(91%) toolbox/controls/controls.js - executed lines 1626/1626; executed functions 165/181
9+
(94%) toolbox/controls/controls.js - executed lines 1686/1686; executed functions 186/197
1210

1311
Guardrail warnings:
14-
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: changed runtime JS file missing from coverage; advisory only
15-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - WARNING: changed runtime JS file missing from coverage; advisory only
12+
(100%) none - no changed runtime JS coverage warnings

‎docs_build/dev/reports/playwright_v8_coverage_report.txt‎

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,25 @@ Note: entry percentages use function coverage when available, otherwise line cov
1212
Note: coverage entries are aggregated across every page/tool where coverageReporter.start(page) and coverageReporter.stop(page) ran.
1313

1414
Exercised tool entry points detected:
15-
(89%) Toolbox Index - exercised 4 runtime JS files
15+
(92%) Toolbox Index - exercised 4 runtime JS files
1616
(0%) Tool Template V2 - not exercised by this Playwright run
1717
(59%) Theme V2 Shared JS - exercised 2 runtime JS files
1818

1919
Changed runtime JS files covered:
20-
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
21-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
22-
(91%) toolbox/controls/controls.js - executed lines 1626/1626; executed functions 165/181
20+
(94%) toolbox/controls/controls.js - executed lines 1686/1686; executed functions 186/197
2321

2422
Files with executed line/function counts where available:
2523
(53%) src/engine/api/server-api-client.js - executed lines 159/159; executed functions 10/19
2624
(58%) assets/theme-v2/js/gamefoundry-partials.js - executed lines 603/603; executed functions 30/52
2725
(64%) assets/theme-v2/js/tool-display-mode.js - executed lines 209/209; executed functions 9/14
2826
(75%) toolbox/tool-registry-api-client.js - executed lines 152/152; executed functions 21/28
29-
(91%) toolbox/controls/controls.js - executed lines 1626/1626; executed functions 165/181
27+
(94%) toolbox/controls/controls.js - executed lines 1686/1686; executed functions 186/197
3028
(100%) toolbox/controls/controls-api-client.js - executed lines 12/12; executed functions 2/2
3129
(100%) toolbox/objects/objects-api-client.js - executed lines 10/10; executed functions 2/2
3230

3331
Uncovered or low-coverage changed JS files:
34-
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: uncovered changed runtime JS file; advisory only
35-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - WARNING: uncovered changed runtime JS file; advisory only
32+
(100%) none - no low-coverage changed runtime JS files
3633

3734
Changed JS files considered:
38-
(0%) src/dev-runtime/persistence/mock-db-store.js - changed JS file not collected as browser runtime coverage
39-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - changed JS file not collected as browser runtime coverage
4035
(0%) tests/playwright/tools/InputMappingV2Tool.spec.mjs - changed JS file not collected as browser runtime coverage
41-
(91%) toolbox/controls/controls.js - changed JS file with browser V8 coverage
36+
(94%) toolbox/controls/controls.js - changed JS file with browser V8 coverage

‎tests/playwright/tools/InputMappingV2Tool.spec.mjs‎

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -600,11 +600,13 @@ test("Controls generates controller profiles, shows fallback status, and mapping
600600
expect(awaitcontrollerProfileRecords(page)).toHaveLength(0);
601601

602602
awaitpage.evaluate(()=>{
603+
window.__arcadeButtons=Array.from({length: 16},()=>({pressed: false,value: 0}));
604+
window.__arcadeAxes=[0,0];
603605
Object.defineProperty(navigator,"getGamepads",{
604606
configurable: true,
605607
value: ()=>[{
606-
axes: [0,0],
607-
buttons: Array.from({length: 16},()=>({pressed: false,value: 0})),
608+
axes: window.__arcadeAxes,
609+
buttons: window.__arcadeButtons,
608610
id: "Arcade Test Pad",
609611
index: 0,
610612
}],
@@ -628,7 +630,7 @@ test("Controls generates controller profiles, shows fallback status, and mapping
628630
awaitpage.locator("[data-controller-profile-add]").click();
629631
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("Arcade Test Pad");
630632
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("Arcade Test Pad Profile");
631-
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("Action Required");
633+
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("0/18 Actions assigned");
632634
awaitexpect(page.locator("[data-controller-profile-table] th")).toHaveText([
633635
"Device Type",
634636
"Controller Name",
@@ -637,10 +639,8 @@ test("Controls generates controller profiles, shows fallback status, and mapping
637639
"Action",
638640
]);
639641
awaitexpect(page.locator("[data-controller-profile-row]").first()).not.toContainText("Button0");
640-
awaitexpect(page.locator("[data-controller-profile-actions-row]").first().locator(".content-grid--three")).toBeVisible();
641-
awaitexpect(page.locator("[data-controller-profile-actions-row]").first().locator("[data-controller-profile-input-pair]")).toHaveCount(18);
642-
awaitexpect(page.locator("[data-controller-profile-actions-row]").first().locator("[data-controller-profile-input-pair]").first().locator("strong")).toHaveText("Button0");
643-
awaitexpect(page.locator("[data-controller-profile-actions-row]").first().locator("[data-controller-profile-input-pair]").first().locator("select")).toBeVisible();
642+
awaitexpect(page.locator("[data-controller-profile-actions-row]")).toHaveCount(0);
643+
awaitexpect(page.locator("[data-controller-profile-input-action]")).toHaveCount(0);
644644
awaitexpect(page.locator("[data-controller-profile-fallback-status]")).toContainText("Exact saved profile");
645645

646646
letprofiles=awaitcontrollerProfileRecords(page);
@@ -673,22 +673,56 @@ test("Controls generates controller profiles, shows fallback status, and mapping
673673
"Axis1",
674674
]);
675675

676-
awaitpage.locator("[data-controller-profile-save-actions]").click();
676+
awaitpage.locator("[data-controller-profile-edit]").click();
677+
consteditRow=page.locator("[data-controller-profile-editing-row]");
678+
awaitexpect(editRow.locator("td").nth(0)).toHaveText("Gamepad");
679+
awaitexpect(editRow.locator("td").nth(1)).toHaveText("Arcade Test Pad");
680+
awaitexpect(editRow.locator("td").nth(2)).toHaveText("Arcade Test Pad");
681+
awaitexpect(editRow.locator("td").nth(3)).toHaveText("Arcade Test Pad Profile");
682+
awaitexpect(editRow.locator("select")).toHaveCount(0);
683+
awaitexpect(editRow.locator("input")).toHaveCount(0);
684+
awaitexpect(editRow.locator("button")).toHaveText(["Save","Cancel"]);
685+
686+
consteditingActionsRow=page.locator("[data-controller-profile-editing-actions-row]");
687+
awaitexpect(editingActionsRow.locator(".content-grid--three")).toBeVisible();
688+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-pair]")).toHaveCount(18);
689+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-pair]").first().locator("strong")).toHaveText("Button0");
690+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-action]")).toHaveCount(18);
691+
692+
awaitpage.locator("[data-controller-profile-save]").click();
677693
awaitexpect(page.locator("[data-controller-profile-status]")).toContainText("Action Required");
678694
profiles=awaitcontrollerProfileRecords(page);
679695
expect(profiles[0].actions).toEqual([]);
680696

681-
constinputActionSelects=page.locator("[data-controller-profile-input-action]");
697+
constinputActionSelects=editingActionsRow.locator("[data-controller-profile-input-action]");
682698
constinputActionCount=awaitinputActionSelects.count();
683699
expect(inputActionCount).toBe(profiles[0].inputs.length);
684700
for(letindex=0;index<inputActionCount;index+=1){
685701
awaitinputActionSelects.nth(index).selectOption(index===0 ? "fire" : "moveRight");
686702
}
687-
awaitpage.locator("[data-controller-profile-save-actions]").click();
703+
awaitexpect(inputActionSelects.nth(1)).toHaveValue("moveRight");
704+
awaitpage.evaluate(()=>{
705+
window.__arcadeButtons[0]={pressed: true,value: 1};
706+
});
707+
constactiveProfileInput=page.locator("[data-controller-profile-input-pair][data-controller-profile-input-active='true']");
708+
awaitexpect(activeProfileInput.locator("strong")).toHaveText("Button0");
709+
awaitexpect(activeProfileInput.locator("[data-controller-profile-input-assigned-action]")).toHaveText("Selected Action: Fire");
710+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-pair]").nth(1)).not.toHaveAttribute("data-controller-profile-input-active","true");
711+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-pair]").nth(1).locator("[data-controller-profile-input-assigned-action]")).toHaveText("Assigned Action: Move Right");
712+
713+
awaitpage.locator("[data-controller-profile-save]").click();
688714
profiles=awaitcontrollerProfileRecords(page);
689715
expect(profiles[0].actions).toHaveLength(profiles[0].inputs.length);
690716
expect(profiles[0].actions[0]).toBe("fire");
691717
expect(profiles[0].actions[1]).toBe("moveRight");
718+
awaitexpect(page.locator("[data-controller-profile-input-action]")).toHaveCount(0);
719+
720+
awaitpage.locator("[data-controller-profile-edit]").click();
721+
awaitpage.locator("[data-controller-profile-input-action]").first().selectOption("jump");
722+
awaitpage.locator("[data-controller-profile-cancel]").click();
723+
profiles=awaitcontrollerProfileRecords(page);
724+
expect(profiles[0].actions[0]).toBe("fire");
725+
awaitexpect(page.locator("[data-controller-profile-input-action]")).toHaveCount(0);
692726

693727
awaitpage.locator("[data-controller-profile-trash]").click();
694728
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("No controller profiles saved yet.");

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Refine Controls controller profile edit mode and input highlighting -… · ToolboxAid/HTML-JavaScript-Gaming@f424497 · GitHub
Skip to content

Commit f424497

Browse files
committed
Refine Controls controller profile edit mode and input highlighting - PR_26161_029-controls-controller-profile-edit-mode
1 parent 2589276 commit f424497

7 files changed

Lines changed: 785 additions & 522 deletions

File tree

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
docs_build/dev/reports/controls-compact-controller-profile-report.md
2-
docs_build/dev/reports/codex_review.diff
31
docs_build/dev/reports/codex_changed_files.txt
4-
docs_build/dev/reports/playwright_v8_coverage_report.txt
2+
docs_build/dev/reports/codex_review.diff
3+
docs_build/dev/reports/controls-controller-profile-edit-mode-report.md
54
docs_build/dev/reports/coverage_changed_js_guardrail.txt
5+
docs_build/dev/reports/playwright_v8_coverage_report.txt
66
tests/playwright/tools/InputMappingV2Tool.spec.mjs
77
toolbox/controls/controls.js
8-
toolbox/controls/index.html

‎docs_build/dev/reports/codex_review.diff‎

Lines changed: 526 additions & 400 deletions
Large diffs are not rendered by default.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# PR_26161_029 Controls Controller Profile Edit Mode Report
2+
3+
## Scope
4+
- Updated Controls controller profile rows so saved profiles render as compact summaries outside edit mode.
5+
- Moved generated controller input Action dropdowns into profile edit mode only.
6+
- Added edit-mode gamepad input highlighting for matching generated controller inputs.
7+
- Kept Controls status as Wireframe and kept persistence through the shared DB/mock adapter.
8+
9+
## Branch Validation
10+
- PASS: current branch verified as `main` before edits.
11+
12+
## Impacted Lane
13+
- Controls / Input Mapping.
14+
15+
## Playwright Impacted
16+
- Yes.
17+
18+
## Validation Performed
19+
- PASS: `node --check toolbox/controls/controls.js`
20+
- PASS: `node --check tests/playwright/tools/InputMappingV2Tool.spec.mjs`
21+
- PASS: `git diff --check`
22+
- PASS: `npx playwright test tests/playwright/tools/InputMappingV2Tool.spec.mjs`
23+
24+
## Manual Validation Steps
25+
- Open Controls and refresh devices with a detected gamepad.
26+
- Add a controller profile and confirm the saved profile row shows only the compact summary.
27+
- Click Edit and confirm profile row values are text while generated input Action dropdowns appear underneath.
28+
- Press a controller button during edit and confirm the matching generated input row highlights with the selected Action.
29+
- Assign generated input Actions, Save, reload, and confirm assignments persist.
30+
- Edit a profile, change an Action, Cancel, reload, and confirm the unsaved change did not persist.
31+
32+
## Skipped Lanes
33+
- Full samples validation skipped by request because this PR only changes Controls UI behavior and targeted Playwright coverage exercises the impacted lane.
34+
35+
## Runtime Engine Behavior
36+
- Confirmed: no runtime engine behavior changed.
37+
38+
## Completion Check
39+
- PASS: Controller Profile Edit shows profile row values as text, not dropdowns.
40+
- PASS: Generated input Action dropdowns appear only in edit mode.
41+
- PASS: Generated input Action dropdowns are hidden outside edit mode.
42+
- PASS: Controller input press during edit highlights the matching generated input.
43+
- PASS: Selected/assigned Action is visibly shown for the pressed input.
44+
- PASS: Editing one input does not alter other inputs.
45+
- PASS: Save persists generated input action assignments after reload.
46+
- PASS: Cancel does not persist unsaved generated input action changes.

‎docs_build/dev/reports/coverage_changed_js_guardrail.txt‎

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,7 @@ Missing changed runtime JS files are WARN, not FAIL.
66
Source: Playwright/Chromium built-in V8 coverage from the active Playwright run.
77

88
Changed runtime JS files considered:
9-
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
10-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
11-
(91%) toolbox/controls/controls.js - executed lines 1626/1626; executed functions 165/181
9+
(94%) toolbox/controls/controls.js - executed lines 1686/1686; executed functions 186/197
1210

1311
Guardrail warnings:
14-
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: changed runtime JS file missing from coverage; advisory only
15-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - WARNING: changed runtime JS file missing from coverage; advisory only
12+
(100%) none - no changed runtime JS coverage warnings

‎docs_build/dev/reports/playwright_v8_coverage_report.txt‎

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,25 @@ Note: entry percentages use function coverage when available, otherwise line cov
1212
Note: coverage entries are aggregated across every page/tool where coverageReporter.start(page) and coverageReporter.stop(page) ran.
1313

1414
Exercised tool entry points detected:
15-
(89%) Toolbox Index - exercised 4 runtime JS files
15+
(92%) Toolbox Index - exercised 4 runtime JS files
1616
(0%) Tool Template V2 - not exercised by this Playwright run
1717
(59%) Theme V2 Shared JS - exercised 2 runtime JS files
1818

1919
Changed runtime JS files covered:
20-
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
21-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
22-
(91%) toolbox/controls/controls.js - executed lines 1626/1626; executed functions 165/181
20+
(94%) toolbox/controls/controls.js - executed lines 1686/1686; executed functions 186/197
2321

2422
Files with executed line/function counts where available:
2523
(53%) src/engine/api/server-api-client.js - executed lines 159/159; executed functions 10/19
2624
(58%) assets/theme-v2/js/gamefoundry-partials.js - executed lines 603/603; executed functions 30/52
2725
(64%) assets/theme-v2/js/tool-display-mode.js - executed lines 209/209; executed functions 9/14
2826
(75%) toolbox/tool-registry-api-client.js - executed lines 152/152; executed functions 21/28
29-
(91%) toolbox/controls/controls.js - executed lines 1626/1626; executed functions 165/181
27+
(94%) toolbox/controls/controls.js - executed lines 1686/1686; executed functions 186/197
3028
(100%) toolbox/controls/controls-api-client.js - executed lines 12/12; executed functions 2/2
3129
(100%) toolbox/objects/objects-api-client.js - executed lines 10/10; executed functions 2/2
3230

3331
Uncovered or low-coverage changed JS files:
34-
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: uncovered changed runtime JS file; advisory only
35-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - WARNING: uncovered changed runtime JS file; advisory only
32+
(100%) none - no low-coverage changed runtime JS files
3633

3734
Changed JS files considered:
38-
(0%) src/dev-runtime/persistence/mock-db-store.js - changed JS file not collected as browser runtime coverage
39-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - changed JS file not collected as browser runtime coverage
4035
(0%) tests/playwright/tools/InputMappingV2Tool.spec.mjs - changed JS file not collected as browser runtime coverage
41-
(91%) toolbox/controls/controls.js - changed JS file with browser V8 coverage
36+
(94%) toolbox/controls/controls.js - changed JS file with browser V8 coverage

‎tests/playwright/tools/InputMappingV2Tool.spec.mjs‎

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -600,11 +600,13 @@ test("Controls generates controller profiles, shows fallback status, and mapping
600600
expect(awaitcontrollerProfileRecords(page)).toHaveLength(0);
601601

602602
awaitpage.evaluate(()=>{
603+
window.__arcadeButtons=Array.from({length: 16},()=>({pressed: false,value: 0}));
604+
window.__arcadeAxes=[0,0];
603605
Object.defineProperty(navigator,"getGamepads",{
604606
configurable: true,
605607
value: ()=>[{
606-
axes: [0,0],
607-
buttons: Array.from({length: 16},()=>({pressed: false,value: 0})),
608+
axes: window.__arcadeAxes,
609+
buttons: window.__arcadeButtons,
608610
id: "Arcade Test Pad",
609611
index: 0,
610612
}],
@@ -628,7 +630,7 @@ test("Controls generates controller profiles, shows fallback status, and mapping
628630
awaitpage.locator("[data-controller-profile-add]").click();
629631
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("Arcade Test Pad");
630632
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("Arcade Test Pad Profile");
631-
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("Action Required");
633+
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("0/18 Actions assigned");
632634
awaitexpect(page.locator("[data-controller-profile-table] th")).toHaveText([
633635
"Device Type",
634636
"Controller Name",
@@ -637,10 +639,8 @@ test("Controls generates controller profiles, shows fallback status, and mapping
637639
"Action",
638640
]);
639641
awaitexpect(page.locator("[data-controller-profile-row]").first()).not.toContainText("Button0");
640-
awaitexpect(page.locator("[data-controller-profile-actions-row]").first().locator(".content-grid--three")).toBeVisible();
641-
awaitexpect(page.locator("[data-controller-profile-actions-row]").first().locator("[data-controller-profile-input-pair]")).toHaveCount(18);
642-
awaitexpect(page.locator("[data-controller-profile-actions-row]").first().locator("[data-controller-profile-input-pair]").first().locator("strong")).toHaveText("Button0");
643-
awaitexpect(page.locator("[data-controller-profile-actions-row]").first().locator("[data-controller-profile-input-pair]").first().locator("select")).toBeVisible();
642+
awaitexpect(page.locator("[data-controller-profile-actions-row]")).toHaveCount(0);
643+
awaitexpect(page.locator("[data-controller-profile-input-action]")).toHaveCount(0);
644644
awaitexpect(page.locator("[data-controller-profile-fallback-status]")).toContainText("Exact saved profile");
645645

646646
letprofiles=awaitcontrollerProfileRecords(page);
@@ -673,22 +673,56 @@ test("Controls generates controller profiles, shows fallback status, and mapping
673673
"Axis1",
674674
]);
675675

676-
awaitpage.locator("[data-controller-profile-save-actions]").click();
676+
awaitpage.locator("[data-controller-profile-edit]").click();
677+
consteditRow=page.locator("[data-controller-profile-editing-row]");
678+
awaitexpect(editRow.locator("td").nth(0)).toHaveText("Gamepad");
679+
awaitexpect(editRow.locator("td").nth(1)).toHaveText("Arcade Test Pad");
680+
awaitexpect(editRow.locator("td").nth(2)).toHaveText("Arcade Test Pad");
681+
awaitexpect(editRow.locator("td").nth(3)).toHaveText("Arcade Test Pad Profile");
682+
awaitexpect(editRow.locator("select")).toHaveCount(0);
683+
awaitexpect(editRow.locator("input")).toHaveCount(0);
684+
awaitexpect(editRow.locator("button")).toHaveText(["Save","Cancel"]);
685+
686+
consteditingActionsRow=page.locator("[data-controller-profile-editing-actions-row]");
687+
awaitexpect(editingActionsRow.locator(".content-grid--three")).toBeVisible();
688+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-pair]")).toHaveCount(18);
689+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-pair]").first().locator("strong")).toHaveText("Button0");
690+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-action]")).toHaveCount(18);
691+
692+
awaitpage.locator("[data-controller-profile-save]").click();
677693
awaitexpect(page.locator("[data-controller-profile-status]")).toContainText("Action Required");
678694
profiles=awaitcontrollerProfileRecords(page);
679695
expect(profiles[0].actions).toEqual([]);
680696

681-
constinputActionSelects=page.locator("[data-controller-profile-input-action]");
697+
constinputActionSelects=editingActionsRow.locator("[data-controller-profile-input-action]");
682698
constinputActionCount=awaitinputActionSelects.count();
683699
expect(inputActionCount).toBe(profiles[0].inputs.length);
684700
for(letindex=0;index<inputActionCount;index+=1){
685701
awaitinputActionSelects.nth(index).selectOption(index===0 ? "fire" : "moveRight");
686702
}
687-
awaitpage.locator("[data-controller-profile-save-actions]").click();
703+
awaitexpect(inputActionSelects.nth(1)).toHaveValue("moveRight");
704+
awaitpage.evaluate(()=>{
705+
window.__arcadeButtons[0]={pressed: true,value: 1};
706+
});
707+
constactiveProfileInput=page.locator("[data-controller-profile-input-pair][data-controller-profile-input-active='true']");
708+
awaitexpect(activeProfileInput.locator("strong")).toHaveText("Button0");
709+
awaitexpect(activeProfileInput.locator("[data-controller-profile-input-assigned-action]")).toHaveText("Selected Action: Fire");
710+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-pair]").nth(1)).not.toHaveAttribute("data-controller-profile-input-active","true");
711+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-pair]").nth(1).locator("[data-controller-profile-input-assigned-action]")).toHaveText("Assigned Action: Move Right");
712+
713+
awaitpage.locator("[data-controller-profile-save]").click();
688714
profiles=awaitcontrollerProfileRecords(page);
689715
expect(profiles[0].actions).toHaveLength(profiles[0].inputs.length);
690716
expect(profiles[0].actions[0]).toBe("fire");
691717
expect(profiles[0].actions[1]).toBe("moveRight");
718+
awaitexpect(page.locator("[data-controller-profile-input-action]")).toHaveCount(0);
719+
720+
awaitpage.locator("[data-controller-profile-edit]").click();
721+
awaitpage.locator("[data-controller-profile-input-action]").first().selectOption("jump");
722+
awaitpage.locator("[data-controller-profile-cancel]").click();
723+
profiles=awaitcontrollerProfileRecords(page);
724+
expect(profiles[0].actions[0]).toBe("fire");
725+
awaitexpect(page.locator("[data-controller-profile-input-action]")).toHaveCount(0);
692726

693727
awaitpage.locator("[data-controller-profile-trash]").click();
694728
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("No controller profiles saved yet.");

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Refine Controls controller profile edit mode and input highlighting -… · ToolboxAid/HTML-JavaScript-Gaming@f424497 · GitHub
Skip to content

Commit f424497

Browse files
committed
Refine Controls controller profile edit mode and input highlighting - PR_26161_029-controls-controller-profile-edit-mode
1 parent 2589276 commit f424497

7 files changed

Lines changed: 785 additions & 522 deletions

File tree

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
docs_build/dev/reports/controls-compact-controller-profile-report.md
2-
docs_build/dev/reports/codex_review.diff
31
docs_build/dev/reports/codex_changed_files.txt
4-
docs_build/dev/reports/playwright_v8_coverage_report.txt
2+
docs_build/dev/reports/codex_review.diff
3+
docs_build/dev/reports/controls-controller-profile-edit-mode-report.md
54
docs_build/dev/reports/coverage_changed_js_guardrail.txt
5+
docs_build/dev/reports/playwright_v8_coverage_report.txt
66
tests/playwright/tools/InputMappingV2Tool.spec.mjs
77
toolbox/controls/controls.js
8-
toolbox/controls/index.html

‎docs_build/dev/reports/codex_review.diff‎

Lines changed: 526 additions & 400 deletions
Large diffs are not rendered by default.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# PR_26161_029 Controls Controller Profile Edit Mode Report
2+
3+
## Scope
4+
- Updated Controls controller profile rows so saved profiles render as compact summaries outside edit mode.
5+
- Moved generated controller input Action dropdowns into profile edit mode only.
6+
- Added edit-mode gamepad input highlighting for matching generated controller inputs.
7+
- Kept Controls status as Wireframe and kept persistence through the shared DB/mock adapter.
8+
9+
## Branch Validation
10+
- PASS: current branch verified as `main` before edits.
11+
12+
## Impacted Lane
13+
- Controls / Input Mapping.
14+
15+
## Playwright Impacted
16+
- Yes.
17+
18+
## Validation Performed
19+
- PASS: `node --check toolbox/controls/controls.js`
20+
- PASS: `node --check tests/playwright/tools/InputMappingV2Tool.spec.mjs`
21+
- PASS: `git diff --check`
22+
- PASS: `npx playwright test tests/playwright/tools/InputMappingV2Tool.spec.mjs`
23+
24+
## Manual Validation Steps
25+
- Open Controls and refresh devices with a detected gamepad.
26+
- Add a controller profile and confirm the saved profile row shows only the compact summary.
27+
- Click Edit and confirm profile row values are text while generated input Action dropdowns appear underneath.
28+
- Press a controller button during edit and confirm the matching generated input row highlights with the selected Action.
29+
- Assign generated input Actions, Save, reload, and confirm assignments persist.
30+
- Edit a profile, change an Action, Cancel, reload, and confirm the unsaved change did not persist.
31+
32+
## Skipped Lanes
33+
- Full samples validation skipped by request because this PR only changes Controls UI behavior and targeted Playwright coverage exercises the impacted lane.
34+
35+
## Runtime Engine Behavior
36+
- Confirmed: no runtime engine behavior changed.
37+
38+
## Completion Check
39+
- PASS: Controller Profile Edit shows profile row values as text, not dropdowns.
40+
- PASS: Generated input Action dropdowns appear only in edit mode.
41+
- PASS: Generated input Action dropdowns are hidden outside edit mode.
42+
- PASS: Controller input press during edit highlights the matching generated input.
43+
- PASS: Selected/assigned Action is visibly shown for the pressed input.
44+
- PASS: Editing one input does not alter other inputs.
45+
- PASS: Save persists generated input action assignments after reload.
46+
- PASS: Cancel does not persist unsaved generated input action changes.

‎docs_build/dev/reports/coverage_changed_js_guardrail.txt‎

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,7 @@ Missing changed runtime JS files are WARN, not FAIL.
66
Source: Playwright/Chromium built-in V8 coverage from the active Playwright run.
77

88
Changed runtime JS files considered:
9-
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
10-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
11-
(91%) toolbox/controls/controls.js - executed lines 1626/1626; executed functions 165/181
9+
(94%) toolbox/controls/controls.js - executed lines 1686/1686; executed functions 186/197
1210

1311
Guardrail warnings:
14-
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: changed runtime JS file missing from coverage; advisory only
15-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - WARNING: changed runtime JS file missing from coverage; advisory only
12+
(100%) none - no changed runtime JS coverage warnings

‎docs_build/dev/reports/playwright_v8_coverage_report.txt‎

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,25 @@ Note: entry percentages use function coverage when available, otherwise line cov
1212
Note: coverage entries are aggregated across every page/tool where coverageReporter.start(page) and coverageReporter.stop(page) ran.
1313

1414
Exercised tool entry points detected:
15-
(89%) Toolbox Index - exercised 4 runtime JS files
15+
(92%) Toolbox Index - exercised 4 runtime JS files
1616
(0%) Tool Template V2 - not exercised by this Playwright run
1717
(59%) Theme V2 Shared JS - exercised 2 runtime JS files
1818

1919
Changed runtime JS files covered:
20-
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
21-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
22-
(91%) toolbox/controls/controls.js - executed lines 1626/1626; executed functions 165/181
20+
(94%) toolbox/controls/controls.js - executed lines 1686/1686; executed functions 186/197
2321

2422
Files with executed line/function counts where available:
2523
(53%) src/engine/api/server-api-client.js - executed lines 159/159; executed functions 10/19
2624
(58%) assets/theme-v2/js/gamefoundry-partials.js - executed lines 603/603; executed functions 30/52
2725
(64%) assets/theme-v2/js/tool-display-mode.js - executed lines 209/209; executed functions 9/14
2826
(75%) toolbox/tool-registry-api-client.js - executed lines 152/152; executed functions 21/28
29-
(91%) toolbox/controls/controls.js - executed lines 1626/1626; executed functions 165/181
27+
(94%) toolbox/controls/controls.js - executed lines 1686/1686; executed functions 186/197
3028
(100%) toolbox/controls/controls-api-client.js - executed lines 12/12; executed functions 2/2
3129
(100%) toolbox/objects/objects-api-client.js - executed lines 10/10; executed functions 2/2
3230

3331
Uncovered or low-coverage changed JS files:
34-
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: uncovered changed runtime JS file; advisory only
35-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - WARNING: uncovered changed runtime JS file; advisory only
32+
(100%) none - no low-coverage changed runtime JS files
3633

3734
Changed JS files considered:
38-
(0%) src/dev-runtime/persistence/mock-db-store.js - changed JS file not collected as browser runtime coverage
39-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - changed JS file not collected as browser runtime coverage
4035
(0%) tests/playwright/tools/InputMappingV2Tool.spec.mjs - changed JS file not collected as browser runtime coverage
41-
(91%) toolbox/controls/controls.js - changed JS file with browser V8 coverage
36+
(94%) toolbox/controls/controls.js - changed JS file with browser V8 coverage

‎tests/playwright/tools/InputMappingV2Tool.spec.mjs‎

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -600,11 +600,13 @@ test("Controls generates controller profiles, shows fallback status, and mapping
600600
expect(awaitcontrollerProfileRecords(page)).toHaveLength(0);
601601

602602
awaitpage.evaluate(()=>{
603+
window.__arcadeButtons=Array.from({length: 16},()=>({pressed: false,value: 0}));
604+
window.__arcadeAxes=[0,0];
603605
Object.defineProperty(navigator,"getGamepads",{
604606
configurable: true,
605607
value: ()=>[{
606-
axes: [0,0],
607-
buttons: Array.from({length: 16},()=>({pressed: false,value: 0})),
608+
axes: window.__arcadeAxes,
609+
buttons: window.__arcadeButtons,
608610
id: "Arcade Test Pad",
609611
index: 0,
610612
}],
@@ -628,7 +630,7 @@ test("Controls generates controller profiles, shows fallback status, and mapping
628630
awaitpage.locator("[data-controller-profile-add]").click();
629631
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("Arcade Test Pad");
630632
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("Arcade Test Pad Profile");
631-
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("Action Required");
633+
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("0/18 Actions assigned");
632634
awaitexpect(page.locator("[data-controller-profile-table] th")).toHaveText([
633635
"Device Type",
634636
"Controller Name",
@@ -637,10 +639,8 @@ test("Controls generates controller profiles, shows fallback status, and mapping
637639
"Action",
638640
]);
639641
awaitexpect(page.locator("[data-controller-profile-row]").first()).not.toContainText("Button0");
640-
awaitexpect(page.locator("[data-controller-profile-actions-row]").first().locator(".content-grid--three")).toBeVisible();
641-
awaitexpect(page.locator("[data-controller-profile-actions-row]").first().locator("[data-controller-profile-input-pair]")).toHaveCount(18);
642-
awaitexpect(page.locator("[data-controller-profile-actions-row]").first().locator("[data-controller-profile-input-pair]").first().locator("strong")).toHaveText("Button0");
643-
awaitexpect(page.locator("[data-controller-profile-actions-row]").first().locator("[data-controller-profile-input-pair]").first().locator("select")).toBeVisible();
642+
awaitexpect(page.locator("[data-controller-profile-actions-row]")).toHaveCount(0);
643+
awaitexpect(page.locator("[data-controller-profile-input-action]")).toHaveCount(0);
644644
awaitexpect(page.locator("[data-controller-profile-fallback-status]")).toContainText("Exact saved profile");
645645

646646
letprofiles=awaitcontrollerProfileRecords(page);
@@ -673,22 +673,56 @@ test("Controls generates controller profiles, shows fallback status, and mapping
673673
"Axis1",
674674
]);
675675

676-
awaitpage.locator("[data-controller-profile-save-actions]").click();
676+
awaitpage.locator("[data-controller-profile-edit]").click();
677+
consteditRow=page.locator("[data-controller-profile-editing-row]");
678+
awaitexpect(editRow.locator("td").nth(0)).toHaveText("Gamepad");
679+
awaitexpect(editRow.locator("td").nth(1)).toHaveText("Arcade Test Pad");
680+
awaitexpect(editRow.locator("td").nth(2)).toHaveText("Arcade Test Pad");
681+
awaitexpect(editRow.locator("td").nth(3)).toHaveText("Arcade Test Pad Profile");
682+
awaitexpect(editRow.locator("select")).toHaveCount(0);
683+
awaitexpect(editRow.locator("input")).toHaveCount(0);
684+
awaitexpect(editRow.locator("button")).toHaveText(["Save","Cancel"]);
685+
686+
consteditingActionsRow=page.locator("[data-controller-profile-editing-actions-row]");
687+
awaitexpect(editingActionsRow.locator(".content-grid--three")).toBeVisible();
688+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-pair]")).toHaveCount(18);
689+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-pair]").first().locator("strong")).toHaveText("Button0");
690+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-action]")).toHaveCount(18);
691+
692+
awaitpage.locator("[data-controller-profile-save]").click();
677693
awaitexpect(page.locator("[data-controller-profile-status]")).toContainText("Action Required");
678694
profiles=awaitcontrollerProfileRecords(page);
679695
expect(profiles[0].actions).toEqual([]);
680696

681-
constinputActionSelects=page.locator("[data-controller-profile-input-action]");
697+
constinputActionSelects=editingActionsRow.locator("[data-controller-profile-input-action]");
682698
constinputActionCount=awaitinputActionSelects.count();
683699
expect(inputActionCount).toBe(profiles[0].inputs.length);
684700
for(letindex=0;index<inputActionCount;index+=1){
685701
awaitinputActionSelects.nth(index).selectOption(index===0 ? "fire" : "moveRight");
686702
}
687-
awaitpage.locator("[data-controller-profile-save-actions]").click();
703+
awaitexpect(inputActionSelects.nth(1)).toHaveValue("moveRight");
704+
awaitpage.evaluate(()=>{
705+
window.__arcadeButtons[0]={pressed: true,value: 1};
706+
});
707+
constactiveProfileInput=page.locator("[data-controller-profile-input-pair][data-controller-profile-input-active='true']");
708+
awaitexpect(activeProfileInput.locator("strong")).toHaveText("Button0");
709+
awaitexpect(activeProfileInput.locator("[data-controller-profile-input-assigned-action]")).toHaveText("Selected Action: Fire");
710+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-pair]").nth(1)).not.toHaveAttribute("data-controller-profile-input-active","true");
711+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-pair]").nth(1).locator("[data-controller-profile-input-assigned-action]")).toHaveText("Assigned Action: Move Right");
712+
713+
awaitpage.locator("[data-controller-profile-save]").click();
688714
profiles=awaitcontrollerProfileRecords(page);
689715
expect(profiles[0].actions).toHaveLength(profiles[0].inputs.length);
690716
expect(profiles[0].actions[0]).toBe("fire");
691717
expect(profiles[0].actions[1]).toBe("moveRight");
718+
awaitexpect(page.locator("[data-controller-profile-input-action]")).toHaveCount(0);
719+
720+
awaitpage.locator("[data-controller-profile-edit]").click();
721+
awaitpage.locator("[data-controller-profile-input-action]").first().selectOption("jump");
722+
awaitpage.locator("[data-controller-profile-cancel]").click();
723+
profiles=awaitcontrollerProfileRecords(page);
724+
expect(profiles[0].actions[0]).toBe("fire");
725+
awaitexpect(page.locator("[data-controller-profile-input-action]")).toHaveCount(0);
692726

693727
awaitpage.locator("[data-controller-profile-trash]").click();
694728
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("No controller profiles saved yet.");

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Refine Controls controller profile edit mode and input highlighting -… · ToolboxAid/HTML-JavaScript-Gaming@f424497 · GitHub
Skip to content

Commit f424497

Browse files
committed
Refine Controls controller profile edit mode and input highlighting - PR_26161_029-controls-controller-profile-edit-mode
1 parent 2589276 commit f424497

7 files changed

Lines changed: 785 additions & 522 deletions

File tree

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
docs_build/dev/reports/controls-compact-controller-profile-report.md
2-
docs_build/dev/reports/codex_review.diff
31
docs_build/dev/reports/codex_changed_files.txt
4-
docs_build/dev/reports/playwright_v8_coverage_report.txt
2+
docs_build/dev/reports/codex_review.diff
3+
docs_build/dev/reports/controls-controller-profile-edit-mode-report.md
54
docs_build/dev/reports/coverage_changed_js_guardrail.txt
5+
docs_build/dev/reports/playwright_v8_coverage_report.txt
66
tests/playwright/tools/InputMappingV2Tool.spec.mjs
77
toolbox/controls/controls.js
8-
toolbox/controls/index.html

‎docs_build/dev/reports/codex_review.diff‎

Lines changed: 526 additions & 400 deletions
Large diffs are not rendered by default.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# PR_26161_029 Controls Controller Profile Edit Mode Report
2+
3+
## Scope
4+
- Updated Controls controller profile rows so saved profiles render as compact summaries outside edit mode.
5+
- Moved generated controller input Action dropdowns into profile edit mode only.
6+
- Added edit-mode gamepad input highlighting for matching generated controller inputs.
7+
- Kept Controls status as Wireframe and kept persistence through the shared DB/mock adapter.
8+
9+
## Branch Validation
10+
- PASS: current branch verified as `main` before edits.
11+
12+
## Impacted Lane
13+
- Controls / Input Mapping.
14+
15+
## Playwright Impacted
16+
- Yes.
17+
18+
## Validation Performed
19+
- PASS: `node --check toolbox/controls/controls.js`
20+
- PASS: `node --check tests/playwright/tools/InputMappingV2Tool.spec.mjs`
21+
- PASS: `git diff --check`
22+
- PASS: `npx playwright test tests/playwright/tools/InputMappingV2Tool.spec.mjs`
23+
24+
## Manual Validation Steps
25+
- Open Controls and refresh devices with a detected gamepad.
26+
- Add a controller profile and confirm the saved profile row shows only the compact summary.
27+
- Click Edit and confirm profile row values are text while generated input Action dropdowns appear underneath.
28+
- Press a controller button during edit and confirm the matching generated input row highlights with the selected Action.
29+
- Assign generated input Actions, Save, reload, and confirm assignments persist.
30+
- Edit a profile, change an Action, Cancel, reload, and confirm the unsaved change did not persist.
31+
32+
## Skipped Lanes
33+
- Full samples validation skipped by request because this PR only changes Controls UI behavior and targeted Playwright coverage exercises the impacted lane.
34+
35+
## Runtime Engine Behavior
36+
- Confirmed: no runtime engine behavior changed.
37+
38+
## Completion Check
39+
- PASS: Controller Profile Edit shows profile row values as text, not dropdowns.
40+
- PASS: Generated input Action dropdowns appear only in edit mode.
41+
- PASS: Generated input Action dropdowns are hidden outside edit mode.
42+
- PASS: Controller input press during edit highlights the matching generated input.
43+
- PASS: Selected/assigned Action is visibly shown for the pressed input.
44+
- PASS: Editing one input does not alter other inputs.
45+
- PASS: Save persists generated input action assignments after reload.
46+
- PASS: Cancel does not persist unsaved generated input action changes.

‎docs_build/dev/reports/coverage_changed_js_guardrail.txt‎

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,7 @@ Missing changed runtime JS files are WARN, not FAIL.
66
Source: Playwright/Chromium built-in V8 coverage from the active Playwright run.
77

88
Changed runtime JS files considered:
9-
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
10-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
11-
(91%) toolbox/controls/controls.js - executed lines 1626/1626; executed functions 165/181
9+
(94%) toolbox/controls/controls.js - executed lines 1686/1686; executed functions 186/197
1210

1311
Guardrail warnings:
14-
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: changed runtime JS file missing from coverage; advisory only
15-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - WARNING: changed runtime JS file missing from coverage; advisory only
12+
(100%) none - no changed runtime JS coverage warnings

‎docs_build/dev/reports/playwright_v8_coverage_report.txt‎

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,25 @@ Note: entry percentages use function coverage when available, otherwise line cov
1212
Note: coverage entries are aggregated across every page/tool where coverageReporter.start(page) and coverageReporter.stop(page) ran.
1313

1414
Exercised tool entry points detected:
15-
(89%) Toolbox Index - exercised 4 runtime JS files
15+
(92%) Toolbox Index - exercised 4 runtime JS files
1616
(0%) Tool Template V2 - not exercised by this Playwright run
1717
(59%) Theme V2 Shared JS - exercised 2 runtime JS files
1818

1919
Changed runtime JS files covered:
20-
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
21-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
22-
(91%) toolbox/controls/controls.js - executed lines 1626/1626; executed functions 165/181
20+
(94%) toolbox/controls/controls.js - executed lines 1686/1686; executed functions 186/197
2321

2422
Files with executed line/function counts where available:
2523
(53%) src/engine/api/server-api-client.js - executed lines 159/159; executed functions 10/19
2624
(58%) assets/theme-v2/js/gamefoundry-partials.js - executed lines 603/603; executed functions 30/52
2725
(64%) assets/theme-v2/js/tool-display-mode.js - executed lines 209/209; executed functions 9/14
2826
(75%) toolbox/tool-registry-api-client.js - executed lines 152/152; executed functions 21/28
29-
(91%) toolbox/controls/controls.js - executed lines 1626/1626; executed functions 165/181
27+
(94%) toolbox/controls/controls.js - executed lines 1686/1686; executed functions 186/197
3028
(100%) toolbox/controls/controls-api-client.js - executed lines 12/12; executed functions 2/2
3129
(100%) toolbox/objects/objects-api-client.js - executed lines 10/10; executed functions 2/2
3230

3331
Uncovered or low-coverage changed JS files:
34-
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: uncovered changed runtime JS file; advisory only
35-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - WARNING: uncovered changed runtime JS file; advisory only
32+
(100%) none - no low-coverage changed runtime JS files
3633

3734
Changed JS files considered:
38-
(0%) src/dev-runtime/persistence/mock-db-store.js - changed JS file not collected as browser runtime coverage
39-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - changed JS file not collected as browser runtime coverage
4035
(0%) tests/playwright/tools/InputMappingV2Tool.spec.mjs - changed JS file not collected as browser runtime coverage
41-
(91%) toolbox/controls/controls.js - changed JS file with browser V8 coverage
36+
(94%) toolbox/controls/controls.js - changed JS file with browser V8 coverage

‎tests/playwright/tools/InputMappingV2Tool.spec.mjs‎

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -600,11 +600,13 @@ test("Controls generates controller profiles, shows fallback status, and mapping
600600
expect(awaitcontrollerProfileRecords(page)).toHaveLength(0);
601601

602602
awaitpage.evaluate(()=>{
603+
window.__arcadeButtons=Array.from({length: 16},()=>({pressed: false,value: 0}));
604+
window.__arcadeAxes=[0,0];
603605
Object.defineProperty(navigator,"getGamepads",{
604606
configurable: true,
605607
value: ()=>[{
606-
axes: [0,0],
607-
buttons: Array.from({length: 16},()=>({pressed: false,value: 0})),
608+
axes: window.__arcadeAxes,
609+
buttons: window.__arcadeButtons,
608610
id: "Arcade Test Pad",
609611
index: 0,
610612
}],
@@ -628,7 +630,7 @@ test("Controls generates controller profiles, shows fallback status, and mapping
628630
awaitpage.locator("[data-controller-profile-add]").click();
629631
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("Arcade Test Pad");
630632
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("Arcade Test Pad Profile");
631-
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("Action Required");
633+
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("0/18 Actions assigned");
632634
awaitexpect(page.locator("[data-controller-profile-table] th")).toHaveText([
633635
"Device Type",
634636
"Controller Name",
@@ -637,10 +639,8 @@ test("Controls generates controller profiles, shows fallback status, and mapping
637639
"Action",
638640
]);
639641
awaitexpect(page.locator("[data-controller-profile-row]").first()).not.toContainText("Button0");
640-
awaitexpect(page.locator("[data-controller-profile-actions-row]").first().locator(".content-grid--three")).toBeVisible();
641-
awaitexpect(page.locator("[data-controller-profile-actions-row]").first().locator("[data-controller-profile-input-pair]")).toHaveCount(18);
642-
awaitexpect(page.locator("[data-controller-profile-actions-row]").first().locator("[data-controller-profile-input-pair]").first().locator("strong")).toHaveText("Button0");
643-
awaitexpect(page.locator("[data-controller-profile-actions-row]").first().locator("[data-controller-profile-input-pair]").first().locator("select")).toBeVisible();
642+
awaitexpect(page.locator("[data-controller-profile-actions-row]")).toHaveCount(0);
643+
awaitexpect(page.locator("[data-controller-profile-input-action]")).toHaveCount(0);
644644
awaitexpect(page.locator("[data-controller-profile-fallback-status]")).toContainText("Exact saved profile");
645645

646646
letprofiles=awaitcontrollerProfileRecords(page);
@@ -673,22 +673,56 @@ test("Controls generates controller profiles, shows fallback status, and mapping
673673
"Axis1",
674674
]);
675675

676-
awaitpage.locator("[data-controller-profile-save-actions]").click();
676+
awaitpage.locator("[data-controller-profile-edit]").click();
677+
consteditRow=page.locator("[data-controller-profile-editing-row]");
678+
awaitexpect(editRow.locator("td").nth(0)).toHaveText("Gamepad");
679+
awaitexpect(editRow.locator("td").nth(1)).toHaveText("Arcade Test Pad");
680+
awaitexpect(editRow.locator("td").nth(2)).toHaveText("Arcade Test Pad");
681+
awaitexpect(editRow.locator("td").nth(3)).toHaveText("Arcade Test Pad Profile");
682+
awaitexpect(editRow.locator("select")).toHaveCount(0);
683+
awaitexpect(editRow.locator("input")).toHaveCount(0);
684+
awaitexpect(editRow.locator("button")).toHaveText(["Save","Cancel"]);
685+
686+
consteditingActionsRow=page.locator("[data-controller-profile-editing-actions-row]");
687+
awaitexpect(editingActionsRow.locator(".content-grid--three")).toBeVisible();
688+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-pair]")).toHaveCount(18);
689+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-pair]").first().locator("strong")).toHaveText("Button0");
690+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-action]")).toHaveCount(18);
691+
692+
awaitpage.locator("[data-controller-profile-save]").click();
677693
awaitexpect(page.locator("[data-controller-profile-status]")).toContainText("Action Required");
678694
profiles=awaitcontrollerProfileRecords(page);
679695
expect(profiles[0].actions).toEqual([]);
680696

681-
constinputActionSelects=page.locator("[data-controller-profile-input-action]");
697+
constinputActionSelects=editingActionsRow.locator("[data-controller-profile-input-action]");
682698
constinputActionCount=awaitinputActionSelects.count();
683699
expect(inputActionCount).toBe(profiles[0].inputs.length);
684700
for(letindex=0;index<inputActionCount;index+=1){
685701
awaitinputActionSelects.nth(index).selectOption(index===0 ? "fire" : "moveRight");
686702
}
687-
awaitpage.locator("[data-controller-profile-save-actions]").click();
703+
awaitexpect(inputActionSelects.nth(1)).toHaveValue("moveRight");
704+
awaitpage.evaluate(()=>{
705+
window.__arcadeButtons[0]={pressed: true,value: 1};
706+
});
707+
constactiveProfileInput=page.locator("[data-controller-profile-input-pair][data-controller-profile-input-active='true']");
708+
awaitexpect(activeProfileInput.locator("strong")).toHaveText("Button0");
709+
awaitexpect(activeProfileInput.locator("[data-controller-profile-input-assigned-action]")).toHaveText("Selected Action: Fire");
710+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-pair]").nth(1)).not.toHaveAttribute("data-controller-profile-input-active","true");
711+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-pair]").nth(1).locator("[data-controller-profile-input-assigned-action]")).toHaveText("Assigned Action: Move Right");
712+
713+
awaitpage.locator("[data-controller-profile-save]").click();
688714
profiles=awaitcontrollerProfileRecords(page);
689715
expect(profiles[0].actions).toHaveLength(profiles[0].inputs.length);
690716
expect(profiles[0].actions[0]).toBe("fire");
691717
expect(profiles[0].actions[1]).toBe("moveRight");
718+
awaitexpect(page.locator("[data-controller-profile-input-action]")).toHaveCount(0);
719+
720+
awaitpage.locator("[data-controller-profile-edit]").click();
721+
awaitpage.locator("[data-controller-profile-input-action]").first().selectOption("jump");
722+
awaitpage.locator("[data-controller-profile-cancel]").click();
723+
profiles=awaitcontrollerProfileRecords(page);
724+
expect(profiles[0].actions[0]).toBe("fire");
725+
awaitexpect(page.locator("[data-controller-profile-input-action]")).toHaveCount(0);
692726

693727
awaitpage.locator("[data-controller-profile-trash]").click();
694728
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("No controller profiles saved yet.");

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' Refine Controls controller profile edit mode and input highlighting -… · ToolboxAid/HTML-JavaScript-Gaming@f424497 · GitHub
Skip to content

Commit f424497

Browse files
committed
Refine Controls controller profile edit mode and input highlighting - PR_26161_029-controls-controller-profile-edit-mode
1 parent 2589276 commit f424497

7 files changed

Lines changed: 785 additions & 522 deletions

File tree

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
docs_build/dev/reports/controls-compact-controller-profile-report.md
2-
docs_build/dev/reports/codex_review.diff
31
docs_build/dev/reports/codex_changed_files.txt
4-
docs_build/dev/reports/playwright_v8_coverage_report.txt
2+
docs_build/dev/reports/codex_review.diff
3+
docs_build/dev/reports/controls-controller-profile-edit-mode-report.md
54
docs_build/dev/reports/coverage_changed_js_guardrail.txt
5+
docs_build/dev/reports/playwright_v8_coverage_report.txt
66
tests/playwright/tools/InputMappingV2Tool.spec.mjs
77
toolbox/controls/controls.js
8-
toolbox/controls/index.html

‎docs_build/dev/reports/codex_review.diff‎

Lines changed: 526 additions & 400 deletions
Large diffs are not rendered by default.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# PR_26161_029 Controls Controller Profile Edit Mode Report
2+
3+
## Scope
4+
- Updated Controls controller profile rows so saved profiles render as compact summaries outside edit mode.
5+
- Moved generated controller input Action dropdowns into profile edit mode only.
6+
- Added edit-mode gamepad input highlighting for matching generated controller inputs.
7+
- Kept Controls status as Wireframe and kept persistence through the shared DB/mock adapter.
8+
9+
## Branch Validation
10+
- PASS: current branch verified as `main` before edits.
11+
12+
## Impacted Lane
13+
- Controls / Input Mapping.
14+
15+
## Playwright Impacted
16+
- Yes.
17+
18+
## Validation Performed
19+
- PASS: `node --check toolbox/controls/controls.js`
20+
- PASS: `node --check tests/playwright/tools/InputMappingV2Tool.spec.mjs`
21+
- PASS: `git diff --check`
22+
- PASS: `npx playwright test tests/playwright/tools/InputMappingV2Tool.spec.mjs`
23+
24+
## Manual Validation Steps
25+
- Open Controls and refresh devices with a detected gamepad.
26+
- Add a controller profile and confirm the saved profile row shows only the compact summary.
27+
- Click Edit and confirm profile row values are text while generated input Action dropdowns appear underneath.
28+
- Press a controller button during edit and confirm the matching generated input row highlights with the selected Action.
29+
- Assign generated input Actions, Save, reload, and confirm assignments persist.
30+
- Edit a profile, change an Action, Cancel, reload, and confirm the unsaved change did not persist.
31+
32+
## Skipped Lanes
33+
- Full samples validation skipped by request because this PR only changes Controls UI behavior and targeted Playwright coverage exercises the impacted lane.
34+
35+
## Runtime Engine Behavior
36+
- Confirmed: no runtime engine behavior changed.
37+
38+
## Completion Check
39+
- PASS: Controller Profile Edit shows profile row values as text, not dropdowns.
40+
- PASS: Generated input Action dropdowns appear only in edit mode.
41+
- PASS: Generated input Action dropdowns are hidden outside edit mode.
42+
- PASS: Controller input press during edit highlights the matching generated input.
43+
- PASS: Selected/assigned Action is visibly shown for the pressed input.
44+
- PASS: Editing one input does not alter other inputs.
45+
- PASS: Save persists generated input action assignments after reload.
46+
- PASS: Cancel does not persist unsaved generated input action changes.

‎docs_build/dev/reports/coverage_changed_js_guardrail.txt‎

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,7 @@ Missing changed runtime JS files are WARN, not FAIL.
66
Source: Playwright/Chromium built-in V8 coverage from the active Playwright run.
77

88
Changed runtime JS files considered:
9-
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
10-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
11-
(91%) toolbox/controls/controls.js - executed lines 1626/1626; executed functions 165/181
9+
(94%) toolbox/controls/controls.js - executed lines 1686/1686; executed functions 186/197
1210

1311
Guardrail warnings:
14-
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: changed runtime JS file missing from coverage; advisory only
15-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - WARNING: changed runtime JS file missing from coverage; advisory only
12+
(100%) none - no changed runtime JS coverage warnings

‎docs_build/dev/reports/playwright_v8_coverage_report.txt‎

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,25 @@ Note: entry percentages use function coverage when available, otherwise line cov
1212
Note: coverage entries are aggregated across every page/tool where coverageReporter.start(page) and coverageReporter.stop(page) ran.
1313

1414
Exercised tool entry points detected:
15-
(89%) Toolbox Index - exercised 4 runtime JS files
15+
(92%) Toolbox Index - exercised 4 runtime JS files
1616
(0%) Tool Template V2 - not exercised by this Playwright run
1717
(59%) Theme V2 Shared JS - exercised 2 runtime JS files
1818

1919
Changed runtime JS files covered:
20-
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
21-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
22-
(91%) toolbox/controls/controls.js - executed lines 1626/1626; executed functions 165/181
20+
(94%) toolbox/controls/controls.js - executed lines 1686/1686; executed functions 186/197
2321

2422
Files with executed line/function counts where available:
2523
(53%) src/engine/api/server-api-client.js - executed lines 159/159; executed functions 10/19
2624
(58%) assets/theme-v2/js/gamefoundry-partials.js - executed lines 603/603; executed functions 30/52
2725
(64%) assets/theme-v2/js/tool-display-mode.js - executed lines 209/209; executed functions 9/14
2826
(75%) toolbox/tool-registry-api-client.js - executed lines 152/152; executed functions 21/28
29-
(91%) toolbox/controls/controls.js - executed lines 1626/1626; executed functions 165/181
27+
(94%) toolbox/controls/controls.js - executed lines 1686/1686; executed functions 186/197
3028
(100%) toolbox/controls/controls-api-client.js - executed lines 12/12; executed functions 2/2
3129
(100%) toolbox/objects/objects-api-client.js - executed lines 10/10; executed functions 2/2
3230

3331
Uncovered or low-coverage changed JS files:
34-
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: uncovered changed runtime JS file; advisory only
35-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - WARNING: uncovered changed runtime JS file; advisory only
32+
(100%) none - no low-coverage changed runtime JS files
3633

3734
Changed JS files considered:
38-
(0%) src/dev-runtime/persistence/mock-db-store.js - changed JS file not collected as browser runtime coverage
39-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - changed JS file not collected as browser runtime coverage
4035
(0%) tests/playwright/tools/InputMappingV2Tool.spec.mjs - changed JS file not collected as browser runtime coverage
41-
(91%) toolbox/controls/controls.js - changed JS file with browser V8 coverage
36+
(94%) toolbox/controls/controls.js - changed JS file with browser V8 coverage

‎tests/playwright/tools/InputMappingV2Tool.spec.mjs‎

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -600,11 +600,13 @@ test("Controls generates controller profiles, shows fallback status, and mapping
600600
expect(awaitcontrollerProfileRecords(page)).toHaveLength(0);
601601

602602
awaitpage.evaluate(()=>{
603+
window.__arcadeButtons=Array.from({length: 16},()=>({pressed: false,value: 0}));
604+
window.__arcadeAxes=[0,0];
603605
Object.defineProperty(navigator,"getGamepads",{
604606
configurable: true,
605607
value: ()=>[{
606-
axes: [0,0],
607-
buttons: Array.from({length: 16},()=>({pressed: false,value: 0})),
608+
axes: window.__arcadeAxes,
609+
buttons: window.__arcadeButtons,
608610
id: "Arcade Test Pad",
609611
index: 0,
610612
}],
@@ -628,7 +630,7 @@ test("Controls generates controller profiles, shows fallback status, and mapping
628630
awaitpage.locator("[data-controller-profile-add]").click();
629631
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("Arcade Test Pad");
630632
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("Arcade Test Pad Profile");
631-
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("Action Required");
633+
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("0/18 Actions assigned");
632634
awaitexpect(page.locator("[data-controller-profile-table] th")).toHaveText([
633635
"Device Type",
634636
"Controller Name",
@@ -637,10 +639,8 @@ test("Controls generates controller profiles, shows fallback status, and mapping
637639
"Action",
638640
]);
639641
awaitexpect(page.locator("[data-controller-profile-row]").first()).not.toContainText("Button0");
640-
awaitexpect(page.locator("[data-controller-profile-actions-row]").first().locator(".content-grid--three")).toBeVisible();
641-
awaitexpect(page.locator("[data-controller-profile-actions-row]").first().locator("[data-controller-profile-input-pair]")).toHaveCount(18);
642-
awaitexpect(page.locator("[data-controller-profile-actions-row]").first().locator("[data-controller-profile-input-pair]").first().locator("strong")).toHaveText("Button0");
643-
awaitexpect(page.locator("[data-controller-profile-actions-row]").first().locator("[data-controller-profile-input-pair]").first().locator("select")).toBeVisible();
642+
awaitexpect(page.locator("[data-controller-profile-actions-row]")).toHaveCount(0);
643+
awaitexpect(page.locator("[data-controller-profile-input-action]")).toHaveCount(0);
644644
awaitexpect(page.locator("[data-controller-profile-fallback-status]")).toContainText("Exact saved profile");
645645

646646
letprofiles=awaitcontrollerProfileRecords(page);
@@ -673,22 +673,56 @@ test("Controls generates controller profiles, shows fallback status, and mapping
673673
"Axis1",
674674
]);
675675

676-
awaitpage.locator("[data-controller-profile-save-actions]").click();
676+
awaitpage.locator("[data-controller-profile-edit]").click();
677+
consteditRow=page.locator("[data-controller-profile-editing-row]");
678+
awaitexpect(editRow.locator("td").nth(0)).toHaveText("Gamepad");
679+
awaitexpect(editRow.locator("td").nth(1)).toHaveText("Arcade Test Pad");
680+
awaitexpect(editRow.locator("td").nth(2)).toHaveText("Arcade Test Pad");
681+
awaitexpect(editRow.locator("td").nth(3)).toHaveText("Arcade Test Pad Profile");
682+
awaitexpect(editRow.locator("select")).toHaveCount(0);
683+
awaitexpect(editRow.locator("input")).toHaveCount(0);
684+
awaitexpect(editRow.locator("button")).toHaveText(["Save","Cancel"]);
685+
686+
consteditingActionsRow=page.locator("[data-controller-profile-editing-actions-row]");
687+
awaitexpect(editingActionsRow.locator(".content-grid--three")).toBeVisible();
688+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-pair]")).toHaveCount(18);
689+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-pair]").first().locator("strong")).toHaveText("Button0");
690+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-action]")).toHaveCount(18);
691+
692+
awaitpage.locator("[data-controller-profile-save]").click();
677693
awaitexpect(page.locator("[data-controller-profile-status]")).toContainText("Action Required");
678694
profiles=awaitcontrollerProfileRecords(page);
679695
expect(profiles[0].actions).toEqual([]);
680696

681-
constinputActionSelects=page.locator("[data-controller-profile-input-action]");
697+
constinputActionSelects=editingActionsRow.locator("[data-controller-profile-input-action]");
682698
constinputActionCount=awaitinputActionSelects.count();
683699
expect(inputActionCount).toBe(profiles[0].inputs.length);
684700
for(letindex=0;index<inputActionCount;index+=1){
685701
awaitinputActionSelects.nth(index).selectOption(index===0 ? "fire" : "moveRight");
686702
}
687-
awaitpage.locator("[data-controller-profile-save-actions]").click();
703+
awaitexpect(inputActionSelects.nth(1)).toHaveValue("moveRight");
704+
awaitpage.evaluate(()=>{
705+
window.__arcadeButtons[0]={pressed: true,value: 1};
706+
});
707+
constactiveProfileInput=page.locator("[data-controller-profile-input-pair][data-controller-profile-input-active='true']");
708+
awaitexpect(activeProfileInput.locator("strong")).toHaveText("Button0");
709+
awaitexpect(activeProfileInput.locator("[data-controller-profile-input-assigned-action]")).toHaveText("Selected Action: Fire");
710+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-pair]").nth(1)).not.toHaveAttribute("data-controller-profile-input-active","true");
711+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-pair]").nth(1).locator("[data-controller-profile-input-assigned-action]")).toHaveText("Assigned Action: Move Right");
712+
713+
awaitpage.locator("[data-controller-profile-save]").click();
688714
profiles=awaitcontrollerProfileRecords(page);
689715
expect(profiles[0].actions).toHaveLength(profiles[0].inputs.length);
690716
expect(profiles[0].actions[0]).toBe("fire");
691717
expect(profiles[0].actions[1]).toBe("moveRight");
718+
awaitexpect(page.locator("[data-controller-profile-input-action]")).toHaveCount(0);
719+
720+
awaitpage.locator("[data-controller-profile-edit]").click();
721+
awaitpage.locator("[data-controller-profile-input-action]").first().selectOption("jump");
722+
awaitpage.locator("[data-controller-profile-cancel]").click();
723+
profiles=awaitcontrollerProfileRecords(page);
724+
expect(profiles[0].actions[0]).toBe("fire");
725+
awaitexpect(page.locator("[data-controller-profile-input-action]")).toHaveCount(0);
692726

693727
awaitpage.locator("[data-controller-profile-trash]").click();
694728
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("No controller profiles saved yet.");

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Refine Controls controller profile edit mode and input highlighting -… · ToolboxAid/HTML-JavaScript-Gaming@f424497 · GitHub
Skip to content

Commit f424497

Browse files
committed
Refine Controls controller profile edit mode and input highlighting - PR_26161_029-controls-controller-profile-edit-mode
1 parent 2589276 commit f424497

7 files changed

Lines changed: 785 additions & 522 deletions

File tree

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
docs_build/dev/reports/controls-compact-controller-profile-report.md
2-
docs_build/dev/reports/codex_review.diff
31
docs_build/dev/reports/codex_changed_files.txt
4-
docs_build/dev/reports/playwright_v8_coverage_report.txt
2+
docs_build/dev/reports/codex_review.diff
3+
docs_build/dev/reports/controls-controller-profile-edit-mode-report.md
54
docs_build/dev/reports/coverage_changed_js_guardrail.txt
5+
docs_build/dev/reports/playwright_v8_coverage_report.txt
66
tests/playwright/tools/InputMappingV2Tool.spec.mjs
77
toolbox/controls/controls.js
8-
toolbox/controls/index.html

‎docs_build/dev/reports/codex_review.diff‎

Lines changed: 526 additions & 400 deletions
Large diffs are not rendered by default.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# PR_26161_029 Controls Controller Profile Edit Mode Report
2+
3+
## Scope
4+
- Updated Controls controller profile rows so saved profiles render as compact summaries outside edit mode.
5+
- Moved generated controller input Action dropdowns into profile edit mode only.
6+
- Added edit-mode gamepad input highlighting for matching generated controller inputs.
7+
- Kept Controls status as Wireframe and kept persistence through the shared DB/mock adapter.
8+
9+
## Branch Validation
10+
- PASS: current branch verified as `main` before edits.
11+
12+
## Impacted Lane
13+
- Controls / Input Mapping.
14+
15+
## Playwright Impacted
16+
- Yes.
17+
18+
## Validation Performed
19+
- PASS: `node --check toolbox/controls/controls.js`
20+
- PASS: `node --check tests/playwright/tools/InputMappingV2Tool.spec.mjs`
21+
- PASS: `git diff --check`
22+
- PASS: `npx playwright test tests/playwright/tools/InputMappingV2Tool.spec.mjs`
23+
24+
## Manual Validation Steps
25+
- Open Controls and refresh devices with a detected gamepad.
26+
- Add a controller profile and confirm the saved profile row shows only the compact summary.
27+
- Click Edit and confirm profile row values are text while generated input Action dropdowns appear underneath.
28+
- Press a controller button during edit and confirm the matching generated input row highlights with the selected Action.
29+
- Assign generated input Actions, Save, reload, and confirm assignments persist.
30+
- Edit a profile, change an Action, Cancel, reload, and confirm the unsaved change did not persist.
31+
32+
## Skipped Lanes
33+
- Full samples validation skipped by request because this PR only changes Controls UI behavior and targeted Playwright coverage exercises the impacted lane.
34+
35+
## Runtime Engine Behavior
36+
- Confirmed: no runtime engine behavior changed.
37+
38+
## Completion Check
39+
- PASS: Controller Profile Edit shows profile row values as text, not dropdowns.
40+
- PASS: Generated input Action dropdowns appear only in edit mode.
41+
- PASS: Generated input Action dropdowns are hidden outside edit mode.
42+
- PASS: Controller input press during edit highlights the matching generated input.
43+
- PASS: Selected/assigned Action is visibly shown for the pressed input.
44+
- PASS: Editing one input does not alter other inputs.
45+
- PASS: Save persists generated input action assignments after reload.
46+
- PASS: Cancel does not persist unsaved generated input action changes.

‎docs_build/dev/reports/coverage_changed_js_guardrail.txt‎

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,7 @@ Missing changed runtime JS files are WARN, not FAIL.
66
Source: Playwright/Chromium built-in V8 coverage from the active Playwright run.
77

88
Changed runtime JS files considered:
9-
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
10-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
11-
(91%) toolbox/controls/controls.js - executed lines 1626/1626; executed functions 165/181
9+
(94%) toolbox/controls/controls.js - executed lines 1686/1686; executed functions 186/197
1210

1311
Guardrail warnings:
14-
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: changed runtime JS file missing from coverage; advisory only
15-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - WARNING: changed runtime JS file missing from coverage; advisory only
12+
(100%) none - no changed runtime JS coverage warnings

‎docs_build/dev/reports/playwright_v8_coverage_report.txt‎

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,25 @@ Note: entry percentages use function coverage when available, otherwise line cov
1212
Note: coverage entries are aggregated across every page/tool where coverageReporter.start(page) and coverageReporter.stop(page) ran.
1313

1414
Exercised tool entry points detected:
15-
(89%) Toolbox Index - exercised 4 runtime JS files
15+
(92%) Toolbox Index - exercised 4 runtime JS files
1616
(0%) Tool Template V2 - not exercised by this Playwright run
1717
(59%) Theme V2 Shared JS - exercised 2 runtime JS files
1818

1919
Changed runtime JS files covered:
20-
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
21-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
22-
(91%) toolbox/controls/controls.js - executed lines 1626/1626; executed functions 165/181
20+
(94%) toolbox/controls/controls.js - executed lines 1686/1686; executed functions 186/197
2321

2422
Files with executed line/function counts where available:
2523
(53%) src/engine/api/server-api-client.js - executed lines 159/159; executed functions 10/19
2624
(58%) assets/theme-v2/js/gamefoundry-partials.js - executed lines 603/603; executed functions 30/52
2725
(64%) assets/theme-v2/js/tool-display-mode.js - executed lines 209/209; executed functions 9/14
2826
(75%) toolbox/tool-registry-api-client.js - executed lines 152/152; executed functions 21/28
29-
(91%) toolbox/controls/controls.js - executed lines 1626/1626; executed functions 165/181
27+
(94%) toolbox/controls/controls.js - executed lines 1686/1686; executed functions 186/197
3028
(100%) toolbox/controls/controls-api-client.js - executed lines 12/12; executed functions 2/2
3129
(100%) toolbox/objects/objects-api-client.js - executed lines 10/10; executed functions 2/2
3230

3331
Uncovered or low-coverage changed JS files:
34-
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: uncovered changed runtime JS file; advisory only
35-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - WARNING: uncovered changed runtime JS file; advisory only
32+
(100%) none - no low-coverage changed runtime JS files
3633

3734
Changed JS files considered:
38-
(0%) src/dev-runtime/persistence/mock-db-store.js - changed JS file not collected as browser runtime coverage
39-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - changed JS file not collected as browser runtime coverage
4035
(0%) tests/playwright/tools/InputMappingV2Tool.spec.mjs - changed JS file not collected as browser runtime coverage
41-
(91%) toolbox/controls/controls.js - changed JS file with browser V8 coverage
36+
(94%) toolbox/controls/controls.js - changed JS file with browser V8 coverage

‎tests/playwright/tools/InputMappingV2Tool.spec.mjs‎

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -600,11 +600,13 @@ test("Controls generates controller profiles, shows fallback status, and mapping
600600
expect(awaitcontrollerProfileRecords(page)).toHaveLength(0);
601601

602602
awaitpage.evaluate(()=>{
603+
window.__arcadeButtons=Array.from({length: 16},()=>({pressed: false,value: 0}));
604+
window.__arcadeAxes=[0,0];
603605
Object.defineProperty(navigator,"getGamepads",{
604606
configurable: true,
605607
value: ()=>[{
606-
axes: [0,0],
607-
buttons: Array.from({length: 16},()=>({pressed: false,value: 0})),
608+
axes: window.__arcadeAxes,
609+
buttons: window.__arcadeButtons,
608610
id: "Arcade Test Pad",
609611
index: 0,
610612
}],
@@ -628,7 +630,7 @@ test("Controls generates controller profiles, shows fallback status, and mapping
628630
awaitpage.locator("[data-controller-profile-add]").click();
629631
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("Arcade Test Pad");
630632
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("Arcade Test Pad Profile");
631-
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("Action Required");
633+
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("0/18 Actions assigned");
632634
awaitexpect(page.locator("[data-controller-profile-table] th")).toHaveText([
633635
"Device Type",
634636
"Controller Name",
@@ -637,10 +639,8 @@ test("Controls generates controller profiles, shows fallback status, and mapping
637639
"Action",
638640
]);
639641
awaitexpect(page.locator("[data-controller-profile-row]").first()).not.toContainText("Button0");
640-
awaitexpect(page.locator("[data-controller-profile-actions-row]").first().locator(".content-grid--three")).toBeVisible();
641-
awaitexpect(page.locator("[data-controller-profile-actions-row]").first().locator("[data-controller-profile-input-pair]")).toHaveCount(18);
642-
awaitexpect(page.locator("[data-controller-profile-actions-row]").first().locator("[data-controller-profile-input-pair]").first().locator("strong")).toHaveText("Button0");
643-
awaitexpect(page.locator("[data-controller-profile-actions-row]").first().locator("[data-controller-profile-input-pair]").first().locator("select")).toBeVisible();
642+
awaitexpect(page.locator("[data-controller-profile-actions-row]")).toHaveCount(0);
643+
awaitexpect(page.locator("[data-controller-profile-input-action]")).toHaveCount(0);
644644
awaitexpect(page.locator("[data-controller-profile-fallback-status]")).toContainText("Exact saved profile");
645645

646646
letprofiles=awaitcontrollerProfileRecords(page);
@@ -673,22 +673,56 @@ test("Controls generates controller profiles, shows fallback status, and mapping
673673
"Axis1",
674674
]);
675675

676-
awaitpage.locator("[data-controller-profile-save-actions]").click();
676+
awaitpage.locator("[data-controller-profile-edit]").click();
677+
consteditRow=page.locator("[data-controller-profile-editing-row]");
678+
awaitexpect(editRow.locator("td").nth(0)).toHaveText("Gamepad");
679+
awaitexpect(editRow.locator("td").nth(1)).toHaveText("Arcade Test Pad");
680+
awaitexpect(editRow.locator("td").nth(2)).toHaveText("Arcade Test Pad");
681+
awaitexpect(editRow.locator("td").nth(3)).toHaveText("Arcade Test Pad Profile");
682+
awaitexpect(editRow.locator("select")).toHaveCount(0);
683+
awaitexpect(editRow.locator("input")).toHaveCount(0);
684+
awaitexpect(editRow.locator("button")).toHaveText(["Save","Cancel"]);
685+
686+
consteditingActionsRow=page.locator("[data-controller-profile-editing-actions-row]");
687+
awaitexpect(editingActionsRow.locator(".content-grid--three")).toBeVisible();
688+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-pair]")).toHaveCount(18);
689+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-pair]").first().locator("strong")).toHaveText("Button0");
690+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-action]")).toHaveCount(18);
691+
692+
awaitpage.locator("[data-controller-profile-save]").click();
677693
awaitexpect(page.locator("[data-controller-profile-status]")).toContainText("Action Required");
678694
profiles=awaitcontrollerProfileRecords(page);
679695
expect(profiles[0].actions).toEqual([]);
680696

681-
constinputActionSelects=page.locator("[data-controller-profile-input-action]");
697+
constinputActionSelects=editingActionsRow.locator("[data-controller-profile-input-action]");
682698
constinputActionCount=awaitinputActionSelects.count();
683699
expect(inputActionCount).toBe(profiles[0].inputs.length);
684700
for(letindex=0;index<inputActionCount;index+=1){
685701
awaitinputActionSelects.nth(index).selectOption(index===0 ? "fire" : "moveRight");
686702
}
687-
awaitpage.locator("[data-controller-profile-save-actions]").click();
703+
awaitexpect(inputActionSelects.nth(1)).toHaveValue("moveRight");
704+
awaitpage.evaluate(()=>{
705+
window.__arcadeButtons[0]={pressed: true,value: 1};
706+
});
707+
constactiveProfileInput=page.locator("[data-controller-profile-input-pair][data-controller-profile-input-active='true']");
708+
awaitexpect(activeProfileInput.locator("strong")).toHaveText("Button0");
709+
awaitexpect(activeProfileInput.locator("[data-controller-profile-input-assigned-action]")).toHaveText("Selected Action: Fire");
710+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-pair]").nth(1)).not.toHaveAttribute("data-controller-profile-input-active","true");
711+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-pair]").nth(1).locator("[data-controller-profile-input-assigned-action]")).toHaveText("Assigned Action: Move Right");
712+
713+
awaitpage.locator("[data-controller-profile-save]").click();
688714
profiles=awaitcontrollerProfileRecords(page);
689715
expect(profiles[0].actions).toHaveLength(profiles[0].inputs.length);
690716
expect(profiles[0].actions[0]).toBe("fire");
691717
expect(profiles[0].actions[1]).toBe("moveRight");
718+
awaitexpect(page.locator("[data-controller-profile-input-action]")).toHaveCount(0);
719+
720+
awaitpage.locator("[data-controller-profile-edit]").click();
721+
awaitpage.locator("[data-controller-profile-input-action]").first().selectOption("jump");
722+
awaitpage.locator("[data-controller-profile-cancel]").click();
723+
profiles=awaitcontrollerProfileRecords(page);
724+
expect(profiles[0].actions[0]).toBe("fire");
725+
awaitexpect(page.locator("[data-controller-profile-input-action]")).toHaveCount(0);
692726

693727
awaitpage.locator("[data-controller-profile-trash]").click();
694728
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("No controller profiles saved yet.");

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Refine Controls controller profile edit mode and input highlighting -… · ToolboxAid/HTML-JavaScript-Gaming@f424497 · GitHub
Skip to content

Commit f424497

Browse files
committed
Refine Controls controller profile edit mode and input highlighting - PR_26161_029-controls-controller-profile-edit-mode
1 parent 2589276 commit f424497

7 files changed

Lines changed: 785 additions & 522 deletions

File tree

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
docs_build/dev/reports/controls-compact-controller-profile-report.md
2-
docs_build/dev/reports/codex_review.diff
31
docs_build/dev/reports/codex_changed_files.txt
4-
docs_build/dev/reports/playwright_v8_coverage_report.txt
2+
docs_build/dev/reports/codex_review.diff
3+
docs_build/dev/reports/controls-controller-profile-edit-mode-report.md
54
docs_build/dev/reports/coverage_changed_js_guardrail.txt
5+
docs_build/dev/reports/playwright_v8_coverage_report.txt
66
tests/playwright/tools/InputMappingV2Tool.spec.mjs
77
toolbox/controls/controls.js
8-
toolbox/controls/index.html

‎docs_build/dev/reports/codex_review.diff‎

Lines changed: 526 additions & 400 deletions
Large diffs are not rendered by default.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# PR_26161_029 Controls Controller Profile Edit Mode Report
2+
3+
## Scope
4+
- Updated Controls controller profile rows so saved profiles render as compact summaries outside edit mode.
5+
- Moved generated controller input Action dropdowns into profile edit mode only.
6+
- Added edit-mode gamepad input highlighting for matching generated controller inputs.
7+
- Kept Controls status as Wireframe and kept persistence through the shared DB/mock adapter.
8+
9+
## Branch Validation
10+
- PASS: current branch verified as `main` before edits.
11+
12+
## Impacted Lane
13+
- Controls / Input Mapping.
14+
15+
## Playwright Impacted
16+
- Yes.
17+
18+
## Validation Performed
19+
- PASS: `node --check toolbox/controls/controls.js`
20+
- PASS: `node --check tests/playwright/tools/InputMappingV2Tool.spec.mjs`
21+
- PASS: `git diff --check`
22+
- PASS: `npx playwright test tests/playwright/tools/InputMappingV2Tool.spec.mjs`
23+
24+
## Manual Validation Steps
25+
- Open Controls and refresh devices with a detected gamepad.
26+
- Add a controller profile and confirm the saved profile row shows only the compact summary.
27+
- Click Edit and confirm profile row values are text while generated input Action dropdowns appear underneath.
28+
- Press a controller button during edit and confirm the matching generated input row highlights with the selected Action.
29+
- Assign generated input Actions, Save, reload, and confirm assignments persist.
30+
- Edit a profile, change an Action, Cancel, reload, and confirm the unsaved change did not persist.
31+
32+
## Skipped Lanes
33+
- Full samples validation skipped by request because this PR only changes Controls UI behavior and targeted Playwright coverage exercises the impacted lane.
34+
35+
## Runtime Engine Behavior
36+
- Confirmed: no runtime engine behavior changed.
37+
38+
## Completion Check
39+
- PASS: Controller Profile Edit shows profile row values as text, not dropdowns.
40+
- PASS: Generated input Action dropdowns appear only in edit mode.
41+
- PASS: Generated input Action dropdowns are hidden outside edit mode.
42+
- PASS: Controller input press during edit highlights the matching generated input.
43+
- PASS: Selected/assigned Action is visibly shown for the pressed input.
44+
- PASS: Editing one input does not alter other inputs.
45+
- PASS: Save persists generated input action assignments after reload.
46+
- PASS: Cancel does not persist unsaved generated input action changes.

‎docs_build/dev/reports/coverage_changed_js_guardrail.txt‎

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,7 @@ Missing changed runtime JS files are WARN, not FAIL.
66
Source: Playwright/Chromium built-in V8 coverage from the active Playwright run.
77

88
Changed runtime JS files considered:
9-
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
10-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
11-
(91%) toolbox/controls/controls.js - executed lines 1626/1626; executed functions 165/181
9+
(94%) toolbox/controls/controls.js - executed lines 1686/1686; executed functions 186/197
1210

1311
Guardrail warnings:
14-
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: changed runtime JS file missing from coverage; advisory only
15-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - WARNING: changed runtime JS file missing from coverage; advisory only
12+
(100%) none - no changed runtime JS coverage warnings

‎docs_build/dev/reports/playwright_v8_coverage_report.txt‎

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,25 @@ Note: entry percentages use function coverage when available, otherwise line cov
1212
Note: coverage entries are aggregated across every page/tool where coverageReporter.start(page) and coverageReporter.stop(page) ran.
1313

1414
Exercised tool entry points detected:
15-
(89%) Toolbox Index - exercised 4 runtime JS files
15+
(92%) Toolbox Index - exercised 4 runtime JS files
1616
(0%) Tool Template V2 - not exercised by this Playwright run
1717
(59%) Theme V2 Shared JS - exercised 2 runtime JS files
1818

1919
Changed runtime JS files covered:
20-
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
21-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
22-
(91%) toolbox/controls/controls.js - executed lines 1626/1626; executed functions 165/181
20+
(94%) toolbox/controls/controls.js - executed lines 1686/1686; executed functions 186/197
2321

2422
Files with executed line/function counts where available:
2523
(53%) src/engine/api/server-api-client.js - executed lines 159/159; executed functions 10/19
2624
(58%) assets/theme-v2/js/gamefoundry-partials.js - executed lines 603/603; executed functions 30/52
2725
(64%) assets/theme-v2/js/tool-display-mode.js - executed lines 209/209; executed functions 9/14
2826
(75%) toolbox/tool-registry-api-client.js - executed lines 152/152; executed functions 21/28
29-
(91%) toolbox/controls/controls.js - executed lines 1626/1626; executed functions 165/181
27+
(94%) toolbox/controls/controls.js - executed lines 1686/1686; executed functions 186/197
3028
(100%) toolbox/controls/controls-api-client.js - executed lines 12/12; executed functions 2/2
3129
(100%) toolbox/objects/objects-api-client.js - executed lines 10/10; executed functions 2/2
3230

3331
Uncovered or low-coverage changed JS files:
34-
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: uncovered changed runtime JS file; advisory only
35-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - WARNING: uncovered changed runtime JS file; advisory only
32+
(100%) none - no low-coverage changed runtime JS files
3633

3734
Changed JS files considered:
38-
(0%) src/dev-runtime/persistence/mock-db-store.js - changed JS file not collected as browser runtime coverage
39-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - changed JS file not collected as browser runtime coverage
4035
(0%) tests/playwright/tools/InputMappingV2Tool.spec.mjs - changed JS file not collected as browser runtime coverage
41-
(91%) toolbox/controls/controls.js - changed JS file with browser V8 coverage
36+
(94%) toolbox/controls/controls.js - changed JS file with browser V8 coverage

‎tests/playwright/tools/InputMappingV2Tool.spec.mjs‎

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -600,11 +600,13 @@ test("Controls generates controller profiles, shows fallback status, and mapping
600600
expect(awaitcontrollerProfileRecords(page)).toHaveLength(0);
601601

602602
awaitpage.evaluate(()=>{
603+
window.__arcadeButtons=Array.from({length: 16},()=>({pressed: false,value: 0}));
604+
window.__arcadeAxes=[0,0];
603605
Object.defineProperty(navigator,"getGamepads",{
604606
configurable: true,
605607
value: ()=>[{
606-
axes: [0,0],
607-
buttons: Array.from({length: 16},()=>({pressed: false,value: 0})),
608+
axes: window.__arcadeAxes,
609+
buttons: window.__arcadeButtons,
608610
id: "Arcade Test Pad",
609611
index: 0,
610612
}],
@@ -628,7 +630,7 @@ test("Controls generates controller profiles, shows fallback status, and mapping
628630
awaitpage.locator("[data-controller-profile-add]").click();
629631
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("Arcade Test Pad");
630632
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("Arcade Test Pad Profile");
631-
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("Action Required");
633+
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("0/18 Actions assigned");
632634
awaitexpect(page.locator("[data-controller-profile-table] th")).toHaveText([
633635
"Device Type",
634636
"Controller Name",
@@ -637,10 +639,8 @@ test("Controls generates controller profiles, shows fallback status, and mapping
637639
"Action",
638640
]);
639641
awaitexpect(page.locator("[data-controller-profile-row]").first()).not.toContainText("Button0");
640-
awaitexpect(page.locator("[data-controller-profile-actions-row]").first().locator(".content-grid--three")).toBeVisible();
641-
awaitexpect(page.locator("[data-controller-profile-actions-row]").first().locator("[data-controller-profile-input-pair]")).toHaveCount(18);
642-
awaitexpect(page.locator("[data-controller-profile-actions-row]").first().locator("[data-controller-profile-input-pair]").first().locator("strong")).toHaveText("Button0");
643-
awaitexpect(page.locator("[data-controller-profile-actions-row]").first().locator("[data-controller-profile-input-pair]").first().locator("select")).toBeVisible();
642+
awaitexpect(page.locator("[data-controller-profile-actions-row]")).toHaveCount(0);
643+
awaitexpect(page.locator("[data-controller-profile-input-action]")).toHaveCount(0);
644644
awaitexpect(page.locator("[data-controller-profile-fallback-status]")).toContainText("Exact saved profile");
645645

646646
letprofiles=awaitcontrollerProfileRecords(page);
@@ -673,22 +673,56 @@ test("Controls generates controller profiles, shows fallback status, and mapping
673673
"Axis1",
674674
]);
675675

676-
awaitpage.locator("[data-controller-profile-save-actions]").click();
676+
awaitpage.locator("[data-controller-profile-edit]").click();
677+
consteditRow=page.locator("[data-controller-profile-editing-row]");
678+
awaitexpect(editRow.locator("td").nth(0)).toHaveText("Gamepad");
679+
awaitexpect(editRow.locator("td").nth(1)).toHaveText("Arcade Test Pad");
680+
awaitexpect(editRow.locator("td").nth(2)).toHaveText("Arcade Test Pad");
681+
awaitexpect(editRow.locator("td").nth(3)).toHaveText("Arcade Test Pad Profile");
682+
awaitexpect(editRow.locator("select")).toHaveCount(0);
683+
awaitexpect(editRow.locator("input")).toHaveCount(0);
684+
awaitexpect(editRow.locator("button")).toHaveText(["Save","Cancel"]);
685+
686+
consteditingActionsRow=page.locator("[data-controller-profile-editing-actions-row]");
687+
awaitexpect(editingActionsRow.locator(".content-grid--three")).toBeVisible();
688+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-pair]")).toHaveCount(18);
689+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-pair]").first().locator("strong")).toHaveText("Button0");
690+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-action]")).toHaveCount(18);
691+
692+
awaitpage.locator("[data-controller-profile-save]").click();
677693
awaitexpect(page.locator("[data-controller-profile-status]")).toContainText("Action Required");
678694
profiles=awaitcontrollerProfileRecords(page);
679695
expect(profiles[0].actions).toEqual([]);
680696

681-
constinputActionSelects=page.locator("[data-controller-profile-input-action]");
697+
constinputActionSelects=editingActionsRow.locator("[data-controller-profile-input-action]");
682698
constinputActionCount=awaitinputActionSelects.count();
683699
expect(inputActionCount).toBe(profiles[0].inputs.length);
684700
for(letindex=0;index<inputActionCount;index+=1){
685701
awaitinputActionSelects.nth(index).selectOption(index===0 ? "fire" : "moveRight");
686702
}
687-
awaitpage.locator("[data-controller-profile-save-actions]").click();
703+
awaitexpect(inputActionSelects.nth(1)).toHaveValue("moveRight");
704+
awaitpage.evaluate(()=>{
705+
window.__arcadeButtons[0]={pressed: true,value: 1};
706+
});
707+
constactiveProfileInput=page.locator("[data-controller-profile-input-pair][data-controller-profile-input-active='true']");
708+
awaitexpect(activeProfileInput.locator("strong")).toHaveText("Button0");
709+
awaitexpect(activeProfileInput.locator("[data-controller-profile-input-assigned-action]")).toHaveText("Selected Action: Fire");
710+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-pair]").nth(1)).not.toHaveAttribute("data-controller-profile-input-active","true");
711+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-pair]").nth(1).locator("[data-controller-profile-input-assigned-action]")).toHaveText("Assigned Action: Move Right");
712+
713+
awaitpage.locator("[data-controller-profile-save]").click();
688714
profiles=awaitcontrollerProfileRecords(page);
689715
expect(profiles[0].actions).toHaveLength(profiles[0].inputs.length);
690716
expect(profiles[0].actions[0]).toBe("fire");
691717
expect(profiles[0].actions[1]).toBe("moveRight");
718+
awaitexpect(page.locator("[data-controller-profile-input-action]")).toHaveCount(0);
719+
720+
awaitpage.locator("[data-controller-profile-edit]").click();
721+
awaitpage.locator("[data-controller-profile-input-action]").first().selectOption("jump");
722+
awaitpage.locator("[data-controller-profile-cancel]").click();
723+
profiles=awaitcontrollerProfileRecords(page);
724+
expect(profiles[0].actions[0]).toBe("fire");
725+
awaitexpect(page.locator("[data-controller-profile-input-action]")).toHaveCount(0);
692726

693727
awaitpage.locator("[data-controller-profile-trash]").click();
694728
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("No controller profiles saved yet.");

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); Refine Controls controller profile edit mode and input highlighting -… · ToolboxAid/HTML-JavaScript-Gaming@f424497 · GitHub
Skip to content

Commit f424497

Browse files
committed
Refine Controls controller profile edit mode and input highlighting - PR_26161_029-controls-controller-profile-edit-mode
1 parent 2589276 commit f424497

7 files changed

Lines changed: 785 additions & 522 deletions

File tree

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
docs_build/dev/reports/controls-compact-controller-profile-report.md
2-
docs_build/dev/reports/codex_review.diff
31
docs_build/dev/reports/codex_changed_files.txt
4-
docs_build/dev/reports/playwright_v8_coverage_report.txt
2+
docs_build/dev/reports/codex_review.diff
3+
docs_build/dev/reports/controls-controller-profile-edit-mode-report.md
54
docs_build/dev/reports/coverage_changed_js_guardrail.txt
5+
docs_build/dev/reports/playwright_v8_coverage_report.txt
66
tests/playwright/tools/InputMappingV2Tool.spec.mjs
77
toolbox/controls/controls.js
8-
toolbox/controls/index.html

‎docs_build/dev/reports/codex_review.diff‎

Lines changed: 526 additions & 400 deletions
Large diffs are not rendered by default.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# PR_26161_029 Controls Controller Profile Edit Mode Report
2+
3+
## Scope
4+
- Updated Controls controller profile rows so saved profiles render as compact summaries outside edit mode.
5+
- Moved generated controller input Action dropdowns into profile edit mode only.
6+
- Added edit-mode gamepad input highlighting for matching generated controller inputs.
7+
- Kept Controls status as Wireframe and kept persistence through the shared DB/mock adapter.
8+
9+
## Branch Validation
10+
- PASS: current branch verified as `main` before edits.
11+
12+
## Impacted Lane
13+
- Controls / Input Mapping.
14+
15+
## Playwright Impacted
16+
- Yes.
17+
18+
## Validation Performed
19+
- PASS: `node --check toolbox/controls/controls.js`
20+
- PASS: `node --check tests/playwright/tools/InputMappingV2Tool.spec.mjs`
21+
- PASS: `git diff --check`
22+
- PASS: `npx playwright test tests/playwright/tools/InputMappingV2Tool.spec.mjs`
23+
24+
## Manual Validation Steps
25+
- Open Controls and refresh devices with a detected gamepad.
26+
- Add a controller profile and confirm the saved profile row shows only the compact summary.
27+
- Click Edit and confirm profile row values are text while generated input Action dropdowns appear underneath.
28+
- Press a controller button during edit and confirm the matching generated input row highlights with the selected Action.
29+
- Assign generated input Actions, Save, reload, and confirm assignments persist.
30+
- Edit a profile, change an Action, Cancel, reload, and confirm the unsaved change did not persist.
31+
32+
## Skipped Lanes
33+
- Full samples validation skipped by request because this PR only changes Controls UI behavior and targeted Playwright coverage exercises the impacted lane.
34+
35+
## Runtime Engine Behavior
36+
- Confirmed: no runtime engine behavior changed.
37+
38+
## Completion Check
39+
- PASS: Controller Profile Edit shows profile row values as text, not dropdowns.
40+
- PASS: Generated input Action dropdowns appear only in edit mode.
41+
- PASS: Generated input Action dropdowns are hidden outside edit mode.
42+
- PASS: Controller input press during edit highlights the matching generated input.
43+
- PASS: Selected/assigned Action is visibly shown for the pressed input.
44+
- PASS: Editing one input does not alter other inputs.
45+
- PASS: Save persists generated input action assignments after reload.
46+
- PASS: Cancel does not persist unsaved generated input action changes.

‎docs_build/dev/reports/coverage_changed_js_guardrail.txt‎

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,7 @@ Missing changed runtime JS files are WARN, not FAIL.
66
Source: Playwright/Chromium built-in V8 coverage from the active Playwright run.
77

88
Changed runtime JS files considered:
9-
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
10-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
11-
(91%) toolbox/controls/controls.js - executed lines 1626/1626; executed functions 165/181
9+
(94%) toolbox/controls/controls.js - executed lines 1686/1686; executed functions 186/197
1210

1311
Guardrail warnings:
14-
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: changed runtime JS file missing from coverage; advisory only
15-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - WARNING: changed runtime JS file missing from coverage; advisory only
12+
(100%) none - no changed runtime JS coverage warnings

‎docs_build/dev/reports/playwright_v8_coverage_report.txt‎

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,25 @@ Note: entry percentages use function coverage when available, otherwise line cov
1212
Note: coverage entries are aggregated across every page/tool where coverageReporter.start(page) and coverageReporter.stop(page) ran.
1313

1414
Exercised tool entry points detected:
15-
(89%) Toolbox Index - exercised 4 runtime JS files
15+
(92%) Toolbox Index - exercised 4 runtime JS files
1616
(0%) Tool Template V2 - not exercised by this Playwright run
1717
(59%) Theme V2 Shared JS - exercised 2 runtime JS files
1818

1919
Changed runtime JS files covered:
20-
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
21-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
22-
(91%) toolbox/controls/controls.js - executed lines 1626/1626; executed functions 165/181
20+
(94%) toolbox/controls/controls.js - executed lines 1686/1686; executed functions 186/197
2321

2422
Files with executed line/function counts where available:
2523
(53%) src/engine/api/server-api-client.js - executed lines 159/159; executed functions 10/19
2624
(58%) assets/theme-v2/js/gamefoundry-partials.js - executed lines 603/603; executed functions 30/52
2725
(64%) assets/theme-v2/js/tool-display-mode.js - executed lines 209/209; executed functions 9/14
2826
(75%) toolbox/tool-registry-api-client.js - executed lines 152/152; executed functions 21/28
29-
(91%) toolbox/controls/controls.js - executed lines 1626/1626; executed functions 165/181
27+
(94%) toolbox/controls/controls.js - executed lines 1686/1686; executed functions 186/197
3028
(100%) toolbox/controls/controls-api-client.js - executed lines 12/12; executed functions 2/2
3129
(100%) toolbox/objects/objects-api-client.js - executed lines 10/10; executed functions 2/2
3230

3331
Uncovered or low-coverage changed JS files:
34-
(0%) src/dev-runtime/persistence/mock-db-store.js - WARNING: uncovered changed runtime JS file; advisory only
35-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - WARNING: uncovered changed runtime JS file; advisory only
32+
(100%) none - no low-coverage changed runtime JS files
3633

3734
Changed JS files considered:
38-
(0%) src/dev-runtime/persistence/mock-db-store.js - changed JS file not collected as browser runtime coverage
39-
(0%) src/dev-runtime/persistence/tool-repositories/input-mapping-mock-repository.js - changed JS file not collected as browser runtime coverage
4035
(0%) tests/playwright/tools/InputMappingV2Tool.spec.mjs - changed JS file not collected as browser runtime coverage
41-
(91%) toolbox/controls/controls.js - changed JS file with browser V8 coverage
36+
(94%) toolbox/controls/controls.js - changed JS file with browser V8 coverage

‎tests/playwright/tools/InputMappingV2Tool.spec.mjs‎

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -600,11 +600,13 @@ test("Controls generates controller profiles, shows fallback status, and mapping
600600
expect(awaitcontrollerProfileRecords(page)).toHaveLength(0);
601601

602602
awaitpage.evaluate(()=>{
603+
window.__arcadeButtons=Array.from({length: 16},()=>({pressed: false,value: 0}));
604+
window.__arcadeAxes=[0,0];
603605
Object.defineProperty(navigator,"getGamepads",{
604606
configurable: true,
605607
value: ()=>[{
606-
axes: [0,0],
607-
buttons: Array.from({length: 16},()=>({pressed: false,value: 0})),
608+
axes: window.__arcadeAxes,
609+
buttons: window.__arcadeButtons,
608610
id: "Arcade Test Pad",
609611
index: 0,
610612
}],
@@ -628,7 +630,7 @@ test("Controls generates controller profiles, shows fallback status, and mapping
628630
awaitpage.locator("[data-controller-profile-add]").click();
629631
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("Arcade Test Pad");
630632
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("Arcade Test Pad Profile");
631-
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("Action Required");
633+
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("0/18 Actions assigned");
632634
awaitexpect(page.locator("[data-controller-profile-table] th")).toHaveText([
633635
"Device Type",
634636
"Controller Name",
@@ -637,10 +639,8 @@ test("Controls generates controller profiles, shows fallback status, and mapping
637639
"Action",
638640
]);
639641
awaitexpect(page.locator("[data-controller-profile-row]").first()).not.toContainText("Button0");
640-
awaitexpect(page.locator("[data-controller-profile-actions-row]").first().locator(".content-grid--three")).toBeVisible();
641-
awaitexpect(page.locator("[data-controller-profile-actions-row]").first().locator("[data-controller-profile-input-pair]")).toHaveCount(18);
642-
awaitexpect(page.locator("[data-controller-profile-actions-row]").first().locator("[data-controller-profile-input-pair]").first().locator("strong")).toHaveText("Button0");
643-
awaitexpect(page.locator("[data-controller-profile-actions-row]").first().locator("[data-controller-profile-input-pair]").first().locator("select")).toBeVisible();
642+
awaitexpect(page.locator("[data-controller-profile-actions-row]")).toHaveCount(0);
643+
awaitexpect(page.locator("[data-controller-profile-input-action]")).toHaveCount(0);
644644
awaitexpect(page.locator("[data-controller-profile-fallback-status]")).toContainText("Exact saved profile");
645645

646646
letprofiles=awaitcontrollerProfileRecords(page);
@@ -673,22 +673,56 @@ test("Controls generates controller profiles, shows fallback status, and mapping
673673
"Axis1",
674674
]);
675675

676-
awaitpage.locator("[data-controller-profile-save-actions]").click();
676+
awaitpage.locator("[data-controller-profile-edit]").click();
677+
consteditRow=page.locator("[data-controller-profile-editing-row]");
678+
awaitexpect(editRow.locator("td").nth(0)).toHaveText("Gamepad");
679+
awaitexpect(editRow.locator("td").nth(1)).toHaveText("Arcade Test Pad");
680+
awaitexpect(editRow.locator("td").nth(2)).toHaveText("Arcade Test Pad");
681+
awaitexpect(editRow.locator("td").nth(3)).toHaveText("Arcade Test Pad Profile");
682+
awaitexpect(editRow.locator("select")).toHaveCount(0);
683+
awaitexpect(editRow.locator("input")).toHaveCount(0);
684+
awaitexpect(editRow.locator("button")).toHaveText(["Save","Cancel"]);
685+
686+
consteditingActionsRow=page.locator("[data-controller-profile-editing-actions-row]");
687+
awaitexpect(editingActionsRow.locator(".content-grid--three")).toBeVisible();
688+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-pair]")).toHaveCount(18);
689+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-pair]").first().locator("strong")).toHaveText("Button0");
690+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-action]")).toHaveCount(18);
691+
692+
awaitpage.locator("[data-controller-profile-save]").click();
677693
awaitexpect(page.locator("[data-controller-profile-status]")).toContainText("Action Required");
678694
profiles=awaitcontrollerProfileRecords(page);
679695
expect(profiles[0].actions).toEqual([]);
680696

681-
constinputActionSelects=page.locator("[data-controller-profile-input-action]");
697+
constinputActionSelects=editingActionsRow.locator("[data-controller-profile-input-action]");
682698
constinputActionCount=awaitinputActionSelects.count();
683699
expect(inputActionCount).toBe(profiles[0].inputs.length);
684700
for(letindex=0;index<inputActionCount;index+=1){
685701
awaitinputActionSelects.nth(index).selectOption(index===0 ? "fire" : "moveRight");
686702
}
687-
awaitpage.locator("[data-controller-profile-save-actions]").click();
703+
awaitexpect(inputActionSelects.nth(1)).toHaveValue("moveRight");
704+
awaitpage.evaluate(()=>{
705+
window.__arcadeButtons[0]={pressed: true,value: 1};
706+
});
707+
constactiveProfileInput=page.locator("[data-controller-profile-input-pair][data-controller-profile-input-active='true']");
708+
awaitexpect(activeProfileInput.locator("strong")).toHaveText("Button0");
709+
awaitexpect(activeProfileInput.locator("[data-controller-profile-input-assigned-action]")).toHaveText("Selected Action: Fire");
710+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-pair]").nth(1)).not.toHaveAttribute("data-controller-profile-input-active","true");
711+
awaitexpect(editingActionsRow.locator("[data-controller-profile-input-pair]").nth(1).locator("[data-controller-profile-input-assigned-action]")).toHaveText("Assigned Action: Move Right");
712+
713+
awaitpage.locator("[data-controller-profile-save]").click();
688714
profiles=awaitcontrollerProfileRecords(page);
689715
expect(profiles[0].actions).toHaveLength(profiles[0].inputs.length);
690716
expect(profiles[0].actions[0]).toBe("fire");
691717
expect(profiles[0].actions[1]).toBe("moveRight");
718+
awaitexpect(page.locator("[data-controller-profile-input-action]")).toHaveCount(0);
719+
720+
awaitpage.locator("[data-controller-profile-edit]").click();
721+
awaitpage.locator("[data-controller-profile-input-action]").first().selectOption("jump");
722+
awaitpage.locator("[data-controller-profile-cancel]").click();
723+
profiles=awaitcontrollerProfileRecords(page);
724+
expect(profiles[0].actions[0]).toBe("fire");
725+
awaitexpect(page.locator("[data-controller-profile-input-action]")).toHaveCount(0);
692726

693727
awaitpage.locator("[data-controller-profile-trash]").click();
694728
awaitexpect(page.locator("[data-controller-profile-list]")).toContainText("No controller profiles saved yet.");

0 commit comments

Comments
 (0)