Skip to content

Commit

Permalink
fix: playwright tests
Browse files Browse the repository at this point in the history
  • Loading branch information
edmundhung committed Feb 11, 2024
1 parent cbe0e14 commit 454c29c
Show file tree
Hide file tree
Showing 13 changed files with 185 additions and 147 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Up @@ -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">
Expand All @@ -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
Expand Down
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",
Expand Down Expand Up @@ -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",
Expand Down
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: {},
Expand Down
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();
});
Loading

0 comments on commit 454c29c

Please sign in to comment.