mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-28 18:26:54 +00:00
feat: convert universal navigation test to Playwright (#54873)
Co-authored-by: Naomi <accounts+github@nhcarrigan.com>
This commit is contained in:
@@ -1,114 +0,0 @@
|
||||
const navigationItems: { [key: string]: string } = {
|
||||
'navigation-list': '.nav-list',
|
||||
'toggle-button': '#toggle-button-nav',
|
||||
'sign-in-button': "[data-test-label='landing-small-cta']",
|
||||
'avatar-link': '.avatar-nav-link',
|
||||
'avatar-container': '.avatar-container',
|
||||
'sign-out-button': "[data-value='sign-out-button']",
|
||||
signout: "[data-test-label='signout']",
|
||||
'cancel-signout': "[data-test-label='cancel-signout']"
|
||||
};
|
||||
|
||||
const navigationLinks: { [key: string]: string } = {
|
||||
'sign-in': '/signin',
|
||||
donate: '/donate',
|
||||
curriculum: '/learn',
|
||||
forum: 'https://forum.freecodecamp.org/',
|
||||
news: 'https://freecodecamp.org/news/',
|
||||
radio: 'https://coderadio.freecodecamp.org',
|
||||
'avatar-link': '/developmentuser',
|
||||
settings: '/settings'
|
||||
};
|
||||
|
||||
describe('Default Navigation Menu', () => {
|
||||
it('should close the menu and focus on the Menu button when the Esc key is pressed while the navigation menu is expanded and an item in the menu is focused', () => {
|
||||
cy.visit('/learn');
|
||||
cy.get(navigationItems['toggle-button']).should('be.visible').click();
|
||||
cy.get(navigationItems['navigation-list']).contains('Curriculum').focus();
|
||||
cy.focused().type('{esc}');
|
||||
cy.get(navigationItems['navigation-list']).should('not.be.visible');
|
||||
cy.get(navigationItems['toggle-button']).should('be.focused');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Authenticated Navigation Menu', () => {
|
||||
before(() => {
|
||||
cy.task('seed');
|
||||
cy.login();
|
||||
cy.visit('/');
|
||||
cy.get(navigationItems['toggle-button']).should('be.visible').click();
|
||||
});
|
||||
it('should show default avatar.', () => {
|
||||
testLink('Settings');
|
||||
cy.get(navigationItems['sign-in-button']).should('not.exist');
|
||||
cy.get(navigationItems['avatar-link'])
|
||||
.should('have.attr', 'href')
|
||||
.and('contain', navigationLinks['avatar-link']);
|
||||
cy.get(navigationItems['avatar-container']).should(
|
||||
'have.class',
|
||||
'default-border'
|
||||
);
|
||||
cy.get(navigationItems['navigation-list']).contains('Night Mode').click();
|
||||
cy.get('body').should('have.class', 'dark-palette');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Authenticated User Sign Out', () => {
|
||||
before(() => {
|
||||
cy.task('seed');
|
||||
});
|
||||
beforeEach(() => {
|
||||
cy.login();
|
||||
cy.visit('/');
|
||||
cy.get(navigationItems['toggle-button']).should('be.visible').click();
|
||||
});
|
||||
it('should sign out user', () => {
|
||||
cy.get(navigationItems['sign-out-button']).click();
|
||||
cy.get(navigationItems['signout']).click();
|
||||
cy.get(navigationItems['sign-in-button']).should('be.visible');
|
||||
cy.get(navigationItems['sign-out-button']).should('not.exist');
|
||||
cy.get(navigationItems['avatar-link']).should('not.exist');
|
||||
cy.get(navigationItems['avatar-container']).should('not.exist');
|
||||
});
|
||||
it('should cancel the sign out', () => {
|
||||
cy.get(navigationItems['sign-out-button']).click();
|
||||
cy.get(navigationItems['cancel-signout']).click();
|
||||
cy.get(navigationItems['sign-in-button']).should('not.exist');
|
||||
cy.get(navigationItems['avatar-link']).should('be.visible');
|
||||
cy.get(navigationItems['avatar-container']).should('be.visible');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Donor Navigation Menu', () => {
|
||||
before(() => {
|
||||
cy.task('seed', ['--donor']);
|
||||
});
|
||||
it('should show donor avatar border and thank you message.', () => {
|
||||
cy.login();
|
||||
cy.visit('/donate');
|
||||
cy.get(navigationItems['avatar-container']).should(
|
||||
'have.class',
|
||||
'gold-border'
|
||||
);
|
||||
cy.get(navigationItems['navigation-list']).contains('Supporters');
|
||||
});
|
||||
});
|
||||
|
||||
const testLink = (
|
||||
item: string,
|
||||
selector = 'navigation-list',
|
||||
checkParent = false
|
||||
) => {
|
||||
if (checkParent) {
|
||||
return cy
|
||||
.get(navigationItems[selector])
|
||||
.should('contain.text', item)
|
||||
.should('have.attr', 'href')
|
||||
.and('contain', navigationLinks[item.replace(/\s+/g, '-').toLowerCase()]);
|
||||
}
|
||||
return cy
|
||||
.get(navigationItems[selector])
|
||||
.contains(item)
|
||||
.should('have.attr', 'href')
|
||||
.and('contain', navigationLinks[item.replace(/\s+/g, '-').toLowerCase()]);
|
||||
};
|
||||
+84
-16
@@ -44,22 +44,6 @@ test('Renders universal nav by default', async ({ page }) => {
|
||||
await expect(universalNavigationLogo).toHaveAttribute('href', '/learn');
|
||||
});
|
||||
|
||||
test('Renders exam nav for Foundational C# with Microsoft exam', async ({
|
||||
page
|
||||
}) => {
|
||||
await page.goto(examUrl);
|
||||
await page
|
||||
.getByRole('button', {
|
||||
name: translations.buttons['click-start-exam']
|
||||
})
|
||||
.click();
|
||||
await expect(page).toHaveURL(examUrl);
|
||||
await expect(page.getByTestId(headerComponentElements.examNav)).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId(headerComponentElements.examNavLogo)
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test('Should display search in header on desktop and in menu on mobile', async ({
|
||||
page,
|
||||
isMobile
|
||||
@@ -120,6 +104,24 @@ test('Clicking the menu button should open the menu', async ({ page }) => {
|
||||
await expect(menu).toBeVisible();
|
||||
});
|
||||
|
||||
test('Focusing on a menu item, and pressing Esc should close the menu and focus on the menu button', async ({
|
||||
page
|
||||
}) => {
|
||||
const menuButton = page.getByTestId(headerComponentElements.menuButton);
|
||||
const menu = page.getByTestId(headerComponentElements.menu);
|
||||
|
||||
await expect(menuButton).toBeVisible();
|
||||
await menuButton.click();
|
||||
|
||||
const link = menu.getByRole('link', { name: translations.buttons.donate });
|
||||
await link.focus();
|
||||
|
||||
await page.keyboard.press('Escape');
|
||||
await expect(menu).toBeHidden();
|
||||
|
||||
await expect(menuButton).toBeFocused();
|
||||
});
|
||||
|
||||
test('The menu should contain links to: donate, curriculum, forum, news, radio, contribute, and podcast', async ({
|
||||
page
|
||||
}) => {
|
||||
@@ -167,6 +169,56 @@ test('The menu should contain links to: donate, curriculum, forum, news, radio,
|
||||
}
|
||||
});
|
||||
|
||||
test('The menu should be able to change the theme', async ({ page }) => {
|
||||
const menuButton = page.getByTestId(headerComponentElements.menuButton);
|
||||
const menu = page.getByTestId(headerComponentElements.menu);
|
||||
await menuButton.click();
|
||||
await expect(menu).toBeVisible();
|
||||
|
||||
const themeButton = menu.getByRole('button', {
|
||||
name: 'Night Mode'
|
||||
});
|
||||
await themeButton.click();
|
||||
|
||||
await expect(page.locator('body')).toHaveClass('dark-palette');
|
||||
|
||||
await expect(page.getByTestId('flash-message')).toContainText(
|
||||
/We have updated your theme/
|
||||
);
|
||||
await expect(menu).toBeHidden();
|
||||
|
||||
await menuButton.click();
|
||||
await expect(menu).toBeVisible();
|
||||
|
||||
await themeButton.click();
|
||||
await expect(page.locator('body')).toHaveClass('light-palette');
|
||||
});
|
||||
|
||||
test('The header should contain an avatar', async ({ page }) => {
|
||||
const avatarLink = page.locator('.avatar-nav-link');
|
||||
await expect(avatarLink).toBeVisible();
|
||||
await expect(avatarLink).toHaveAttribute('href', '/certifieduser');
|
||||
|
||||
const avatarContainer = page.locator('.avatar-container');
|
||||
await expect(avatarContainer).toHaveClass('avatar-container blue-border');
|
||||
});
|
||||
|
||||
test('Renders exam nav for Foundational C# with Microsoft exam', async ({
|
||||
page
|
||||
}) => {
|
||||
await page.goto(examUrl);
|
||||
await page
|
||||
.getByRole('button', {
|
||||
name: translations.buttons['click-start-exam']
|
||||
})
|
||||
.click();
|
||||
await expect(page).toHaveURL(examUrl);
|
||||
await expect(page.getByTestId(headerComponentElements.examNav)).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId(headerComponentElements.examNavLogo)
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test('The Sign In button should redirect to api/signin', async ({
|
||||
browser
|
||||
}) => {
|
||||
@@ -185,3 +237,19 @@ test('The Sign In button should redirect to api/signin', async ({
|
||||
|
||||
await expect(signInButton).toHaveAttribute('href', `${apiLocation}/signin`);
|
||||
});
|
||||
|
||||
test('When the user is signed out, only certain elements should be visible', async ({
|
||||
browser
|
||||
}) => {
|
||||
const context = await browser.newContext({
|
||||
storageState: { cookies: [], origins: [] }
|
||||
});
|
||||
const page = await context.newPage();
|
||||
await page.goto('/');
|
||||
const signInButton = page
|
||||
.getByTestId(headerComponentElements.signInButton)
|
||||
.nth(0);
|
||||
await expect(signInButton).toBeVisible();
|
||||
await expect(page.locator('.avatar-nav-link')).toBeHidden();
|
||||
await expect(page.locator('.avatar-container')).toBeHidden();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user