feat(client/curriculum): release new superblocks, certs coming soon (#63574)

Co-authored-by: ahmad abdolsaheb <ahmad.abdolsaheb@gmail.com>
This commit is contained in:
Tom
2025-11-12 12:50:49 -06:00
committed by GitHub
parent 4352a5b628
commit 8ec4053a05
25 changed files with 520 additions and 101 deletions
+2 -2
View File
@@ -16,7 +16,7 @@ test.describe('Public profile certifications', () => {
await expect(
page.getByRole('link', { name: /View.+Certification/ })
).toHaveCount(20);
).toHaveCount(22);
});
test('Should show claimed certifications if the username includes uppercase characters', async ({
@@ -48,7 +48,7 @@ test.describe('Public profile certifications', () => {
await page.waitForURL('/certifiedboozer');
await expect(
page.getByRole('link', { name: /View.+Certification/ })
).toHaveCount(20);
).toHaveCount(22);
});
test.afterAll(() => {
+3 -3
View File
@@ -318,7 +318,7 @@ test.describe('Donation modal appearance logic - Certified user claiming a new b
page
}) => {
await page.goto(
'/learn/full-stack-developer/review-basic-html/basic-html-review'
'/learn/responsive-web-design-v9/review-basic-html/basic-html-review'
);
await page.getByRole('checkbox', { name: /Review/ }).click();
@@ -334,7 +334,7 @@ test.describe('Donation modal appearance logic - Certified user claiming a new b
test('should not appear if FSD review module is completed', async ({
page
}) => {
await page.goto('/learn/full-stack-developer/review-html/review-html');
await page.goto('/learn/responsive-web-design-v9/review-html/review-html');
await page.getByRole('checkbox', { name: /Review/ }).click();
await page.getByRole('button', { name: 'Submit', exact: true }).click();
await page.getByRole('button', { name: /Submit and go/ }).click();
@@ -361,7 +361,7 @@ test.describe('Donation modal appearance logic - Certified user claiming a new m
// This lecture is not added to the seed data, so it is not completed.
// By completing this lecture, we claim both the block and its module.
await page.goto(
'/learn/full-stack-developer/lecture-working-with-code-editors-and-ides/what-are-some-good-vs-code-extensions-you-can-use-in-your-editor'
'/learn/relational-databases-v9/lecture-working-with-code-editors-and-ides/what-are-some-good-vs-code-extensions-you-can-use-in-your-editor'
);
// Wait for the page content to render
+82
View File
@@ -0,0 +1,82 @@
import { test, expect } from '@playwright/test';
const requiredCerts = [
{
text: 'Responsive Web Design Certification',
slug: '/learn/responsive-web-design-v9/'
},
{
text: 'JavaScript Certification',
slug: '/learn/javascript-v9/'
},
{
text: 'Front End Development Libraries Certification',
slug: '/learn/front-end-development-libraries-v9/'
},
{
text: 'Python Certification',
slug: '/learn/python-v9/'
},
{
text: 'Relational Databases Certification',
slug: '/learn/relational-databases-v9/'
},
{
text: 'Back End Development and APIs Certification',
slug: '/learn/back-end-development-and-apis-v9/'
}
];
test.describe('Full Stack Developer V9 superBlock page', () => {
test('lists and links to requirements', async ({ page }) => {
await page.goto('/learn/full-stack-developer-v9/');
const reqList = page.locator('.requirement-list');
await expect(reqList).toBeVisible();
const reqLinks = reqList.locator('.chapter.requirement .chapter-button');
await expect(reqLinks).toHaveCount(requiredCerts.length);
for (let i = 0; i < requiredCerts.length; i++) {
const reqLink = reqLinks.nth(i);
await expect(reqLink).toBeVisible();
await expect(reqLink).toContainText(requiredCerts[i].text);
await expect(reqLink).toHaveAttribute('href', requiredCerts[i].slug);
}
});
if (process.env.SHOW_UPCOMING_CHANGES === 'true') {
test('shows the exam', async ({ page }) => {
await page.goto('/learn/full-stack-developer-v9/');
const examChapterButton = page.locator('.chapter .chapter-button', {
hasText: /certified full stack developer exam/i
});
await expect(examChapterButton).toBeVisible();
await expect(examChapterButton).toHaveAttribute(
'href',
'/learn/full-stack-developer-v9/exam-certified-full-stack-developer/exam-certified-full-stack-developer'
);
});
} else {
test('shows the exam module and coming soon text', async ({ page }) => {
await page.goto('/learn/full-stack-developer-v9/');
const examChapterButton = page.locator('.chapter .chapter-button', {
hasText: /certified full stack developer exam/i
});
await expect(examChapterButton).toBeVisible();
const examModuleButton = page.locator('.module-button', {
hasText: /certified full stack developer exam/i
});
await examModuleButton.click();
const moduleIntro = page.locator('.module-intro');
await expect(moduleIntro).toBeVisible();
await expect(moduleIntro).toContainText('Coming Late 2026');
await expect(moduleIntro).toContainText(
'This exam will test what you have learned throughout the previous six certifications.'
);
});
}
});
+1 -1
View File
@@ -25,7 +25,7 @@ const links = {
multipleChoiceQuestion:
'/learn/a2-english-for-developers/learn-greetings-in-your-first-day-at-the-office/task-7',
assignment:
'/learn/full-stack-developer/review-semantic-html/review-semantic-html'
'/learn/responsive-web-design-v9/review-semantic-html/review-semantic-html'
};
const titles = {
+1 -1
View File
@@ -26,7 +26,7 @@ interface PageData {
}
const challengePath =
'/learn/full-stack-developer/lecture-what-is-css/what-are-some-default-browser-styles-applied-to-html';
'/learn/responsive-web-design-v9/lecture-what-is-css/what-are-some-default-browser-styles-applied-to-html';
const challengeTitle = 'Test Challenge Title';
+7 -1
View File
@@ -18,7 +18,13 @@ const landingPageElements = {
} as const;
const nonArchivedSuperBlocks = [
intro[SuperBlocks.FullStackDeveloper].title,
intro[SuperBlocks.RespWebDesignV9].title,
intro[SuperBlocks.JsV9].title,
intro[SuperBlocks.FrontEndDevLibsV9].title,
intro[SuperBlocks.PythonV9].title,
intro[SuperBlocks.RelationalDbV9].title,
intro[SuperBlocks.BackEndDevApisV9].title,
intro[SuperBlocks.FullStackDeveloperV9].title,
intro[SuperBlocks.A2English].title,
intro[SuperBlocks.B1English].title,
intro[SuperBlocks.TheOdinProject].title,
+26 -2
View File
@@ -7,7 +7,31 @@ test.beforeEach(async ({ page }) => {
const LANDING_PAGE_LINKS = [
{
slug: 'full-stack-developer',
slug: 'responsive-web-design-v9',
name: 'Responsive Web Design Certification'
},
{
slug: 'javascript-v9',
name: 'JavaScript Certification'
},
{
slug: 'front-end-development-libraries-v9',
name: 'Front End Development Libraries Certification'
},
{
slug: 'python-v9',
name: 'Python Certification'
},
{
slug: 'relational-databases-v9',
name: 'Relational Databases Certification'
},
{
slug: 'back-end-development-and-apis-v9',
name: 'Back End Development and APIs Certification'
},
{
slug: 'full-stack-developer-v9',
name: 'Certified Full Stack Developer Curriculum'
},
{
@@ -40,7 +64,7 @@ test.describe('Map Component', () => {
page.getByText(translations.landing['interview-prep-heading'])
).toBeVisible();
const curriculumBtns = page.getByTestId('curriculum-map-button');
await expect(curriculumBtns).toHaveCount(8);
await expect(curriculumBtns).toHaveCount(14);
for (const { name, slug } of LANDING_PAGE_LINKS) {
const superblockLink = page.getByRole('link', {
@@ -4,7 +4,7 @@ import translations from '../client/i18n/locales/english/translations.json';
const pageWithSpeaking =
'/learn/b1-english-for-developers/learn-about-adverbial-phrases/task-19';
const pageWithoutSpeaking =
'/learn/full-stack-developer/lecture-what-is-css/what-is-the-basic-anatomy-of-a-css-rule';
'/learn/responsive-web-design-v9/lecture-what-is-css/what-is-the-basic-anatomy-of-a-css-rule';
test.describe('Multiple Choice Question Challenge - With Speaking Modal', () => {
test.beforeEach(async ({ page }) => {
+1 -1
View File
@@ -52,7 +52,7 @@ test.describe('Should be shown automatically', () => {
test.describe('Should be shown manually', () => {
test.beforeEach(async ({ page }) => {
const urlWithProjectPreview =
'/learn/full-stack-developer/lab-drum-machine/build-drum-machine';
'/learn/javascript-v9/lab-drum-machine/build-drum-machine';
await page.goto(urlWithProjectPreview);
});
+5 -4
View File
@@ -23,7 +23,8 @@ interface PageData {
};
}
const quizPath = '/learn/full-stack-developer/quiz-basic-html/quiz-basic-html';
const quizPath =
'/learn/responsive-web-design-v9/quiz-basic-html/quiz-basic-html';
test.describe('Quiz challenge', () => {
test.beforeEach(async ({ page }) => {
@@ -205,7 +206,7 @@ test.describe('Quiz challenge', () => {
// The navigation should be blocked, the user should stay on the same page
await expect(page).toHaveURL(
allowTrailingSlash(
'/learn/full-stack-developer/quiz-basic-html/quiz-basic-html'
'/learn/responsive-web-design-v9/quiz-basic-html/quiz-basic-html'
)
);
@@ -223,7 +224,7 @@ test.describe('Quiz challenge', () => {
.getByRole('button', { name: 'Yes, I want to leave the quiz' })
.click();
await page.waitForURL('/learn/full-stack-developer/#quiz-basic-html');
await page.waitForURL('/learn/responsive-web-design-v9/#quiz-basic-html');
await expect(
page.getByRole('heading', { level: 3, name: 'Basic HTML Quiz' })
).toBeVisible();
@@ -242,7 +243,7 @@ test.describe('Quiz challenge', () => {
.getByRole('button', { name: 'Yes, I want to leave the quiz' })
.click();
await page.waitForURL('/learn/full-stack-developer/#quiz-basic-html');
await page.waitForURL('/learn/responsive-web-design-v9/#quiz-basic-html');
await expect(
page.getByRole('heading', { level: 3, name: 'Basic HTML Quiz' })
).toBeVisible();
+13 -7
View File
@@ -106,7 +106,9 @@ test.describe('Super Block Page - Authenticated User', () => {
test('should expand the correct block when user goes to the page from breadcrumb click', async ({
page
}) => {
await page.goto(`/learn/full-stack-developer/workshop-cafe-menu/step-2`);
await page.goto(
`/learn/responsive-web-design-v9/workshop-cafe-menu/step-2`
);
await page
.getByRole('link', {
@@ -114,7 +116,9 @@ test.describe('Super Block Page - Authenticated User', () => {
})
.click();
await page.waitForURL('/learn/full-stack-developer/#workshop-cafe-menu');
await page.waitForURL(
'/learn/responsive-web-design-v9/#workshop-cafe-menu'
);
// Chapter
await expect(
@@ -146,7 +150,7 @@ test.describe('Super Block Page - Authenticated User', () => {
);
});
await page.goto('/learn/full-stack-developer');
await page.goto('/learn/responsive-web-design-v9');
// HTML chapter
await expect(
@@ -173,7 +177,7 @@ test.describe('Super Block Page - Authenticated User', () => {
}) => {
test.setTimeout(20000);
await page.goto('/learn/full-stack-developer');
await page.goto('/learn/responsive-web-design-v9');
// HTML chapter
await expect(
@@ -194,7 +198,9 @@ test.describe('Super Block Page - Authenticated User', () => {
})
).toHaveAttribute('aria-expanded', 'true');
await page.goto('/learn/full-stack-developer/workshop-blog-page/step-2');
await page.goto(
'/learn/responsive-web-design-v9/workshop-blog-page/step-2'
);
// Wait for the page to finish loading so that the current challenge ID can be registered.
await expect(
@@ -202,7 +208,7 @@ test.describe('Super Block Page - Authenticated User', () => {
).toBeVisible();
// Go back to the super block page
await page.goto('/learn/full-stack-developer');
await page.goto('/learn/responsive-web-design-v9');
// Semantic HTML module
await expect(
@@ -248,7 +254,7 @@ test.describe('Super Block Page - Unauthenticated User', () => {
test('should expand the first block of the super block', async ({
page
}) => {
await page.goto('/learn/full-stack-developer');
await page.goto('/learn/responsive-web-design-v9');
// First chapter
await expect(