Skip to content

Commit

Permalink
Fixed schedules not showing tooltip for user details (#4033)
Browse files Browse the repository at this point in the history
# What this PR does

## Which issue(s) this PR closes

## Checklist

- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
    show up in the autogenerated release notes.

---------

Co-authored-by: Dominik <[email protected]>
  • Loading branch information
teodosii and brojd authored Mar 7, 2024
1 parent d27bd6a commit 6680abb
Show file tree
Hide file tree
Showing 11 changed files with 48 additions and 21 deletions.
4 changes: 2 additions & 2 deletions grafana-plugin/e2e-tests/alerts/onCallSchedule.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ import { verifyThatAlertGroupIsTriggered } from '../utils/alertGroup';
import { createEscalationChain, EscalationStep } from '../utils/escalationChain';
import { generateRandomValue } from '../utils/forms';
import { createIntegrationAndSendDemoAlert } from '../utils/integrations';
import { createOnCallSchedule } from '../utils/schedule';
import { createOnCallScheduleWithRotation } from '../utils/schedule';

test('we can create an oncall schedule + receive an alert', async ({ adminRolePage }) => {
const { page, userName } = adminRolePage;
const escalationChainName = generateRandomValue();
const integrationName = generateRandomValue();
const onCallScheduleName = generateRandomValue();

await createOnCallSchedule(page, onCallScheduleName, userName);
await createOnCallScheduleWithRotation(page, onCallScheduleName, userName);
await createEscalationChain(
page,
escalationChainName,
Expand Down
4 changes: 2 additions & 2 deletions grafana-plugin/e2e-tests/insights/insights.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { createEscalationChain, EscalationStep } from '../utils/escalationChain'
import { clickButton, generateRandomValue } from '../utils/forms';
import { createIntegrationAndSendDemoAlert } from '../utils/integrations';
import { goToGrafanaPage, goToOnCallPage } from '../utils/navigation';
import { createOnCallSchedule } from '../utils/schedule';
import { createOnCallScheduleWithRotation } from '../utils/schedule';

/**
* Insights is dependent on Scenes which were only added in Grafana 10.0.0
Expand Down Expand Up @@ -42,7 +42,7 @@ test.describe('Insights', () => {
const escalationChainName = generateRandomValue();
const integrationName = generateRandomValue();
const onCallScheduleName = generateRandomValue();
await createOnCallSchedule(page, onCallScheduleName, userName);
await createOnCallScheduleWithRotation(page, onCallScheduleName, userName);
await createEscalationChain(
page,
escalationChainName,
Expand Down
4 changes: 2 additions & 2 deletions grafana-plugin/e2e-tests/schedules/addOverride.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import dayjs from 'dayjs';

import { test, expect } from '../fixtures';
import { clickButton, generateRandomValue } from '../utils/forms';
import { createOnCallSchedule, getOverrideFormDateInputs } from '../utils/schedule';
import { createOnCallScheduleWithRotation, getOverrideFormDateInputs } from '../utils/schedule';

test('default dates in override creation modal are correct', async ({ adminRolePage }) => {
const { page, userName } = adminRolePage;

const onCallScheduleName = generateRandomValue();
await createOnCallSchedule(page, onCallScheduleName, userName);
await createOnCallScheduleWithRotation(page, onCallScheduleName, userName);

await clickButton({ page, buttonText: 'Add override' });

Expand Down
4 changes: 2 additions & 2 deletions grafana-plugin/e2e-tests/schedules/quality.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { test, expect } from '../fixtures';
import { generateRandomValue } from '../utils/forms';
import { createOnCallSchedule } from '../utils/schedule';
import { createOnCallScheduleWithRotation } from '../utils/schedule';

test('check schedule quality for simple 1-user schedule', async ({ adminRolePage }) => {
const { page, userName } = adminRolePage;
const onCallScheduleName = generateRandomValue();

await createOnCallSchedule(page, onCallScheduleName, userName);
await createOnCallScheduleWithRotation(page, onCallScheduleName, userName);

const scheduleQualityElement = page.getByTestId('schedule-quality');
await scheduleQualityElement.waitFor({ state: 'visible' });
Expand Down
18 changes: 18 additions & 0 deletions grafana-plugin/e2e-tests/schedules/scheduleDetails.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { test, expect } from '../fixtures';
import { generateRandomValue } from '../utils/forms';
import { createOnCallScheduleWithRotation, createRotation } from '../utils/schedule';

test(`user can see the other user's details`, async ({ adminRolePage, editorRolePage }) => {
const { page, userName: adminUserName } = adminRolePage;
const editorUserName = editorRolePage.userName;
const onCallScheduleName = generateRandomValue();

await createOnCallScheduleWithRotation(page, onCallScheduleName, adminUserName);
await createRotation(page, editorUserName, false);

await page.getByTestId('user-avatar-in-schedule').first().hover();
await expect(page.getByTestId('schedule-user-details')).toHaveText(new RegExp(editorUserName));

await page.getByTestId('user-avatar-in-schedule').nth(1).hover();
await expect(page.getByTestId('schedule-user-details')).toHaveText(new RegExp(adminUserName));
});
4 changes: 2 additions & 2 deletions grafana-plugin/e2e-tests/schedules/schedulesList.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { expect, test } from '../fixtures';
import { generateRandomValue } from '../utils/forms';
import { goToOnCallPage } from '../utils/navigation';
import { createOnCallSchedule } from '../utils/schedule';
import { createOnCallScheduleWithRotation } from '../utils/schedule';

test('schedule calendar and list of schedules is correctly displayed', async ({ adminRolePage }) => {
const { page, userName } = adminRolePage;

const onCallScheduleName = generateRandomValue();
await createOnCallSchedule(page, onCallScheduleName, userName);
await createOnCallScheduleWithRotation(page, onCallScheduleName, userName);

await goToOnCallPage(page, 'schedules');

Expand Down
4 changes: 2 additions & 2 deletions grafana-plugin/e2e-tests/schedules/timezones.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import utc from 'dayjs/plugin/utc';
import { test } from '../fixtures';
import { clickButton, generateRandomValue } from '../utils/forms';
import { setTimezoneInProfile } from '../utils/grafanaProfile';
import { createOnCallSchedule } from '../utils/schedule';
import { createOnCallScheduleWithRotation } from '../utils/schedule';

dayjs.extend(utc);
dayjs.extend(isoWeek);
Expand All @@ -23,7 +23,7 @@ test('dates in schedule are correct according to selected current timezone', asy
await setTimezoneInProfile(page, 'Europe/Moscow');

const onCallScheduleName = generateRandomValue();
await createOnCallSchedule(page, onCallScheduleName, userName);
await createOnCallScheduleWithRotation(page, onCallScheduleName, userName);

// Current timezone is selected by default to currently logged in user timezone
await expect(page.getByTestId('timezone-select')).toHaveText('GMT+3');
Expand Down
15 changes: 12 additions & 3 deletions grafana-plugin/e2e-tests/utils/schedule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import dayjs from 'dayjs';
import { clickButton, selectDropdownValue } from './forms';
import { goToOnCallPage } from './navigation';

export const createOnCallSchedule = async (page: Page, scheduleName: string, userName: string): Promise<void> => {
export const createOnCallScheduleWithRotation = async (
page: Page,
scheduleName: string,
userName: string
): Promise<void> => {
// go to the schedules page
await goToOnCallPage(page, 'schedules');

Expand All @@ -18,15 +22,20 @@ export const createOnCallSchedule = async (page: Page, scheduleName: string, use
// Add a new layer w/ the current user to it
await clickButton({ page, buttonText: 'Create Schedule' });

await clickButton({ page, buttonText: 'Add rotation' });
await createRotation(page, userName);
};

export const createRotation = async (page: Page, userName: string, isFirstScheduleRotation = true) => {
await clickButton({ page, buttonText: 'Add rotation' });
if (!isFirstScheduleRotation) {
await page.getByText('Layer 1 rotation', { exact: true }).click();
}
await selectDropdownValue({
page,
selectType: 'grafanaSelect',
placeholderText: 'Add user',
value: userName,
});

await clickButton({ page, buttonText: 'Create' });
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export const ScheduleUserDetails: FC<ScheduleUserDetailsProps> = observer((props
organizationStore.currentOrganization.slack_team_identity?.cached_name?.replace(/[^0-9a-z]/gi, '') || '';

return (
<div className={cx('root')}>
<div className={cx('root')} data-testid="schedule-user-details">
<VerticalGroup spacing="xs">
<ScheduleBorderedAvatar
colors={colorSchemeList}
Expand Down
1 change: 0 additions & 1 deletion grafana-plugin/src/models/loader/action-keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,5 @@ export enum ActionKey {
FETCH_INCIDENTS_AND_STATS = 'FETCH_INCIDENTS_AND_STATS',
UPDATE_FILTERS_AND_FETCH_INCIDENTS = 'UPDATE_FILTERS_AND_FETCH_INCIDENTS',
FETCH_INTEGRATIONS = 'FETCH_INTEGRATIONS',
FETCH_USERS = 'FETCH_USERS',
TEST_CALL_OR_SMS = 'TEST_CALL_OR_SMS',
}
9 changes: 5 additions & 4 deletions grafana-plugin/src/models/user/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export class UserStore {
notificationChoices: any = [];
notifyByOptions: any = [];
currentUserPk?: ApiSchemas['User']['pk'];
usersCurrentlyBeingFetched: { [pk: string]: boolean } = {};

constructor(rootStore: RootStore) {
makeAutoObservable(this, undefined, { autoBind: true });
Expand Down Expand Up @@ -69,7 +70,6 @@ export class UserStore {
return response;
}

@AutoLoadingState(ActionKey.FETCH_USERS)
@action.bound
async fetchItemById({
userPk,
Expand All @@ -80,19 +80,20 @@ export class UserStore {
skipErrorHandling?: boolean;
skipIfAlreadyPending?: boolean;
}) {
const isAlreadyFetching = this.rootStore.loaderStore.isLoading(ActionKey.FETCH_USERS);

if (skipIfAlreadyPending && isAlreadyFetching) {
if (skipIfAlreadyPending && this.usersCurrentlyBeingFetched[userPk]) {
return this.items[userPk];
}

this.usersCurrentlyBeingFetched[userPk] = true;

const { data } = await onCallApi({ skipErrorHandling }).GET('/users/{id}/', { params: { path: { id: userPk } } });

runInAction(() => {
this.items = {
...this.items,
[data.pk]: { ...data, timezone: UserHelper.getTimezone(data) },
};
delete this.usersCurrentlyBeingFetched[userPk];
});

return data;
Expand Down

0 comments on commit 6680abb

Please sign in to comment.