Skip to content

Commit 31fbf0c

Browse files
committed
[WIP] E2E Tests
1 parent dcad856 commit 31fbf0c

File tree

18 files changed

+362
-44
lines changed

18 files changed

+362
-44
lines changed

.github/workflows/basic.yml

Lines changed: 184 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,16 @@ 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 }}
1826

1927
jobs:
2028
lint-typecheck:
@@ -75,3 +83,178 @@ jobs:
7583

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

core/playwright.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,5 @@ export default defineConfig({
3939
},
4040
},
4141
],
42-
retries: 1,
42+
retries: 2,
4343
});

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/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
});

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ test('Cart page displays empty state when no items are in the cart', async ({ pa
88
await page.goto('/cart');
99

1010
await expect(page.getByRole('heading', { name: t('title') })).toBeVisible();
11-
await expect(page.getByText(t('Empty.title'))).toBeVisible();
12-
await expect(page.getByText(t('Empty.subtitle'))).toBeVisible();
11+
await expect(page.getByRole('heading', { name: t('Empty.title'), exact: true })).toBeVisible();
12+
await expect(page.getByText(t('Empty.subtitle')).first()).toBeVisible();
1313
await expect(page.getByRole('link', { name: t('Empty.cta') })).toBeVisible();
1414
});
1515

0 commit comments

Comments
 (0)