Skip to content
Merged
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
36 changes: 36 additions & 0 deletions frontend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,39 @@
docker-compose build frontend
docker-compose up
```

## Guide for Jest Testing

Two kinds of tests are implemented using Jest:

### Rendering Tests

Run rendering tests with the following command:

```bash
npm run test:without-snapshot
```

> **Note:** The output may show yellow lines marking snapshots as obsolete. This can be safely ignored.

### Snapshot Tests

Run snapshot tests with:

```bash
npm run test:snapshot
```

If one of the tests fails, verify whether the component change was intentional. If so, update the snapshot using:

```bash
npm run test:update-snapshot <componentFileName>
```

### Running All Tests

Both test types can be run simultaneously:

```bash
npm run test
```
3 changes: 3 additions & 0 deletions frontend/jest.config.cjs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// Activer le serializer Radix pour tous les tests
process.env.RADIX_SNAPSHOT = '1';

module.exports = {
preset: 'ts-jest',
testEnvironment: 'jsdom',
Expand Down
52 changes: 52 additions & 0 deletions frontend/jest.setup.ts
Original file line number Diff line number Diff line change
@@ -1 +1,53 @@
import '@testing-library/jest-dom';
import { expect } from '@jest/globals';
import type { Plugin } from 'pretty-format';

let isSerializing = false;

const radixSnapshotSerializer: Plugin = {
test(val) {
return (
!isSerializing &&
val &&
typeof val === 'object' &&
'nodeType' in (val as any) &&
((val as any).nodeType === 1 || (val as any).nodeType === 11)
);
},
print(val, serialize) {
const clone = (val as any).cloneNode(true);

if (clone && typeof (clone as any).querySelectorAll === 'function') {
const elements = (clone as any).querySelectorAll(
'[id],[aria-controls],[aria-labelledby]'
);

elements.forEach((element: Element) => {
const id = element.getAttribute('id');
if (id && id.startsWith('radix-:r')) {
element.setAttribute('id', 'radix-:ID:');
}

const ariaControls = element.getAttribute('aria-controls');
if (ariaControls && ariaControls.startsWith('radix-:r')) {
element.setAttribute('aria-controls', 'radix-:ID:');
}

const ariaLabelledby = element.getAttribute('aria-labelledby');
if (ariaLabelledby && ariaLabelledby.startsWith('radix-:r')) {
element.setAttribute('aria-labelledby', 'radix-:ID:');
}
});
}

isSerializing = true;
const result = serialize(clone);
isSerializing = false;
return result;
},
};

// Serializer Radix actif uniquement pour les snapshots (quand RADIX_SNAPSHOT=1)
if (process.env.RADIX_SNAPSHOT) {
expect.addSnapshotSerializer(radixSnapshotSerializer);
}
3 changes: 3 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,9 @@
"dev": "vite",
"build": "tsc && vite build",
"test": "jest",
"test:without-snapshot": "jest --testNamePattern=\"^(?!.*snapshot).*$\"",
"test:snapshot": "jest --testNamePattern='snapshot'",
"test:update-snapshot": " jest -u --testNamePattern='snapshot'",
"coverage": "jest --coverage",
"postinstall": "git config core.hooksPath .githooks",
"lint": "npx prettier --write .",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,41 @@ describe('BottomBar Component', () => {
expect(screen.getByTestId('multiselect-count-tags')).toHaveTextContent('1');
});
});

describe('BottomBar Component using Snapshot', () => {
test('renders correctly without selected props', () => {
const mockNoSelectedProps: BottomBarProps = {
...mockProps,
selectedProjects: [],
selectedStatuses: [],
selectedTags: [],
};
const { asFragment } = render(<BottomBar {...mockNoSelectedProps} />);
expect(asFragment()).toMatchSnapshot('Bottom bar without selected props');
});
test('renders correctly with only one selected props', () => {
const mockOnlyOneSelectedProps: BottomBarProps = {
...mockProps,
selectedProjects: ['Project A'],
selectedStatuses: ['pending'],
selectedTags: ['tag1'],
};

const { asFragment } = render(<BottomBar {...mockOnlyOneSelectedProps} />);
expect(asFragment()).toMatchSnapshot(
'Bottom bar with only one selected props'
);
});
test('renders correctly with several selected props', () => {
const mockSeveralSelectedProps: BottomBarProps = {
...mockProps,
selectedProjects: ['Project A', 'Project B'],
selectedStatuses: ['pending', 'completed'],
selectedTags: ['tag1', 'tag2', 'tag3'],
};
const { asFragment } = render(<BottomBar {...mockSeveralSelectedProps} />);
expect(asFragment()).toMatchSnapshot(
'Bottom bar with several selected props'
);
});
});
Loading
Loading