diff --git a/public/app/percona/shared/components/PerconaBootstrapper/PerconaUpdateVersion/PerconaUpdateVersion.test.tsx b/public/app/percona/shared/components/PerconaBootstrapper/PerconaUpdateVersion/PerconaUpdateVersion.test.tsx index e69de29bb2d1d..e45eb11d885a4 100644 --- a/public/app/percona/shared/components/PerconaBootstrapper/PerconaUpdateVersion/PerconaUpdateVersion.test.tsx +++ b/public/app/percona/shared/components/PerconaBootstrapper/PerconaUpdateVersion/PerconaUpdateVersion.test.tsx @@ -0,0 +1,114 @@ +import { render, screen } from '@testing-library/react'; +import React from 'react'; +import { Provider } from 'react-redux'; +import { waitFor } from 'test/test-utils'; + +import * as GrafanaUpdates from 'app/percona/shared/core/reducers/updates/updates'; +import { UpdatesService } from 'app/percona/shared/services/updates'; +import { configureStore } from 'app/store/configureStore'; + +import PerconaUpdateVersion from './PerconaUpdateVersion'; + +const checkUpdatesChangeLogsSpy = jest.spyOn(GrafanaUpdates, 'checkUpdatesChangeLogs'); +describe('PerconaUpdateVersion', () => { + function setup(store) { + return render( + + + + ); + } + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should render modal with one update', async () => { + const state = { + percona: { + updates: { + updateAvailable: true, + latest: { version: '3.0.1' }, + lastChecked: '', + snoozeCurrentVersion: { + user_id: 0, + productTourCompleted: true, + alertingTourCompleted: true, + snoozedPmmVersion: '', + }, + changeLogs: { + updates: [ + { + version: 'PMM 3.0.1', + tag: 'string', + timestamp: '2024-09-24T09:12:31.488Z', + releaseNotesUrl: 'http://localhost:3000', + releaseNotesText: 'text1', + }, + ], + }, + }, + }, + }; + jest + .spyOn(UpdatesService, 'getUpdatesChangelogs') + .mockReturnValue(Promise.resolve({ ...state.percona.updates.changeLogs })); + + const store = configureStore(state); + + const { container } = setup(store); + await waitFor(() => { + expect(checkUpdatesChangeLogsSpy).toHaveBeenCalled(); + }); + + expect(screen.getByTestId('one-update-modal')).toBeInTheDocument(); + }); + + it('should render modal with multiple updates', async () => { + const state = { + percona: { + updates: { + updateAvailable: true, + latest: { version: '3.0.1' }, + lastChecked: '', + snoozeCurrentVersion: { + user_id: 0, + productTourCompleted: true, + alertingTourCompleted: true, + snoozedPmmVersion: '', + }, + changeLogs: { + updates: [ + { + version: 'PMM 3.0.1', + tag: 'string', + timestamp: '2024-09-24T09:12:31.488Z', + releaseNotesUrl: 'http://localhost:3000', + releaseNotesText: 'text1', + }, + { + version: 'PMM 3.0.2', + tag: 'string', + timestamp: '2024-09-24T09:12:31.488Z', + releaseNotesUrl: 'http://localhost:3000', + releaseNotesText: 'text2', + }, + ], + }, + }, + }, + }; + jest + .spyOn(UpdatesService, 'getUpdatesChangelogs') + .mockReturnValue(Promise.resolve({ ...state.percona.updates.changeLogs })); + + const store = configureStore(state); + + const { container } = setup(store); + await waitFor(() => { + expect(checkUpdatesChangeLogsSpy).toHaveBeenCalled(); + }); + + expect(screen.getByTestId('multiple-updates-modal')).toBeInTheDocument(); + }); +}); diff --git a/public/app/percona/shared/components/PerconaBootstrapper/PerconaUpdateVersion/PerconaUpdateVersion.tsx b/public/app/percona/shared/components/PerconaBootstrapper/PerconaUpdateVersion/PerconaUpdateVersion.tsx index 84dd606035961..c3901a088cb18 100644 --- a/public/app/percona/shared/components/PerconaBootstrapper/PerconaUpdateVersion/PerconaUpdateVersion.tsx +++ b/public/app/percona/shared/components/PerconaBootstrapper/PerconaUpdateVersion/PerconaUpdateVersion.tsx @@ -24,11 +24,6 @@ const PerconaUpdateVersion: FC = () => { const styles = useStyles2(getStyles); useEffect(() => { - const showModal = async () => { - await dispatch(checkUpdatesChangeLogs()); - setShowUpdate(true); - }; - const differenceInDays = () => { if (lastChecked) { const lastCheckDate = new Date(lastChecked); @@ -40,9 +35,9 @@ const PerconaUpdateVersion: FC = () => { } }; - if (updateAvailable) { + const prepareModal = async () => { if (!snoozeCurrentVersion) { - dispatch(getSnoozeCurrentVersion()); + await dispatch(getSnoozeCurrentVersion()); } const days = differenceInDays(); if ( @@ -51,16 +46,21 @@ const PerconaUpdateVersion: FC = () => { snoozeCurrentVersion?.snoozedPmmVersion !== latest?.version) || !lastChecked ) { - showModal(); + setShowUpdate(true); + await dispatch(checkUpdatesChangeLogs()); } + }; + + if (updateAvailable) { + prepareModal(); } }, [dispatch, updateAvailable, installed, latest, snoozeCurrentVersion, lastChecked]); const snoozeUpdate = async () => { if (latest && latest.version) { const payload = { - productTourCompleted: true, // ? - alertingTourCompleted: true, // ? + productTourCompleted: snoozeCurrentVersion?.productTourCompleted || true, + alertingTourCompleted: snoozeCurrentVersion?.alertingTourCompleted || true, snoozedPmmVersion: latest.version, }; await dispatch(setSnoozeCurrentUpdate(payload)); @@ -77,49 +77,53 @@ const PerconaUpdateVersion: FC = () => { -
{changeLogs?.updates[0].version}
-

- {Messages.fullReleaseNotes} -

-
{Messages.howToUpdate}
-

{Messages.howToUpdateDescription}

-
- - +
+
{changeLogs?.updates[0]?.version || ''}
+

+ {Messages.fullReleaseNotes} +

+
{Messages.howToUpdate}
+

{Messages.howToUpdateDescription}

+
+ + +
1} + isOpen={showUpdate && changeLogs && changeLogs?.updates?.length > 1} className={styles.updateVersionModal} > -
{Messages.newVersions}
- -
{Messages.notes}
-

{Messages.notesDescription}

-
- - +
+
{Messages.newVersions}
+ +
{Messages.notes}
+

{Messages.notesDescription}

+
+ + +
diff --git a/public/app/percona/shared/core/reducers/updates/updates.ts b/public/app/percona/shared/core/reducers/updates/updates.ts index 0a54171d01321..f60738dcaea6f 100644 --- a/public/app/percona/shared/core/reducers/updates/updates.ts +++ b/public/app/percona/shared/core/reducers/updates/updates.ts @@ -3,13 +3,7 @@ import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'; import { withSerializedError } from 'app/features/alerting/unified/utils/redux'; import { UpdatesService } from 'app/percona/shared/services/updates'; -import { - CheckUpdatesChangeLogsResponse, - CheckUpdatesPayload, - SnoozePayloadBody, - SnoozePayloadResponse, - UpdatesState, -} from './updates.types'; +import { CheckUpdatesPayload, SnoozePayloadBody, SnoozePayloadResponse, UpdatesState } from './updates.types'; import { responseToPayload } from './updates.utils'; const initialState: UpdatesState = { @@ -22,52 +16,26 @@ export const updatesSlice = createSlice({ reducers: {}, extraReducers: (builder) => { builder.addCase(checkUpdatesAction.pending, (state) => ({ - ...initialState, + ...state, isLoading: true, })); - builder.addCase(checkUpdatesAction.fulfilled, (state, { payload }) => ({ ...state, ...payload, - updateAvailable: true, // to remove - latest: { version: '3.0.1' }, // to remove - isLoading: false, - lastChecked: '', })); - builder.addCase(checkUpdatesAction.rejected, (state) => ({ - ...initialState, + ...state, isLoading: false, })); builder.addCase(checkUpdatesChangeLogs.pending, (state) => ({ - ...initialState, + ...state, isLoading: true, })); - builder.addCase(checkUpdatesChangeLogs.fulfilled, (state, { payload }) => ({ ...state, isLoading: false, - changeLogs: { - ...payload, - updates: [ - { - version: 'PMM 3.0.1', - tag: 'string', - timestamp: '2024-09-24T09:12:31.488Z', - releaseNotesUrl: 'https://google.com', - releaseNotesText: 'asdasd', - }, - { - version: 'PMM 3.0.1', - tag: 'string', - timestamp: '2024-09-24T09:12:31.488Z', - releaseNotesUrl: 'https://google.com', - releaseNotesText: 'asdasd', - }, - ], - }, + changeLogs: payload, })); - builder.addCase(checkUpdatesChangeLogs.rejected, (state) => ({ ...state, isLoading: false, @@ -76,13 +44,11 @@ export const updatesSlice = createSlice({ ...state, isLoading: true, })); - builder.addCase(getSnoozeCurrentVersion.fulfilled, (state, { payload }) => ({ ...state, snoozeCurrentVersion: payload, isLoading: false, })); - builder.addCase(getSnoozeCurrentVersion.rejected, (state) => ({ ...state, isLoading: false, @@ -91,13 +57,11 @@ export const updatesSlice = createSlice({ ...state, isLoading: true, })); - builder.addCase(setSnoozeCurrentUpdate.fulfilled, (state, { payload }) => ({ ...state, snoozeCurrentVersion: payload, isLoading: false, })); - builder.addCase(setSnoozeCurrentUpdate.rejected, (state) => ({ ...state, isLoading: false, @@ -115,15 +79,9 @@ export const checkUpdatesAction = createAsyncThunk('percona/checkUpdates', async } }); -export const checkUpdatesChangeLogs = createAsyncThunk( - 'percona/checkUpdatesChangelogs', - async (): Promise => - withSerializedError( - (async () => { - return await UpdatesService.getUpdatesChangelogs(); - })() - ) -); +export const checkUpdatesChangeLogs = createAsyncThunk('percona/checkUpdatesChangelogs', async () => { + return await UpdatesService.getUpdatesChangelogs(); +}); export const setSnoozeCurrentUpdate = createAsyncThunk( 'percona/setSnoozeCurrentUpdate',