diff --git a/client/src/components/profile/components/internet.test.tsx b/client/src/components/profile/components/internet.test.tsx new file mode 100644 index 00000000000..795016dd2db --- /dev/null +++ b/client/src/components/profile/components/internet.test.tsx @@ -0,0 +1,99 @@ +import { configureStore } from '@reduxjs/toolkit'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import React from 'react'; +import { Provider } from 'react-redux'; +import { describe, expect, it, vi } from 'vitest'; + +import type { User } from '../../../redux/prop-types'; +import Internet from './internet'; + +const baseUser = { + githubProfile: '', + linkedin: '', + twitter: '', + bluesky: '', + website: '' +} as User; + +const socialFields = [ + { + label: 'GitHub', + url: 'https://github.com/certified-user', + checkTestId: 'internet-github-check' + }, + { + label: 'LinkedIn', + url: 'https://www.linkedin.com/in/certified-user', + checkTestId: 'internet-linkedin-check' + }, + { + label: 'X', + url: 'https://x.com/certified-user', + checkTestId: 'internet-twitter-check' + }, + { + label: 'Bluesky', + url: 'https://bsky.app/profile/certified-user.bsky.social', + checkTestId: 'internet-bluesky-check' + }, + { + label: 'settings.labels.personal', + url: 'https://certified-user.com', + checkTestId: 'internet-website-check' + } +]; + +function makeStore() { + return configureStore({ + reducer: (state: Record = {}) => state + }); +} + +function renderInternet(userOverrides: Partial = {}) { + const store = makeStore(); + + return render( + + + + ); +} + +describe('', () => { + it('renders the internet presence form with a disabled save button', () => { + renderInternet(); + + expect( + screen.getByRole('heading', { name: 'settings.headings.internet' }) + ).toBeInTheDocument(); + expect( + screen.getByRole('group', { name: 'settings.headings.internet' }) + ).toBeInTheDocument(); + expect( + screen.getByRole('button', { name: /buttons\.save/ }) + ).toHaveAttribute('aria-disabled', 'true'); + + socialFields.forEach(({ checkTestId }) => { + expect(screen.queryByTestId(checkTestId)).not.toBeInTheDocument(); + }); + }); + + it('shows a checkmark for each valid social URL', async () => { + const user = userEvent.setup(); + renderInternet(); + + for (const { label, url, checkTestId } of socialFields) { + await user.type(screen.getByRole('textbox', { name: label }), url); + + expect(screen.getByTestId(checkTestId)).toBeInTheDocument(); + } + + expect( + screen.getByRole('button', { name: /buttons\.save/ }) + ).not.toHaveAttribute('aria-disabled', 'true'); + }); +}); diff --git a/client/src/components/profile/components/internet.tsx b/client/src/components/profile/components/internet.tsx index 818014505fd..5b1305f3b6b 100644 --- a/client/src/components/profile/components/internet.tsx +++ b/client/src/components/profile/components/internet.tsx @@ -154,7 +154,7 @@ const InternetSettings = ({
@@ -196,7 +196,7 @@ const InternetSettings = ({ @@ -215,7 +215,7 @@ const InternetSettings = ({ @@ -236,7 +236,7 @@ const InternetSettings = ({ @@ -257,7 +257,7 @@ const InternetSettings = ({ @@ -279,20 +279,16 @@ const InternetSettings = ({ const Check = ({ url, validation, - dataPlaywrightTestLabel + dataTestId }: { url: string; validation: URLValidation['state']; - dataPlaywrightTestLabel: string; + dataTestId: string; }) => url && validation === 'success' ? ( - + ) : null; diff --git a/e2e/internet-presence-settings.spec.ts b/e2e/internet-presence-settings.spec.ts index d7744505a0c..c5fd899eddc 100644 --- a/e2e/internet-presence-settings.spec.ts +++ b/e2e/internet-presence-settings.spec.ts @@ -3,16 +3,11 @@ import { test, expect } from '@playwright/test'; import translations from '../client/i18n/locales/english/translations.json'; const settingsPageElement = { - githubInput: 'internet-github-input', - githubCheckmark: 'internet-github-check', - linkedinCheckmark: 'internet-linkedin-check', - twitterCheckmark: 'internet-twitter-check', - blueskyCheckmark: 'internet-bluesky-check', - personalWebsiteCheckmark: 'internet-website-check', - flashMessageAlert: 'flash-message', internetPresenceForm: 'internet-presence' } as const; +const githubUrl = 'https://github.com/certified-user'; + test.beforeEach(async ({ page }) => { // Reset input values execSync('node ../tools/scripts/seed/seed-demo-user --certified-user'); @@ -24,7 +19,8 @@ test.beforeEach(async ({ page }) => { test.describe('Your Internet Presence', () => { test.skip(({ browserName }) => browserName === 'webkit', 'flaky on Safari'); - test('should display the section with save button being disabled', async ({ + + test('should save a social link and keep it after reload', async ({ page }) => { await expect( @@ -34,69 +30,24 @@ test.describe('Your Internet Presence', () => { }) ).toBeVisible(); - await expect( - page - .getByTestId(settingsPageElement.internetPresenceForm) - .getByRole('button', { name: translations.buttons.save }) - ).toBeVisible(); - }); + const socialInput = page.getByRole('textbox', { name: 'GitHub' }); + await expect(socialInput).toBeVisible(); + await socialInput.fill(githubUrl); - const socials = [ - { - name: 'github', - url: 'https://github.com/certified-user', - label: 'GitHub', - checkTestId: settingsPageElement.githubCheckmark - }, - { - name: 'linkedin', - url: 'https://www.linkedin.com/in/certified-user', - label: 'LinkedIn', - checkTestId: settingsPageElement.linkedinCheckmark - }, - { - name: 'twitter', - url: 'https://x.com/certified-user', - label: 'X', - checkTestId: settingsPageElement.twitterCheckmark - }, - { - name: 'bluesky', - url: 'https://bsky.app/profile/certified-user.bsky.social', - label: 'Bluesky', - checkTestId: settingsPageElement.blueskyCheckmark - }, - { - name: 'website', - url: 'https://certified-user.com', - label: translations.settings.labels.personal, - checkTestId: settingsPageElement.personalWebsiteCheckmark - } - ]; + const saveButton = page + .locator(`[data-testid="${settingsPageElement.internetPresenceForm}"]`) + .getByRole('button', { name: translations.buttons.save }); - socials.forEach(social => { - test(`should hide ${social.name} checkmark by default`, async ({ - page - }) => { - await expect(page.getByTestId(social.checkTestId)).toBeHidden(); - }); + await expect(saveButton).toBeVisible(); + await saveButton.click(); + await expect(page.getByRole('alert').first()).toContainText( + 'We have updated your social links' + ); - test(`should update ${social.name} URL`, async ({ page }) => { - const socialInput = page.getByRole('textbox', { name: social.label }); - await expect(socialInput).toBeVisible(); - await socialInput.fill(social.url); - const socialCheckmark = page.getByTestId(social.checkTestId); - await expect(socialCheckmark).toBeVisible(); - - const saveButton = page - .getByTestId(settingsPageElement.internetPresenceForm) - .getByRole('button', { name: translations.buttons.save }); - - await expect(saveButton).toBeVisible(); - await saveButton.click(); - await expect(page.getByRole('alert').first()).toContainText( - 'We have updated your social links' - ); - }); + await page.reload(); + await page.getByRole('button', { name: 'Edit my profile' }).click(); + await expect(page.getByRole('textbox', { name: 'GitHub' })).toHaveValue( + githubUrl + ); }); });