Skip to content

Commit

Permalink
feat(repo): Add integration test for express + vite
Browse files Browse the repository at this point in the history
  • Loading branch information
dimkl committed Oct 19, 2023
1 parent 1616b3c commit 09dfbc5
Show file tree
Hide file tree
Showing 15 changed files with 282 additions and 5 deletions.
17 changes: 17 additions & 0 deletions integration/presets/express.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { constants } from '../constants';
import { applicationConfig } from '../models/applicationConfig';
import { templates } from '../templates';

const vite = applicationConfig()
.setName('express-vite')
.useTemplate(templates['express-vite'])
.setEnvFormatter('public', key => `VITE_${key}`)
.addScript('setup', 'npm i --prefer-offline')
.addScript('dev', 'npm run dev')
.addScript('build', 'npm run build')
.addScript('serve', 'npm run start')
.addDependency('@clerk/clerk-sdk-node', constants.E2E_CLERK_VERSION);

export const express = {
vite,
} as const;
2 changes: 2 additions & 0 deletions integration/presets/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { envs } from './envs';
import { express } from './express';
import { createLongRunningApps } from './longRunningApps';
import { next } from './next';
import { react } from './react';
import { remix } from './remix';

export const appConfigs = {
envs,
express,
longRunningApps: createLongRunningApps(),
next,
react,
Expand Down
2 changes: 2 additions & 0 deletions integration/presets/longRunningApps.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { LongRunningApplication } from '../models/longRunningApplication';
import { longRunningApplication } from '../models/longRunningApplication';
import { envs } from './envs';
import { express } from './express';
import { next } from './next';
import { react } from './react';
import { remix } from './remix';
Expand All @@ -12,6 +13,7 @@ import { remix } from './remix';
*/
export const createLongRunningApps = () => {
const configs = [
{ id: 'express.vite.withEmailCodes', config: express.vite, env: envs.withEmailCodes },
{ id: 'react.vite.withEmailCodes', config: react.vite, env: envs.withEmailCodes },
{ id: 'react.vite.withEmailLinks', config: react.vite, env: envs.withEmailLinks },
{ id: 'remix.node.withEmailCodes', config: remix.remixNode, env: envs.withEmailCodes },
Expand Down
24 changes: 24 additions & 0 deletions integration/templates/express-vite/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
25 changes: 25 additions & 0 deletions integration/templates/express-vite/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"name": "express-vite",
"private": true,
"version": "0.0.0",
"scripts": {
"dev": "PORT=$PORT ts-node src/server/main.ts",
"start": "PORT=$PORT ts-node src/server/main.ts",
"build": "vite build",
"lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview --port $PORT --no-open"
},
"dependencies": {
"ejs": "^3.1.6",
"express": "^4.18.2",
"ts-node": "^10.9.1",
"typescript": "^4.9.3",
"vite-express": "*"
},
"devDependencies": {
"@types/express": "^4.17.15",
"@types/node": "^18.11.18",
"nodemon": "^2.0.20",
"vite": "^4.0.4"
}
}
60 changes: 60 additions & 0 deletions integration/templates/express-vite/src/server/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Should be at the top of the file - used to load clerk secret key
import * as dotenv from 'dotenv';
dotenv.config();

import { clerkClient } from '@clerk/clerk-sdk-node';
import express from 'express';
import ViteExpress from 'vite-express';

const app = express();

app.set('view engine', 'ejs');
app.set('views', 'src/views');

app.get('/api/protected', [clerkClient.expressRequireAuth()], (_req: any, res: any) => {
res.send('Protected API response').end();
});

app.get('/sign-in', (_req: any, res: any) => {
return res.render('sign-in.ejs', {
publishableKey: process.env.VITE_CLERK_PUBLISHABLE_KEY,
signInUrl: process.env.CLERK_SIGN_IN_URL,
});
});

app.get('/', (_req: any, res: any) => {
return res.render('index.ejs', {
publishableKey: process.env.VITE_CLERK_PUBLISHABLE_KEY,
signInUrl: process.env.CLERK_SIGN_IN_URL,
});
});

app.get('/sign-up', (_req: any, res: any) => {
return res.render('sign-up.ejs', {
publishableKey: process.env.VITE_CLERK_PUBLISHABLE_KEY,
signUpUrl: process.env.CLERK_SIGN_UP_URL,
});
});

app.get('/protected', (_req: any, res: any) => {
return res.render('protected.ejs', {
publishableKey: process.env.VITE_CLERK_PUBLISHABLE_KEY,
signInUrl: process.env.CLERK_SIGN_IN_URL,
signUpUrl: process.env.CLERK_SIGN_UP_URL,
});
});

// Handle authentication error, otherwise application will crash
// @ts-ignore
app.use((err, req, res, next) => {
if (err) {
console.error(err);
res.status(401).end();
return;
}

return next();
});

const port = parseInt(process.env.PORT as string) || 3002;
ViteExpress.listen(app, port, () => console.log(`Server is listening on port ${port}...`));
32 changes: 32 additions & 0 deletions integration/templates/express-vite/src/views/index.ejs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<script
data-clerk-publishable-key="<%= publishableKey %>"
onLoad="startClerk()"
crossorigin="anonymous"
async=""
src="https://clerk.clerk.com/npm/@clerk/clerk-js@4/dist/clerk.browser.js"
></script>
</head>
<body>
<div id="app"></div>
<div id="user-state"></div>

<script>
window.startClerk = async () => {
await Clerk.load({ signInUrl: '<%= signInUrl %>' });
const appEl = document.querySelector('#app');
const controlStateEl = document.querySelector('#user-state');
if (Clerk.user) {
Clerk.mountUserButton(appEl);
controlStateEl.innerHTML = 'SignedIn';
} else {
controlStateEl.innerHTML = 'SignedOut';
}
};
</script>
</body>
</html>
32 changes: 32 additions & 0 deletions integration/templates/express-vite/src/views/protected.ejs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<script
data-clerk-publishable-key="<%= publishableKey %>"
onLoad="startClerk()"
crossorigin="anonymous"
async=""
src="https://clerk.clerk.com/npm/@clerk/clerk-js@4/dist/clerk.browser.js"
></script>
</head>
<body>
<div id="app"></div>
<div id="user-state"></div>

<script>
window.startClerk = async () => {
await Clerk.load({ signInUrl: '<%= signInUrl %>' });
if (Clerk.user) {
const apiResponse = await fetch('/api/protected').then(res => res.text());
const div = document.createElement('div');
div.setAttribute('data-test-id', 'protected-api-response');
div.innerText = apiResponse;
document.body.appendChild(div);
}
};
</script>
</body>
</html>
24 changes: 24 additions & 0 deletions integration/templates/express-vite/src/views/sign-in.ejs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<script
data-clerk-publishable-key="<%= publishableKey %>"
onLoad="startClerk()"
crossorigin="anonymous"
async=""
src="https://clerk.clerk.com/npm/@clerk/clerk-js@4/dist/clerk.browser.js"
></script>
</head>
<body>
<div id="app"></div>
<div id="user-state"></div>

<script>
window.startClerk = async () => {
await Clerk.load({ signInUrl: '<%= signInUrl %>' });
Clerk.mountSignIn(document.querySelector('#app'));
};
</script>
</body>
</html>
24 changes: 24 additions & 0 deletions integration/templates/express-vite/src/views/sign-up.ejs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<script
data-clerk-publishable-key="<%= publishableKey %>"
onLoad="startClerk()"
crossorigin="anonymous"
async=""
src="https://clerk.clerk.com/npm/@clerk/clerk-js@4/dist/clerk.browser.js"
></script>
</head>
<body>
<div id="app"></div>
<div id="user-state"></div>

<script>
window.startClerk = async () => {
await Clerk.load({ signInUrl: '<%= signInUrl %>' });
Clerk.mountSignUp(document.querySelector('#app'));
};
</script>
</body>
</html>
19 changes: 19 additions & 0 deletions integration/templates/express-vite/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"allowJs": false,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "CommonJS",
"moduleResolution": "Node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true
},
"include": ["src"]
}
4 changes: 4 additions & 0 deletions integration/templates/express-vite/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { defineConfig } from 'vite';

// https://vitejs.dev/config/
export default defineConfig({});
1 change: 1 addition & 0 deletions integration/templates/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const templates = {
'next-app-router': resolve(__dirname, './next-app-router'),
'react-cra': resolve(__dirname, './react-cra'),
'react-vite': resolve(__dirname, './react-vite'),
'express-vite': resolve(__dirname, './express-vite'),
'remix-node': resolve(__dirname, './remix-node'),
} as const;

Expand Down
14 changes: 13 additions & 1 deletion integration/tests/sign-in-smoke.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { test } from '@playwright/test';
import { expect, test } from '@playwright/test';

import { appConfigs } from '../presets';
import type { FakeUser } from '../testUtils';
Expand Down Expand Up @@ -37,4 +37,16 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withEmailCodes] })('sign in s
await u.po.expect.toBeSignedIn();
await u.page.pause();
});

test('access protected page', async ({ page, context }) => {
const u = createTestUtils({ app, page, context });
await u.po.signIn.goTo();
await u.po.signIn.signInWithEmailAndInstantPassword({ email: fakeUser.email, password: fakeUser.password });
await u.po.expect.toBeSignedIn();

expect(await u.page.locator("data-test-id='protected-api-response'").count()).toEqual(0);
await u.page.goToRelative('/protected');
await u.page.isVisible("data-test-id='protected-api-response'");
await u.page.pause();
});
});
7 changes: 3 additions & 4 deletions turbo.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@
"NODE_EXTRA_CA_CERTS",
"NODE_VERSION",
"NPM_VERSION",
"PORT",
"RUNNER_ARCH",
"RUNNER_DEBUG",
"RUNNER_OS",
"TZ",
"VERCEL"
"VERCEL",
"VITE_CLERK_*"
],
"pipeline": {
"build": {
Expand All @@ -40,7 +42,6 @@
"tsconfig.build.json",
"tsconfig.declarations.json",
"tsup.config.ts",

"!**/**/*.test.*",
"!**/test/**",
"!**/tests/**",
Expand Down Expand Up @@ -79,7 +80,6 @@
"tsconfig.json",
"tsconfig.*.json",
"tsup.config.ts",

"!**/__snapshots__/**",
"!coverage/**",
"!examples/**",
Expand All @@ -103,7 +103,6 @@
"tsconfig.json",
"tsconfig.*.json",
"tsup.config.ts",

"!**/__snapshots__/**",
"!coverage/**",
"!examples/**",
Expand Down

0 comments on commit 09dfbc5

Please sign in to comment.