Skip to content

Commit

Permalink
refactor(core): functional test changes (#1359)
Browse files Browse the repository at this point in the history
* test(core): remove unused JS coverage collection

* chore(core): move ui test files around

* test(core): update skipped tests

* test(core): remove serial ran tests

* test(core): add customer account fixture for tests
  • Loading branch information
chanceaclark committed Sep 13, 2024
1 parent 27cbfd2 commit f37deb6
Show file tree
Hide file tree
Showing 41 changed files with 306 additions and 738 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/regression-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ on:

env:
PLAYWRIGHT_TEST_BASE_URL: ${{ github.event.deployment_status.target_url }}
TEST_ACCOUNT_EMAIL: ${{ secrets.TEST_ACCOUNT_EMAIL }}
TEST_ACCOUNT_PASSWORD: ${{ secrets.TEST_ACCOUNT_PASSWORD }}
VERCEL_PROTECTION_BYPASS: ${{ secrets.VERCEL_PROTECTION_BYPASS_CATALYST_LATEST }}
BIGCOMMERCE_ACCESS_TOKEN: ${{ secrets.BIGCOMMERCE_ACCESS_TOKEN }}
BIGCOMMERCE_STORE_HASH: ${{ secrets.BIGCOMMERCE_STORE_HASH }}

jobs:
generate-lighthouse-audit:
Expand Down Expand Up @@ -146,7 +146,7 @@ jobs:
if: failure()
with:
name: playwright-report-ui
path: core/test-results/
path: core/playwright-report/
retention-days: 30

- name: Send slack notification
Expand Down Expand Up @@ -208,7 +208,7 @@ jobs:
if: failure()
with:
name: playwright-report-visual-regression
path: core/test-results/
path: core/playwright-report/
retention-days: 30

- name: Send slack notification
Expand Down
10 changes: 7 additions & 3 deletions core/app/[locale]/(default)/blog/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,15 @@ export default async function Blog({ searchParams }: Props) {
<div className="mx-auto max-w-screen-xl">
<h1 className="mb-8 text-3xl font-black lg:text-5xl">{blogPosts.name}</h1>

<div className="grid grid-cols-1 gap-10 sm:grid-cols-2 lg:grid-cols-3 lg:gap-8">
<ul className="grid grid-cols-1 gap-10 sm:grid-cols-2 lg:grid-cols-3 lg:gap-8">
{blogPosts.posts.items.map((post) => {
return <BlogPostCard data={post} key={post.entityId} />;
return (
<li key={post.entityId}>
<BlogPostCard data={post} />
</li>
);
})}
</div>
</ul>

<Pagination
endCursor={blogPosts.posts.pageInfo.endCursor ?? undefined}
Expand Down
2 changes: 0 additions & 2 deletions core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,6 @@
"dotenv-cli": "^7.4.2",
"eslint": "^8.57.0",
"eslint-config-next": "14.2.8",
"monocart-coverage-reports": "^2.10.3",
"monocart-reporter": "^2.8.0",
"postcss": "^8.4.45",
"prettier": "^3.3.3",
"prettier-plugin-tailwindcss": "^0.6.6",
Expand Down
43 changes: 1 addition & 42 deletions core/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -1,57 +1,16 @@
import { defineConfig, devices } from '@playwright/test';
import { config } from 'dotenv';
import { CoverageReportOptions } from 'monocart-reporter';

config();

const coverageReportOptions: CoverageReportOptions = {
name: 'Catalyst Code Coverage Report',

entryFilter: (entry) => {
return entry.url.includes('next/static/chunks') || entry.url.includes('next/server/app');
},

sourceFilter: (sourcePath) => {
return (
sourcePath.startsWith('bigcommerce/catalyst-core') &&
(sourcePath.endsWith('.ts') || sourcePath.endsWith('.tsx'))
);
},

sourcePath: (fileSource) => {
const list = ['core/'];

// eslint-disable-next-line no-restricted-syntax
for (const pre of list) {
if (fileSource.startsWith(pre)) {
return fileSource.slice(pre.length);
}
}

return fileSource;
},
reports: ['v8'],
};

export default defineConfig({
testDir: './tests',
expect: {
toHaveScreenshot: {
maxDiffPixelRatio: 0.02,
},
},
reporter: process.env.CI
? [['list'], ['monocart-reporter']]
: [
['list'],
[
'monocart-reporter',
{
coverage: coverageReportOptions,
},
],
],
globalTeardown: './tests/global-teardown.js',
reporter: [['list'], ['html']],
use: {
baseURL: process.env.PLAYWRIGHT_TEST_BASE_URL,
screenshot: 'only-on-failure',
Expand Down
33 changes: 0 additions & 33 deletions core/tests/fixtures.js

This file was deleted.

25 changes: 25 additions & 0 deletions core/tests/fixtures/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { test as base } from '@playwright/test';

import { AccountFactory } from './utils/account';

interface Fixtures {
/**
* This fixture enables the creation, deletion, and the ability to login and logout of customer accounts.
*/
account: AccountFactory;
}

export const test = base.extend<Fixtures>({
account: [
async ({ page }, use) => {
const accountFactory = new AccountFactory(page);

await use(accountFactory);

await accountFactory.cleanup();
},
{ scope: 'test' },
],
});

export { expect, type Page } from '@playwright/test';
25 changes: 25 additions & 0 deletions core/tests/fixtures/utils/account/account.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { type Page } from '@playwright/test';

export class Account {
constructor(
private readonly page: Page,
readonly firstName: string,
readonly lastName: string,
readonly email: string,
readonly password: string,
readonly id: number,
) {}

async login() {
await this.page.goto('/login/');
await this.page.getByLabel('Email').fill(this.email);
await this.page.getByLabel('Password').fill(this.password);
await this.page.getByRole('button', { name: 'Log in' }).click();
await this.page.waitForURL('/account/');
}

async logout() {
await this.page.getByRole('button', { name: 'Account' }).click();
await this.page.getByRole('menuitem', { name: 'Log out' }).click();
}
}
74 changes: 74 additions & 0 deletions core/tests/fixtures/utils/account/create.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { faker, fi } from '@faker-js/faker';
import { z } from 'zod';

const Customer = z.object({
id: z.number(),
});

const CreateCustomersResponse = z.object({
data: z.array(Customer),
});

export async function createAccount() {
const firstName = faker.person.firstName();
const lastName = faker.person.lastName();
const email = faker.internet.email({ firstName, lastName });
// Prefix is added to ensure that the password requirements are met
const password = faker.internet.password({ pattern: /[a-zA-Z0-9]/, prefix: '1At', length: 10 });
const address1 = faker.location.streetAddress();
const city = faker.location.city();
const state = faker.location.state();
const postal_code = faker.location.zipCode('#####');

if (!process.env.BIGCOMMERCE_ACCESS_TOKEN) {
throw new Error('BIGCOMMERCE_ACCESS_TOKEN is not set');
}

if (!process.env.BIGCOMMERCE_STORE_HASH) {
throw new Error('BIGCOMMERCE_STORE_HASH is not set');
}

const response = await fetch(
`https://api.bigcommerce.com/stores/${process.env.BIGCOMMERCE_STORE_HASH}/v3/customers`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Auth-Token': process.env.BIGCOMMERCE_ACCESS_TOKEN,
},
body: JSON.stringify([
{
first_name: firstName,
last_name: lastName,
email,
authentication: {
new_password: password,
},
addresses: [
{
first_name: firstName,
last_name: lastName,
address1,
city,
state_or_province: state,
country_code: 'US',
postal_code,
},
],
},
]),
},
);

const data: unknown = await response.json();
const parsedResponse = CreateCustomersResponse.parse(data);
const customer = Customer.parse(parsedResponse.data[0]);

return {
firstName,
lastName,
email,
password,
id: customer.id,
};
}
24 changes: 24 additions & 0 deletions core/tests/fixtures/utils/account/delete.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
export async function deleteAccount(customerId: number) {
if (!process.env.BIGCOMMERCE_ACCESS_TOKEN) {
throw new Error('BIGCOMMERCE_ACCESS_TOKEN is not set');
}

if (!process.env.BIGCOMMERCE_STORE_HASH) {
throw new Error('BIGCOMMERCE_STORE_HASH is not set');
}

try {
await fetch(
`https://api.bigcommerce.com/stores/${process.env.BIGCOMMERCE_STORE_HASH}/v3/customers?id:in=${customerId}`,
{
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
'X-Auth-Token': process.env.BIGCOMMERCE_ACCESS_TOKEN,
},
},
);
} catch (error) {
console.error(error);
}
}
33 changes: 33 additions & 0 deletions core/tests/fixtures/utils/account/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { type Page } from '@playwright/test';

import { Account } from './account';
import { createAccount } from './create';
import { deleteAccount } from './delete';

export class AccountFactory {
autoCleanup = false;
private accounts: Account[] = [];

constructor(private readonly page: Page) {}

async create() {
const customer = await createAccount();

const account = new Account(
this.page,
customer.firstName,
customer.lastName,
customer.email,
customer.password,
customer.id,
);

this.accounts.push(account);

return account;
}

async cleanup() {
await Promise.all(this.accounts.map(async (account) => await deleteAccount(account.id)));
}
}
60 changes: 0 additions & 60 deletions core/tests/global-teardown.js

This file was deleted.

Loading

0 comments on commit f37deb6

Please sign in to comment.