123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292 |
- import { within } from '@testing-library/dom';
- import { render, screen, waitFor } from '@testing-library/react';
- import userEvent, { PointerEventsCheckLevel } from '@testing-library/user-event';
- import React from 'react';
- import { OrgRole } from '@grafana/data';
- import { selectors } from '@grafana/e2e-selectors';
- import TestProvider from '../../../test/helpers/TestProvider';
- import { getNavModel } from '../../core/selectors/navModel';
- import { backendSrv } from '../../core/services/backend_srv';
- import { TeamPermissionLevel } from '../../types';
- import { Props, UserProfileEditPage } from './UserProfileEditPage';
- import { initialUserState } from './state/reducers';
- const defaultProps: Props = {
- ...initialUserState,
- user: {
- id: 1,
- name: 'Test User',
- email: 'test@test.com',
- login: 'test',
- isDisabled: false,
- isGrafanaAdmin: false,
- orgId: 0,
- },
- teams: [
- {
- id: 0,
- name: 'Team One',
- email: 'team.one@test.com',
- avatarUrl: '/avatar/07d881f402480a2a511a9a15b5fa82c0',
- memberCount: 2000,
- permission: TeamPermissionLevel.Admin,
- },
- ],
- orgs: [
- {
- name: 'Main',
- orgId: 0,
- role: OrgRole.Editor,
- },
- {
- name: 'Second',
- orgId: 1,
- role: OrgRole.Viewer,
- },
- {
- name: 'Third',
- orgId: 2,
- role: OrgRole.Admin,
- },
- ],
- sessions: [
- {
- id: 0,
- browser: 'Chrome',
- browserVersion: '90',
- clientIp: 'localhost',
- createdAt: '2021-01-01 04:00:00',
- device: 'Macbook Pro',
- isActive: true,
- os: 'Mac OS X',
- osVersion: '11',
- seenAt: new Date().toUTCString(),
- },
- ],
- navModel: getNavModel(
- {
- 'profile-settings': {
- icon: 'sliders-v-alt',
- id: 'profile-settings',
- parentItem: {
- id: 'profile',
- text: 'Test User',
- img: '/avatar/46d229b033af06a191ff2267bca9ae56',
- url: '/profile',
- },
- text: 'Preferences',
- url: '/profile',
- },
- },
- 'profile-settings'
- ),
- initUserProfilePage: jest.fn().mockResolvedValue(undefined),
- revokeUserSession: jest.fn().mockResolvedValue(undefined),
- changeUserOrg: jest.fn().mockResolvedValue(undefined),
- updateUserProfile: jest.fn().mockResolvedValue(undefined),
- };
- 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);
- return {
- name: () => screen.getByRole('textbox', { name: /^name$/i }),
- 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 }),
- orgsTable,
- orgsEditorRow: () => within(orgsTable()).getByRole('row', { name: /main editor current/i }),
- orgsViewerRow: () => within(orgsTable()).getByRole('row', { name: /second viewer select organisation/i }),
- orgsAdminRow: () => within(orgsTable()).getByRole('row', { name: /third admin select organisation/i }),
- sessionsTable,
- sessionsRow: () =>
- within(sessionsTable()).getByRole('row', {
- name: /now January 1, 2021 localhost chrome on mac os x 11/i,
- }),
- };
- }
- async function getTestContext(overrides: Partial<Props> = {}) {
- jest.clearAllMocks();
- const putSpy = jest.spyOn(backendSrv, 'put');
- const getSpy = jest
- .spyOn(backendSrv, 'get')
- .mockResolvedValue({ timezone: 'UTC', homeDashboardId: 0, theme: 'dark' });
- const searchSpy = jest.spyOn(backendSrv, 'search').mockResolvedValue([]);
- const props = { ...defaultProps, ...overrides };
- const { rerender } = render(
- <TestProvider>
- <UserProfileEditPage {...props} />
- </TestProvider>
- );
- await waitFor(() => expect(props.initUserProfilePage).toHaveBeenCalledTimes(1));
- return { rerender, putSpy, getSpy, searchSpy, props };
- }
- describe('UserProfileEditPage', () => {
- describe('when loading user', () => {
- it('should show loading placeholder', async () => {
- await getTestContext({ user: null });
- expect(screen.getByText(/loading \.\.\./i)).toBeInTheDocument();
- });
- });
- describe('when user has loaded', () => {
- it('should show edit profile form', async () => {
- await getTestContext();
- const { name, email, username, saveProfile } = getSelectors();
- expect(screen.getByText(/edit profile/i)).toBeInTheDocument();
- expect(name()).toBeInTheDocument();
- expect(name()).toHaveValue('Test User');
- expect(email()).toBeInTheDocument();
- expect(email()).toHaveValue('test@test.com');
- expect(username()).toBeInTheDocument();
- expect(username()).toHaveValue('test');
- expect(saveProfile()).toBeInTheDocument();
- });
- 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();
- });
- describe('and teams are loading', () => {
- it('should show teams loading placeholder', async () => {
- await getTestContext({ teamsAreLoading: true });
- expect(screen.getByText(/loading teams\.\.\./i)).toBeInTheDocument();
- });
- });
- describe('and teams are loaded', () => {
- it('should show teams', async () => {
- await getTestContext();
- const { teamsTable, teamsRow } = getSelectors();
- expect(screen.getByRole('heading', { name: /teams/i })).toBeInTheDocument();
- expect(teamsTable()).toBeInTheDocument();
- expect(teamsRow()).toBeInTheDocument();
- });
- });
- describe('and organizations are loading', () => {
- it('should show teams loading placeholder', async () => {
- await getTestContext({ orgsAreLoading: true });
- expect(screen.getByText(/loading organizations\.\.\./i)).toBeInTheDocument();
- });
- });
- describe('and organizations are loaded', () => {
- it('should show organizations', async () => {
- await getTestContext();
- const { orgsTable, orgsEditorRow, orgsViewerRow, orgsAdminRow } = getSelectors();
- expect(screen.getByRole('heading', { name: /organizations/i })).toBeInTheDocument();
- expect(orgsTable()).toBeInTheDocument();
- expect(orgsEditorRow()).toBeInTheDocument();
- expect(orgsViewerRow()).toBeInTheDocument();
- expect(orgsAdminRow()).toBeInTheDocument();
- });
- });
- describe('and sessions are loading', () => {
- it('should show teams loading placeholder', async () => {
- await getTestContext({ sessionsAreLoading: true });
- expect(screen.getByText(/loading sessions\.\.\./i)).toBeInTheDocument();
- });
- });
- describe('and sessions are loaded', () => {
- it('should show sessions', async () => {
- await getTestContext();
- const { sessionsTable, sessionsRow } = getSelectors();
- expect(sessionsTable()).toBeInTheDocument();
- expect(sessionsRow()).toBeInTheDocument();
- });
- });
- describe('and user is edited and saved', () => {
- it('should call updateUserProfile', async () => {
- const { props } = await getTestContext();
- const { email, saveProfile } = getSelectors();
- await userEvent.clear(email());
- await userEvent.type(email(), 'test@test.se');
- // TODO remove skipPointerEventsCheck once https://github.com/jsdom/jsdom/issues/3232 is fixed
- await userEvent.click(saveProfile(), { pointerEventsCheck: PointerEventsCheckLevel.Never });
- await waitFor(() => expect(props.updateUserProfile).toHaveBeenCalledTimes(1));
- expect(props.updateUserProfile).toHaveBeenCalledWith({
- email: 'test@test.se',
- login: 'test',
- name: 'Test User',
- });
- });
- });
- describe('and organization is changed', () => {
- it('should call changeUserOrg', async () => {
- const { props } = await getTestContext();
- const orgsAdminSelectButton = () =>
- within(getSelectors().orgsAdminRow()).getByRole('button', {
- name: /select organisation/i,
- });
- await userEvent.click(orgsAdminSelectButton());
- await waitFor(() => expect(props.changeUserOrg).toHaveBeenCalledTimes(1));
- expect(props.changeUserOrg).toHaveBeenCalledWith({
- name: 'Third',
- orgId: 2,
- role: 'Admin',
- });
- });
- });
- describe('and session is revoked', () => {
- it('should call revokeUserSession', async () => {
- const { props } = await getTestContext();
- const sessionsRevokeButton = () =>
- within(getSelectors().sessionsRow()).getByRole('button', {
- name: /revoke user session/i,
- });
- await userEvent.click(sessionsRevokeButton());
- await waitFor(() => expect(props.revokeUserSession).toHaveBeenCalledTimes(1));
- expect(props.revokeUserSession).toHaveBeenCalledWith(0);
- });
- });
- });
- });
|