diff --git a/client/test/preview/integration/components/asset/AssetBoard.test.tsx b/client/test/preview/integration/components/asset/AssetBoard.test.tsx
index 17b3e204a..5bb51fac5 100644
--- a/client/test/preview/integration/components/asset/AssetBoard.test.tsx
+++ b/client/test/preview/integration/components/asset/AssetBoard.test.tsx
@@ -119,4 +119,19 @@ describe('AssetBoard Integration Tests', () => {
expect(screen.queryByText('Asset 1')).not.toBeInTheDocument();
});
});
+
+ it('shows an error message', async () => {
+ const error = 'An error occurred';
+ jest.spyOn(React, 'useState').mockReturnValue([error, jest.fn()]);
+
+ act(() => {
+ render(
+
+
+ ,
+ );
+ });
+
+ expect(screen.getByText(error)).toBeInTheDocument();
+ });
});
diff --git a/client/test/preview/integration/route/digitaltwins/create/ChangeFileNameDialog.test.tsx b/client/test/preview/integration/route/digitaltwins/create/ChangeFileNameDialog.test.tsx
new file mode 100644
index 000000000..a860a4904
--- /dev/null
+++ b/client/test/preview/integration/route/digitaltwins/create/ChangeFileNameDialog.test.tsx
@@ -0,0 +1,80 @@
+import * as React from 'react';
+import ChangeFileNameDialog from 'preview/route/digitaltwins/create/ChangeFileNameDialog';
+import { Provider } from 'react-redux';
+import { fireEvent, render, screen, waitFor } from '@testing-library/react';
+import {
+ combineReducers,
+ configureStore,
+ getDefaultMiddleware,
+} from '@reduxjs/toolkit';
+import fileSlice from 'preview/store/file.slice';
+import { act } from 'react';
+
+const store = configureStore({
+ reducer: combineReducers({
+ files: fileSlice,
+ }),
+ middleware: getDefaultMiddleware({
+ serializableCheck: false,
+ }),
+});
+
+describe('ChangeFileNameDialog', () => {
+ const setShowDialog = jest.fn();
+ const setFileName = jest.fn();
+ const setFileType = jest.fn();
+ const fileName = 'testName';
+
+ beforeEach(() => {
+ act(() => {
+ render(
+
+
+ ,
+ );
+ });
+ });
+
+ afterEach(() => {
+ jest.clearAllMocks();
+ });
+
+ it('handles click on change button', () => {
+ const changeButton = screen.getByRole('button', { name: /Change/i });
+ act(() => {
+ changeButton.click();
+ });
+
+ expect(setFileName).toHaveBeenCalled();
+ expect(setFileType).toHaveBeenCalled();
+ });
+
+ it('handles click on cancel button', () => {
+ const cancelButton = screen.getByRole('button', { name: /Cancel/i });
+ act(() => {
+ cancelButton.click();
+ });
+
+ expect(setShowDialog).toHaveBeenCalled();
+ });
+
+ it('handles change in text field', () => {
+ const textField = screen.getByRole('textbox');
+
+ act(() => {
+ fireEvent.change(textField, {
+ target: { value: 'modifiedDTName' },
+ });
+ });
+
+ waitFor(() => {
+ expect(textField).toHaveValue('modifiedDTName');
+ });
+ });
+});
diff --git a/client/test/preview/integration/route/digitaltwins/create/ConfirmDeleteDialog.test.tsx b/client/test/preview/integration/route/digitaltwins/create/ConfirmDeleteDialog.test.tsx
new file mode 100644
index 000000000..b92aefe97
--- /dev/null
+++ b/client/test/preview/integration/route/digitaltwins/create/ConfirmDeleteDialog.test.tsx
@@ -0,0 +1,79 @@
+import * as React from 'react';
+import ConfirmDeleteDialog from 'preview/route/digitaltwins/create/ConfirmDeleteDialog';
+import { act } from 'react';
+import { render, screen } from '@testing-library/react';
+import {
+ combineReducers,
+ configureStore,
+ getDefaultMiddleware,
+} from '@reduxjs/toolkit';
+import { Provider } from 'react-redux';
+import fileSlice, { addOrUpdateFile } from 'preview/store/file.slice';
+
+const store = configureStore({
+ reducer: combineReducers({
+ files: fileSlice,
+ }),
+ middleware: getDefaultMiddleware({
+ serializableCheck: false,
+ }),
+});
+
+describe('ConfirmDeleteDialog', () => {
+ const setOpenConfirmDeleteDialog = jest.fn();
+ const setFileName = jest.fn();
+ const setFileContent = jest.fn();
+ const setFileType = jest.fn();
+ const setNewDigitalTwinName = jest.fn();
+
+ beforeEach(() => {
+ act(() => {
+ render(
+
+
+ ,
+ );
+ });
+ });
+
+ afterEach(() => {
+ jest.clearAllMocks();
+ });
+
+ it('handles fileExists functionality', () => {
+ const file = {
+ name: 'description.md',
+ content: 'test',
+ isNew: true,
+ isModified: false,
+ };
+
+ act(() => {
+ store.dispatch(addOrUpdateFile(file));
+ });
+
+ const yesButton = screen.getByRole('button', { name: /Yes/i });
+ act(() => {
+ yesButton.click();
+ });
+
+ expect(setOpenConfirmDeleteDialog).toHaveBeenCalled();
+ });
+
+ it('handles cancel', () => {
+ const cancelButton = screen.getByRole('button', { name: /Cancel/i });
+
+ act(() => {
+ cancelButton.click();
+ });
+
+ expect(setOpenConfirmDeleteDialog).toHaveBeenCalled();
+ });
+});
diff --git a/client/test/preview/integration/route/digitaltwins/create/CreateDTDialog.test.tsx b/client/test/preview/integration/route/digitaltwins/create/CreateDTDialog.test.tsx
new file mode 100644
index 000000000..b692143a0
--- /dev/null
+++ b/client/test/preview/integration/route/digitaltwins/create/CreateDTDialog.test.tsx
@@ -0,0 +1,118 @@
+import * as React from 'react';
+import CreateDTDialog from 'preview/route/digitaltwins/create/CreateDTDialog';
+import { act, render, screen } from '@testing-library/react';
+import { Provider } from 'react-redux';
+import {
+ combineReducers,
+ configureStore,
+ getDefaultMiddleware,
+} from '@reduxjs/toolkit';
+import fileSlice from 'preview/store/file.slice';
+import { validateFiles } from 'preview/util/fileUtils';
+import { initDigitalTwin } from 'preview/util/init';
+
+jest.mock('preview/util/fileUtils', () => ({
+ validateFiles: jest.fn(),
+ addDefaultFiles: jest.fn(),
+}));
+jest.mock('preview/util/init', () => ({
+ initDigitalTwin: jest.fn(),
+}));
+
+const store = configureStore({
+ reducer: combineReducers({
+ files: fileSlice,
+ }),
+ middleware: getDefaultMiddleware({
+ serializableCheck: false,
+ }),
+});
+
+describe('CreateDTDialog - handleConfirm function', () => {
+ const newDigitalTwinName = 'newDTName';
+ const errorMessage = '';
+ const setOpenCreateDTDialog = jest.fn();
+ const setNewDigitalTwinName = jest.fn();
+ const setErrorMessage = jest.fn();
+ const setFileName = jest.fn();
+ const setFileContent = jest.fn();
+ const setFileType = jest.fn();
+
+ beforeEach(() => {
+ act(() => {
+ render(
+
+
+ ,
+ );
+ });
+ });
+
+ afterEach(() => {
+ jest.clearAllMocks();
+ });
+
+ it('does not proceed if file validation fails', async () => {
+ (validateFiles as jest.Mock).mockReturnValue(true);
+
+ const confirmButton = screen.getByRole('button', { name: /Confirm/i });
+ await act(async () => {
+ confirmButton.click();
+ });
+
+ expect(validateFiles).toHaveBeenCalled();
+ expect(initDigitalTwin).not.toHaveBeenCalled();
+ });
+
+ it('handles error if digitalTwin.create returns an error', async () => {
+ (validateFiles as jest.Mock).mockReturnValue(false);
+ const mockDigitalTwin = {
+ create: jest.fn().mockResolvedValue('Error: creation failed'),
+ };
+ (initDigitalTwin as jest.Mock).mockResolvedValue(mockDigitalTwin);
+
+ const confirmButton = screen.getByRole('button', { name: /Confirm/i });
+ await act(async () => {
+ confirmButton.click();
+ });
+
+ expect(initDigitalTwin).toHaveBeenCalledWith(newDigitalTwinName);
+ expect(mockDigitalTwin.create).toHaveBeenCalled();
+ });
+
+ it('handles success if digitalTwin.create is successful', async () => {
+ (validateFiles as jest.Mock).mockReturnValue(false);
+ const mockDigitalTwin = { create: jest.fn().mockResolvedValue('Success') };
+ (initDigitalTwin as jest.Mock).mockResolvedValue(mockDigitalTwin);
+
+ const confirmButton = screen.getByRole('button', { name: /Confirm/i });
+ await act(async () => {
+ confirmButton.click();
+ });
+
+ expect(initDigitalTwin).toHaveBeenCalledWith(newDigitalTwinName);
+ expect(mockDigitalTwin.create).toHaveBeenCalled();
+ });
+
+ it('resets dialog after clicking cancel', async () => {
+ const cancelButton = screen.getByRole('button', { name: /Cancel/i });
+ await act(async () => {
+ cancelButton.click();
+ });
+
+ expect(setOpenCreateDTDialog).toHaveBeenCalled();
+ expect(setFileName).toHaveBeenCalledWith('');
+ expect(setFileContent).toHaveBeenCalledWith('');
+ expect(setFileType).toHaveBeenCalledWith('');
+ });
+});
diff --git a/client/test/preview/integration/route/digitaltwins/create/CreatePage.test.tsx b/client/test/preview/integration/route/digitaltwins/create/CreatePage.test.tsx
new file mode 100644
index 000000000..3ad183e3f
--- /dev/null
+++ b/client/test/preview/integration/route/digitaltwins/create/CreatePage.test.tsx
@@ -0,0 +1,99 @@
+import * as React from 'react';
+import CreatePage from 'preview/route/digitaltwins/create/CreatePage';
+import {
+ act,
+ fireEvent,
+ render,
+ screen,
+ waitFor,
+} from '@testing-library/react';
+import { Provider } from 'react-redux';
+import {
+ combineReducers,
+ configureStore,
+ getDefaultMiddleware,
+} from '@reduxjs/toolkit';
+import digitalTwinReducer from 'preview/store/digitalTwin.slice';
+import snackbarSlice from 'preview/store/snackbar.slice';
+import fileSlice from 'preview/store/file.slice';
+
+const store = configureStore({
+ reducer: combineReducers({
+ digitalTwin: digitalTwinReducer,
+ snackbar: snackbarSlice,
+ files: fileSlice,
+ }),
+ middleware: getDefaultMiddleware({
+ serializableCheck: false,
+ }),
+});
+
+describe('CreatePage', () => {
+ const setNewDigitalTwinName = jest.fn();
+
+ beforeEach(() => {
+ act(() => {
+ render(
+
+
+ ,
+ );
+ });
+ });
+
+ afterEach(() => {
+ jest.clearAllMocks();
+ });
+
+ /*
+ it('renders CreatePage', () => {
+ expect(screen.getByText('Please select a file to edit')).toBeInTheDocument();
+ });
+ */
+
+ it('handles cancel when clicking on cancel button and confirm', () => {
+ act(() => {
+ screen.getByText('Cancel').click();
+ });
+
+ expect(
+ screen.getByText(
+ 'Are you sure you want to delete the inserted files and their content?',
+ ),
+ ).toBeInTheDocument();
+
+ act(() => {
+ screen.getByText('Yes').click();
+ });
+
+ expect(setNewDigitalTwinName).toHaveBeenCalled();
+ });
+
+ it('opens confirm dialog when clicking on save button', () => {
+ act(() => {
+ screen.getByText('Save').click();
+ });
+
+ expect(
+ screen.getByText(/Are you sure you want to create/i),
+ ).toBeInTheDocument();
+ });
+
+ it('changes the digital twin name', () => {
+ const textField = screen.getByRole('textbox');
+
+ act(() => {
+ fireEvent.change(textField, {
+ target: { value: 'modifiedDTName' },
+ });
+ });
+
+ waitFor(() => {
+ expect(textField).toHaveValue('modifiedDTName');
+ });
+ expect(setNewDigitalTwinName).toHaveBeenCalled();
+ });
+});
diff --git a/client/test/preview/integration/route/digitaltwins/create/DeleteFileDialog.test.tsx b/client/test/preview/integration/route/digitaltwins/create/DeleteFileDialog.test.tsx
new file mode 100644
index 000000000..8a3b9c812
--- /dev/null
+++ b/client/test/preview/integration/route/digitaltwins/create/DeleteFileDialog.test.tsx
@@ -0,0 +1,65 @@
+import * as React from 'react';
+import DeleteFileDialog from 'preview/route/digitaltwins/create/DeleteFileDialog';
+import { render, screen } from '@testing-library/react';
+import { Provider } from 'react-redux';
+import {
+ combineReducers,
+ configureStore,
+ getDefaultMiddleware,
+} from '@reduxjs/toolkit';
+import fileSlice from 'preview/store/file.slice';
+import { act } from 'react';
+
+const store = configureStore({
+ reducer: combineReducers({
+ files: fileSlice,
+ }),
+ middleware: getDefaultMiddleware({
+ serializableCheck: false,
+ }),
+});
+
+describe('DeleteFileDialog', () => {
+ const setOpenDeleteFileDialog = jest.fn();
+ const setFileName = jest.fn();
+ const setFileContent = jest.fn();
+
+ beforeEach(() => {
+ act(() => {
+ render(
+
+
+ ,
+ );
+ });
+ });
+
+ afterEach(() => {
+ jest.clearAllMocks();
+ });
+
+ it('handles click on yes button', () => {
+ const yesButton = screen.getByRole('button', { name: /Yes/i });
+ act(() => {
+ yesButton.click();
+ });
+
+ expect(setFileName).toHaveBeenCalled();
+ expect(setFileContent).toHaveBeenCalled();
+ });
+
+ it('handles click on no button', () => {
+ const noButton = screen.getByRole('button', { name: /No/i });
+ act(() => {
+ noButton.click();
+ });
+
+ expect(setOpenDeleteFileDialog).toHaveBeenCalled();
+ });
+});
diff --git a/client/test/preview/integration/route/digitaltwins/create/FileActionButtons.test.tsx b/client/test/preview/integration/route/digitaltwins/create/FileActionButtons.test.tsx
new file mode 100644
index 000000000..27bc2e8d9
--- /dev/null
+++ b/client/test/preview/integration/route/digitaltwins/create/FileActionButtons.test.tsx
@@ -0,0 +1,45 @@
+import { render, screen } from '@testing-library/react';
+import FileActionButtons from 'preview/route/digitaltwins/create/FileActionButtons';
+import * as React from 'react';
+import { act } from 'react';
+
+describe('FileActionButtons', () => {
+ const setOpenDeleteFileDialog = jest.fn();
+ const setOpenChangeFileNameDialog = jest.fn();
+
+ beforeEach(() => {
+ act(() => {
+ render(
+ ,
+ );
+ });
+ });
+
+ afterEach(() => {
+ jest.clearAllMocks();
+ });
+
+ it('handles click on delete button', () => {
+ const deleteButton = screen.getByRole('button', { name: /Delete/i });
+ act(() => {
+ deleteButton.click();
+ });
+
+ expect(setOpenDeleteFileDialog).toHaveBeenCalled();
+ });
+
+ it('handles click on change file name button', () => {
+ const changeFileNameButton = screen.getByRole('button', {
+ name: /Change file name/i,
+ });
+ act(() => {
+ changeFileNameButton.click();
+ });
+
+ expect(setOpenChangeFileNameDialog).toHaveBeenCalled();
+ });
+});
diff --git a/client/test/preview/integration/route/digitaltwins/editor/Sidebar.test.tsx b/client/test/preview/integration/route/digitaltwins/editor/Sidebar.test.tsx
index ee93add0a..8b983926d 100644
--- a/client/test/preview/integration/route/digitaltwins/editor/Sidebar.test.tsx
+++ b/client/test/preview/integration/route/digitaltwins/editor/Sidebar.test.tsx
@@ -20,6 +20,7 @@ import { Provider } from 'react-redux';
import * as React from 'react';
import { mockGitlabInstance } from 'test/preview/__mocks__/global_mocks';
import DigitalTwin from 'preview/util/digitalTwin';
+import * as SidebarFunctions from 'preview/route/digitaltwins/editor/sidebarFunctions';
describe('Sidebar', () => {
const setFileNameMock = jest.fn();
@@ -119,7 +120,13 @@ describe('Sidebar', () => {
setupDigitalTwin('Asset 1');
store.dispatch(setDigitalTwin({ assetName: 'Asset 1', digitalTwin }));
+ });
+
+ afterEach(() => {
+ jest.clearAllMocks();
+ });
+ it('calls handleFileClick when a file type is clicked', async () => {
await act(async () => {
render(
@@ -133,13 +140,87 @@ describe('Sidebar', () => {
,
);
});
+
+ await performFileTests();
});
- afterEach(() => {
- jest.clearAllMocks();
+ it('calls handle addFileCkick when add file is clicked', async () => {
+ const handleAddFileClick = jest.spyOn(
+ SidebarFunctions,
+ 'handleAddFileClick',
+ );
+
+ await act(async () => {
+ render(
+
+
+ ,
+ );
+ });
+
+ const addFile = screen.getByText('Add new file');
+ await act(async () => {
+ fireEvent.click(addFile);
+ });
+
+ await waitFor(() => {
+ expect(handleAddFileClick).toHaveBeenCalled();
+ });
});
- it('calls handleFileClick when a file type is clicked', async () => {
- await performFileTests();
+ it('should open the sidebar dialog when a new file is added', async () => {
+ await act(async () => {
+ render(
+
+
+ ,
+ );
+ });
+
+ const addFile = screen.getByText('Add new file');
+ act(() => {
+ fireEvent.click(addFile);
+ });
+
+ waitFor(() => {
+ expect(screen.getByText('Enter the file name')).toBeInTheDocument();
+ });
+ });
+
+ it('renders file section when no digital twin is selected', async () => {
+ await act(async () => {
+ render(
+
+
+ ,
+ );
+ });
+
+ const lifecycle = screen.getByText('Lifecycle');
+ act(() => {
+ fireEvent.click(lifecycle);
+ });
+
+ waitFor(() => {
+ expect(screen.getByText('Asset 1')).toBeInTheDocument();
+ });
});
});
diff --git a/client/test/preview/integration/route/digitaltwins/editor/SidebarDialog.test.tsx b/client/test/preview/integration/route/digitaltwins/editor/SidebarDialog.test.tsx
new file mode 100644
index 000000000..0788106fc
--- /dev/null
+++ b/client/test/preview/integration/route/digitaltwins/editor/SidebarDialog.test.tsx
@@ -0,0 +1,87 @@
+import {
+ combineReducers,
+ configureStore,
+ getDefaultMiddleware,
+} from '@reduxjs/toolkit';
+import { fireEvent, render, screen, waitFor } from '@testing-library/react';
+import SidebarDialog from 'preview/route/digitaltwins/editor/SidebarDialog';
+import fileSlice from 'preview/store/file.slice';
+import * as React from 'react';
+import { act } from 'react';
+import { Provider } from 'react-redux';
+
+const store = configureStore({
+ reducer: combineReducers({
+ files: fileSlice,
+ }),
+ middleware: getDefaultMiddleware({
+ serializableCheck: false,
+ }),
+});
+
+describe('SidebarDialog', () => {
+ const setNewFileName = jest.fn();
+ const setIsFileNameDialogOpen = jest.fn();
+ const setErrorMessage = jest.fn();
+
+ beforeEach(() => {
+ act(() => {
+ render(
+
+
+ ,
+ );
+ });
+ });
+
+ afterEach(() => {
+ jest.clearAllMocks();
+ });
+
+ it('should handle click on cancel button', () => {
+ const cancelButton = screen.getByText('Cancel');
+
+ act(() => {
+ cancelButton.click();
+ });
+
+ expect(setIsFileNameDialogOpen).toHaveBeenCalledTimes(1);
+ expect(setNewFileName).toHaveBeenCalledTimes(1);
+ expect(setErrorMessage).toHaveBeenCalledTimes(1);
+ });
+
+ it('should handle click on add button', () => {
+ const addButton = screen.getByText('Add');
+
+ act(() => {
+ addButton.click();
+ });
+
+ expect(setErrorMessage).toHaveBeenCalledTimes(1);
+ });
+
+ it('should handle change in file name', () => {
+ const textField = screen.getByRole('textbox');
+
+ act(() => {
+ fireEvent.change(textField, {
+ target: { value: 'modifiedFileName' },
+ });
+ });
+
+ waitFor(() => {
+ expect(textField).toHaveValue('modifiedFileName');
+ });
+
+ expect(setNewFileName).toHaveBeenCalledTimes(1);
+ });
+});
diff --git a/client/test/preview/integration/route/digitaltwins/editor/SidebarFunctions.test.tsx b/client/test/preview/integration/route/digitaltwins/editor/SidebarFunctions.test.tsx
new file mode 100644
index 000000000..5bd70e607
--- /dev/null
+++ b/client/test/preview/integration/route/digitaltwins/editor/SidebarFunctions.test.tsx
@@ -0,0 +1,142 @@
+import {
+ handleFileClick,
+ handleFileSubmit,
+} from 'preview/route/digitaltwins/editor/sidebarFunctions';
+import DigitalTwin from 'preview/util/digitalTwin';
+import { FileState, addOrUpdateFile } from 'preview/store/file.slice';
+import { mockGitlabInstance } from 'test/preview/__mocks__/global_mocks';
+import { useDispatch } from 'react-redux';
+
+describe('File Click Handlers', () => {
+ const mockSetFileName = jest.fn();
+ const mockSetFileContent = jest.fn();
+ const mockSetFileType = jest.fn();
+
+ const mockDigitalTwin = new DigitalTwin('Asset 1', mockGitlabInstance);
+
+ afterEach(() => {
+ jest.clearAllMocks();
+ });
+
+ it('calls handleCreateFileClick if tab is "create"', () => {
+ const fileName = 'example.md';
+ const files: FileState[] = [
+ { name: fileName, content: 'content', isNew: true, isModified: false },
+ ];
+
+ handleFileClick(
+ fileName,
+ null,
+ mockSetFileName,
+ mockSetFileContent,
+ mockSetFileType,
+ files,
+ 'create',
+ );
+ expect(mockSetFileName).toHaveBeenCalledWith(fileName);
+ expect(mockSetFileContent).toHaveBeenCalledWith('content');
+ });
+
+ it('calls handleReconfigureFileClick if tab is "reconfigure"', () => {
+ const fileName = 'example.json';
+ const files: FileState[] = [
+ { name: fileName, content: 'content', isNew: false, isModified: true },
+ ];
+
+ handleFileClick(
+ fileName,
+ mockDigitalTwin,
+ mockSetFileName,
+ mockSetFileContent,
+ mockSetFileType,
+ files,
+ 'reconfigure',
+ );
+ expect(mockSetFileName).toHaveBeenCalledWith(fileName);
+ expect(mockSetFileContent).toHaveBeenCalledWith('content');
+ });
+});
+
+jest.mock('react-redux', () => ({
+ useDispatch: jest.fn(),
+}));
+
+describe('handleFileSubmit', () => {
+ const mockSetErrorMessage = jest.fn();
+ const mockSetIsFileNameDialogOpen = jest.fn();
+ const mockSetNewFileName = jest.fn();
+ const dispatch = jest.fn();
+
+ (useDispatch as jest.Mock).mockReturnValue(dispatch);
+
+ afterEach(() => {
+ jest.clearAllMocks();
+ });
+
+ it('dispatches addOrUpdateFile if new file name does not exist', () => {
+ const files: FileState[] = [
+ { name: 'existingFile.md', content: '', isNew: true, isModified: false },
+ ];
+ const newFileName = 'newFile.md';
+
+ handleFileSubmit(
+ files,
+ newFileName,
+ mockSetErrorMessage,
+ dispatch,
+ mockSetIsFileNameDialogOpen,
+ mockSetNewFileName,
+ );
+ expect(dispatch).toHaveBeenCalledWith(
+ addOrUpdateFile({
+ name: newFileName,
+ content: '',
+ isNew: true,
+ isModified: false,
+ type: 'description',
+ }),
+ );
+ expect(mockSetIsFileNameDialogOpen).toHaveBeenCalledWith(false);
+ expect(mockSetNewFileName).toHaveBeenCalledWith('');
+ });
+
+ it('sets error message if file name already exists', () => {
+ const files: FileState[] = [
+ { name: 'existingFile.md', content: '', isNew: true, isModified: false },
+ ];
+ const newFileName = 'existingFile.md';
+
+ handleFileSubmit(
+ files,
+ newFileName,
+ mockSetErrorMessage,
+ dispatch,
+ mockSetIsFileNameDialogOpen,
+ mockSetNewFileName,
+ );
+ expect(mockSetErrorMessage).toHaveBeenCalledWith(
+ 'A file with this name already exists.',
+ );
+ expect(dispatch).not.toHaveBeenCalled();
+ });
+
+ it('sets error message if file name is empty', () => {
+ const files: FileState[] = [
+ { name: 'existingFile.md', content: '', isNew: true, isModified: false },
+ ];
+ const newFileName = '';
+
+ handleFileSubmit(
+ files,
+ newFileName,
+ mockSetErrorMessage,
+ dispatch,
+ mockSetIsFileNameDialogOpen,
+ mockSetNewFileName,
+ );
+ expect(mockSetErrorMessage).toHaveBeenCalledWith(
+ "File name can't be empty.",
+ );
+ expect(dispatch).not.toHaveBeenCalled();
+ });
+});
diff --git a/client/test/preview/integration/route/digitaltwins/manage/ConfigDialog.test.tsx b/client/test/preview/integration/route/digitaltwins/manage/ConfigDialog.test.tsx
index 1c31c8f7f..9db5258ed 100644
--- a/client/test/preview/integration/route/digitaltwins/manage/ConfigDialog.test.tsx
+++ b/client/test/preview/integration/route/digitaltwins/manage/ConfigDialog.test.tsx
@@ -7,7 +7,10 @@ import { mockGitlabInstance } from 'test/preview/__mocks__/global_mocks';
import { showSnackbar } from 'preview/store/snackbar.slice';
import * as ReconfigureDialog from 'preview/route/digitaltwins/manage/ReconfigureDialog';
import FileHandler from 'preview/util/fileHandler';
-import { addOrUpdateFile } from 'preview/store/file.slice';
+import {
+ addOrUpdateFile,
+ removeAllModifiedFiles,
+} from 'preview/store/file.slice';
import setupStore from './utils';
jest.useFakeTimers();
@@ -18,10 +21,13 @@ jest.mock('preview/util/init', () => ({
describe('ReconfigureDialog', () => {
let storeConfig: ReturnType;
+ let dispatchSpy: jest.SpyInstance;
beforeEach(() => {
storeConfig = setupStore();
+ dispatchSpy = jest.spyOn(storeConfig, 'dispatch');
+
React.act(() => {
render(
@@ -81,6 +87,8 @@ describe('ReconfigureDialog', () => {
await waitFor(() => {
expect(screen.queryByText('Editor')).toBeNull();
});
+
+ expect(dispatchSpy).toHaveBeenCalledWith(removeAllModifiedFiles());
});
it('updates the description when description.md is modified', async () => {