From 6d7ccc9b1f479965489213aa6966ccc015777cb7 Mon Sep 17 00:00:00 2001 From: Sem Bauke Date: Tue, 4 Jun 2024 21:09:53 +0200 Subject: [PATCH] feat: convert c-sharp exam tests to Playwright (#54946) Co-authored-by: Oliver Eyton-Williams --- .../foundational-c-sharp-survey-alert.tsx | 2 +- .../default/learn/challenges/c-sharp-exam.ts | 65 ------------------- e2e/exam-survey.spec.ts | 39 +++++++++++ tools/scripts/seed/seed-demo-user.js | 13 ++-- tools/scripts/seed/seed-surveys.js | 10 ++- tools/scripts/seed/user-data.js | 19 ++++-- 6 files changed, 61 insertions(+), 87 deletions(-) delete mode 100644 cypress/e2e/default/learn/challenges/c-sharp-exam.ts create mode 100644 e2e/exam-survey.spec.ts diff --git a/client/src/templates/Challenges/exam/components/foundational-c-sharp-survey-alert.tsx b/client/src/templates/Challenges/exam/components/foundational-c-sharp-survey-alert.tsx index 6ec6d38917e..a1c69826baf 100644 --- a/client/src/templates/Challenges/exam/components/foundational-c-sharp-survey-alert.tsx +++ b/client/src/templates/Challenges/exam/components/foundational-c-sharp-survey-alert.tsx @@ -25,7 +25,7 @@ function FoundationalCSharpSurveyAlert({ const { t } = useTranslation(); return ( - + {t('survey.foundational-c-sharp.title')}

{t('survey.misc.two-questions')}

diff --git a/cypress/e2e/default/learn/challenges/c-sharp-exam.ts b/cypress/e2e/default/learn/challenges/c-sharp-exam.ts deleted file mode 100644 index f90dd23e97f..00000000000 --- a/cypress/e2e/default/learn/challenges/c-sharp-exam.ts +++ /dev/null @@ -1,65 +0,0 @@ -const examUrl = - '/learn/foundational-c-sharp-with-microsoft/foundational-c-sharp-with-microsoft-certification-exam/foundational-c-sharp-with-microsoft-certification-exam'; - -const el = { - qualifiedAlert: "[data-cy='qualified-for-exam-alert']", - surveyAlert: "[data-cy='c-sharp-survey-alert']", - startSurveyBtn: "[data-cy='start-csharp-survey-btn']", - submitSurveyBtn: "[data-cy='submit-csharp-survey-btn']", - startExamBtn: "[data-cy='start-exam-btn']", - examTime: "[data-cy='exam-time']", - examInput: '.exam-answer-input-visible', - prevQuestionBtn: "[data-cy='previous-exam-question-btn']", - nextQuestionBtn: "[data-cy='next-exam-question-btn']", - exitExamBtn: "[data-cy='exit-exam-btn']", - finishExamBtn: "[data-cy='finish-exam-btn']" -}; - -describe('C# Exam Challenge', () => { - describe('Before completing prerequisite challenges', () => { - before(() => { - cy.task('seed'); - cy.login(); - }); - - it('Should show prerequisites alert and have "start exam" button disabled', () => { - cy.visit(examUrl); - cy.get(el.qualifiedAlert).should('not.exist'); - cy.contains( - 'You have not met the requirements to be eligible for the exam. To qualify, please complete the following challenges:' - ).should('be.visible'); - cy.contains('Trophy - Write Your First Code Using C#').should( - 'be.visible' - ); - cy.get(el.surveyAlert).should('not.exist'); - cy.get(el.startExamBtn).should('have.attr', 'aria-disabled'); - }); - }); - - describe('After completing prerequisite challenges', () => { - before(() => { - cy.task('seed', ['--seed-trophy-challenges']); - cy.task('deleteSurveys'); - cy.login('trophy-user'); - cy.visit(examUrl); - }); - - it('Should show the survey alert and be able to complete the survey', () => { - cy.contains('Trophy - Write Your First Code Using C#').should( - 'not.exist' - ); - cy.get(el.qualifiedAlert).should('not.exist'); - cy.contains( - 'You have not met the requirements to be eligible for the exam. To qualify, please complete the following challenges:' - ).should('not.exist'); - cy.get(el.surveyAlert).should('be.visible'); - cy.get(el.startExamBtn).should('have.attr', 'aria-disabled'); - cy.get(el.startSurveyBtn).click(); - cy.contains('Foundational C# with Microsoft Survey').should('be.visible'); - cy.get(el.submitSurveyBtn).should('have.attr', 'aria-disabled'); - cy.contains('Student developer').click(); - cy.contains('Novice (no prior experience').click(); - cy.get(el.submitSurveyBtn).should('be.enabled'); - }); - }); -}); diff --git a/e2e/exam-survey.spec.ts b/e2e/exam-survey.spec.ts new file mode 100644 index 00000000000..da010610fdd --- /dev/null +++ b/e2e/exam-survey.spec.ts @@ -0,0 +1,39 @@ +import { execSync } from 'child_process'; +import { test, expect } from '@playwright/test'; +const url = + '/learn/foundational-c-sharp-with-microsoft/foundational-c-sharp-with-microsoft-certification-exam/foundational-c-sharp-with-microsoft-certification-exam'; +test.describe('Exam Survey', () => { + test.use({ storageState: 'playwright/.auth/certified-user.json' }); + test.beforeAll(() => { + execSync('node ./tools/scripts/seed/seed-demo-user certified-user'); + execSync('node tools/scripts/seed/seed-surveys.js delete-only'); + }); + + test('Should show the survey alert and be able to complete the survey', async ({ + page + }) => { + await page.goto(url); + + await expect(page.getByTestId('c-sharp-survey-alert')).toBeVisible(); + await page.getByRole('button', { name: 'Take the survey' }).click(); + await expect(page.getByRole('dialog')).toBeVisible(); + await expect( + page.getByRole('heading', { + name: 'Foundational C# with Microsoft Survey' + }) + ).toBeVisible(); + + await page.getByText('Student developer').click(); + await expect( + page.getByRole('button', { name: 'Submit the survey' }) + ).toBeDisabled(); + + await page.getByText('Novice (no prior experience)').click(); + + await page.getByRole('button', { name: 'Submit the survey' }).click(); + + await expect(page.getByTestId('flash-message')).toContainText( + /Thank you. Your survey was submitted./ + ); + }); +}); diff --git a/tools/scripts/seed/seed-demo-user.js b/tools/scripts/seed/seed-demo-user.js index 7df0ceda43b..75a82a70b83 100644 --- a/tools/scripts/seed/seed-demo-user.js +++ b/tools/scripts/seed/seed-demo-user.js @@ -1,12 +1,14 @@ const path = require('path'); const debug = require('debug'); +const { MongoClient } = require('mongodb'); + require('dotenv').config({ path: path.resolve(__dirname, '../../../.env') }); -const { MongoClient, ObjectId } = require('mongodb'); const { demoUser, blankUser, publicUser, - fullyCertifiedUser + fullyCertifiedUser, + userIds } = require('./user-data'); const args = process.argv.slice(2); @@ -104,13 +106,6 @@ const client = new MongoClient(MONGOHQ_URL, { useNewUrlParser: true }); const db = client.db('freecodecamp'); const user = db.collection('user'); -const userIds = [ - new ObjectId('5fa2db00a25c1c1fa49ce067'), - new ObjectId('5bd30e0f1caf6ac3ddddddb5'), - new ObjectId('5bd30e0f1caf6ac3ddddddb9'), - new ObjectId('663b839b24a8b29f57728b13') -]; - const dropUserTokens = async function () { await db.collection('UserToken').deleteMany({ userId: { diff --git a/tools/scripts/seed/seed-surveys.js b/tools/scripts/seed/seed-surveys.js index 730a3df0a12..f9258d96268 100644 --- a/tools/scripts/seed/seed-surveys.js +++ b/tools/scripts/seed/seed-surveys.js @@ -1,8 +1,10 @@ const path = require('path'); const debug = require('debug'); -require('dotenv').config({ path: path.resolve(__dirname, '../../../.env') }); const { MongoClient, ObjectId } = require('mongodb'); +const { userIds } = require('./user-data'); +require('dotenv').config({ path: path.resolve(__dirname, '../../../.env') }); + const args = process.argv.slice(2); const allowedArgs = ['delete-only']; @@ -81,11 +83,7 @@ const run = async () => { const db = client.db('freecodecamp'); const survey = db.collection('Survey'); - await survey.deleteMany({ - _id: { - $in: surveyIds - } - }); + await survey.deleteMany({ userId: { $in: userIds } }); log('Survey info deleted'); if (!args.includes('delete-only')) { diff --git a/tools/scripts/seed/user-data.js b/tools/scripts/seed/user-data.js index dd1ed60478a..ccca8cd4b77 100644 --- a/tools/scripts/seed/user-data.js +++ b/tools/scripts/seed/user-data.js @@ -1,9 +1,16 @@ /* eslint-disable max-len */ const { ObjectId } = require('mongodb'); +const blankUserId = new ObjectId('5bd30e0f1caf6ac3ddddddb9'); +const publicUserId = new ObjectId('663b839b24a8b29f57728b13'); +const demoUserId = new ObjectId('5bd30e0f1caf6ac3ddddddb5'); +const fullyCertifiedUserId = new ObjectId('5fa2db00a25c1c1fa49ce067'); + +const userIds = [blankUserId, publicUserId, demoUserId, fullyCertifiedUserId]; + module.exports = { blankUser: { - _id: new ObjectId('5bd30e0f1caf6ac3ddddddb9'), + _id: blankUserId, email: 'bar@bar.com', emailVerified: true, progressTimestamps: [], @@ -64,7 +71,7 @@ module.exports = { unsubscribeId: 'ecJxUi7OM49f24hTpauP8' }, publicUser: { - _id: new ObjectId('663b839b24a8b29f57728b13'), + _id: publicUserId, email: 'bar@bars.com', emailVerified: true, progressTimestamps: [], @@ -125,7 +132,7 @@ module.exports = { unsubscribeId: 'ecJxUi7OM49f24hTpauP8' }, demoUser: { - _id: new ObjectId('5bd30e0f1caf6ac3ddddddb5'), + _id: demoUserId, email: 'foo@bar.com', emailVerified: true, progressTimestamps: [], @@ -187,9 +194,8 @@ module.exports = { externalId: '', unsubscribeId: 'ecJxUi7OM49f24hTpauP8' }, - fullyCertifiedUser: { - _id: new ObjectId('5fa2db00a25c1c1fa49ce067'), + _id: fullyCertifiedUserId, email: 'foo@bar.com', emailVerified: true, progressTimestamps: [], @@ -12253,5 +12259,6 @@ module.exports = { emailVerifyTTL: null, externalId: '', unsubscribeId: 'tBX8stC5jiustPBteF2mV' - } + }, + userIds };