Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions GUI/src/components/Flow/NodeTypes/StepNode.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { fireEvent, render, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import useServiceStore from 'store/new-services.store';
import useToastStore from 'store/toasts.store';
import { StepType } from 'types';
import { NodeDataProps } from 'types/service-flow';
import { beforeEach, describe, expect, it, vi } from 'vitest';
Expand All @@ -11,6 +12,15 @@
useTranslation: () => ({ t: (key: string) => key }),
}));

vi.mock('i18next', () => {
const mockI18n = {
use: vi.fn().mockReturnThis(),
init: vi.fn().mockResolvedValue(undefined),
t: (key: string) => key,
};
return { default: mockI18n, t: mockI18n.t };
});

const mockNavigate = vi.fn();
vi.mock('react-router-dom', async () => {
const actual = await vi.importActual<typeof import('react-router-dom')>('react-router-dom');
Expand All @@ -33,6 +43,27 @@
beforeEach(() => {
mockNavigate.mockClear();
useServiceStore.setState({ hasUnsavedChanges: false, nextLocation: null });
useToastStore.setState({ toasts: [] });
});

it('does not navigate away and shows a toast when the node references the currently open service (self-loop)', () => {
useServiceStore.setState({ serviceId: 'other-service-id', hasUnsavedChanges: false, nextLocation: null });
const resetStateSpy = vi.spyOn(useServiceStore.getState(), 'resetState');

render(
<MemoryRouter>
<StepNode data={jumpToServiceData} />
</MemoryRouter>,
);

fireEvent.click(screen.getByText(/Other Service/));

expect(mockNavigate).not.toHaveBeenCalled();
expect(resetStateSpy).not.toHaveBeenCalled();
expect(useServiceStore.getState().nextLocation).toBeNull();
expect(useToastStore.getState().toasts).toHaveLength(1);
expect(useToastStore.getState().toasts[0].title).toBe('serviceFlow.element.jumpToService.title');
expect(useToastStore.getState().toasts[0].message).toBe('serviceFlow.element.jumpToService.alreadyOnService');
});

it('navigates directly to the target service when there are no unsaved changes', () => {
Expand All @@ -44,7 +75,7 @@

fireEvent.click(screen.getByText(/Other Service/));

expect(mockNavigate).toHaveBeenCalledWith('/edit/other-service-id');

Check failure on line 78 in GUI/src/components/Flow/NodeTypes/StepNode.test.tsx

View workflow job for this annotation

GitHub Actions / frontend-test / run-check

src/components/Flow/NodeTypes/StepNode.test.tsx > StepNode jump-to-service navigation > navigates directly to the target service when there are no unsaved changes

AssertionError: expected "spy" to be called with arguments: [ '/edit/other-service-id' ] Number of calls: 0 ❯ src/components/Flow/NodeTypes/StepNode.test.tsx:78:26
expect(useServiceStore.getState().nextLocation).toBeNull();
});

Expand All @@ -60,6 +91,6 @@
fireEvent.click(screen.getByText(/Other Service/));

expect(mockNavigate).not.toHaveBeenCalled();
expect(useServiceStore.getState().nextLocation).toBe('/edit/other-service-id');

Check failure on line 94 in GUI/src/components/Flow/NodeTypes/StepNode.test.tsx

View workflow job for this annotation

GitHub Actions / frontend-test / run-check

src/components/Flow/NodeTypes/StepNode.test.tsx > StepNode jump-to-service navigation > defers navigation through the unsaved-changes dialog when there are unsaved changes

AssertionError: expected null to be '/edit/other-service-id' // Object.is equality - Expected: "/edit/other-service-id" + Received: null ❯ src/components/Flow/NodeTypes/StepNode.test.tsx:94:53
});
});
3 changes: 2 additions & 1 deletion GUI/src/i18n/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,8 @@
"selectService": "Select a service...",
"noActiveServices": "No active services available",
"parameters": "Parameters",
"navigateToService": "Open this service"
"navigateToService": "Open this service",
"alreadyOnService": "You are already viewing this service"
}
},
"popup": {
Expand Down
3 changes: 2 additions & 1 deletion GUI/src/i18n/et/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,8 @@
"selectService": "Vali teenus...",
"noActiveServices": "Aktiivseid teenuseid pole saadaval",
"parameters": "Parameetrid",
"navigateToService": "Ava see teenus"
"navigateToService": "Ava see teenus",
"alreadyOnService": "Sa vaatad juba seda teenust"
}
},
"popup": {
Expand Down
10 changes: 10 additions & 0 deletions GUI/src/utils/service-navigation-utils.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
import { t } from 'i18next';
import { NavigateFunction } from 'react-router-dom';
import { ROUTES } from 'resources/routes-constants';
import useServiceStore from 'store/new-services.store';
import useToastStore from 'store/toasts.store';

export const navigateToService = (serviceId: string, navigate: NavigateFunction) => {
if (serviceId === useServiceStore.getState().serviceId) {
useToastStore.getState().info({
title: t('serviceFlow.element.jumpToService.title'),
message: t('serviceFlow.element.jumpToService.alreadyOnService'),
});
return;
}

const target = ROUTES.replaceWithId(ROUTES.EDITSERVICE_ROUTE, serviceId);

if (useServiceStore.getState().hasUnsavedChanges) {
Expand Down
Loading