mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-03 00:15:11 +03:00
Added E2E tests for API in signup form
fixes https://github.com/TryGhost/Team/issues/3330
This commit is contained in:
parent
73e8e9837b
commit
dbcdc8219d
@ -59,10 +59,10 @@ const Form: React.FC = () => {
|
||||
return (
|
||||
<div>
|
||||
<form className='flex' onSubmit={submit}>
|
||||
<input className={'flex-1 p-3 border ' + borderStyle} disabled={loading} placeholder='jamie@example.com' type="text" value={email} onChange={e => setEmail(e.target.value)}/>
|
||||
<button className='bg-accent p-3 text-white' disabled={loading} type='submit'>Subscribe</button>
|
||||
<input className={'flex-1 p-3 border ' + borderStyle} data-testid="input" disabled={loading} placeholder='jamie@example.com' type="text" value={email} onChange={e => setEmail(e.target.value)}/>
|
||||
<button className='bg-accent p-3 text-white' data-testid="button" disabled={loading} type='submit'>Subscribe</button>
|
||||
</form>
|
||||
{error && <p className='pt-0.5 text-red-500'>{error}</p>}
|
||||
{error && <p className='pt-0.5 text-red-500' data-testid="error-message">{error}</p>}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -14,7 +14,7 @@ export const SuccessPage: React.FC<SuccessPageProps> = ({email}) => {
|
||||
<h1 className="text-xl font-bold">Now check your email!</h1>
|
||||
</div>;
|
||||
}
|
||||
return <div className='bg-grey-300 p-24'>
|
||||
return <div className='bg-grey-300 p-24' data-testid="success-page">
|
||||
<h1 className="text-4xl font-bold">Now check your email!</h1>
|
||||
<p className='pb-3'>An email has been send to {email}.</p>
|
||||
</div>;
|
||||
|
@ -3,47 +3,182 @@ import {initialize} from '../utils/e2e';
|
||||
import {test} from '@playwright/test';
|
||||
|
||||
test.describe('Form', async () => {
|
||||
test('Displays the title', async ({page}) => {
|
||||
const frame = await initialize({page, title: 'Sign up to get the latest news and updates.'});
|
||||
test.describe('Display options', () => {
|
||||
test('Displays the title', async ({page}) => {
|
||||
const {frame} = await initialize({page, title: 'Sign up to get the latest news and updates.'});
|
||||
|
||||
// Check the Frame
|
||||
const h1 = frame.getByRole('heading');
|
||||
expect(await h1.innerText()).toBe('Sign up to get the latest news and updates.');
|
||||
});
|
||||
|
||||
test('Displays the description', async ({page}) => {
|
||||
const frame = await initialize({page, title: 'Title', description: 'Sign up to get the latest news and updates.'});
|
||||
|
||||
// Check the Frame
|
||||
const p = frame.getByRole('paragraph');
|
||||
expect(await p.innerText()).toBe('Sign up to get the latest news and updates.');
|
||||
});
|
||||
|
||||
test('Uses the accent color', async ({page}) => {
|
||||
// Need rgb notation here, because getComputedStyle returns rgb notation
|
||||
const color = 'rgb(255, 123, 0)';
|
||||
const frame = await initialize({page, color});
|
||||
const submitButton = frame.getByRole('button');
|
||||
|
||||
// Check calculated background color of the button
|
||||
const backgroundColor = await submitButton.evaluate((el) => {
|
||||
return window.getComputedStyle(el).backgroundColor;
|
||||
// Check the Frame
|
||||
const h1 = frame.getByRole('heading');
|
||||
expect(await h1.innerText()).toBe('Sign up to get the latest news and updates.');
|
||||
});
|
||||
|
||||
test('Displays the description', async ({page}) => {
|
||||
const {frame} = await initialize({page, title: 'Title', description: 'Sign up to get the latest news and updates.'});
|
||||
|
||||
// Check the Frame
|
||||
const p = frame.getByRole('paragraph');
|
||||
expect(await p.innerText()).toBe('Sign up to get the latest news and updates.');
|
||||
});
|
||||
|
||||
test('Uses the accent color', async ({page}) => {
|
||||
// Need rgb notation here, because getComputedStyle returns rgb notation
|
||||
const color = 'rgb(255, 123, 0)';
|
||||
const {frame} = await initialize({page, color});
|
||||
const submitButton = frame.getByRole('button');
|
||||
|
||||
// Check calculated background color of the button
|
||||
const backgroundColor = await submitButton.evaluate((el) => {
|
||||
return window.getComputedStyle(el).backgroundColor;
|
||||
});
|
||||
expect(backgroundColor).toBe(color);
|
||||
});
|
||||
|
||||
test('Has a minimal style when title is missing', async ({page}) => {
|
||||
let {frame} = await initialize({page});
|
||||
|
||||
// Check no title or description present
|
||||
await expect(frame.getByRole('heading')).toHaveCount(0);
|
||||
await expect(frame.getByRole('paragraph')).toHaveCount(0);
|
||||
|
||||
frame = (await initialize({page, description: 'Ignored'})).frame;
|
||||
|
||||
// Check no title or description present
|
||||
await expect(frame.getByRole('heading')).toHaveCount(0);
|
||||
await expect(frame.getByRole('paragraph')).toHaveCount(0);
|
||||
});
|
||||
expect(backgroundColor).toBe(color);
|
||||
});
|
||||
|
||||
test('Has a minimal style when title is missing', async ({page}) => {
|
||||
let frame = await initialize({page});
|
||||
test.describe('Submitting', () => {
|
||||
test('Can submit the form', async ({page}) => {
|
||||
const {frame, lastApiRequest} = await initialize({page, title: 'Sign up'});
|
||||
|
||||
// Check no title or description present
|
||||
await expect(frame.getByRole('heading')).toHaveCount(0);
|
||||
await expect(frame.getByRole('paragraph')).toHaveCount(0);
|
||||
// Fill out the form
|
||||
const emailInput = frame.getByTestId('input');
|
||||
await emailInput.fill('jamie@example.com');
|
||||
|
||||
frame = await initialize({page, description: 'Ignored'});
|
||||
// Click the submit button
|
||||
const submitButton = frame.getByTestId('button');
|
||||
await submitButton.click();
|
||||
|
||||
// Check no title or description present
|
||||
await expect(frame.getByRole('heading')).toHaveCount(0);
|
||||
await expect(frame.getByRole('paragraph')).toHaveCount(0);
|
||||
// Check input and button are gone
|
||||
await expect(frame.getByTestId('input')).toHaveCount(0);
|
||||
await expect(frame.getByTestId('button')).toHaveCount(0);
|
||||
|
||||
// Showing the success page
|
||||
await expect(frame.getByTestId('success-page')).toHaveCount(1);
|
||||
|
||||
// Check email address text is visible on the page
|
||||
await expect(frame.getByText('jamie@example.com')).toBeVisible();
|
||||
|
||||
// Check the request body
|
||||
expect(lastApiRequest.body).not.toBeNull();
|
||||
expect(lastApiRequest.body).toHaveProperty('labels', []);
|
||||
expect(lastApiRequest.body).toHaveProperty('email', 'jamie@example.com');
|
||||
});
|
||||
|
||||
test('Send a label when submitting the form', async ({page}) => {
|
||||
const {frame, lastApiRequest} = await initialize({page, title: 'Sign up', labels: 'Hello world'});
|
||||
|
||||
// Fill out the form
|
||||
const emailInput = frame.getByTestId('input');
|
||||
await emailInput.fill('jamie@example.com');
|
||||
|
||||
// Click the submit button
|
||||
const submitButton = frame.getByTestId('button');
|
||||
await submitButton.click();
|
||||
|
||||
// Showing the success page
|
||||
await expect(frame.getByTestId('success-page')).toHaveCount(1);
|
||||
|
||||
// Check the request body
|
||||
expect(lastApiRequest.body).not.toBeNull();
|
||||
expect(lastApiRequest.body).toHaveProperty('labels', ['Hello world']);
|
||||
expect(lastApiRequest.body).toHaveProperty('email', 'jamie@example.com');
|
||||
});
|
||||
|
||||
test('Send multiple labels when submitting the form', async ({page}) => {
|
||||
const {frame, lastApiRequest} = await initialize({page, title: 'Sign up', labels: 'Hello world,and another one'});
|
||||
|
||||
// Fill out the form
|
||||
const emailInput = frame.getByTestId('input');
|
||||
await emailInput.fill('hey@example.com');
|
||||
|
||||
// Click the submit button
|
||||
const submitButton = frame.getByTestId('button');
|
||||
await submitButton.click();
|
||||
|
||||
// Showing the success page
|
||||
await expect(frame.getByTestId('success-page')).toHaveCount(1);
|
||||
|
||||
// Check the request body
|
||||
expect(lastApiRequest.body).not.toBeNull();
|
||||
expect(lastApiRequest.body).toHaveProperty('labels', ['Hello world', 'and another one']);
|
||||
expect(lastApiRequest.body).toHaveProperty('email', 'hey@example.com');
|
||||
});
|
||||
|
||||
test('Cannot submit the form with invalid email address', async ({page}) => {
|
||||
const {frame, lastApiRequest} = await initialize({page, title: 'Sign up'});
|
||||
|
||||
// Fill out the form
|
||||
const emailInput = frame.getByTestId('input');
|
||||
await emailInput.fill('invalid');
|
||||
|
||||
// Click the submit button
|
||||
const submitButton = frame.getByTestId('button');
|
||||
await submitButton.click();
|
||||
|
||||
// Check input and button are not gone
|
||||
await expect(frame.getByTestId('input')).toHaveCount(1);
|
||||
await expect(frame.getByTestId('button')).toHaveCount(1);
|
||||
|
||||
// Not showing the success page
|
||||
await expect(frame.getByTestId('success-page')).toHaveCount(0);
|
||||
|
||||
// Check error message is visible on the page
|
||||
const errorMessage = frame.getByTestId('error-message');
|
||||
await expect(errorMessage).toHaveCount(1);
|
||||
expect(await errorMessage.innerText()).toBe('Please enter a valid email address');
|
||||
|
||||
expect(lastApiRequest.body).toBeNull();
|
||||
|
||||
// Try again
|
||||
await emailInput.fill('valid@example.com');
|
||||
await submitButton.click();
|
||||
|
||||
// Check input and button are gone
|
||||
await expect(frame.getByTestId('input')).toHaveCount(0);
|
||||
await expect(frame.getByTestId('button')).toHaveCount(0);
|
||||
|
||||
// Showing the success page
|
||||
await expect(frame.getByTestId('success-page')).toHaveCount(1);
|
||||
|
||||
// Check email address text is visible on the page
|
||||
await expect(frame.getByText('valid@example.com')).toBeVisible();
|
||||
});
|
||||
|
||||
test('Shows error message on network issues', async ({page}) => {
|
||||
const {frame} = await initialize({page, title: 'Sign up', site: '127.0.0.1:9999'});
|
||||
|
||||
// Fill out the form
|
||||
const emailInput = frame.getByTestId('input');
|
||||
await emailInput.fill('valid@example.com');
|
||||
|
||||
// Click the submit button
|
||||
const submitButton = frame.getByTestId('button');
|
||||
await submitButton.click();
|
||||
|
||||
// Check input and button are not gone
|
||||
await expect(frame.getByTestId('input')).toHaveCount(1);
|
||||
await expect(frame.getByTestId('button')).toHaveCount(1);
|
||||
|
||||
// Not showing the success page
|
||||
await expect(frame.getByTestId('success-page')).toHaveCount(0);
|
||||
|
||||
// Check error message is visible on the page
|
||||
const errorMessage = frame.getByTestId('error-message');
|
||||
await expect(errorMessage).toHaveCount(1);
|
||||
expect(await errorMessage.innerText()).toBe('Something went wrong, please try again.');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -1,10 +1,21 @@
|
||||
import {E2E_PORT} from '../../playwright.config';
|
||||
|
||||
const MOCKED_SITE_URL = 'http://localhost:1234';
|
||||
|
||||
type LastApiRequest = {
|
||||
body: null | any
|
||||
};
|
||||
|
||||
export async function initialize({page, ...options}: {page: any; title?: string, description?: string, logo?: string, color?: string, site?: string, labels?: string}) {
|
||||
const url = `http://localhost:${E2E_PORT}/signup-form.min.js`;
|
||||
|
||||
await page.goto('about:blank');
|
||||
await page.setViewportSize({width: 1000, height: 1000});
|
||||
const lastApiRequest = await mockApi({page});
|
||||
|
||||
if (!options.site) {
|
||||
options.site = MOCKED_SITE_URL;
|
||||
}
|
||||
|
||||
await page.evaluate((data) => {
|
||||
const scriptTag = document.createElement('script');
|
||||
@ -16,5 +27,27 @@ export async function initialize({page, ...options}: {page: any; title?: string,
|
||||
document.body.appendChild(scriptTag);
|
||||
}, {url, options});
|
||||
await page.waitForSelector('iframe');
|
||||
return page.frameLocator('iframe');
|
||||
|
||||
return {
|
||||
frame: page.frameLocator('iframe'),
|
||||
lastApiRequest
|
||||
};
|
||||
}
|
||||
|
||||
export async function mockApi({page}: {page: any}) {
|
||||
const lastApiRequest: LastApiRequest = {
|
||||
body: null
|
||||
};
|
||||
|
||||
await page.route(`${MOCKED_SITE_URL}/members/api/send-magic-link/`, async (route) => {
|
||||
const requestBody = JSON.parse(route.request().postData());
|
||||
lastApiRequest.body = requestBody;
|
||||
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
body: 'ok'
|
||||
});
|
||||
});
|
||||
|
||||
return lastApiRequest;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user