]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-22018 Introduce active version in notification banner
authorViktor Vorona <viktor.vorona@sonarsource.com>
Tue, 9 Apr 2024 14:43:01 +0000 (16:43 +0200)
committersonartech <sonartech@sonarsource.com>
Wed, 10 Apr 2024 20:02:53 +0000 (20:02 +0000)
server/sonar-web/src/main/js/app/components/update-notification/UpdateNotification.tsx
server/sonar-web/src/main/js/app/components/update-notification/__tests__/UpdateNotification-test.tsx
server/sonar-web/src/main/js/components/upgrade/SystemUpgradeButton.tsx
server/sonar-web/src/main/js/components/upgrade/__tests__/SystemUpgradeButton-test.tsx
server/sonar-web/src/main/js/components/upgrade/__tests__/__snapshots__/SystemUpgradeButton-test.tsx.snap

index d63ffc032ca57e1fa0f09529abdfb6fe4e2825fc..b15c1268be8a3722769fb1900a7ef3354cb225ef 100644 (file)
@@ -23,7 +23,8 @@ import { getSystemUpgrades } from '../../../api/system';
 import { Alert, AlertVariant } from '../../../components/ui/Alert';
 import DismissableAlert from '../../../components/ui/DismissableAlert';
 import SystemUpgradeButton from '../../../components/upgrade/SystemUpgradeButton';
-import { sortUpgrades, UpdateUseCase } from '../../../components/upgrade/utils';
+import { UpdateUseCase, sortUpgrades } from '../../../components/upgrade/utils';
+import { now, parseDate } from '../../../helpers/dates';
 import { translate } from '../../../helpers/l10n';
 import { hasGlobalPermission } from '../../../helpers/users';
 import { AppState } from '../../../types/appstate';
@@ -158,7 +159,7 @@ export class UpdateNotification extends React.PureComponent<Props, State> {
 
     const { upgrades, latestLTS } = await getSystemUpgrades();
 
-    if (isEmpty(upgrades)) {
+    if (isEmpty(upgrades) && parseDate(this.props.appState.versionEOL) > now()) {
       // No new upgrades
       this.noPromptToShow();
       return;
@@ -177,7 +178,9 @@ export class UpdateNotification extends React.PureComponent<Props, State> {
 
     let useCase = UpdateUseCase.NewMinorVersion;
 
-    if (this.isPreviousLTSUpdate(parsedVersion, latestLTS, systemUpgrades)) {
+    if (parseDate(this.props.appState.versionEOL) <= now()) {
+      useCase = UpdateUseCase.PreviousLTS;
+    } else if (this.isPreviousLTSUpdate(parsedVersion, latestLTS, systemUpgrades)) {
       useCase = UpdateUseCase.PreviousLTS;
     } else if (this.isPreLTSUpdate(parsedVersion, latestLTS)) {
       useCase = UpdateUseCase.PreLTS;
@@ -193,7 +196,7 @@ export class UpdateNotification extends React.PureComponent<Props, State> {
         new Date(upgrade1.releaseDate || '').getTime()
     )[0];
 
-    const dismissKey = useCase + latest.version;
+    const dismissKey = useCase + latest?.version;
 
     if (this.mounted) {
       this.setState({
index 622b0c3dca430a3b25aefd56a9d4f3df2a4c2a43..f770c53ccebfb614709be79e932cd19ec3e18c9f 100644 (file)
@@ -43,14 +43,14 @@ function formatDate(date: Date): string {
 
 it('should render correctly', async () => {
   let wrapper = shallowRender({
-    appState: mockAppState({ version: '9.0' }),
+    appState: mockAppState({ version: '9.0', versionEOL: '2026-01-01' }),
     currentUser: mockLoggedInUser({ permissions: { global: [Permissions.Admin] } }),
   });
   await waitAndUpdate(wrapper);
   expect(wrapper).toMatchSnapshot('default');
 
   wrapper = shallowRender({
-    appState: mockAppState({ version: '9.0' }),
+    appState: mockAppState({ version: '9.0', versionEOL: '2026-01-01' }),
     currentUser: mockCurrentUser(),
   });
   expect(wrapper.type()).toBeNull();
@@ -69,7 +69,9 @@ it('should not show prompt when not admin', async () => {
 });
 
 it('should not show prompt when no current version', async () => {
-  const wrapper = shallowRender({ appState: mockAppState({ version: 'NOVERSION' }) });
+  const wrapper = shallowRender({
+    appState: mockAppState({ version: 'NOVERSION', versionEOL: '2026-01-01' }),
+  });
   await waitAndUpdate(wrapper);
   expect(wrapper.type()).toBeNull();
 });
@@ -77,7 +79,7 @@ it('should not show prompt when no current version', async () => {
 it('should not show prompt when no upgrade', async () => {
   (getSystemUpgrades as jest.Mock).mockResolvedValueOnce({ upgrades: [], latestLTS: '8.9' });
   const wrapper = shallowRender({
-    appState: mockAppState({ version: '9.1' }),
+    appState: mockAppState({ version: '9.1', versionEOL: '2026-01-01' }),
     currentUser: mockLoggedInUser({ permissions: { global: [Permissions.Admin] } }),
   });
   await waitAndUpdate(wrapper);
@@ -90,7 +92,7 @@ it('should show prompt when no lts date', async () => {
     latestLTS: '8.9',
   });
   const wrapper = shallowRender({
-    appState: mockAppState({ version: '8.1' }),
+    appState: mockAppState({ version: '8.1', versionEOL: '2026-01-01' }),
     currentUser: mockLoggedInUser({ permissions: { global: [Permissions.Admin] } }),
   });
   await waitAndUpdate(wrapper);
@@ -104,7 +106,7 @@ it('should show prompt when minor upgrade', async () => {
     latestLTS: '8.9',
   });
   const wrapper = shallowRender({
-    appState: mockAppState({ version: '9.1' }),
+    appState: mockAppState({ version: '9.1', versionEOL: '2026-01-01' }),
     currentUser: mockLoggedInUser({ permissions: { global: [Permissions.Admin] } }),
   });
   await waitAndUpdate(wrapper);
@@ -118,7 +120,7 @@ it('should show prompt when patch upgrade', async () => {
     latestLTS: '8.9',
   });
   const wrapper = shallowRender({
-    appState: mockAppState({ version: '9.1' }),
+    appState: mockAppState({ version: '9.1', versionEOL: '2026-01-01' }),
     currentUser: mockLoggedInUser({ permissions: { global: [Permissions.Admin] } }),
   });
   await waitAndUpdate(wrapper);
@@ -136,7 +138,7 @@ it('should show prompt when lts upgrade', async () => {
     latestLTS: '8.9',
   });
   const wrapper = shallowRender({
-    appState: mockAppState({ version: '8.8' }),
+    appState: mockAppState({ version: '8.8', versionEOL: '2026-01-01' }),
     currentUser: mockLoggedInUser({ permissions: { global: [Permissions.Admin] } }),
   });
   await waitAndUpdate(wrapper);
@@ -156,7 +158,7 @@ it('should show prompt when lts upgrade is more than 6 month', async () => {
     latestLTS: '8.9',
   });
   const wrapper = shallowRender({
-    appState: mockAppState({ version: '8.8' }),
+    appState: mockAppState({ version: '8.8', versionEOL: '2026-01-01' }),
     currentUser: mockLoggedInUser({ permissions: { global: [Permissions.Admin] } }),
   });
   await waitAndUpdate(wrapper);
@@ -174,7 +176,7 @@ it('should show correct alert when not dismissable', async () => {
     latestLTS: '8.9',
   });
   const wrapper = shallowRender({
-    appState: mockAppState({ version: '8.8' }),
+    appState: mockAppState({ version: '8.8', versionEOL: '2026-01-01' }),
     currentUser: mockLoggedInUser({ permissions: { global: [Permissions.Admin] } }),
   });
   await waitAndUpdate(wrapper);
@@ -183,6 +185,16 @@ it('should show correct alert when not dismissable', async () => {
   expect(wrapper.find(Alert).type).toBeDefined();
 });
 
+it('should show alert if version has reached eol, but there are no upgrades', async () => {
+  (getSystemUpgrades as jest.Mock).mockResolvedValueOnce({ upgrades: [], latestLTS: '9.9' });
+  const wrapper = shallowRender({
+    appState: mockAppState({ version: '9.9', versionEOL: '2020-01-01' }),
+    currentUser: mockLoggedInUser({ permissions: { global: [Permissions.Admin] } }),
+  });
+  await waitAndUpdate(wrapper);
+  expect(wrapper.contains('admin_notification.update.previous_lts')).toBe(true);
+});
+
 function shallowRender(props: Partial<UpdateNotification['props']> = {}) {
   return shallow(
     <UpdateNotification
index ed1b3573c3be918daec59e35a64b69ea8522aeb1..cbd8ba2f1a5b5510d05b8a8047f29c05d095db52 100644 (file)
@@ -48,6 +48,11 @@ export default class SystemUpgradeButton extends React.PureComponent<Props, Stat
   render() {
     const { latestLTS, systemUpgrades, updateUseCase } = this.props;
     const { openSystemUpgradeForm } = this.state;
+
+    if (systemUpgrades.length === 0) {
+      return null;
+    }
+
     return (
       <>
         <Button className="spacer-left" onClick={this.handleOpenSystemUpgradeForm}>
index 7cd2ccbeada97713205432c1fbcbcea8f44c84d6..0a6f6a6af696fd4e86944aeaaa8c5232d1a5f5e4 100644 (file)
@@ -19,6 +19,7 @@
  */
 import { shallow } from 'enzyme';
 import * as React from 'react';
+import { mockSystemUpgrade } from '../../../helpers/mocks/system-upgrades';
 import { click } from '../../../helpers/testUtils';
 import { Button } from '../../controls/buttons';
 import SystemUpgradeButton from '../SystemUpgradeButton';
@@ -31,8 +32,14 @@ it('should open modal correctly', () => {
   expect(wrapper.find(SystemUpgradeForm)).toBeDefined();
 });
 
+it('should not show button if there are no upgrades', () => {
+  const wrapper = shallowRender({ systemUpgrades: [] });
+  expect(wrapper).toMatchSnapshot();
+  expect(wrapper.find(Button).exists()).toBe(false);
+});
+
 function shallowRender(props: Partial<SystemUpgradeButton['props']> = {}) {
   return shallow<SystemUpgradeButton['props']>(
-    <SystemUpgradeButton systemUpgrades={[]} latestLTS="9.2" {...props} />
+    <SystemUpgradeButton systemUpgrades={[mockSystemUpgrade()]} latestLTS="9.2" {...props} />
   );
 }
index 037b14bb219703acec55be6e9484ffbaf508daf9..1b581220ca7e50156f5d802731a4ddadba129e4e 100644 (file)
@@ -1,5 +1,7 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
+exports[`should not show button if there are no upgrades 1`] = `""`;
+
 exports[`should open modal correctly 1`] = `
 <Fragment>
   <Button