diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json
index 97fbb23301..a6bc784942 100644
--- a/plugins/user-settings/package.json
+++ b/plugins/user-settings/package.json
@@ -33,6 +33,7 @@
"devDependencies": {
"@backstage/cli": "^0.1.1-alpha.21",
"@backstage/dev-utils": "^0.1.1-alpha.21",
+ "@backstage/test-utils": "^0.1.1-alpha.21",
"@testing-library/jest-dom": "^5.10.1",
"@testing-library/react": "^10.4.1",
"@testing-library/user-event": "^12.0.7",
diff --git a/plugins/user-settings/src/components/AppSettingsList.tsx b/plugins/user-settings/src/components/AppSettingsList.tsx
index ab106cf28e..3f2b455520 100644
--- a/plugins/user-settings/src/components/AppSettingsList.tsx
+++ b/plugins/user-settings/src/components/AppSettingsList.tsx
@@ -15,12 +15,12 @@
*/
import React from 'react';
import { List } from '@material-ui/core';
-import { SidebarThemeToggle } from './ThemeToggle';
-import { SidebarPinButton } from './PinButton';
+import { ThemeToggle } from './ThemeToggle';
+import { PinButton } from './PinButton';
export const AppSettingsList = () => (
-
-
+
+
);
diff --git a/plugins/user-settings/src/components/ConfiguredProviderSettings.test.tsx b/plugins/user-settings/src/components/ConfiguredProviderSettings.test.tsx
new file mode 100644
index 0000000000..d4d8c1cbc2
--- /dev/null
+++ b/plugins/user-settings/src/components/ConfiguredProviderSettings.test.tsx
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2020 Spotify AB
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {
+ ApiProvider,
+ ApiRegistry,
+ configApiRef,
+ ConfigReader,
+ googleAuthApiRef,
+} from '@backstage/core';
+import { renderWithEffects, wrapInTestApp } from '@backstage/test-utils';
+import { fireEvent } from '@testing-library/react';
+import * as React from 'react';
+import { ConfiguredProviderSettings } from './ConfiguredProviderSettings';
+
+const mockSignInHandler = jest.fn().mockReturnValue('');
+const mockGoogleAuth = {
+ sessionState$: () => ({
+ subscribe: () => ({
+ unsubscribe: () => null,
+ }),
+ }),
+ getIdToken: mockSignInHandler,
+};
+
+const createConfig = () =>
+ ConfigReader.fromConfigs([
+ {
+ context: '',
+ data: {
+ auth: {
+ providers: {
+ google: { development: {} },
+ },
+ },
+ },
+ },
+ ]);
+
+const config = createConfig();
+
+const apiRegistry = ApiRegistry.from([
+ [configApiRef, config],
+ [googleAuthApiRef, mockGoogleAuth],
+]);
+
+describe('', () => {
+ it('displays a provider and calls its sign-in handler on click', async () => {
+ const rendered = await renderWithEffects(
+ wrapInTestApp(
+
+
+ ,
+ ),
+ );
+
+ expect(rendered.getByText('Google')).toBeInTheDocument();
+ expect(
+ rendered.getByText(googleAuthApiRef.description),
+ ).toBeInTheDocument();
+
+ const button = rendered.getByTitle('Sign in to Google');
+ expect(mockSignInHandler).toHaveBeenCalledTimes(1);
+ fireEvent.click(button);
+ expect(mockSignInHandler).toHaveBeenCalledTimes(2);
+ });
+});
diff --git a/plugins/user-settings/src/components/PinButton.test.tsx b/plugins/user-settings/src/components/PinButton.test.tsx
new file mode 100644
index 0000000000..a800193c06
--- /dev/null
+++ b/plugins/user-settings/src/components/PinButton.test.tsx
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2020 Spotify AB
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { SidebarPinStateContext } from '@backstage/core';
+import { renderWithEffects, wrapInTestApp } from '@backstage/test-utils';
+import { fireEvent } from '@testing-library/react';
+import * as React from 'react';
+import { PinButton } from './PinButton';
+
+describe('', () => {
+ it('toggles the pin sidebar button', async () => {
+ const mockToggleFn = jest.fn();
+ const rendered = await renderWithEffects(
+ wrapInTestApp(
+
+
+ ,
+ ),
+ );
+
+ expect(rendered.getByText('Pin Sidebar')).toBeInTheDocument();
+
+ const pinButton = rendered.getByTitle('Pin Sidebar');
+ fireEvent.click(pinButton);
+ expect(mockToggleFn).toHaveBeenCalled();
+ });
+});
diff --git a/plugins/user-settings/src/components/PinButton.tsx b/plugins/user-settings/src/components/PinButton.tsx
index 8e50eae9d4..f8017ef215 100644
--- a/plugins/user-settings/src/components/PinButton.tsx
+++ b/plugins/user-settings/src/components/PinButton.tsx
@@ -26,7 +26,7 @@ import LockOpenIcon from '@material-ui/icons/LockOpen';
import { ToggleButton } from '@material-ui/lab';
import { SidebarPinStateContext } from '@backstage/core';
-export const SidebarPinButton = () => {
+export const PinButton = () => {
const { isPinned, toggleSidebarPinState } = useContext(
SidebarPinStateContext,
);
diff --git a/plugins/user-settings/src/components/SettingsDialog.test.tsx b/plugins/user-settings/src/components/SettingsDialog.test.tsx
new file mode 100644
index 0000000000..d738c2ece0
--- /dev/null
+++ b/plugins/user-settings/src/components/SettingsDialog.test.tsx
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2020 Spotify AB
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {
+ ApiProvider,
+ ApiRegistry,
+ FeatureFlags,
+ featureFlagsApiRef,
+} from '@backstage/core';
+import { renderWithEffects, wrapInTestApp } from '@backstage/test-utils';
+import * as React from 'react';
+import { SettingsDialog } from './SettingsDialog';
+
+const apiRegistry = ApiRegistry.from([
+ [featureFlagsApiRef, new FeatureFlags()],
+]);
+
+describe('', () => {
+ const mockRef = { current: null };
+
+ it('displays the users name and email, and the tabs and titles', async () => {
+ const rendered = await renderWithEffects(
+ wrapInTestApp(
+
+
+ ,
+ ),
+ );
+
+ expect(rendered.getByText('Guest')).toBeInTheDocument();
+ expect(rendered.getByText('guest@example.com')).toBeInTheDocument();
+ expect(rendered.getByText('App Settings')).toBeInTheDocument();
+ expect(rendered.getByText('Additional Settings')).toBeInTheDocument();
+ expect(rendered.getByText('Auth Providers')).toBeInTheDocument();
+ expect(rendered.getByText('Feature Flags')).toBeInTheDocument();
+ });
+});
diff --git a/plugins/user-settings/src/components/ThemeToggle.test.tsx b/plugins/user-settings/src/components/ThemeToggle.test.tsx
new file mode 100644
index 0000000000..df36a985f6
--- /dev/null
+++ b/plugins/user-settings/src/components/ThemeToggle.test.tsx
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2020 Spotify AB
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {
+ ApiProvider,
+ ApiRegistry,
+ appThemeApiRef,
+ AppThemeSelector,
+} from '@backstage/core';
+import { renderWithEffects, wrapInTestApp } from '@backstage/test-utils';
+import { lightTheme } from '@backstage/theme';
+import { fireEvent } from '@testing-library/react';
+import * as React from 'react';
+import { ThemeToggle } from './ThemeToggle';
+
+const mockTheme = {
+ id: 'light',
+ title: 'Mock Theme',
+ variant: 'light' as 'light', // wut?
+ theme: lightTheme,
+};
+
+const apiRegistry = ApiRegistry.from([
+ [appThemeApiRef, AppThemeSelector.createWithStorage([mockTheme])],
+]);
+
+describe('', () => {
+ it('toggles the theme select button', async () => {
+ const themeApi = apiRegistry.get(appThemeApiRef);
+ const rendered = await renderWithEffects(
+ wrapInTestApp(
+
+
+ ,
+ ),
+ );
+
+ expect(rendered.getByText('Theme')).toBeInTheDocument();
+
+ const themeButton = rendered.getByTitle('Select Mock Theme');
+ expect(themeApi?.getActiveThemeId()).toBe(undefined);
+ fireEvent.click(themeButton);
+ expect(themeApi?.getActiveThemeId()).toBe('light');
+ });
+});
diff --git a/plugins/user-settings/src/components/ThemeToggle.tsx b/plugins/user-settings/src/components/ThemeToggle.tsx
index 166d0454c5..b041e1f76b 100644
--- a/plugins/user-settings/src/components/ThemeToggle.tsx
+++ b/plugins/user-settings/src/components/ThemeToggle.tsx
@@ -27,7 +27,7 @@ import {
Tooltip,
} from '@material-ui/core';
-export const SidebarThemeToggle = () => {
+export const ThemeToggle = () => {
const appThemeApi = useApi(appThemeApiRef);
const themeId = useObservable(
appThemeApi.activeThemeId$(),
@@ -89,7 +89,8 @@ export const SidebarThemeToggle = () => {
>
{themeIds.map(theme => (
diff --git a/plugins/user-settings/src/components/UserSettings.test.tsx b/plugins/user-settings/src/components/UserSettings.test.tsx
new file mode 100644
index 0000000000..1d43f4093e
--- /dev/null
+++ b/plugins/user-settings/src/components/UserSettings.test.tsx
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2020 Spotify AB
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import * as React from 'react';
+import { renderWithEffects, wrapInTestApp } from '@backstage/test-utils';
+import { UserSettings } from './UserSettings';
+
+describe('', () => {
+ it('renders', async () => {
+ const rendered = await renderWithEffects(wrapInTestApp());
+ expect(rendered.getByText('G')).toBeInTheDocument();
+ });
+});
diff --git a/plugins/user-settings/src/components/UserSettingsMenu.test.tsx b/plugins/user-settings/src/components/UserSettingsMenu.test.tsx
new file mode 100644
index 0000000000..b1ad059611
--- /dev/null
+++ b/plugins/user-settings/src/components/UserSettingsMenu.test.tsx
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2020 Spotify AB
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { renderWithEffects, wrapInTestApp } from '@backstage/test-utils';
+import { fireEvent } from '@testing-library/react';
+import * as React from 'react';
+import { UserSettingsMenu } from './UserSettingsMenu';
+
+describe('', () => {
+ it('displays a menu button with a sign-out option', async () => {
+ const rendered = await renderWithEffects(
+ wrapInTestApp(),
+ );
+
+ const menuButton = rendered.getByLabelText('more');
+ fireEvent.click(menuButton);
+
+ expect(rendered.getByText('Sign Out')).toBeInTheDocument();
+ });
+});
diff --git a/plugins/user-settings/src/components/UserSettingsMenu.tsx b/plugins/user-settings/src/components/UserSettingsMenu.tsx
index 40b101fe4d..19c3ee4e2d 100644
--- a/plugins/user-settings/src/components/UserSettingsMenu.tsx
+++ b/plugins/user-settings/src/components/UserSettingsMenu.tsx
@@ -39,7 +39,7 @@ export const UserSettingsMenu = () => {
return (
<>
-
+