Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
01a17ad
feat(testing): add comprehensive testing workflows
arunsanna Aug 27, 2025
cf7079d
fix(workflows): correct Docker service names and add error handling
arunsanna Aug 27, 2025
6e21d6f
fix(workflows): resolve pipeline failures for E2E and API testing
arunsanna Aug 27, 2025
472e39c
fix(workflows): remove npm cache configuration to fix Node.js setup
arunsanna Aug 27, 2025
8eb387e
fix(workflows): install dev dependencies for tsx to run backend
arunsanna Aug 27, 2025
18f3ef1
fix(workflows): provide longer JWT secrets to meet validation require…
arunsanna Aug 27, 2025
a59f1f5
fix(workflows): provide valid hex encryption key for backend
arunsanna Aug 27, 2025
3a0fd16
fix(workflows): use correct health check endpoint path
arunsanna Aug 27, 2025
7ce801f
fix(workflows): add Redis password environment variable for E2E tests
arunsanna Aug 27, 2025
6f57342
fix(workflows): use npx to run tsx directly in E2E tests
arunsanna Aug 27, 2025
3eecd49
fix(e2e-testing): fix npm workspace dependencies in E2E Testing workflow
arunsanna Aug 27, 2025
912987e
fix(workflows): fix mutation testing for npm workspaces monorepo
arunsanna Aug 27, 2025
93e5f7a
feat(e2e): enable all browser testing by default
arunsanna Aug 27, 2025
dbe7063
fix(ci): resolve port conflicts in parallel E2E tests
arunsanna Aug 27, 2025
c197fbb
fix(ci): use correct port commands for frontend and backend
arunsanna Aug 27, 2025
f49d9bb
fix(accessibility): Fix keyboard navigation tests and remove inline t…
arunsanna Aug 27, 2025
bf91320
fix(accessibility): Remove dynamic config creation for keyboard tests
arunsanna Aug 27, 2025
90346f2
feat(testing): Add keyboard CI config file
arunsanna Aug 27, 2025
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
188 changes: 91 additions & 97 deletions .github/workflows/accessibility.yml
Original file line number Diff line number Diff line change
Expand Up @@ -226,56 +226,39 @@ jobs:
echo "SERVER_PID=$!" >> $GITHUB_ENV
sleep 5

- name: Create Axe accessibility test
working-directory: ./frontend
run: |
mkdir -p tests/accessibility
cat > tests/accessibility/axe.spec.ts << 'EOF'
import { test, expect } from '@playwright/test';
import AxeBuilder from '@axe-core/playwright';

test('should not have accessibility violations', async ({ page }) => {
await page.goto('http://localhost:3001');

const accessibilityScanResults = await new AxeBuilder({ page })
.withTags(['wcag2a', 'wcag2aa'])
.analyze();

// Log violations for debugging but don't fail the test
if (accessibilityScanResults.violations.length > 0) {
console.log('Accessibility violations found:', accessibilityScanResults.violations.length);
accessibilityScanResults.violations.forEach((violation, index) => {
console.log(`Violation ${index + 1}: ${violation.id} - ${violation.description}`);
});
}

// We expect no violations, but test continues even if there are some
expect(accessibilityScanResults.violations.length).toBeLessThanOrEqual(10);
});
EOF

- name: Run Axe accessibility tests
working-directory: ./frontend
run: |
cat > playwright.config.ts << 'EOF'
# Create a specific config for axe tests
cat > playwright.axe.config.ts << 'EOF'
import { defineConfig } from '@playwright/test';

export default defineConfig({
testDir: './tests/accessibility',
testMatch: '**/axe.spec.ts',
fullyParallel: false,
forbidOnly: !!process.env.CI,
retries: 1,
retries: 2,
workers: 1,
reporter: [['html'], ['json', { outputFile: 'test-results.json' }]],
reporter: [
['html', { outputFolder: 'playwright-report-axe' }],
['json', { outputFile: 'axe-results.json' }],
['list']
],
use: {
baseURL: 'http://localhost:3001',
trace: 'on-first-retry',
screenshot: 'only-on-failure',
},
timeout: 60000,
expect: {
timeout: 10000,
},
timeout: 30000,
});
EOF

npx playwright test || echo "Axe tests completed with violations"
echo "Running Axe accessibility tests..."
npx playwright test --config=playwright.axe.config.ts || echo "Axe tests completed with violations"
continue-on-error: true

- name: Upload Axe results
Expand All @@ -284,8 +267,10 @@ jobs:
with:
name: axe-results-${{ github.run_number }}
path: |
frontend/test-results.json
frontend/playwright-report/
frontend/axe-results.json
frontend/playwright-report-axe/
frontend/playwright.axe.config.ts
frontend/test-results/
retention-days: 7

- name: Stop frontend server
Expand Down Expand Up @@ -323,7 +308,7 @@ jobs:
run: |
echo "Installing workspace dependencies..."
npm install
npm install puppeteer
npm install puppeteer serve

- name: Build frontend
working-directory: ./frontend
Expand Down Expand Up @@ -369,7 +354,18 @@ jobs:
run: |
npx serve -s dist -l 3002 &
echo "SERVER_PID=$!" >> $GITHUB_ENV
sleep 5
echo "Waiting for server to start..."
sleep 10

# Check if server is running
for i in {1..5}; do
if curl -f http://localhost:3002 > /dev/null 2>&1; then
echo "Server is ready!"
break
fi
echo "Waiting for server... attempt $i"
sleep 2
done

- name: Run WAVE-style tests
run: |
Expand All @@ -391,7 +387,24 @@ jobs:

try {
const page = await browser.newPage();
await page.goto('http://localhost:3002', { waitUntil: 'networkidle2', timeout: 30000 });

// Retry logic for connection
let connected = false;
let retries = 3;
while (retries > 0 && !connected) {
try {
await page.goto('http://localhost:3002', { waitUntil: 'networkidle2', timeout: 30000 });
connected = true;
} catch (error) {
console.log(`Connection attempt failed. Retries left: ${retries - 1}`);
retries--;
if (retries > 0) {
await new Promise(resolve => setTimeout(resolve, 5000));
} else {
throw error;
}
}
}

const pageResults = await page.evaluate(() => {
const errors = [];
Expand Down Expand Up @@ -519,7 +532,7 @@ jobs:
run: |
echo "Installing workspace dependencies..."
npm install
npm install puppeteer
npm install puppeteer serve

- name: Build frontend
working-directory: ./frontend
Expand Down Expand Up @@ -565,7 +578,18 @@ jobs:
run: |
npx serve -s dist -l 3003 &
echo "SERVER_PID=$!" >> $GITHUB_ENV
sleep 5
echo "Waiting for server to start..."
sleep 10

# Check if server is running
for i in {1..5}; do
if curl -f http://localhost:3003 > /dev/null 2>&1; then
echo "Server is ready!"
break
fi
echo "Waiting for server... attempt $i"
sleep 2
done

- name: Run color contrast tests
run: |
Expand All @@ -587,7 +611,24 @@ jobs:

try {
const page = await browser.newPage();
await page.goto('http://localhost:3003', { waitUntil: 'networkidle2', timeout: 30000 });

// Retry logic for connection
let connected = false;
let retries = 3;
while (retries > 0 && !connected) {
try {
await page.goto('http://localhost:3003', { waitUntil: 'networkidle2', timeout: 30000 });
connected = true;
} catch (error) {
console.log(`Connection attempt failed. Retries left: ${retries - 1}`);
retries--;
if (retries > 0) {
await new Promise(resolve => setTimeout(resolve, 5000));
} else {
throw error;
}
}
}

const contrastResults = await page.evaluate(() => {
const elements = document.querySelectorAll('*');
Expand Down Expand Up @@ -751,64 +792,14 @@ jobs:
echo "SERVER_PID=$!" >> $GITHUB_ENV
sleep 5

- name: Create keyboard navigation test
working-directory: ./frontend
run: |
mkdir -p tests/accessibility
cat > tests/accessibility/keyboard.spec.ts << 'EOF'
import { test, expect } from '@playwright/test';

test('keyboard navigation should work', async ({ page }) => {
await page.goto('http://localhost:3004');

// Find all interactive elements
const interactiveElements = await page.locator('button, a, input, select, textarea, [tabindex]:not([tabindex="-1"])').all();

console.log(`Found ${interactiveElements.length} interactive elements`);

// Test Tab navigation through first few elements
const elementsToTest = Math.min(interactiveElements.length, 5);

for (let i = 0; i < elementsToTest; i++) {
await page.keyboard.press('Tab');
await page.waitForTimeout(100);

// Verify an element is focused
const focusedElement = await page.locator(':focus').first();
const isVisible = await focusedElement.isVisible().catch(() => false);

if (isVisible) {
console.log(`Element ${i + 1} is focusable`);
}
}

// Test should pass even if some elements aren't perfectly focusable
expect(elementsToTest).toBeGreaterThan(0);
});
EOF

- name: Run keyboard navigation tests
working-directory: ./frontend
run: |
cat > playwright.config.ts << 'EOF'
import { defineConfig } from '@playwright/test';

export default defineConfig({
testDir: './tests/accessibility',
fullyParallel: false,
forbidOnly: !!process.env.CI,
retries: 1,
workers: 1,
reporter: [['html'], ['json', { outputFile: 'keyboard-results.json' }]],
use: {
baseURL: 'http://localhost:3004',
trace: 'on-first-retry',
},
timeout: 30000,
});
EOF

npx playwright test keyboard.spec.ts || echo "Keyboard tests completed"
echo "Running keyboard navigation tests using existing CI config..."
npx playwright test --config=playwright.keyboard.ci.config.ts || {
echo "Keyboard navigation tests completed with issues"
echo "Check the report for details"
}
continue-on-error: true

- name: Upload keyboard navigation results
Expand All @@ -818,7 +809,10 @@ jobs:
name: keyboard-results-${{ github.run_number }}
path: |
frontend/keyboard-results.json
frontend/playwright-report/
frontend/playwright-report-keyboard/
frontend/playwright.keyboard.ci.config.ts
frontend/test-results/
frontend/keyboard-ci-results.json
retention-days: 7

- name: Stop frontend server
Expand Down
Loading
Loading