Skip to content

Commit f332816

Browse files
committed
[WIP] E2E Tests
1 parent b5f460c commit f332816

19 files changed

Lines changed: 426 additions & 85 deletions

File tree

.github/workflows/basic.yml

Lines changed: 187 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,18 @@ env:
1313
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
1414
TURBO_REMOTE_CACHE_SIGNATURE_KEY: ${{ secrets.TURBO_REMOTE_CACHE_SIGNATURE_KEY }}
1515
BIGCOMMERCE_STORE_HASH: ${{ vars.BIGCOMMERCE_STORE_HASH }}
16-
BIGCOMMERCE_STOREFRONT_TOKEN: ${{ secrets.BIGCOMMERCE_STOREFRONT_TOKEN }}
1716
BIGCOMMERCE_CHANNEL_ID: ${{ vars.BIGCOMMERCE_CHANNEL_ID }}
17+
BIGCOMMERCE_CLIENT_ID: ${{ secrets.BIGCOMMERCE_CLIENT_ID }}
18+
BIGCOMMERCE_CLIENT_SECRET: ${{ secrets.BIGCOMMERCE_CLIENT_SECRET }}
19+
BIGCOMMERCE_STOREFRONT_TOKEN: ${{ secrets.BIGCOMMERCE_STOREFRONT_TOKEN }}
20+
BIGCOMMERCE_ACCESS_TOKEN: ${{ secrets.BIGCOMMERCE_ACCESS_TOKEN }}
21+
TEST_CUSTOMER_ID: ${{ vars.TEST_CUSTOMER_ID }}
22+
TEST_CUSTOMER_EMAIL: ${{ vars.TEST_CUSTOMER_EMAIL }}
23+
TEST_CUSTOMER_PASSWORD: ${{ secrets.TEST_CUSTOMER_PASSWORD }}
24+
TESTS_FALLBACK_LOCALE: ${{ vars.TESTS_FALLBACK_LOCALE }}
25+
TESTS_READ_ONLY: ${{ vars.TESTS_READ_ONLY }}
26+
DEFAULT_PRODUCT_ID: ${{ vars.DEFAULT_PRODUCT_ID }}
27+
DEFAULT_COMPLEX_PRODUCT_ID: ${{ vars.DEFAULT_COMPLEX_PRODUCT_ID }}
1828

1929
jobs:
2030
lint-typecheck:
@@ -75,3 +85,179 @@ jobs:
7585

7686
- name: Run Tests
7787
run: pnpm run test
88+
89+
e2e-tests:
90+
name: E2E Functional Tests
91+
92+
runs-on: ubuntu-latest
93+
94+
steps:
95+
- name: Checkout code
96+
uses: actions/checkout@v4
97+
with:
98+
fetch-depth: 2
99+
100+
- uses: pnpm/action-setup@v3
101+
102+
- name: Use Node.js
103+
uses: actions/setup-node@v4
104+
with:
105+
node-version-file: ".nvmrc"
106+
cache: "pnpm"
107+
108+
- name: Install dependencies
109+
run: pnpm install --frozen-lockfile
110+
111+
- name: Install Playwright browsers
112+
run: pnpm exec playwright install --with-deps chromium webkit
113+
working-directory: ./core
114+
115+
- name: Build catalyst-client
116+
run: pnpm --filter @bigcommerce/catalyst-client build
117+
118+
- name: Build catalyst-core
119+
run: pnpm --filter @bigcommerce/catalyst-core build
120+
121+
- name: Start server
122+
run: |
123+
pnpm start &
124+
npx wait-on http://localhost:3000 --timeout 60000
125+
working-directory: ./core
126+
env:
127+
PORT: 3000
128+
AUTH_SECRET: ${{ secrets.TESTS_AUTH_SECRET }}
129+
AUTH_TRUST_HOST: ${{ vars.TESTS_AUTH_TRUST_HOST }}
130+
BIGCOMMERCE_TRUSTED_PROXY_SECRET: ${{ secrets.BIGCOMMERCE_TRUSTED_PROXY_SECRET }}
131+
TESTS_LOCALE: ${{ vars.TESTS_LOCALE }}
132+
DEFAULT_REVALIDATE_TARGET: 1
133+
134+
- name: Run E2E tests
135+
run: pnpm exec playwright test tests/ui/e2e
136+
working-directory: ./core
137+
env:
138+
PLAYWRIGHT_TEST_BASE_URL: http://localhost:3000
139+
140+
- name: Upload test results
141+
if: ${{ !cancelled() }}
142+
uses: actions/upload-artifact@v4
143+
with:
144+
name: playwright-report
145+
path: ./core/.tests/reports/
146+
retention-days: 3
147+
148+
e2e-tests-no-trailing:
149+
name: E2E Functional Tests (TRAILING_SLASH=false)
150+
151+
runs-on: ubuntu-latest
152+
153+
steps:
154+
- name: Checkout code
155+
uses: actions/checkout@v4
156+
with:
157+
fetch-depth: 2
158+
159+
- uses: pnpm/action-setup@v3
160+
161+
- name: Use Node.js
162+
uses: actions/setup-node@v4
163+
with:
164+
node-version-file: ".nvmrc"
165+
cache: "pnpm"
166+
167+
- name: Install dependencies
168+
run: pnpm install --frozen-lockfile
169+
170+
- name: Install Playwright browsers
171+
run: pnpm exec playwright install --with-deps chromium
172+
working-directory: ./core
173+
174+
- name: Build catalyst-client
175+
run: pnpm --filter @bigcommerce/catalyst-client build
176+
177+
- name: Build catalyst-core
178+
run: pnpm --filter @bigcommerce/catalyst-core build
179+
180+
- name: Start server
181+
run: |
182+
pnpm start &
183+
npx wait-on http://localhost:3000 --timeout 60000
184+
working-directory: ./core
185+
env:
186+
PORT: 3000
187+
AUTH_SECRET: ${{ secrets.TESTS_AUTH_SECRET }}
188+
AUTH_TRUST_HOST: ${{ vars.TESTS_AUTH_TRUST_HOST }}
189+
BIGCOMMERCE_TRUSTED_PROXY_SECRET: ${{ secrets.BIGCOMMERCE_TRUSTED_PROXY_SECRET }}
190+
TESTS_LOCALE: ${{ vars.TESTS_LOCALE }}
191+
TRAILING_SLASH: false
192+
193+
- name: Run E2E tests
194+
run: pnpm exec playwright test tests/ui/e2e --grep @no-trailing-slash
195+
working-directory: ./core
196+
env:
197+
PLAYWRIGHT_TEST_BASE_URL: http://localhost:3000
198+
199+
- name: Upload test results
200+
if: ${{ !cancelled() }}
201+
uses: actions/upload-artifact@v4
202+
with:
203+
name: playwright-report-no-trailing
204+
path: ./core/.tests/reports/
205+
retention-days: 3
206+
207+
e2e-tests-alternate-locale:
208+
name: E2E Functional Tests (alternate locale)
209+
210+
runs-on: ubuntu-latest
211+
212+
steps:
213+
- name: Checkout code
214+
uses: actions/checkout@v4
215+
with:
216+
fetch-depth: 2
217+
218+
- uses: pnpm/action-setup@v3
219+
220+
- name: Use Node.js
221+
uses: actions/setup-node@v4
222+
with:
223+
node-version-file: ".nvmrc"
224+
cache: "pnpm"
225+
226+
- name: Install dependencies
227+
run: pnpm install --frozen-lockfile
228+
229+
- name: Install Playwright browsers
230+
run: pnpm exec playwright install --with-deps chromium
231+
working-directory: ./core
232+
233+
- name: Build catalyst-client
234+
run: pnpm --filter @bigcommerce/catalyst-client build
235+
236+
- name: Build catalyst-core
237+
run: pnpm --filter @bigcommerce/catalyst-core build
238+
239+
- name: Start server
240+
run: |
241+
pnpm start &
242+
npx wait-on http://localhost:3000 --timeout 60000
243+
working-directory: ./core
244+
env:
245+
PORT: 3000
246+
AUTH_SECRET: ${{ secrets.TESTS_AUTH_SECRET }}
247+
AUTH_TRUST_HOST: ${{ vars.TESTS_AUTH_TRUST_HOST }}
248+
BIGCOMMERCE_TRUSTED_PROXY_SECRET: ${{ secrets.BIGCOMMERCE_TRUSTED_PROXY_SECRET }}
249+
TESTS_LOCALE: ${{ vars.TESTS_ALTERNATE_LOCALE }}
250+
251+
- name: Run E2E tests
252+
run: pnpm exec playwright test tests/ui/e2e --grep @alternate-locale
253+
working-directory: ./core
254+
env:
255+
PLAYWRIGHT_TEST_BASE_URL: http://localhost:3000
256+
257+
- name: Upload test results
258+
if: ${{ !cancelled() }}
259+
uses: actions/upload-artifact@v4
260+
with:
261+
name: playwright-report-alternate-locale
262+
path: ./core/.tests/reports/
263+
retention-days: 3

core/playwright.config.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export default defineConfig({
2929
projects: [
3030
{
3131
name: 'tests-chromium',
32+
testIgnore: /.*\.mobile\.spec\.ts$/,
3233
use: {
3334
...devices['Desktop Chrome'],
3435
launchOptions: {
@@ -38,6 +39,14 @@ export default defineConfig({
3839
},
3940
},
4041
},
42+
{
43+
name: 'tests-webkit-mobile',
44+
testMatch: /.*\.mobile\.spec\.ts$/,
45+
use: {
46+
...devices['iPhone 11'],
47+
// WebKit doesn't support --disable-web-security
48+
},
49+
},
4150
],
42-
retries: 1,
51+
retries: 2,
4352
});

core/tests/fixtures/utils/api/subscribe/http.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1+
import { testEnv } from '~/tests/environment';
2+
13
import { httpClient } from '../client';
24

35
import { SubscribeApi } from '.';
46

57
export const subscribeHttpClient: SubscribeApi = {
68
subscribe: async (email: string, firstName: string, lastName: string) => {
79
await httpClient.post('/v3/customers/subscribers', {
10+
channel_id: testEnv.BIGCOMMERCE_CHANNEL_ID ?? 1,
811
email,
912
first_name: firstName,
1013
last_name: lastName,

core/tests/tags.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
export const TAGS = {
22
// @writes-data is used to mark tests that modify data on the storefront without directly using the API.
33
writesData: '@writes-data',
4+
// @alternate-locale is used to mark tests that should be run with an alternate locale setting.
5+
alternateLocale: '@alternate-locale',
6+
// @no-trailing-slash is used to mark tests that should be run with TRAILING_SLASH disabled.
7+
noTrailingSlash: '@no-trailing-slash',
48
};

core/tests/ui/e2e/account/account.spec.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { defaultLocale } from '~/i18n/locales';
22
import { testEnv } from '~/tests/environment';
33
import { expect, test } from '~/tests/fixtures';
44
import { getTranslations } from '~/tests/lib/i18n';
5+
import { TAGS } from '~/tests/tags';
56

67
const accountUrls = [
78
'/account/orders',
@@ -18,14 +19,16 @@ accountUrls.forEach((url) => {
1819
});
1920

2021
accountUrls.forEach((url) => {
21-
test(`${url} is restricted for guest users when explicitly browsing to the locale URL`, async ({
22-
page,
23-
}) => {
24-
test.skip(testEnv.TESTS_LOCALE === defaultLocale);
22+
test(
23+
`${url} is restricted for guest users when explicitly browsing to the locale URL`,
24+
{ tag: TAGS.alternateLocale },
25+
async ({ page }) => {
26+
test.skip(testEnv.TESTS_LOCALE === defaultLocale);
2527

26-
await page.goto(`/${testEnv.TESTS_LOCALE}/${url}`);
27-
await expect(page).toHaveURL('/login/', { timeout: 1000 });
28-
});
28+
await page.goto(`/${testEnv.TESTS_LOCALE}/${url}`);
29+
await expect(page).toHaveURL('/login/', { timeout: 1000 });
30+
},
31+
);
2932
});
3033

3134
test('Account page displays the menu items for each section', async ({ page, customer }) => {

core/tests/ui/e2e/account/wishlist-details.spec.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,12 @@ test('Wishlist details displays an out of stock product correctly', async ({
129129
page,
130130
catalog,
131131
customer,
132+
settings,
132133
}) => {
134+
await settings.setInventorySettings({ showOutOfStockMessage: true });
135+
133136
const product = await catalog.createSimpleProduct({
137+
inventoryTracking: 'product',
134138
inventoryLevel: 0,
135139
});
136140

core/tests/ui/e2e/account/wishlists.mobile.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ test('Share button calls navigator.share with the correct URL', async ({ page, c
3636
});
3737

3838
await page.goto('/account/wishlists/');
39+
await page.waitForLoadState('networkidle');
3940

4041
const locator = page.getByRole('region', { name });
4142

core/tests/ui/e2e/auth/login.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ test('JWT login redirects to the specified redirect_to value in the token payloa
8686

8787
await page.goto(`/login/token/${jwt}`);
8888
await page.waitForURL('/account/addresses/');
89-
await expect(page.getByRole('heading', { name: t('title') })).toBeVisible();
89+
await expect(page.getByRole('heading', { name: t('title'), exact: true })).toBeVisible();
9090
});
9191

9292
test('JWT login with an invalid/expired token shows an error message', async ({ page }) => {

core/tests/ui/e2e/auth/register.spec.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ test('Registration works as expected', { tag: [TAGS.writesData] }, async ({ page
3737
await page.getByRole('combobox', { name: 'Country' }).click();
3838
await page.keyboard.type('United States');
3939
await page.keyboard.press('Enter');
40-
await page.getByRole('radio', { name: 'Home' }).click();
4140
await page.getByRole('button', { name: t('Auth.Register.cta') }).click();
4241

4342
await expect(page).toHaveURL('/account/orders/');
@@ -84,7 +83,6 @@ test('Registration fails if email is already in use', async ({ page, customer })
8483
await page.getByRole('combobox', { name: 'Country' }).click();
8584
await page.keyboard.type('United States');
8685
await page.keyboard.press('Enter');
87-
await page.getByRole('radio', { name: 'Home' }).click();
8886
await page.getByRole('button', { name: t('cta') }).click();
8987

9088
await expect(page).not.toHaveURL('/account/orders/');

core/tests/ui/e2e/blog.spec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ test('Blog is accessible and displays posts', async ({ page, blog }) => {
1313

1414
const breadcrumbs = page.getByLabel('breadcrumb');
1515

16-
await expect(breadcrumbs.getByText(t('home'))).toBeVisible();
17-
await expect(breadcrumbs.getByText(name)).toBeVisible();
16+
await expect(breadcrumbs.getByText(t('home')).first()).toBeVisible();
17+
await expect(breadcrumbs.getByText(name).first()).toBeVisible();
1818

1919
// eslint-disable-next-line @typescript-eslint/no-misused-promises
2020
posts.forEach(async (post) => {
2121
await expect(
22-
page.locator(`a[href*="${post.path}"]`).filter({ hasText: post.title }),
22+
page.locator(`a[href*="${post.path}"]`).filter({ hasText: post.title }).first(),
2323
).toBeVisible();
2424
});
2525
});

0 commit comments

Comments
 (0)