Skip to content

Commit

Permalink
fix: toggle of help menu (#10339)
Browse files Browse the repository at this point in the history
* fix: toggle of help menu

### What does this PR do?

Fixes toggling the help menu

### Screenshot / video of UI

<!-- If this PR is changing UI, please include
screenshots or screencasts showing the difference -->

### What issues does this PR fix or reference?

<!-- Include any related issues from Podman Desktop
repository (or from another issue tracker). -->

Closes podman-desktop/podman-desktop#10154

### How to test this PR?

<!-- Please explain steps to verify the functionality,
do not forget to provide unit/component tests -->

- [X] Tests are covering the bug fix or the new feature

Toggle the help menu button, it should close now

Signed-off-by: Charlie Drage <[email protected]>

* chore: improved tests

add more improved tests

Signed-off-by: Charlie Drage <[email protected]>

---------

Signed-off-by: Charlie Drage <[email protected]>
  • Loading branch information
cdrage authored Dec 17, 2024
1 parent 333f183 commit 8c79939
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 9 deletions.
61 changes: 55 additions & 6 deletions packages/renderer/src/lib/help/HelpActions.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,28 +26,77 @@ import { Items } from './HelpItems';

let toggleMenuCallback: () => void;

const receiveEventMock = vi.fn();

suite('HelpActions component', () => {
beforeEach(() => {
vi.resetAllMocks();
(window as any).events = {
receive: vi.fn(),
receive: receiveEventMock,
};
(window as any).ResizeObserver = vi.fn().mockReturnValue({ observe: vi.fn(), unobserve: vi.fn() });
vi.mocked(window.events.receive).mockImplementation((channel: string, callback: () => void) => {
});

test('by default is not visible', () => {
const ha = render(HelpActions);
const items = ha.queryAllByTitle(Items[0].title);
expect(items).toHaveLength(0);
});

test('simulate clicking outside the menu closes it', async () => {
vi.mocked(receiveEventMock).mockImplementation((channel: string, callback: () => void) => {
toggleMenuCallback = callback;
return {
dispose: () => {},
};
});
const ha = render(HelpActions);

toggleMenuCallback();

await vi.waitFor(() => {
const helpMenu = ha.getByTestId('help-menu');
expect(helpMenu).toBeVisible();
});

// Click "outside" the menu (body)
const event = new MouseEvent('click', { bubbles: true });
document.body.dispatchEvent(event);

await vi.waitFor(() => {
const helpMenu = ha.queryByTestId('help-menu');
expect(helpMenu).toBeNull();
});
});

test('by default is not visible', () => {
const ha = render(HelpActions);
const items = ha.queryAllByTitle(Items[0].title);
expect(items).toHaveLength(0);
test('create a span that has data-task-button=Help attribute, spy on and make sure that it is only called once each click', async () => {
render(HelpActions);

// Create data-task-button=Help to simulate the status bar icon / button
const span = document.createElement('span');
span.setAttribute('data-task-button', 'Help');
document.body.appendChild(span);

// Click
const event = new MouseEvent('click', { bubbles: true, cancelable: true });
span.dispatchEvent(event);

// Expect receiveEventMock to have been called
// why we do this is because we are mocking receiveEvent already, so we're not "toggling" it
// this test ensures that the event is only called once / we are toggling correctly.
expect(receiveEventMock).toHaveBeenCalledTimes(1);

// Remove the span after (unsure if needed, but dont want to break other tests)
span.remove();
});

test.each(Items)('contains item with $title', async ({ title, tooltip }) => {
vi.mocked(receiveEventMock).mockImplementation((channel: string, callback: () => void) => {
toggleMenuCallback = callback;
return {
dispose: () => {},
};
});
const ha = render(HelpActions);
toggleMenuCallback();
await vi.waitFor(async () => {
Expand Down
6 changes: 5 additions & 1 deletion packages/renderer/src/lib/help/HelpActions.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ function handleEscape({ key }: KeyboardEvent): void {
}
function onWindowClick(e: any): void {
showMenu = outsideWindow.contains(e.target);
const target = e.target as HTMLElement;
// Listen to anything **but** the button that has "data-task-button" attribute with a value of "Help"
if (target && target.getAttribute('data-task-button') !== 'Help') {
showMenu = outsideWindow.contains(e.target);
}
}
async function onClick(action?: ItemAction): Promise<void> {
Expand Down
3 changes: 2 additions & 1 deletion packages/renderer/src/lib/help/HelpMenu.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ onDestroy(() => window.removeEventListener('resize', updateMenuLocation));
bind:offsetHeight={dropDownHeight}
bind:offsetWidth={dropDownWidth}
bind:this={dropDownElement}
class="absolute">
class="absolute"
data-testid="help-menu">
<div
title="Help Menu Items"
class="z-10 m-1 rounded-md shadow-lg bg-[var(--pd-dropdown-bg)] ring-2 ring-[var(--pd-dropdown-ring)] hover:ring-[var(--pd-dropdown-hover-ring)] divide-y divide-[var(--pd-dropdown-divider)] focus:outline-none">
Expand Down
2 changes: 1 addition & 1 deletion packages/renderer/src/lib/statusbar/StatusBarItem.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ async function executeCommand(entry: StatusBarEntry) {
)} relative inline-block"
title={tooltipText(entry)}>
{#if iconClass(entry)}
<span class={iconClass(entry)} aria-hidden="true"></span>
<span class={iconClass(entry)} aria-hidden="true" data-task-button="{tooltipText(entry)}"></span>
{/if}
{#if entry.text}
<span class="ml-1">{entry.text}</span>
Expand Down

0 comments on commit 8c79939

Please sign in to comment.