Skip to content

Commit

Permalink
intial setup
Browse files Browse the repository at this point in the history
  • Loading branch information
nitinawari committed Jan 20, 2025
1 parent 6cca7a9 commit 3e809d0
Show file tree
Hide file tree
Showing 7 changed files with 304 additions and 9 deletions.
16 changes: 16 additions & 0 deletions .github/workflows/ci-cd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,21 @@ jobs:
working-directory: frontend
run: npm run lint:check

- name: Run accessibility tests
run: |
npm run test -- -t "accessibility"
- name: Generate accessibility report
run: |
npm run test:a11y
continue-on-error: true # Don't fail the build, but record issues

- name: Upload accessibility report
uses: actions/upload-artifact@v2
with:
name: accessibility-report
path: accessibility-report.json

- name: Check for uncommitted changes
run: |
git diff --exit-code || (echo 'Unstaged changes detected. \
Expand Down Expand Up @@ -174,6 +189,7 @@ jobs:
- name: Run frontend tests
run: |
docker run --env-file frontend/.env.example ${{ env.DOCKERHUB_USERNAME }}/owasp-nest-test-frontend:latest npm run test

build-docker-staging-images:
name: Build Docker Staging Images
Expand Down
16 changes: 15 additions & 1 deletion frontend/__tests__/src/pages/ChapterDetails.test.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { screen, waitFor } from '@testing-library/react'

import { fetchAlgoliaData } from 'api/fetchAlgoliaData'
import { axe, toHaveNoViolations } from 'jest-axe'
import { ChapterDetailsPage } from 'pages'
import { render } from 'wrappers/testUtil'

import { mockChapterData } from '@tests/data/mockChapterData'

expect.extend(toHaveNoViolations)

jest.mock('api/fetchAlgoliaData', () => ({
fetchAlgoliaData: jest.fn(),
}))
Expand All @@ -26,6 +28,18 @@ describe('ChapterDetailsPage Component', () => {
jest.clearAllMocks()
})

test('should not have any accessibility violations', async () => {
const { container } = render(<ChapterDetailsPage />)

// Wait for content to load
await waitFor(() => {
expect(screen.queryByText('Loading indicator')).not.toBeInTheDocument()
})

const results = await axe(container)
expect(results).toHaveNoViolations()
})

test('renders loading spinner initially', async () => {
render(<ChapterDetailsPage />)
const loadingSpinner = screen.getAllByAltText('Loading indicator')
Expand Down
15 changes: 15 additions & 0 deletions frontend/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import typescriptParser from '@typescript-eslint/parser'
import prettierConfig from 'eslint-config-prettier'
import importPlugin from 'eslint-plugin-import'
import jest from 'eslint-plugin-jest'
import jsxA11y from 'eslint-plugin-jsx-a11y'
import prettier from 'eslint-plugin-prettier'
import react from 'eslint-plugin-react'
import reactHooks from 'eslint-plugin-react-hooks'
Expand Down Expand Up @@ -41,6 +42,7 @@ export default [
jest,
prettier,
react,
'jsx-a11y': jsxA11y,
},
settings: {
'import/resolver': {
Expand All @@ -59,6 +61,19 @@ export default [
rules: {
...jest.configs.recommended.rules,
...prettierConfig.rules,
'jsx-a11y/alt-text': 'error',
'jsx-a11y/anchor-has-content': 'error',
'jsx-a11y/anchor-is-valid': 'error',
'jsx-a11y/aria-props': 'error',
'jsx-a11y/aria-proptypes': 'error',
'jsx-a11y/aria-unsupported-elements': 'error',
'jsx-a11y/role-has-required-aria-props': 'error',
'jsx-a11y/role-supports-aria-props': 'error',
'jsx-a11y/tabindex-no-positive': 'error',
'jsx-a11y/no-redundant-roles': 'error',
'jsx-a11y/label-has-associated-control': 'error',
'jsx-a11y/no-autofocus': 'warn',
'jsx-a11y/no-noninteractive-tabindex': 'error',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'warn',
Expand Down
25 changes: 25 additions & 0 deletions frontend/jest.setup.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
import '@testing-library/jest-dom'
import { TextEncoder } from 'util'
import dotenv from 'dotenv'
import { toHaveNoViolations } from 'jest-axe'
import React from 'react'

dotenv.config()
expect.extend(toHaveNoViolations)

global.React = React
global.TextEncoder = TextEncoder
global.axe = {
run: async () => ({
violations: [],
}),
configure: () => null,
}

beforeEach(() => {
jest.spyOn(console, 'error').mockImplementation((...args) => {
Expand All @@ -28,4 +36,21 @@ beforeEach(() => {
})
})

expect.extend({
toBeAccessible: async (received) => {
const results = await global.axe.run(received)
return {
pass: results.violations.length === 0,
message: () =>
results.violations.length === 0
? 'Expected element to not be accessible'
: `Expected element to be accessible but found violations:\n${JSON.stringify(
results.violations,
null,
2
)}`,
}
},
})

jest.mock('@algolia/autocomplete-theme-classic', () => ({}))
Loading

0 comments on commit 3e809d0

Please sign in to comment.