Skip to content

Commit 591d9e2

Browse files
Natallia HarshunovaDevtools-frontend LUCI CQ
authored andcommitted
Migrate chromium unittest http/tests/devtools/unit/soft-context-menu.js
Bug: 466795519 Change-Id: I4a38abe77317eeef6f33ab1faed56dd62c52bd50 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/7253255 Reviewed-by: Nikolay Vitkov <[email protected]> Commit-Queue: Natallia Harshunova <[email protected]>
1 parent b6701a0 commit 591d9e2

File tree

2 files changed

+149
-0
lines changed

2 files changed

+149
-0
lines changed

front_end/ui/legacy/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ devtools_ui_module("unittests") {
196196
"ListWidget.test.ts",
197197
"SearchableView.test.ts",
198198
"ShortcutRegistry.test.ts",
199+
"SoftContextMenu.test.ts",
199200
"SoftDropDown.test.ts",
200201
"SplitWidget.test.ts",
201202
"SuggestBox.test.ts",
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
// Copyright 2025 The Chromium Authors
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import {
6+
dispatchKeyDownEvent,
7+
renderElementIntoDOM,
8+
} from '../../testing/DOMHelpers.js';
9+
import {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js';
10+
11+
import * as UI from './legacy.js';
12+
13+
describeWithEnvironment('SoftContextMenu', () => {
14+
const items: UI.SoftContextMenu.SoftContextMenuDescriptor[] = [
15+
{
16+
type: 'item',
17+
id: 0,
18+
label: 'First',
19+
enabled: true,
20+
},
21+
{
22+
type: 'subMenu',
23+
label: 'Second',
24+
enabled: true,
25+
subItems: [
26+
{
27+
type: 'subMenu',
28+
label: 'Child 1',
29+
enabled: true,
30+
subItems: [
31+
{type: 'item', label: 'Grandchild', id: 2, enabled: true},
32+
],
33+
},
34+
{type: 'item', label: 'Child 2', enabled: true},
35+
{type: 'item', label: 'Child 3', enabled: true},
36+
{type: 'item', label: 'Child 4', enabled: true},
37+
],
38+
},
39+
{
40+
type: 'separator',
41+
},
42+
{
43+
type: 'item',
44+
id: 1,
45+
label: 'Third',
46+
enabled: true,
47+
},
48+
];
49+
50+
function getOpenMenus(): HTMLElement[] {
51+
const glassPanes = document.querySelectorAll('div[data-devtools-glass-pane]');
52+
return Array.from(glassPanes)
53+
.map(pane => pane.shadowRoot?.querySelector('.widget > .soft-context-menu') as HTMLElement);
54+
}
55+
56+
function getSelectedText(menuElement: HTMLElement): string|null {
57+
const selected = menuElement.querySelector('.soft-context-menu-item-mouse-over');
58+
if (!selected) {
59+
return null;
60+
}
61+
return selected.textContent?.trim() || null;
62+
}
63+
64+
function getSelection(): string {
65+
const menus = getOpenMenus();
66+
if (menus.length === 0) {
67+
return '';
68+
}
69+
return menus
70+
.map(menu => {
71+
const selected = getSelectedText(menu);
72+
return selected ? `[${selected}]` : 'null';
73+
})
74+
.join(' -> ');
75+
}
76+
77+
function dispatchKeyDown(key: string) {
78+
const activeElement = UI.DOMUtilities.deepActiveElement(document);
79+
if (activeElement) {
80+
dispatchKeyDownEvent(activeElement, {key, bubbles: true});
81+
} else {
82+
assert.fail('No active element found to dispatch keydown event');
83+
}
84+
}
85+
86+
it('navigates with keyboard', () => {
87+
const container = document.createElement('div');
88+
renderElementIntoDOM(container);
89+
const itemSelected = sinon.spy();
90+
const menu = new UI.SoftContextMenu.SoftContextMenu(items, itemSelected, true);
91+
menu.show(document, new AnchorBox(50, 50, 0, 0));
92+
93+
assert.strictEqual(getSelection(), '[First]');
94+
95+
dispatchKeyDown('ArrowDown');
96+
assert.strictEqual(getSelection(), '[Second]');
97+
98+
dispatchKeyDown('ArrowDown');
99+
assert.strictEqual(getSelection(), '[Third]');
100+
101+
dispatchKeyDown('ArrowDown'); // Does not wrap
102+
assert.strictEqual(getSelection(), '[Third]');
103+
104+
dispatchKeyDown('ArrowUp');
105+
assert.strictEqual(getSelection(), '[Second]');
106+
107+
dispatchKeyDown('ArrowUp');
108+
assert.strictEqual(getSelection(), '[First]');
109+
110+
dispatchKeyDown('ArrowUp'); // Does not wrap
111+
assert.strictEqual(getSelection(), '[First]');
112+
113+
dispatchKeyDown('ArrowDown');
114+
assert.strictEqual(getSelection(), '[Second]');
115+
116+
dispatchKeyDown('ArrowRight'); // Enters submenu
117+
assert.strictEqual(getSelection(), '[Second] -> [Child 1]');
118+
119+
dispatchKeyDown('ArrowDown');
120+
assert.strictEqual(getSelection(), '[Second] -> [Child 2]');
121+
122+
dispatchKeyDown('ArrowDown');
123+
assert.strictEqual(getSelection(), '[Second] -> [Child 3]');
124+
125+
dispatchKeyDown('ArrowDown');
126+
assert.strictEqual(getSelection(), '[Second] -> [Child 4]');
127+
128+
dispatchKeyDown('ArrowLeft'); // Leaves submenu
129+
assert.strictEqual(getSelection(), '[Second]');
130+
131+
dispatchKeyDown('ArrowRight'); // Enters submenu
132+
assert.strictEqual(getSelection(), '[Second] -> [Child 1]');
133+
134+
dispatchKeyDown('Escape'); // Closes submenu
135+
assert.strictEqual(getSelection(), '[Second]');
136+
137+
dispatchKeyDown(' '); // Opens on Space
138+
assert.strictEqual(getSelection(), '[Second] -> [Child 1]');
139+
140+
dispatchKeyDown('Enter'); // Opens on Enter
141+
assert.strictEqual(getSelection(), '[Second] -> [Child 1] -> [Grandchild]');
142+
143+
dispatchKeyDown('Enter'); // Selects item
144+
sinon.assert.calledWith(itemSelected, 2);
145+
146+
menu.discard();
147+
});
148+
});

0 commit comments

Comments
 (0)