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
36 changes: 35 additions & 1 deletion frontend/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,15 @@ module.exports = {
extraFileExtensions: ['.json'],
tsconfigRootDir: './',
},
plugins: ['react', 'react-hooks', '@typescript-eslint', 'graphql', 'eslint-plugin-tsdoc'],
plugins: [
'react',
'react-hooks',
'@typescript-eslint',
'graphql',
'eslint-plugin-tsdoc',
'testing-library',
'jest-dom',
],
rules: {
camelcase: [
'error',
Expand Down Expand Up @@ -129,4 +137,30 @@ module.exports = {
VoidFunction: 'readonly',
RequestInit: 'readonly',
},
overrides: [
{
files: ['**/__tests__/**/*.[jt]s?(x)', '**/?(*.)+(spec|test).[jt]s?(x)'],
plugins: ['testing-library', 'jest-dom'],
extends: ['plugin:testing-library/react', 'plugin:jest-dom/recommended'],
rules: {
// NOTE: Using eslint-plugin-testing-library v3.x (compatible with ESLint 6)
// Some newer rules are not available in this version:
// - prefer-user-event (added in v5.x) - Use code review to enforce userEvent over fireEvent
// - no-node-access (added in v5.x) - Use code review to enforce no container usage
// - prefer-query-by-disappearance - Not available in v3.x
//
// Additional limitations (no ESLint rule exists):
// - No rule to enforce .toBeVisible() over .toBeInTheDocument() for user-facing elements
// See SKILL.md Rule 8 - enforce through code review
//
// Available rules being enforced:
'testing-library/await-fire-event': 'off', // Disabled: fireEvent is sync, userEvent not yet supported (SKILL.md Rule 14)
'testing-library/prefer-find-by': 'error', // Similar to prefer-query-by-disappearance
'testing-library/no-await-sync-query': 'error',
'testing-library/no-wait-for-empty-callback': 'error',
'testing-library/prefer-screen-queries': 'error',
'testing-library/prefer-presence-queries': 'error',
},
},
],
};
2 changes: 2 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,8 @@
"cypress-jest-adapter": "^0.1.1",
"cypress-multi-reporters": "^2.0.5",
"esbuild-loader": "^4.4.2",
"eslint-plugin-jest-dom": "^4.0.3",
"eslint-plugin-testing-library": "^3.10.0",
"file-loader": "6.2.0",
"find-up": "4.x",
"fork-ts-checker-webpack-plugin": "9.1.0",
Expand Down
26 changes: 26 additions & 0 deletions frontend/packages/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,30 @@
module.exports = {
root: true,
extends: ['plugin:console/react-typescript-prettier'],
plugins: ['testing-library', 'jest-dom'],
overrides: [
{
files: ['**/__tests__/**/*.[jt]s?(x)', '**/?(*.)+(spec|test).[jt]s?(x)'],
extends: ['plugin:testing-library/react', 'plugin:jest-dom/recommended'],
rules: {
// NOTE: Using eslint-plugin-testing-library v3.x (compatible with ESLint 6)
// Some newer rules are not available in this version:
// - prefer-user-event (added in v5.x) - Use code review to enforce userEvent over fireEvent
// - no-node-access (added in v5.x) - Use code review to enforce no container usage
// - prefer-query-by-disappearance - Not available in v3.x
//
// Additional limitations (no ESLint rule exists):
// - No rule to enforce .toBeVisible() over .toBeInTheDocument() for user-facing elements
// See SKILL.md Rule 8 - enforce through code review
//
// Available rules being enforced:
'testing-library/await-fire-event': 'off', // Disabled: fireEvent is sync, userEvent not yet supported (SKILL.md Rule 14)
'testing-library/prefer-find-by': 'error', // Similar to prefer-query-by-disappearance
'testing-library/no-await-sync-query': 'error',
'testing-library/no-wait-for-empty-callback': 'error',
'testing-library/prefer-screen-queries': 'error',
'testing-library/prefer-presence-queries': 'error',
},
},
],
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { render, fireEvent } from '@testing-library/react';
import { render, fireEvent, screen } from '@testing-library/react';
import { ReplaceCodeModal } from '../replace-code-modal';

jest.mock('react-i18next', () => ({
Expand All @@ -18,46 +18,48 @@ describe('ReplaceCodeModal', () => {
render(<ReplaceCodeModal handleCodeReplace={handleCodeReplaceMock} />);

it('should render the modal with correct title and message', () => {
const { getByText } = renderComponent();
renderComponent();

expect(getByText('Replace current content?')).toBeTruthy();
expect(getByText('Existing content will be replaced. Do you want to continue?')).toBeTruthy();
expect(screen.getByText('Replace current content?')).toBeInTheDocument();
expect(
screen.getByText('Existing content will be replaced. Do you want to continue?'),
).toBeInTheDocument();
});

it('should render buttons with correct text', () => {
const { getByText } = renderComponent();
renderComponent();

expect(getByText('Yes')).toBeTruthy();
expect(getByText('No')).toBeTruthy();
expect(getByText('Keep both')).toBeTruthy();
expect(screen.getByText('Yes')).toBeInTheDocument();
expect(screen.getByText('No')).toBeInTheDocument();
expect(screen.getByText('Keep both')).toBeInTheDocument();
});

it('should call handleCodeReplace when "Yes" button is clicked', () => {
const { getByText } = renderComponent();
renderComponent();

fireEvent.click(getByText('Yes'));
fireEvent.click(screen.getByText('Yes'));
expect(handleCodeReplaceMock).toHaveBeenCalledTimes(1);
});

it('should call handleCodeReplace when "No" button is clicked', () => {
const { getByText } = renderComponent();
renderComponent();

fireEvent.click(getByText('No'));
fireEvent.click(screen.getByText('No'));
expect(handleCodeReplaceMock).toHaveBeenCalledTimes(1);
});

it('should call handleCodeReplace when "Keep both" button is clicked', () => {
const { getByText } = renderComponent();
renderComponent();

fireEvent.click(getByText('Keep both'));
fireEvent.click(screen.getByText('Keep both'));
expect(handleCodeReplaceMock).toHaveBeenCalledTimes(1);
});

it('should call handleCodeReplace when close button (X) is clicked', () => {
const { getByLabelText } = renderComponent();
renderComponent();

const closeButton = getByLabelText('Close');
expect(closeButton).toBeTruthy();
const closeButton = screen.getByLabelText('Close');
expect(closeButton).toBeInTheDocument();

fireEvent.click(closeButton);
expect(handleCodeReplaceMock).toHaveBeenCalledTimes(1);
Expand Down
Loading