diff --git a/public/app/core/components/SharedPreferences/SharedPreferences.test.tsx b/public/app/core/components/SharedPreferences/SharedPreferences.test.tsx new file mode 100644 index 00000000000..7ab303c8800 --- /dev/null +++ b/public/app/core/components/SharedPreferences/SharedPreferences.test.tsx @@ -0,0 +1,153 @@ +import { render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import React from 'react'; +import TestProvider from 'test/helpers/TestProvider'; +import { assertInstanceOf } from 'test/helpers/asserts'; +import { getSelectParent, selectOptionInTest } from 'test/helpers/selectOptionInTest'; + +import { UserPreferencesDTO } from 'app/types'; + +import SharedPreferences from './SharedPreferences'; + +jest.mock('app/core/services/backend_srv', () => { + return { + backendSrv: { + search: jest.fn().mockResolvedValue([ + { + id: 2, + title: 'My Dashboard', + tags: [], + type: '', + uid: '', + uri: '', + url: '', + folderId: 0, + folderTitle: '', + folderUid: '', + folderUrl: '', + isStarred: false, + slug: '', + items: [], + }, + { + id: 3, + title: 'Another Dashboard', + tags: [], + type: '', + uid: '', + uri: '', + url: '', + folderId: 0, + folderTitle: '', + folderUid: '', + folderUrl: '', + isStarred: false, + slug: '', + items: [], + }, + ]), + }, + }; +}); + +const mockPreferences: UserPreferencesDTO = { + timezone: 'browser', + weekStart: 'monday', + theme: 'light', + homeDashboardId: 2, + queryHistory: { + homeTab: '', + }, +}; + +const mockPrefsPatch = jest.fn(); +const mockPrefsUpdate = jest.fn(); +const mockPrefsLoad = jest.fn().mockResolvedValue(mockPreferences); + +jest.mock('app/core/services/PreferencesService', () => ({ + PreferencesService: function () { + return { + patch: mockPrefsPatch, + update: mockPrefsUpdate, + load: mockPrefsLoad, + }; + }, +})); + +const props = { + resourceUri: '/fake-api/user/1', +}; + +describe('SharedPreferences', () => { + const original = window.location; + const mockReload = jest.fn(); + + beforeAll(() => { + Object.defineProperty(window, 'location', { + configurable: true, + value: { reload: mockReload }, + }); + }); + + afterAll(() => { + Object.defineProperty(window, 'location', { configurable: true, value: original }); + }); + + beforeEach(async () => { + mockReload.mockReset(); + mockPrefsUpdate.mockReset(); + + render( + + + + ); + + await waitFor(() => expect(mockPrefsLoad).toHaveBeenCalled()); + }); + + it('renders the theme preference', () => { + const lightThemeRadio = assertInstanceOf(screen.getByLabelText('Light'), HTMLInputElement); + expect(lightThemeRadio.checked).toBeTruthy(); + }); + + it('renders the home dashboard preference', () => { + const dashboardSelect = getSelectParent(screen.getByLabelText('Home Dashboard')); + expect(dashboardSelect).toHaveTextContent('My Dashboard'); + }); + + it('renders the timezone preference', () => { + const tzSelect = getSelectParent(screen.getByLabelText('Timezone')); + expect(tzSelect).toHaveTextContent('Browser Time'); + }); + + it('renders the week start preference', async () => { + const weekSelect = getSelectParent(screen.getByLabelText('Week start')); + expect(weekSelect).toHaveTextContent('Monday'); + }); + + it("saves the user's new preferences", async () => { + const darkThemeRadio = assertInstanceOf(screen.getByLabelText('Dark'), HTMLInputElement); + await userEvent.click(darkThemeRadio); + + await selectOptionInTest(screen.getByLabelText('Home Dashboard'), 'Another Dashboard'); + await selectOptionInTest(screen.getByLabelText('Timezone'), 'Australia/Sydney'); + await selectOptionInTest(screen.getByLabelText('Week start'), 'Saturday'); + + await userEvent.click(screen.getByText('Save')); + expect(mockPrefsUpdate).toHaveBeenCalledWith({ + timezone: 'Australia/Sydney', + weekStart: 'saturday', + theme: 'dark', + homeDashboardId: 3, + queryHistory: { + homeTab: '', + }, + }); + }); + + it('refreshes the page after saving preferences', async () => { + await userEvent.click(screen.getByText('Save')); + expect(mockReload).toHaveBeenCalled(); + }); +}); diff --git a/public/app/features/profile/UserProfileEditPage.test.tsx b/public/app/features/profile/UserProfileEditPage.test.tsx index 83ada3e7937..905c9d4f77c 100644 --- a/public/app/features/profile/UserProfileEditPage.test.tsx +++ b/public/app/features/profile/UserProfileEditPage.test.tsx @@ -90,8 +90,6 @@ const defaultProps: Props = { }; function getSelectors() { - const dashboardSelect = () => screen.getByTestId('User preferences home dashboard drop down'); - const timepickerSelect = () => screen.getByTestId(selectors.components.TimeZonePicker.containerV2); const teamsTable = () => screen.getByRole('table', { name: /user teams table/i }); const orgsTable = () => screen.getByTestId(selectors.components.UserProfile.orgsTable); const sessionsTable = () => screen.getByTestId(selectors.components.UserProfile.sessionsTable); @@ -100,10 +98,6 @@ function getSelectors() { email: () => screen.getByRole('textbox', { name: /email/i }), username: () => screen.getByRole('textbox', { name: /username/i }), saveProfile: () => screen.getByTestId(selectors.components.UserProfile.profileSaveButton), - dashboardSelect, - dashboardValue: () => within(dashboardSelect()).getByText(/default/i), - timepickerSelect, - timepickerValue: () => within(timepickerSelect()).getByText(/coordinated universal time/i), savePreferences: () => screen.getByTestId(selectors.components.UserProfile.preferencesSaveButton), teamsTable, teamsRow: () => within(teamsTable()).getByRole('row', { name: /team one team.one@test\.com 2000/i }), @@ -166,16 +160,8 @@ describe('UserProfileEditPage', () => { it('should show shared preferences', async () => { await getTestContext(); - const { dashboardSelect, dashboardValue, timepickerSelect, timepickerValue, savePreferences } = getSelectors(); - expect(screen.getByRole('group', { name: /preferences/i })).toBeInTheDocument(); - expect(screen.getByRole('radio', { name: /default/i })).toBeInTheDocument(); - expect(screen.getByRole('radio', { name: /dark/i })).toBeInTheDocument(); - expect(screen.getByRole('radio', { name: /light/i })).toBeInTheDocument(); - expect(dashboardSelect()).toBeInTheDocument(); - expect(dashboardValue()).toBeInTheDocument(); - expect(timepickerSelect()).toBeInTheDocument(); - expect(timepickerValue()).toBeInTheDocument(); - expect(savePreferences()).toBeInTheDocument(); + // SharedPreferences itself is tested, so here just make sure it's being rendered + expect(screen.getByLabelText('Home Dashboard')).toBeInTheDocument(); }); describe('and teams are loading', () => { diff --git a/public/test/helpers/asserts.ts b/public/test/helpers/asserts.ts new file mode 100644 index 00000000000..994741e0137 --- /dev/null +++ b/public/test/helpers/asserts.ts @@ -0,0 +1,10 @@ +export function assertInstanceOf }>( + value: unknown, + type: T +): InstanceType { + if (!(value instanceof type)) { + throw new Error(`Expected value to be an instanceof ${typeof type} but got ${typeof value}`); + } + + return value; +}