Skip to content

Commit

Permalink
feat(test): Add Clerk Elements E2E (#3394)
Browse files Browse the repository at this point in the history
  • Loading branch information
LekoArts authored May 24, 2024
1 parent 1292358 commit 980493f
Show file tree
Hide file tree
Showing 41 changed files with 1,773 additions and 220 deletions.
5 changes: 5 additions & 0 deletions .changeset/healthy-turtles-compete.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@clerk/elements': patch
---

Update the TypeScript type of `<Input />` to allow the `validatePassword` prop also on `type="text"` (in addition to `type="password"`)
5 changes: 3 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ jobs:

strategy:
matrix:
test-name: ['generic', 'nextjs', 'express', 'quickstart', 'ap-flows']
test-name: ['generic', 'nextjs', 'express', 'quickstart', 'ap-flows', 'elements']
test-project: ['chrome']

steps:
Expand All @@ -152,7 +152,7 @@ jobs:
uses: ./.github/actions/verdaccio
with:
publish-cmd: |
if [ "$(npm config get registry)" = "https://registry.npmjs.org/" ]; then echo 'Error: Using default registry' && exit 1; else npx turbo build $TURBO_ARGS --filter=!elements --only && npx changeset publish --no-git-tag; fi
if [ "$(npm config get registry)" = "https://registry.npmjs.org/" ]; then echo 'Error: Using default registry' && exit 1; else npx turbo build $TURBO_ARGS --only && npx changeset publish --no-git-tag; fi
- name: Install @clerk/backend in /integration
working-directory: ./integration
Expand All @@ -163,6 +163,7 @@ jobs:
run: mkdir clerk-js && cd clerk-js && npm init -y && npm install @clerk/clerk-js

- name: Run Integration Tests
id: integration-tests
run: npx turbo test:integration:${{ matrix.test-name }} $TURBO_ARGS --only -- --project=${{ matrix.test-project }}
env:
E2E_APP_CLERK_JS_DIR: ${{runner.temp}}
Expand Down
3 changes: 3 additions & 0 deletions integration/models/applicationConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ export const applicationConfig = () => {
scripts[name] = cmd;
return self;
},
/**
* Adds a dependency to the template's `package.json` file. If the version is undefined, the dependency is not added. If the dependency already exists, the version is overwritten.
*/
addDependency: (name: string, version: string | undefined) => {
if (version) {
dependencies.set(name, version);
Expand Down
24 changes: 24 additions & 0 deletions integration/presets/elements.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { constants } from '../constants';
import { applicationConfig } from '../models/applicationConfig.js';
import { templates } from '../templates/index.js';

const clerkNextjsLocal = `file:${process.cwd()}/packages/nextjs`;
const clerkElementsLocal = `file:${process.cwd()}/packages/elements`;

const nextAppRouter = applicationConfig()
.setName('elements-next')
.useTemplate(templates['elements-next'])
.setEnvFormatter('public', key => `NEXT_PUBLIC_${key}`)
.addScript('setup', 'npm i')
.addScript('dev', 'npm run dev')
.addScript('build', 'npm run build')
.addScript('serve', 'npm run start')
.addDependency('next', constants.E2E_NEXTJS_VERSION)
.addDependency('react', constants.E2E_REACT_VERSION)
.addDependency('react-dom', constants.E2E_REACT_DOM_VERSION)
.addDependency('@clerk/nextjs', constants.E2E_CLERK_VERSION || clerkNextjsLocal)
.addDependency('@clerk/elements', constants.E2E_CLERK_VERSION || clerkElementsLocal);

export const elements = {
nextAppRouter,
} as const;
2 changes: 2 additions & 0 deletions integration/presets/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { elements } from './elements';
import { envs } from './envs';
import { express } from './express';
import { createLongRunningApps } from './longRunningApps';
Expand All @@ -12,4 +13,5 @@ export const appConfigs = {
next,
react,
remix,
elements,
} as const;
2 changes: 2 additions & 0 deletions integration/presets/longRunningApps.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { LongRunningApplication } from '../models/longRunningApplication';
import { longRunningApplication } from '../models/longRunningApplication';
import { elements } from './elements';
import { envs } from './envs';
import { express } from './express';
import { next } from './next';
Expand All @@ -20,6 +21,7 @@ export const createLongRunningApps = () => {
{ id: 'next.appRouter.withEmailCodes', config: next.appRouter, env: envs.withEmailCodes },
{ id: 'next.appRouter.withCustomRoles', config: next.appRouter, env: envs.withCustomRoles },
{ id: 'quickstart.next.appRouter', config: next.appRouterQuickstart, env: envs.withEmailCodesQuickstart },
{ id: 'elements.next.appRouter', config: elements.nextAppRouter, env: envs.withEmailCodes },
] as const;

const apps = configs.map(longRunningApplication);
Expand Down
3 changes: 3 additions & 0 deletions integration/templates/elements-next/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
root: true,
};
37 changes: 37 additions & 0 deletions integration/templates/elements-next/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env*.local

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts

package-lock.json
34 changes: 34 additions & 0 deletions integration/templates/elements-next/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).

## Getting Started

First, run the development server:

```bash
npm run dev
# or
yarn dev
# or
pnpm dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.

This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.

## Learn More

To learn more about Next.js, take a look at the following resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!

## Deploy on Vercel

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.

Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
8 changes: 8 additions & 0 deletions integration/templates/elements-next/next.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
eslint: {
ignoreDuringBuilds: true,
},
};

module.exports = nextConfig;
30 changes: 30 additions & 0 deletions integration/templates/elements-next/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "elements-next",
"version": "0.1.0",
"private": true,
"scripts": {
"build": "next build",
"dev": "next dev",
"lint": "next lint",
"start": "next start"
},
"dependencies": {
"@clerk/elements": "file:../../../packages/elements",
"@clerk/nextjs": "file:../../../packages/nextjs",
"@types/node": "^18.17.0",
"@types/react": "^18.3.1",
"@types/react-dom": "^18.3.0",
"next": "^14.2.3",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"typescript": "^5.4.5"
},
"devDependencies": {
"autoprefixer": "^10.4.19",
"postcss": "^8.4.38",
"tailwindcss": "^3.4.3"
},
"engines": {
"node": ">=18.17.0"
}
}
6 changes: 6 additions & 0 deletions integration/templates/elements-next/postcss.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
Binary file not shown.
37 changes: 37 additions & 0 deletions integration/templates/elements-next/src/app/globals.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

:root {
--foreground-rgb: 0, 0, 0;
--background-start-rgb: 214, 219, 220;
--background-end-rgb: 255, 255, 255;
}

* {
box-sizing: border-box;
padding: 0;
margin: 0;
}

html,
body {
max-width: 100vw;
overflow-x: hidden;
}

body {
color: rgb(var(--foreground-rgb));
background: linear-gradient(to bottom, transparent, rgb(var(--background-end-rgb))) rgb(var(--background-start-rgb));
font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell,
Ubuntu, roboto, noto, arial, sans-serif;
}

main {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 6rem;
min-height: 100vh;
}
19 changes: 19 additions & 0 deletions integration/templates/elements-next/src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import './globals.css';

import { ClerkProvider } from '@clerk/nextjs';
import type { Metadata } from 'next';

export const metadata: Metadata = {
title: 'Clerk Elements - Next.js E2E',
description: 'Clerk Elements - Next.js E2E',
};

export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang='en'>
<ClerkProvider clerkJSVariant='headless'>
<body>{children}</body>
</ClerkProvider>
</html>
);
}
118 changes: 118 additions & 0 deletions integration/templates/elements-next/src/app/otp/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
'use client';

import * as Clerk from '@clerk/elements/common';
import * as SignIn from '@clerk/elements/sign-in';

function clsx(...args: (string | undefined | Record<string, boolean>)[]): string {
const classes: string[] = [];

for (const arg of args) {
switch (typeof arg) {
case 'string':
classes.push(arg);
break;
case 'object':
for (const key in arg) {
if (arg[key]) {
classes.push(key);
}
}
break;
}
}

return classes.join(' ');
}

export default function OTP() {
return (
<main>
<SignIn.Root path='/otp'>
<SignIn.Step
name='start'
className='w-full space-y-6 rounded-2xl px-4 py-10 sm:w-96 sm:px-8 bg-white text-center shadow-md'
>
<header className='text-center'>
<h1 className='text-xl font-medium tracking-tight text-neutral-950'>OTP Playground</h1>
</header>
<Clerk.Field
name='simple-otp'
className='space-y-2'
>
<Clerk.Label className='text-sm font-medium text-zinc-950'>Simple OTP Input</Clerk.Label>
<Clerk.Input
type='otp'
className='w-full rounded-md bg-white px-3.5 py-2 text-sm outline-none ring-1 ring-inset ring-zinc-300 hover:ring-zinc-400 focus:ring-[1.5px] focus:ring-zinc-950 data-[invalid]:ring-red-400'
data-testid='simple-otp'
/>
</Clerk.Field>
<Clerk.Field
name='segmented-otp'
className='space-y-2'
>
<Clerk.Label className='text-sm font-medium text-zinc-950'>Segmented OTP Input</Clerk.Label>
<Clerk.Input
className='flex justify-center has-[:disabled]:opacity-50 segmented-otp-wrapper'
type='otp'
data-testid='segmented-otp'
render={({ value, status, index }) => {
return (
<div
data-status={status}
data-testid={`segmented-otp-${index}`}
className={clsx(
'relative flex size-10 items-center justify-center border-y border-r border-input text-sm transition-all first:rounded-l-md first:border-l last:rounded-r-md',
{
'z-10 ring-2 ring-black ring-offset-black': status === 'cursor' || status === 'selected',
},
)}
>
{value}
{status === 'cursor' && (
<div className='pointer-events-none absolute inset-0 flex items-center justify-center'>
<div className='animate-caret-blink h-4 w-px bg-black duration-1000' />
</div>
)}
</div>
);
}}
/>
</Clerk.Field>
<Clerk.Field
name='segmented-otp-with-props'
className='space-y-2'
>
<Clerk.Label className='text-sm font-medium text-zinc-950'>Segmented OTP Input (with props)</Clerk.Label>
<Clerk.Input
className='flex justify-center has-[:disabled]:opacity-50 segmented-otp-with-props-wrapper'
type='otp'
data-testid='segmented-otp-with-props'
passwordManagerOffset={4}
length={4}
render={({ value, status }) => {
return (
<div
data-status={status}
className={clsx(
'relative flex size-10 items-center justify-center border-y border-r border-input text-sm transition-all first:rounded-l-md first:border-l last:rounded-r-md',
{
'z-10 ring-2 ring-black ring-offset-black': status === 'cursor' || status === 'selected',
},
)}
>
{value}
{status === 'cursor' && (
<div className='pointer-events-none absolute inset-0 flex items-center justify-center'>
<div className='animate-caret-blink h-4 w-px bg-black duration-1000' />
</div>
)}
</div>
);
}}
/>
</Clerk.Field>
</SignIn.Step>
</SignIn.Root>
</main>
);
}
Loading

0 comments on commit 980493f

Please sign in to comment.