### Plan
1. **Add Detailed Accessibility Tests for Keyboard Navigation:**
- Test keyboard navigation for form inputs, buttons, and lightbox.
- Ensure interactive elements are focusable and navigable via the keyboard.
2. **Optimize the CI/CD Pipeline:**
- Use caching to speed up dependency installation.
- Parallelize test execution if possible.
### Complete Code
#### JavaScript Unit Tests (using Jest and jest-axe)
Install necessary dependencies:
```sh
npm install --save-dev jest jest-axe
```
Accessibility tests using `jest-axe` and keyboard navigation tests:
```javascript
// __tests__/accessibility.test.js
const { JSDOM } = require('jsdom');
const { axe, toHaveNoViolations } = require('jest-axe');
expect.extend(toHaveNoViolations);
describe('Accessibility Tests', () => {
let dom;
let document;
beforeEach(() => {
dom = new JSDOM(`
Welcome to eBook for Enjoyment
About Us
Our Books

Contact Us
×
`, { url: "http://localhost" });
document = dom.window.document;
});
test('should have no accessibility violations', async () => {
const results = await axe(document);
expect(results).toHaveNoViolations();
});
test('should have appropriate ARIA roles and attributes', () => {
const banner = document.querySelector('[role="banner"]');
const navigation = document.querySelector('[role="navigation"]');
const regions = document.querySelectorAll('[role="region"]');
const form = document.querySelector('[role="form"]');
const liveRegions = document.querySelectorAll('[aria-live="polite"]');
const requiredFields = document.querySelectorAll('[aria-required="true"]');
expect(banner).not.toBeNull();
expect(navigation).not.toBeNull();
expect(regions.length).toBeGreaterThan(0);
expect(form).not.toBeNull();
expect(liveRegions.length).toBeGreaterThan(0);
expect(requiredFields.length).toBeGreaterThan(0);
});
test('buttons should have appropriate ARIA labels', () => {
const buttons = document.querySelectorAll('button');
buttons.forEach(button => {
expect(button.getAttribute('aria-label')).not.toBeNull();
});
});
test('form inputs should have appropriate ARIA attributes', () => {
const inputs = document.querySelectorAll('input, textarea');
inputs.forEach(input => {
expect(input.hasAttribute('aria-required')).toBe(true);
expect(input.getAttribute('aria-required')).toBe('true');
});
});
test('lightbox should have ARIA attributes', () => {
const lightbox = document.getElementById('lightbox');
const closeBtn = document.querySelector('.close');
const lightboxImg = document.getElementById('lightbox-img');
const lightboxCaption = document.getElementById('lightbox-caption');
expect(lightbox.getAttribute('aria-label')).toBe('Image Lightbox');
expect(closeBtn.getAttribute('aria-label')).toBe('Close Lightbox');
expect(lightboxImg.getAttribute('aria-live')).toBe('polite');
expect(lightboxCaption.getAttribute('aria-live')).toBe('polite');
});
test('should allow keyboard navigation for form inputs', () => {
const nameInput = document.getElementById('name');
const emailInput = document.getElementById('email');
const messageTextarea = document.getElementById('message');
const submitButton = document.querySelector('button[type="submit"]');
nameInput.focus();
expect(document.activeElement).toBe(nameInput);
nameInput.dispatchEvent(new dom.window.KeyboardEvent('keydown', { key: 'Tab' }));
expect(document.activeElement).toBe(emailInput);
emailInput.dispatchEvent(new dom.window.KeyboardEvent('keydown', { key: 'Tab' }));
expect(document.activeElement).toBe(messageTextarea);
messageTextarea.dispatchEvent(new dom.window.KeyboardEvent('keydown', { key: 'Tab' }));
expect(document.activeElement).toBe(submitButton);
});
test('should allow keyboard navigation for lightbox', () => {
const img = document.querySelector('.book-item img');
const lightbox = document.getElementById('lightbox');
const closeBtn = document.querySelector('.close');
img.focus();
img.dispatchEvent(new dom.window.KeyboardEvent('keydown', { key: 'Enter' }));
expect(lightbox.style.display).toBe('block');
expect(document.activeElement).toBe(closeBtn);
closeBtn.dispatchEvent(new dom.window.KeyboardEvent('keydown', { key: 'Enter' }));
expect(lightbox.style.display).toBe('none');
expect(document.activeElement).toBe(img);
});
});
```
#### GitHub Actions CI/CD Pipeline with Notifications and Optimizations
Create a GitHub Actions workflow file:
```yaml
# .github/workflows/ci.yml
name: CI
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14, 16]
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Set up Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- name: Cache Node.js modules
uses: actions/cache@v2
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ matrix.node-version }}-${{ hashFiles('package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-${{ matrix.node-version }}-
- name: Install dependencies
run: npm install
- name: Run tests
run: npm test
notify:
needs: test
runs-on: ubuntu-latest
if: failure()
steps:
- name: Send email notification
uses: dawidd6/action-send-mail@v3
with:
server_address: smtp.example.com
server_port: 587
username: ${{ secrets.EMAIL_USERNAME }}
password: ${{ secrets.EMAIL_PASSWORD }}
subject: GitHub Actions Job Failed
to: you@example.com
from: github-actions@example.com
body: The CI/CD pipeline failed. Please check the logs for more details.
```
Make sure to add `EMAIL_USERNAME` and `EMAIL_PASSWORD` to your GitHub secrets.
### Running Tests
To run the tests, ensure you have Jest and jest-axe set up in your project:
1. Install Jest and jest-axe:
```sh
npm install --save-dev jest jest-
Comments
Post a Comment