diff --git a/src/about/AboutDialog.test.tsx b/src/about/AboutDialog.test.tsx
new file mode 100644
index 00000000..5c57eb19
--- /dev/null
+++ b/src/about/AboutDialog.test.tsx
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: MIT
+// Copyright (c) 2021 The Pybricks Authors
+
+import { I18nContext, I18nManager } from '@shopify/react-i18n';
+import {
+ getByLabelText,
+ render,
+ screen,
+ waitForElementToBeRemoved,
+} from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
+import React from 'react';
+import { Provider } from 'react-redux';
+import { createStore } from 'redux';
+import { rootReducer } from '../reducers';
+import AboutDialog from './AboutDialog';
+
+it('should close when the button is clicked', () => {
+ const store = createStore(rootReducer);
+ const i18n = new I18nManager({ locale: 'en' });
+ const close = jest.fn();
+ render(
+
+
+ close()} />
+
+ ,
+ );
+
+ userEvent.click(screen.getByLabelText('Close'));
+
+ expect(close).toHaveBeenCalled();
+});
+
+it('should manage license dialog open/close', async () => {
+ const store = createStore(rootReducer);
+ const i18n = new I18nManager({ locale: 'en' });
+ render(
+
+
+ undefined} />
+
+ ,
+ );
+
+ userEvent.click(screen.getByText('Open Source Licenses'));
+
+ expect(
+ screen.getByText('Pybricks Code is built on open source software.', {
+ exact: false,
+ }),
+ ).toBeInTheDocument();
+
+ const licenseDialog = document.querySelector(
+ '.pb-license-dialog',
+ ) as HTMLDivElement;
+ userEvent.click(getByLabelText(licenseDialog, 'Close'));
+
+ await waitForElementToBeRemoved(() =>
+ screen.queryByText('Pybricks Code is built on open source software.', {
+ exact: false,
+ }),
+ );
+});