Skip to content

Commit

Permalink
fix: playwright tests
Browse files Browse the repository at this point in the history
edmundhung committed Feb 11, 2024
1 parent cbe0e14 commit 454c29c
Showing 13 changed files with 185 additions and 147 deletions.
Original file line number Diff line number Diff line change
@@ -19,9 +19,9 @@ jobs:
- name: 🎭 Install Playwright
run: npx playwright install --with-deps
- name: 📦 Build the worker
run: npm run build
run: npx remix vite:build
- name: 💣 Run some tests
run: npm run test
run: npx playwright test

lint:
name: ⬣ Linting
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -8,5 +8,9 @@ node_modules
# Cloudflare
.wrangler

# Playwright
/test-results
/playwright-report

# Remix stacks
/package-lock.json
3 changes: 0 additions & 3 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npx lint-staged
6 changes: 4 additions & 2 deletions app/root.tsx
Original file line number Diff line number Diff line change
@@ -95,7 +95,9 @@ function Layout({
return (
<div className="container mx-auto">
<div className="flex flex-col-reverse lg:flex-row">
<section className="flex-1 relative border-t lg:border-t-0">
<section
className={`flex-1 relative ${children ? 'border-t lg:border-t-0' : ''}`.trim()}
>
<div className="sticky top-0">
<div className="flex flex-col lg:min-h-screen lg:py-10 px-5 py-5">
<header className="py-4">
@@ -115,7 +117,7 @@ function Layout({
</a>
) : null}
</div>
<footer>
<footer className="pt-8">
Wanna know more about Remix? Check out{' '}
<a className="underline" href="https://remix.guide">
Remix Guide
11 changes: 6 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
{
"private": true,
"name": "remix-worker-template",
"name": "remix-cloudflare-template",
"type": "module",
"description": "All-in-one remix starter template for Cloudflare Pages",
"module": "./dist/worker.mjs",
"scripts": {
"dev": "remix vite:dev",
"test": "NODE_OPTIONS=\"--experimental-vm-modules --no-warnings\" playwright test",
"test": "playwright test --ui",
"start": "wrangler pages dev ./build/client",
"build": "remix vite:build",
"cleanup": "rimraf .cache ./build ./public/build",
"cleanup": "rimraf .cache ./build",
"lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .",
"typecheck": "tsc",
"prepare": "husky install"
"prepare": "husky"
},
"dependencies": {
"@markdoc/markdoc": "^0.4.0",
@@ -39,6 +39,7 @@
"husky": "^9.0.10",
"lint-staged": "^15.2.2",
"miniflare": "^3.20240129.1",
"msw": "^2.1.7",
"postcss": "^8.4.35",
"prettier": "^3.2.5",
"rimraf": "^5.0.5",
30 changes: 17 additions & 13 deletions playwright.config.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
import { type PlaywrightTestConfig, devices } from '@playwright/test';
import { defineConfig, devices } from '@playwright/test';

const config: PlaywrightTestConfig = {
const PORT = process.env.PORT || '5173';

export default defineConfig({
testDir: './tests/e2e',
timeout: 15 * 1000,
expect: {
timeout: 5 * 1000,
},
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: 'html',
use: {
baseURL: `http://localhost:${PORT}`,
trace: 'on-first-retry',
},

projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
{
name: 'firefox',
use: { ...devices['Desktop Firefox'] },
},
{
name: 'webkit',
use: { ...devices['Desktop Safari'] },
use: {
...devices['Desktop Chrome'],
},
},
],
};
export default config;
});
2 changes: 1 addition & 1 deletion postcss.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module.exports = {
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
6 changes: 4 additions & 2 deletions tailwind.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
module.exports = {
import typeography from '@tailwindcss/typography';

export default {
content: ['./app/**/*.tsx', './app/**/*.ts'],
theme: {},
plugins: [require('@tailwindcss/typography')],
plugins: [typeography],
};
65 changes: 65 additions & 0 deletions tests/e2e/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { http } from 'msw';
import { test, expect } from '../playwright';

/**
* You can interact with browser through the page instance
*/
test('shows the package name', async ({ page }) => {
await page.goto('/');

const title = page.getByRole('heading', {
name: 'remix-cloudflare-template',
level: 2,
});

await expect(title).toBeVisible();
});

/**
* You can interact with the wrangler binding similar to the remix app
*/
test('cache the README in KV', async ({ page, wrangler }) => {
await wrangler.bindings.cache.put('github/README.md', '# cached-readme');
await page.goto('/');

const title = page.getByRole('heading', {
name: 'cached-readme',
level: 1,
});

await expect(title).toBeVisible();
});

/**
* You can also mock the requests with MSW
*/
test('fetch README from GitHub if not cached', async ({
page,
wrangler,
msw,
}) => {
// Mock request
msw.use(
http.get(
'https://api.github.com/repos/edmundhung/remix-cloudflare-template/contents/README.md',
() => {
return Response.json({
type: 'file',
content: btoa('# testing'),
});
},
),
);

// Clear cache
await wrangler.bindings.cache.delete('github/README.md');

await page.goto('/');

const title = page.getByRole('heading', {
name: 'testing',
level: 1,
});

await expect(title).toBeVisible();
});
49 changes: 0 additions & 49 deletions tests/index.spec.ts

This file was deleted.

81 changes: 81 additions & 0 deletions tests/playwright.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { test as baseTest, expect as baseExpect } from '@playwright/test';
import type { Env } from 'env';
import { type ViteDevServer, createServer } from 'vite';
import { type SetupServer, setupServer } from 'msw/node';
import { type BindingsProxy, getBindingsProxy } from 'wrangler';

interface TestFixtures {}

interface WorkerFixtures {
port: number;
wrangler: BindingsProxy<Env>;
server: ViteDevServer;
msw: SetupServer;
}

export const expect = baseExpect.extend({});

export const test = baseTest.extend<TestFixtures, WorkerFixtures>({
// Assign a unique "port" for each worker process
port: [
// eslint-disable-next-line no-empty-pattern
async ({}, use, workerInfo) => {
await use(3515 + workerInfo.workerIndex);
},
{ scope: 'worker' },
],

// Ensure visits works with relative path
baseURL: ({ port }, use) => {
use(`http://localhost:${port}`);
},

// Start a Vite dev server for each worker
// This allows MSW to intercept requests properly
server: [
async ({ port }, use) => {
const server = await createServer({
configFile: './vite.config.ts',
});

await server.listen(port);

await use(server);

await server.close();
},
{ scope: 'worker', auto: true },
],

msw: [
// eslint-disable-next-line no-empty-pattern
async ({}, use) => {
const server = setupServer();

server.listen();

await use(server);

server.close();
},
{ scope: 'worker', auto: true },
],

// To access wrangler bindings similar to Remix / Vite
wrangler: [
// eslint-disable-next-line no-empty-pattern
async ({}, use) => {
const bindings = await getBindingsProxy<Env>();

// To access bindings in the tests.
await use(bindings);

await bindings.dispose();
},
{ scope: 'worker', auto: true },
],
});

test.beforeEach(({ msw }) => {
msw.resetHandlers();
});
69 changes: 0 additions & 69 deletions tests/setup.ts

This file was deleted.

2 changes: 1 addition & 1 deletion wrangler.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name = "remix-cloudflare-template"
kv_namespaces = [
{ binding = "cache", id = "7bd353e1660544f497319275f6e241fa" }
{ binding = "cache", id = "cache" }
]

0 comments on commit 454c29c

Please sign in to comment.