mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2025-12-19 10:07:46 -05:00
Co-authored-by: Huyen Nguyen <25715018+huyenltnguyen@users.noreply.github.com> Co-authored-by: ahmad abdolsaheb <ahmad.abdolsaheb@gmail.com>
349 lines
11 KiB
TypeScript
349 lines
11 KiB
TypeScript
import { execSync } from 'child_process';
|
|
import { test, expect } from '@playwright/test';
|
|
|
|
import translations from '../client/i18n/locales/english/translations.json';
|
|
import {
|
|
currentCertifications,
|
|
legacyCertifications as legacyCerts
|
|
} from '../shared/config/certification-settings';
|
|
import { alertToBeVisible } from './utils/alerts';
|
|
|
|
const settingsTestIds = {
|
|
settingsHeading: 'settings-heading',
|
|
portfolioItems: 'portfolio-items'
|
|
};
|
|
|
|
const settingsObject = {
|
|
email: 'foo@bar.com',
|
|
userNamePlaceholder: '{{username}}',
|
|
certifiedUsername: 'certifieduser',
|
|
testEmail: 'test@gmail.com',
|
|
pageTitle: `${translations.buttons.settings} | freeCodeCamp.org`,
|
|
private: 'Private',
|
|
public: 'Public',
|
|
supportEmail: 'support@freecodecamp.org',
|
|
supportEmailPlaceholder: '<0>{{email}}</0>'
|
|
};
|
|
|
|
const certifications = [
|
|
translations.certification.title['foundational-c-sharp-with-microsoft']
|
|
];
|
|
|
|
const legacyCertifications = [
|
|
translations.certification.title['responsive-web-design'],
|
|
translations.certification.title[
|
|
'javascript-algorithms-and-data-structures-v8'
|
|
],
|
|
translations.certification.title['front-end-development-libraries'],
|
|
translations.certification.title['data-visualization'],
|
|
translations.certification.title['relational-database-v8'],
|
|
translations.certification.title['back-end-development-and-apis'],
|
|
translations.certification.title['quality-assurance-v7'],
|
|
translations.certification.title['scientific-computing-with-python-v7'],
|
|
translations.certification.title['data-analysis-with-python-v7'],
|
|
translations.certification.title['information-security-v7'],
|
|
translations.certification.title['machine-learning-with-python-v7'],
|
|
translations.certification.title['college-algebra-with-python-v8'],
|
|
translations.certification.title['legacy-front-end'],
|
|
translations.certification.title['legacy-back-end'],
|
|
translations.certification.title['legacy-data-visualization'],
|
|
translations.certification.title['information-security-and-quality-assurance']
|
|
];
|
|
|
|
test.describe('Settings - Certified User', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
execSync('node ./tools/scripts/seed/seed-demo-user --certified-user');
|
|
await page.goto('/settings');
|
|
});
|
|
|
|
test('Should render correctly', async ({ page }) => {
|
|
// Title
|
|
await expect(page).toHaveTitle(settingsObject.pageTitle);
|
|
|
|
// Header
|
|
const header = page.getByTestId(settingsTestIds.settingsHeading);
|
|
await expect(header).toBeVisible();
|
|
await expect(header).toContainText(
|
|
`${translations.settings.for.replace(
|
|
settingsObject.userNamePlaceholder,
|
|
settingsObject.certifiedUsername
|
|
)}`
|
|
);
|
|
|
|
// Privacy Settings
|
|
await expect(
|
|
page.getByRole('heading', {
|
|
name: translations.settings.headings.privacy
|
|
})
|
|
).toBeVisible();
|
|
await expect(page.getByText(translations.settings.privacy)).toBeVisible();
|
|
await expect(
|
|
page
|
|
.getByRole('group', {
|
|
name: translations.settings.labels['my-profile']
|
|
})
|
|
.locator('p')
|
|
.filter({ hasText: translations.settings.labels['my-profile'] })
|
|
).toBeVisible();
|
|
await expect(
|
|
page
|
|
.getByRole('group', {
|
|
name: translations.settings.labels['my-name']
|
|
})
|
|
.locator('p')
|
|
.filter({ hasText: translations.settings.labels['my-name'] })
|
|
).toBeVisible();
|
|
await expect(
|
|
page
|
|
.getByRole('group', {
|
|
name: translations.settings.labels['my-about']
|
|
})
|
|
.locator('p')
|
|
.filter({ hasText: translations.settings.labels['my-about'] })
|
|
).toBeVisible();
|
|
await expect(
|
|
page
|
|
.getByRole('group', {
|
|
name: translations.settings.labels['my-points']
|
|
})
|
|
.locator('p')
|
|
.filter({ hasText: translations.settings.labels['my-points'] })
|
|
).toBeVisible();
|
|
await expect(
|
|
page
|
|
.getByRole('group', {
|
|
name: translations.settings.labels['my-certs']
|
|
})
|
|
.locator('p')
|
|
.filter({ hasText: translations.settings.labels['my-certs'] })
|
|
).toBeVisible();
|
|
await expect(
|
|
page
|
|
.getByRole('group', {
|
|
name: translations.settings.labels['my-donations']
|
|
})
|
|
.locator('p')
|
|
.filter({ hasText: translations.settings.labels['my-donations'] })
|
|
).toBeVisible();
|
|
await expect(
|
|
page
|
|
.getByRole('group', {
|
|
name: translations.settings.labels['my-heatmap']
|
|
})
|
|
.locator('p')
|
|
.filter({ hasText: translations.settings.labels['my-heatmap'] })
|
|
).toBeVisible();
|
|
await expect(
|
|
page
|
|
.getByRole('group', {
|
|
name: translations.settings.labels['my-location']
|
|
})
|
|
.locator('p')
|
|
.filter({ hasText: translations.settings.labels['my-location'] })
|
|
).toBeVisible();
|
|
await expect(
|
|
page
|
|
.getByRole('group', {
|
|
name: translations.settings.labels['my-timeline']
|
|
})
|
|
.locator('p')
|
|
.filter({ hasText: translations.settings.labels['my-timeline'] })
|
|
).toBeVisible();
|
|
await expect(
|
|
page
|
|
.getByRole('group', {
|
|
name: translations.settings.labels['my-portfolio']
|
|
})
|
|
.locator('p')
|
|
.filter({ hasText: translations.settings.labels['my-portfolio'] })
|
|
).toBeVisible();
|
|
await expect(
|
|
page.getByText(settingsObject.private, { exact: true })
|
|
).toHaveCount(10);
|
|
await expect(
|
|
page.getByText(settingsObject.public, { exact: true })
|
|
).toHaveCount(10);
|
|
const saveButton = page.getByRole('button', {
|
|
name: translations.settings.headings.privacy
|
|
});
|
|
await expect(saveButton).toBeVisible();
|
|
await expect(page.getByText(translations.settings.data)).toBeVisible();
|
|
const downloadButton = page.getByRole('link', {
|
|
name: translations.buttons['download-data']
|
|
});
|
|
await expect(downloadButton).toBeVisible();
|
|
await expect(page.locator('#legendsound')).toBeVisible();
|
|
await expect(
|
|
page.getByText(translations.settings['sound-volume'])
|
|
).toBeVisible();
|
|
await expect(
|
|
page
|
|
.getByRole('group', {
|
|
name: translations.settings.labels['keyboard-shortcuts']
|
|
})
|
|
.locator('p')
|
|
.first()
|
|
).toBeVisible();
|
|
await expect(
|
|
page.getByText(translations.settings['scrollbar-width'])
|
|
).toBeVisible();
|
|
|
|
// Certifications
|
|
await expect(
|
|
page.getByRole('heading', {
|
|
name: translations.settings.headings.certs,
|
|
exact: true
|
|
})
|
|
).toBeVisible();
|
|
for (let i = 0; i < certifications.length; i++) {
|
|
await expect(
|
|
page.getByRole('heading', {
|
|
name: certifications[i],
|
|
exact: true
|
|
})
|
|
).toBeVisible();
|
|
await expect(
|
|
page.getByRole('link', {
|
|
name: `${translations.buttons['show-cert']} ${certifications[i]}`
|
|
})
|
|
).toBeVisible();
|
|
}
|
|
|
|
// Legacy Certifications
|
|
await expect(
|
|
page.getByRole('heading', {
|
|
name: translations.settings.headings['legacy-certs'],
|
|
exact: true
|
|
})
|
|
).toBeVisible();
|
|
for (let i = 0; i < legacyCertifications.length; i++) {
|
|
await expect(
|
|
page.getByRole('heading', {
|
|
name: legacyCertifications[i],
|
|
exact: true
|
|
})
|
|
).toBeVisible();
|
|
await expect(
|
|
page.getByRole('link', {
|
|
name: `${translations.buttons['show-cert']} ${legacyCertifications[i]}`,
|
|
exact: true
|
|
})
|
|
).toBeVisible();
|
|
}
|
|
|
|
// Danger Zone
|
|
await expect(page.getByRole('main').getByText('Danger Zone')).toBeVisible();
|
|
await expect(
|
|
page.getByText(
|
|
'Please be careful. Changes in this section are permanent.'
|
|
)
|
|
).toBeVisible();
|
|
await expect(
|
|
page.getByRole('button', {
|
|
name: 'Reset all of my progress'
|
|
})
|
|
).toBeVisible();
|
|
await expect(
|
|
page.getByRole('button', {
|
|
name: 'Delete my account'
|
|
})
|
|
).toBeVisible();
|
|
});
|
|
});
|
|
|
|
// In order to claim the Full Stack cert, the user needs to complete 6 certs.
|
|
// Instead of simulating 6 cert claim flows,
|
|
// we use the data of Certified User but remove the Full Stack cert.
|
|
test.describe('Settings - Certified User without Full Stack Certification', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
execSync(
|
|
'node ./tools/scripts/seed/seed-demo-user --certified-user --set-false isFullStackCert'
|
|
);
|
|
await page.goto('/settings');
|
|
});
|
|
|
|
test.afterAll(() => {
|
|
execSync('node ./tools/scripts/seed/seed-demo-user --certified-user');
|
|
});
|
|
|
|
test('should allow claiming Full Stack cert if the user has completed all requirements', async ({
|
|
page
|
|
}) => {
|
|
const claimButton = page.getByRole('button', {
|
|
name: 'Claim Certification Legacy Full Stack'
|
|
});
|
|
const showButton = page.getByRole('link', {
|
|
name: 'Show Certification Legacy Full Stack'
|
|
});
|
|
|
|
await expect(claimButton).toBeVisible();
|
|
await expect(claimButton).toBeEnabled();
|
|
await claimButton.click();
|
|
|
|
await alertToBeVisible(
|
|
page,
|
|
'@certifieduser, you have successfully claimed the Legacy Full Stack Certification! Congratulations on behalf of the freeCodeCamp.org team!'
|
|
);
|
|
await expect(claimButton).toBeHidden();
|
|
await expect(showButton).toBeVisible();
|
|
await expect(showButton).toHaveAttribute(
|
|
'href',
|
|
'/certification/certifieduser/full-stack'
|
|
);
|
|
});
|
|
});
|
|
|
|
test.describe('Settings - New User', () => {
|
|
test.use({ storageState: 'playwright/.auth/development-user.json' });
|
|
|
|
test.beforeEach(async ({ page }) => {
|
|
execSync('node ./tools/scripts/seed/seed-demo-user');
|
|
await page.goto('/settings');
|
|
});
|
|
|
|
test.afterAll(() => {
|
|
execSync('node ./tools/scripts/seed/seed-demo-user --certified-user');
|
|
});
|
|
|
|
test('should not allow claiming Full Stack cert if the user has not completed all the required certs', async ({
|
|
page
|
|
}) => {
|
|
const claimFullStackCertButton = page.getByRole('button', {
|
|
name: 'Claim Certification Legacy Full Stack'
|
|
});
|
|
|
|
const claimRwdCertButton = page.getByRole('button', {
|
|
name: 'Claim Certification Legacy Responsive Web Design V8'
|
|
});
|
|
|
|
// Buttons for normal certs are enabled
|
|
await expect(claimRwdCertButton).toBeVisible();
|
|
await expect(claimRwdCertButton).toBeEnabled();
|
|
|
|
// Button for full stack cert is disabled if the user hasn't claimed the required certs
|
|
await expect(claimFullStackCertButton).toBeVisible();
|
|
await expect(claimFullStackCertButton).toBeDisabled();
|
|
});
|
|
});
|
|
|
|
test.describe('Setting - Hash Navigation', () => {
|
|
test('should scroll to certification sections when navigating with hash', async ({
|
|
page
|
|
}) => {
|
|
const allCerts = [...currentCertifications, ...legacyCerts];
|
|
for (const certSlug of allCerts) {
|
|
await page.goto(`/settings#cert-${certSlug}`);
|
|
|
|
// Wait for scroll animation
|
|
await page.waitForTimeout(300);
|
|
|
|
const certHeading = page.getByRole('heading', {
|
|
name: translations.certification.title[certSlug],
|
|
exact: true
|
|
});
|
|
|
|
await expect(certHeading).toBeInViewport();
|
|
}
|
|
});
|
|
});
|