diff --git a/src/about/AboutDialog.test.tsx b/src/about/AboutDialog.test.tsx index 08eefcdc..098a1392 100644 --- a/src/about/AboutDialog.test.tsx +++ b/src/about/AboutDialog.test.tsx @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT // Copyright (c) 2021-2022 The Pybricks Authors -import { getByLabelText, waitForElementToBeRemoved } from '@testing-library/react'; +import { getByLabelText, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; import { testRender } from '../../test'; @@ -22,28 +22,19 @@ it('should manage license dialog open/close', async () => { undefined} />, ); + expect( + dialog.queryByRole('dialog', { name: 'Open Source Software Licenses' }), + ).toBeNull(); + userEvent.click(dialog.getByText('Software Licenses')); - expect( - dialog.getByText( - `${process.env.REACT_APP_NAME} is built on open source software.`, - { - exact: false, - }, - ), - ).toBeInTheDocument(); + const licenseDialog = dialog.getByRole('dialog', { + name: 'Open Source Software Licenses', + }); + + expect(licenseDialog).toBeVisible(); - const licenseDialog = document.querySelector( - '.pb-license-dialog', - ) as HTMLDivElement; userEvent.click(getByLabelText(licenseDialog, 'Close')); - await waitForElementToBeRemoved(() => - dialog.queryByText( - `${process.env.REACT_APP_NAME} is built on open source software.`, - { - exact: false, - }, - ), - ); + await waitFor(() => expect(licenseDialog).not.toBeVisible()); }); diff --git a/src/about/AboutDialog.tsx b/src/about/AboutDialog.tsx index 48aa2bab..a71d5805 100644 --- a/src/about/AboutDialog.tsx +++ b/src/about/AboutDialog.tsx @@ -34,7 +34,7 @@ const AboutDialog: React.VoidFunctionComponent = ({ return ( @@ -45,6 +45,7 @@ const AboutDialog: React.VoidFunctionComponent = ({

{i18n.translate(AboutStringId.Description)}

+

{`v${firmwareVersion} (${appName} v${appVersion})`}

{pybricksCopyright}

diff --git a/src/about/i18n.en.json b/src/about/i18n.en.json index b57121db..3cd3402c 100644 --- a/src/about/i18n.en.json +++ b/src/about/i18n.en.json @@ -1,5 +1,6 @@ { "about": { + "title": "About {appName}", "description": "MicroPython for LEGO® Powered Up smart hubs.", "licenseButton": { "label": "Software Licenses" }, "changelogButton": { "label": "Changelog" }, diff --git a/src/about/i18n.ts b/src/about/i18n.ts index 02001d88..fd7137da 100644 --- a/src/about/i18n.ts +++ b/src/about/i18n.ts @@ -1,9 +1,10 @@ // SPDX-License-Identifier: MIT -// Copyright (c) 2021 The Pybricks Authors +// Copyright (c) 2021-2022 The Pybricks Authors // About dialog translation keys. export enum AboutStringId { + Title = 'about.title', Description = 'about.description', LicenseButtonLabel = 'about.licenseButton.label', ChangelogButtonLabel = 'about.changelogButton.label', diff --git a/src/explorer/Explorer.test.tsx b/src/explorer/Explorer.test.tsx index 78af7f67..9001578c 100644 --- a/src/explorer/Explorer.test.tsx +++ b/src/explorer/Explorer.test.tsx @@ -57,7 +57,7 @@ describe('new file button', () => { userEvent.click(button); - const dialog = explorer.getByRole('dialog'); + const dialog = explorer.getByRole('dialog', { name: 'Create a new file' }); expect(dialog).toBeVisible(); userEvent.click(getByLabelText(dialog, 'Close')); diff --git a/src/settings/SettingsDrawer.test.tsx b/src/settings/SettingsDrawer.test.tsx index dbf20faa..c7b4f638 100644 --- a/src/settings/SettingsDrawer.test.tsx +++ b/src/settings/SettingsDrawer.test.tsx @@ -108,11 +108,13 @@ describe('about dialog', () => { undefined} />, ); - expect(settings.queryByRole('dialog')).toBeNull(); + const appName = process.env.REACT_APP_NAME; + + expect(settings.queryByRole('dialog', { name: `About ${appName}` })).toBeNull(); settings.getByText('About').click(); - const dialog = settings.getByRole('dialog'); + const dialog = settings.getByRole('dialog', { name: `About ${appName}` }); expect(dialog).toBeVisible(); diff --git a/src/settings/SettingsDrawer.tsx b/src/settings/SettingsDrawer.tsx index 9df0e933..c685bdf5 100644 --- a/src/settings/SettingsDrawer.tsx +++ b/src/settings/SettingsDrawer.tsx @@ -19,7 +19,7 @@ import { } from '@blueprintjs/core'; import { Tooltip2 } from '@blueprintjs/popover2'; import { useI18n } from '@shopify/react-i18n'; -import React, { useMemo, useState } from 'react'; +import React, { useCallback, useMemo, useState } from 'react'; import { useDispatch } from 'react-redux'; import { useTernaryDarkMode } from 'usehooks-ts'; import AboutDialog from '../about/AboutDialog'; @@ -98,12 +98,24 @@ const SettingsDrawer: React.VoidFunctionComponent = ({ useHotkeys(hotkeys); + // HACK: set additional attributes that are not supported via Drawer props + const handleDrawerOpening = useCallback<(node: HTMLElement) => void>((n) => { + n.setAttribute('role', 'dialog'); + n.setAttribute('aria-modal', 'true'); + n.setAttribute('aria-labelledby', 'settings-drawer-dialog-title'); + }, []); + return ( + {i18n.translate(SettingsStringId.Title)} + + } + onOpening={handleDrawerOpening} onClose={onClose} // work around https://github.com/palantir/blueprint/issues/5169 shouldReturnFocusOnClose={false} diff --git a/src/toolbar/Toolbar.test.tsx b/src/toolbar/Toolbar.test.tsx new file mode 100644 index 00000000..43d90571 --- /dev/null +++ b/src/toolbar/Toolbar.test.tsx @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT +// Copyright (c) 2022 The Pybricks Authors + +import { getByLabelText, waitFor } from '@testing-library/dom'; +import React from 'react'; +import { testRender } from '../../test'; +import Toolbar from './Toolbar'; + +describe('settings button', () => { + it('should open settings drawer', async () => { + const [toolbar] = testRender(); + + const settingButton = toolbar.getByLabelText('Settings'); + + expect( + toolbar.queryByRole('dialog', { + name: 'Settings & Help', + }), + ).toBeNull(); + + settingButton.click(); + + const settingsDrawer = toolbar.getByRole('dialog', { + name: 'Settings & Help', + }); + + expect(settingsDrawer).toBeVisible(); + + getByLabelText(settingsDrawer, 'Close').click(); + + await waitFor(() => expect(settingsDrawer).not.toBeVisible()); + }); +});