test(e2e): mock quiz data in quiz-challenge.spec.ts (#62011)

Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>
This commit is contained in:
Huyen Nguyen
2025-09-03 20:45:19 +07:00
committed by GitHub
parent 041074b7bc
commit 63c19acfc3
2 changed files with 87 additions and 4 deletions

View File

@@ -0,0 +1,26 @@
[
{
"questions": [
{ "distractors": ["Wrong 1", "Wrong 2", "<pre><code>const x = 1;</code></pre>"], "text": "Question 1", "answer": "<pre><code>console.log('ok')</code></pre> Correct answer" },
{ "distractors": ["Wrong 1", "Wrong 2", "Wrong 3"], "text": "Question 2", "answer": "Correct answer" },
{ "distractors": ["Wrong 1", "Wrong 2", "Wrong 3"], "text": "Question 3", "answer": "Correct answer" },
{ "distractors": ["Wrong 1", "Wrong 2", "Wrong 3"], "text": "Question 4", "answer": "Correct answer" },
{ "distractors": ["Wrong 1", "Wrong 2", "Wrong 3"], "text": "Question 5", "answer": "Correct answer" },
{ "distractors": ["Wrong 1", "Wrong 2", "Wrong 3"], "text": "Question 6", "answer": "Correct answer" },
{ "distractors": ["Wrong 1", "Wrong 2", "Wrong 3"], "text": "Question 7", "answer": "Correct answer" },
{ "distractors": ["Wrong 1", "Wrong 2", "Wrong 3"], "text": "Question 8", "answer": "Correct answer" },
{ "distractors": ["Wrong 1", "Wrong 2", "Wrong 3"], "text": "Question 9", "answer": "Correct answer" },
{ "distractors": ["Wrong 1", "Wrong 2", "Wrong 3"], "text": "Question 10", "answer": "Correct answer" },
{ "distractors": ["Wrong 1", "Wrong 2", "Wrong 3"], "text": "Question 11", "answer": "Correct answer" },
{ "distractors": ["Wrong 1", "Wrong 2", "Wrong 3"], "text": "Question 12", "answer": "Correct answer" },
{ "distractors": ["Wrong 1", "Wrong 2", "Wrong 3"], "text": "Question 13", "answer": "Correct answer" },
{ "distractors": ["Wrong 1", "Wrong 2", "Wrong 3"], "text": "Question 14", "answer": "Correct answer" },
{ "distractors": ["Wrong 1", "Wrong 2", "Wrong 3"], "text": "Question 15", "answer": "Correct answer" },
{ "distractors": ["Wrong 1", "Wrong 2", "Wrong 3"], "text": "Question 16", "answer": "Correct answer" },
{ "distractors": ["Wrong 1", "Wrong 2", "Wrong 3"], "text": "Question 17", "answer": "Correct answer" },
{ "distractors": ["Wrong 1", "Wrong 2", "Wrong 3"], "text": "Question 18", "answer": "Correct answer" },
{ "distractors": ["Wrong 1", "Wrong 2", "Wrong 3"], "text": "Question 19", "answer": "Correct answer" },
{ "distractors": ["Wrong 1", "Wrong 2", "Wrong 3"], "text": "Question 20", "answer": "Correct answer" }
]
}
]

View File

@@ -1,8 +1,47 @@
import fs from 'fs';
import path from 'path';
import { test, expect } from '@playwright/test';
import { allowTrailingSlash } from './utils/url';
interface QuizQuestion {
distractors: string[];
text: string;
answer: string;
}
interface Quiz {
questions: QuizQuestion[];
}
interface PageData {
result: {
data: {
challengeNode: {
challenge: { quizzes: Quiz[] };
};
};
};
}
test.describe('Quiz challenge', () => {
test.beforeEach(async ({ page }) => {
const fixturePath = path.join(__dirname, 'fixtures', 'quiz-fixture.json');
const fixture = JSON.parse(fs.readFileSync(fixturePath, 'utf8')) as Quiz[];
// Intercept Gatsby page-data and inject a deterministic quiz fixture
await page.route('**/page-data/**/page-data.json', async route => {
const response = await route.fetch();
const body = await response.text();
const pageData = JSON.parse(body) as PageData;
pageData.result.data.challengeNode.challenge.quizzes = fixture;
await route.fulfill({
contentType: 'application/json',
body: JSON.stringify(pageData)
});
});
await page.goto(
'/learn/full-stack-developer/quiz-basic-html/quiz-basic-html'
);
@@ -13,6 +52,18 @@ test.describe('Quiz challenge', () => {
}) => {
// Wait for the page content to render
await expect(page.getByRole('radiogroup')).toHaveCount(20);
const radioGroups = await page.getByRole('radiogroup').all();
// The radio label contents are rendered with `PrismFormatted`.
// For accessibility we must ensure:
// - The formatted content is wrapped in a `span`
// - No ARIA role is added to `pre` elements
const firstGroup = radioGroups[0];
const spanLabel = firstGroup.locator('span.quiz-answer-label');
await expect(spanLabel).toHaveCount(4);
const preWithRole = firstGroup.locator('pre[role]');
await expect(preWithRole).toHaveCount(0);
for (let i = 0; i < 15; i++) {
const radioGroups = await page.getByRole('radiogroup').all();
@@ -41,10 +92,13 @@ test.describe('Quiz challenge', () => {
// Answer 18 questions correctly.
// This is enough to pass the quiz, and also allowing us to test the quiz passing criteria.
for (let i = 0; i < radioGroups.length; i++) {
const group = radioGroups[i];
const correct = group.getByRole('radio', { name: /Correct answer/i });
const wrong = group.getByRole('radio', { name: /Wrong 1/i });
if (i <= 17) {
await radioGroups[i].locator("[role='radio'][data-value='4']").click();
await correct.click();
} else {
await radioGroups[i].locator("[role='radio'][data-value='1']").click();
await wrong.click();
}
}
@@ -105,10 +159,13 @@ test.describe('Quiz challenge', () => {
// Answer only 10 questions correctly.
for (let i = 0; i < radioGroups.length; i++) {
const group = radioGroups[i];
const correct = group.getByRole('radio', { name: /Correct answer/i });
const wrong = group.getByRole('radio', { name: /Wrong 1/i });
if (i <= 9) {
await radioGroups[i].locator("[role='radio'][data-value='4']").click();
await correct.click();
} else {
await radioGroups[i].locator("[role='radio'][data-value='1']").click();
await wrong.click();
}
}