Skip to content

Commit

Permalink
Add unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
vanessa committed Sep 10, 2024
1 parent 4b54723 commit e3bce4c
Show file tree
Hide file tree
Showing 12 changed files with 1,035 additions and 147 deletions.
2 changes: 1 addition & 1 deletion client/src/components/asset/StartStopButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ function StartStopButton({
return (
<>
{digitalTwin?.pipelineLoading ? (
<CircularProgress size={22} style={{ marginRight: '8px' }} />
<CircularProgress size={22} style={{ marginRight: '8px' }} data-testid="circular-progress"/>
) : null}{' '}
<Button
variant="contained"
Expand Down
58 changes: 58 additions & 0 deletions client/test/unit/components/asset/AssetBoard.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import * as React from 'react';
import { render, screen } from '@testing-library/react';
import AssetBoard from 'components/asset/AssetBoard';
import { Asset } from 'components/asset/Asset';
import { GitlabInstance } from 'util/gitlab';
import '@testing-library/jest-dom';
import store from 'store/store';
import { Provider } from 'react-redux';

jest.unmock('components/asset/AssetBoard');

jest.mock('react-redux', () => ({
...jest.requireActual('react-redux'),
}));

jest.mock('util/envUtil', () => ({
...jest.requireActual('util/envUtil'),
getAuthority: jest.fn(() => 'https://example.com'),
}));

jest.mock('')

const assetsMock: Asset[] = [
{ name: 'Asset1', path: 'path1', description: 'Description1' },
{ name: 'Asset2', path: 'path2', description: 'Description2' },
];

jest.mock('util/gitlab', () => ({
GitlabInstance: jest.fn().mockImplementation(() => ({
init: jest.fn(),
})),
}));

const mockGitlabInstance = new GitlabInstance('username', 'authority', 'access_token');

describe('AssetBoard', () => {
it('renders AssetCard components for each asset', () => {
render(
<Provider store={store}>
<AssetBoard subfolders={assetsMock} gitlabInstance={mockGitlabInstance} error={null} />);
</Provider>
);
const cards = screen.getAllByText(/Description/);
expect(cards).toHaveLength(assetsMock.length);
});

it('displays an error message when error prop is provided', () => {
const errorMessage = 'Something went wrong!';
render(<AssetBoard subfolders={[]} gitlabInstance={mockGitlabInstance} error={errorMessage} />);
expect(screen.getByText(errorMessage)).toBeInTheDocument();
});

it('renders correctly with no assets', () => {
render(<AssetBoard subfolders={[]} gitlabInstance={mockGitlabInstance} error={null} />);
const cards = screen.queryAllByText(/Description/);
expect(cards).toHaveLength(0);
});
});
53 changes: 53 additions & 0 deletions client/test/unit/components/asset/AssetCard.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import * as React from 'react';
import { render, screen } from '@testing-library/react';
import AssetCardExecute from 'components/asset/AssetCard';
import { Provider } from 'react-redux';
import store from 'store/store';
import '@testing-library/jest-dom';

if (!AbortSignal.timeout) {
AbortSignal.timeout = (ms) => {
const controller = new AbortController();
setTimeout(() => controller.abort(new DOMException('TimeoutError')), ms);
return controller.signal;
};
}

jest.deepUnmock('components/asset/AssetCard');

jest.mock('react-redux', () => ({
...jest.requireActual('react-redux'),
}));

jest.mock('react-oidc-context', () => ({
...jest.requireActual('react-oidc-context'),
useAuth: jest.fn(),
}));

jest.mock('util/envUtil', () => ({
...jest.requireActual('util/envUtil'),
getAuthority: jest.fn(() => 'https://example.com'),
}));

jest.mock('')


describe('AssetCard', () => {
const assetMock = {
name: 'TestName',
path: 'testPath',
description: 'testDescription',
};

beforeEach(() => {
render(
<Provider store={store}>
<AssetCardExecute asset={assetMock} />);
</Provider>
);
});

it('renders asset name correctly', () => {
expect(screen.getByText(assetMock.name)).toBeInTheDocument();
});
});
39 changes: 39 additions & 0 deletions client/test/unit/components/asset/LogButton.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import * as React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import LogButton from 'components/asset/LogButton';

const mockSetShowLog = jest.fn();

describe('LogButton', () => {
afterEach(() => {
jest.clearAllMocks();
});

it('calls setShowLog with the correct value when clicked', () => {
render(
<LogButton setShowLog={mockSetShowLog} logButtonDisabled={false} />
);

fireEvent.click(screen.getByText('Log'));

expect(mockSetShowLog).toHaveBeenCalledTimes(1);
expect(mockSetShowLog).toHaveBeenCalledWith(expect.any(Function));

const toggleFunction = mockSetShowLog.mock.calls[0][0];
expect(toggleFunction(true)).toBe(false);
});

it('disables button when logButtonDisabled is true', () => {
render(<LogButton setShowLog={mockSetShowLog} logButtonDisabled={true} />);

const button = screen.getByText('Log') as HTMLButtonElement;
expect(button.disabled).toBe(true);
});

it('enables button when logButtonDisabled is false', () => {
render(<LogButton setShowLog={mockSetShowLog} logButtonDisabled={false} />);

const button = screen.getByText('Log') as HTMLButtonElement;
expect(button.disabled).toBe(false);
});
});
172 changes: 172 additions & 0 deletions client/test/unit/components/asset/StartStopButton.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
import * as React from 'react';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import StartStopButton from 'components/asset/StartStopButton';
import { handleButtonClick } from 'route/digitaltwins/ExecutionFunctions';
import { useSelector, useDispatch } from 'react-redux';
import { RootState } from 'store/store';
import '@testing-library/jest-dom';

jest.mock('route/digitaltwins/ExecutionFunctions', () => ({
handleButtonClick: jest.fn(),
}));

jest.mock('react-redux', () => ({
useSelector: jest.fn(),
useDispatch: jest.fn(),
}));

const mockSetSnackbarOpen = jest.fn();
const mockSetSnackbarMessage = jest.fn();
const mockSetSnackbarSeverity = jest.fn();
const mockSetLogButtonDisabled = jest.fn();
const mockDispatch = jest.fn();
const mockHandleButtonClick = handleButtonClick as jest.MockedFunction<typeof handleButtonClick>;

describe('StartStopButton', () => {
beforeEach(() => {
(useSelector as jest.Mock).mockImplementation((selector) =>
selector({
digitalTwin: {
'testAsset': { DTName: 'Test Digital Twin', pipelineLoading: false },
},
} as unknown as RootState)
);
(useDispatch as jest.Mock).mockReturnValue(mockDispatch);
});

afterEach(() => {
jest.clearAllMocks();
});

test('renders with start button text initially', () => {
render(
<StartStopButton
assetName="testAsset"
setSnackbarOpen={mockSetSnackbarOpen}
setSnackbarMessage={mockSetSnackbarMessage}
setSnackbarSeverity={mockSetSnackbarSeverity}
setLogButtonDisabled={mockSetLogButtonDisabled}
/>
);

expect(screen.getByText('Start')).toBeInTheDocument();
});

test('renders circular progress when pipelineLoading is true', async () => {
(useSelector as jest.Mock).mockImplementationOnce((selector) =>
selector({
digitalTwin: {
'testAsset': { DTName: 'Test Digital Twin', pipelineLoading: true },
},
} as unknown as RootState)
);

render(
<StartStopButton
assetName="testAsset"
setSnackbarOpen={mockSetSnackbarOpen}
setSnackbarMessage={mockSetSnackbarMessage}
setSnackbarSeverity={mockSetSnackbarSeverity}
setLogButtonDisabled={mockSetLogButtonDisabled}
/>
);

expect(screen.getByTestId('circular-progress')).toBeInTheDocument();

expect(screen.getByText('Start')).toBeInTheDocument();
});

test('does not render circular progress when pipelineLoading is false', () => {
render(
<StartStopButton
assetName="testAsset"
setSnackbarOpen={mockSetSnackbarOpen}
setSnackbarMessage={mockSetSnackbarMessage}
setSnackbarSeverity={mockSetSnackbarSeverity}
setLogButtonDisabled={mockSetLogButtonDisabled}
/>
);

expect(screen.queryByTestId('circular-progress')).not.toBeInTheDocument();

expect(screen.getByText('Start')).toBeInTheDocument();
});

test('calls handleButtonClick with correct arguments when button is clicked', () => {
render(
<StartStopButton
assetName="testAsset"
setSnackbarOpen={mockSetSnackbarOpen}
setSnackbarMessage={mockSetSnackbarMessage}
setSnackbarSeverity={mockSetSnackbarSeverity}
setLogButtonDisabled={mockSetLogButtonDisabled}
/>
);

fireEvent.click(screen.getByText('Start'));

expect(mockHandleButtonClick).toHaveBeenCalledTimes(1);
expect(mockHandleButtonClick).toHaveBeenCalledWith(
'Start',
expect.any(Function),
{ DTName: 'Test Digital Twin', pipelineLoading: false },
mockSetSnackbarMessage,
mockSetSnackbarSeverity,
mockSetSnackbarOpen,
mockSetLogButtonDisabled,
mockDispatch,
);
});

test('updates snackbar message and severity on execution status change', async () => {
mockHandleButtonClick.mockImplementationOnce((buttonText, setButtonText, digitalTwin, setSnackbarMessage, setSnackbarSeverity, setSnackbarOpen, setLogButtonDisabled, dispatch) => {
setSnackbarMessage('Execution started successfully');
setSnackbarSeverity('success');
setSnackbarOpen(true);
});

render(
<StartStopButton
assetName="testAsset"
setSnackbarOpen={mockSetSnackbarOpen}
setSnackbarMessage={mockSetSnackbarMessage}
setSnackbarSeverity={mockSetSnackbarSeverity}
setLogButtonDisabled={mockSetLogButtonDisabled}
/>
);

fireEvent.click(screen.getByText('Start'));

await waitFor(() => {
expect(mockSetSnackbarMessage).toHaveBeenCalledWith('Execution started successfully');
expect(mockSetSnackbarSeverity).toHaveBeenCalledWith('success');
expect(mockSetSnackbarOpen).toHaveBeenCalledWith(true);
});
});

test('updates snackbar message and severity on execution status change to error', async () => {
mockHandleButtonClick.mockImplementationOnce((buttonText, setButtonText, digitalTwin, setSnackbarMessage, setSnackbarSeverity, setSnackbarOpen, setLogButtonDisabled, dispatch) => {
setSnackbarMessage('Execution failed');
setSnackbarSeverity('error');
setSnackbarOpen(true);
});

render(
<StartStopButton
assetName="testAsset"
setSnackbarOpen={mockSetSnackbarOpen}
setSnackbarMessage={mockSetSnackbarMessage}
setSnackbarSeverity={mockSetSnackbarSeverity}
setLogButtonDisabled={mockSetLogButtonDisabled}
/>
);

fireEvent.click(screen.getByText('Start'));

await waitFor(() => {
expect(mockSetSnackbarMessage).toHaveBeenCalledWith('Execution failed');
expect(mockSetSnackbarSeverity).toHaveBeenCalledWith('error');
expect(mockSetSnackbarOpen).toHaveBeenCalledWith(true);
});
});
});
Loading

0 comments on commit e3bce4c

Please sign in to comment.