Skip to content

Commit

Permalink
Dvr 143 e2e tests (#2048)
Browse files Browse the repository at this point in the history
Co-authored-by: zaid.arain <[email protected]>
  • Loading branch information
proletesseract and zaidarain1 authored Aug 2, 2024
1 parent 6dabb51 commit 18f2a87
Show file tree
Hide file tree
Showing 59 changed files with 596 additions and 195 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,7 @@ docs/
.nx/cache
.nx/workspace-data
nx-cloud.env
dep-graph.json
dep-graph.json
examples/**/.env
examples/**/playwright-report/
examples/**/test-results/
79 changes: 75 additions & 4 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,18 @@ yarn add @imtbl/sdk
yarn add @ethersproject/providers@^5.7.2
```

create a `.env` file in the root of the example.
create a `.env.example` file in the root of the example. This will be committed to git so don't fill in the values

add environment variables to the `.env` file and populate any API keys and secrets e.g.
add a template for any environment variables you need to the `.env.example` file e.g.

```
NEXT_PUBLIC_PUBLISHABLE_KEY=
NEXT_PUBLIC_CLIENT_ID=
```

copy the `.env.example` file to `.env` in the root of the example. The `.env` file should be automatically ignored by git.

populate any API keys and secrets e.g.

```
NEXT_PUBLIC_PUBLISHABLE_KEY="ABC"
Expand All @@ -90,6 +99,15 @@ NEXT_PUBLIC_CLIENT_ID="XYZ"

note: variables must be prefixed with `NEXT_PUBLIC_` to be piped into the browser env.

Update the readme with any instructions required to run the app, and include what required env variables there are with any instructions on what to populate there.

```
## Required Environment Variables
- NEXT_PUBLIC_PUBLISHABLE_KEY // replace with your publishable API key from Hub
- NEXT_PUBLIC_CLIENT_ID // replace with your client ID from Hub
```

start the project with hot reloading

```
Expand Down Expand Up @@ -193,6 +211,59 @@ All examples should be heavily commented and the comments should make sense in t

## Tests

All examples should be covered by e2e tests to ensure they successfully do the action the code sample is showing in the docs site.
All examples should be covered by basic e2e tests to ensure they at least render the examples. Ideally they would also have e2e tests that prove the functionality that you're trying to show works. Depending on what you're doing in the examples, it may be difficult to e2e test certain things e.g. logging in with Passport. For this reason, testing of functionality with e2e testing is recommended if practical, but not required.

Install `@playwright/test` as a dev dependency for the e2e tests.

```
yarn add -D @playwright/test
```

Create a `playwright.config.ts` file in the root of the example app and add this configuration;

```
import { defineConfig, devices } from "@playwright/test";
export default defineConfig({
testDir: "./tests",
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: "html",
use: {
baseURL: "http://localhost:3000",
trace: "on-first-retry",
},
projects: [
{ name: "chromium", use: { ...devices["Desktop Chrome"] } },
{ name: "firefox", use: { ...devices["Desktop Firefox"] } },
{ name: "webkit", use: { ...devices["Desktop Safari"] } },
{ name: "Mobile Chrome", use: { ...devices["Pixel 5"] } },
{ name: "Mobile Safari", use: { ...devices["iPhone 12"] } },
],
webServer: {
command: "yarn dev",
url: "http://localhost:3000",
reuseExistingServer: !process.env.CI,
},
});
```

Make sure you update the localhost urls `http://localhost:3000` in the above example to be the correct port for your local environment.

Create a `tests` directory in the root of the example app and start adding tests.

Example of the base level of testing required can be found in `/examples/passport/wallets-signing-with-nextjs/tests/base.spec.ts`

Add the test runner to the scripts in your package.json

```
"test": "playwright install --with-deps && playwright test"
```

More info on e2e tests coming soon.
Run your tests with `yarn test`
4 changes: 3 additions & 1 deletion examples/passport/identity-with-nextjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
},
"devDependencies": {
"@imtbl/sdk": "latest",
"@playwright/test": "^1.45.3",
"@types/node": "^20",
"@types/react": "^18.0.28",
"@types/react-dom": "^18.0.11",
Expand All @@ -23,6 +24,7 @@
"build": "next build",
"dev": "next dev",
"lint": "next lint",
"start": "next start"
"start": "next start",
"test": "playwright install --with-deps && playwright test"
}
}
30 changes: 30 additions & 0 deletions examples/passport/identity-with-nextjs/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { defineConfig, devices } from "@playwright/test";

export default defineConfig({
testDir: "./tests",
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: "html",

use: {
baseURL: "http://localhost:3000",
trace: "on-first-retry",
},

projects: [
{ name: "chromium", use: { ...devices["Desktop Chrome"] } },
{ name: "firefox", use: { ...devices["Desktop Firefox"] } },
{ name: "webkit", use: { ...devices["Desktop Safari"] } },

{ name: "Mobile Chrome", use: { ...devices["Pixel 5"] } },
{ name: "Mobile Safari", use: { ...devices["iPhone 12"] } },
],

webServer: {
command: "yarn dev",
url: "http://localhost:3000",
reuseExistingServer: !process.env.CI,
},
});
4 changes: 3 additions & 1 deletion examples/passport/identity-with-nextjs/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import './globals.css';
const inter = Inter({ subsets: ['latin'] });

export const metadata: Metadata = {
title: 'Passport Identity example',
title: 'Passport Identity Examples',
description: 'Examples of how to use Passport\'s Identity features with NextJS',
};

export default function RootLayout({
children,
}: Readonly<{
Expand Down
25 changes: 15 additions & 10 deletions examples/passport/identity-with-nextjs/src/app/logout/page.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
'use client';

import { useEffect } from 'react';
import { useRouter } from 'next/navigation';

export default function Page() {
const { push } = useRouter();

useEffect(() => {
push('/');
}, [push]);
return <p />;
export default function Logout() {
// render the view for after the logout is complete
return (
<div className="flex flex-col items-center justify-center min-h-screen p-8">
<h1 className="text-3xl font-bold mb-8">Logged Out</h1>
<div className="grid grid-cols-1 gap-4 text-center">
<a
className="underline"
href="/"
>
Return to examples
</a>
</div>
</div>
);
}
4 changes: 2 additions & 2 deletions examples/passport/identity-with-nextjs/src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export default function Home() {
return (
<div className="flex flex-col items-center justify-center min-h-screen p-8">
<h1 className="text-3xl font-bold mb-8">Passport Identity Examples</h1>
<div className="space-x-4 space-y-4 max-w-screen-lg w-full">
<div className="grid grid-cols-1 gap-4 text-center">
<button
className="bg-black text-white py-2 px-4 rounded hover:bg-gray-800"
onClick={login}
Expand All @@ -38,7 +38,7 @@ export default function Home() {
onClick={loginWithEthersjs}
type="button"
>
Login With Ethers.js
Login With EtherJS
</button>
<button
className="bg-black text-white py-2 px-4 rounded hover:bg-gray-800"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,10 @@ export default function Redirect() {
}
}, [passportInstance]);

return (<h1>Redirecting...</h1>);
// render the view for the login popup after the login is complete
return (
<div className="flex flex-col items-center justify-center min-h-screen p-8">
<h1 className="text-3xl font-bold mb-8">Logged in</h1>
</div>
);
}
12 changes: 12 additions & 0 deletions examples/passport/identity-with-nextjs/tests/base.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { test, expect } from "@playwright/test";

test.beforeEach(async ({ page }) => {
await page.goto("/");
});

test.describe("home page", () => {
test("has title and heading", async ({ page }) => {
await expect(page).toHaveTitle("Passport Identity Examples");
await expect(page.getByRole("heading", { name: "Passport Identity Examples" })).toBeVisible();
});
});
2 changes: 2 additions & 0 deletions examples/passport/wallets-connect-with-nextjs/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
NEXT_PUBLIC_PUBLISHABLE_KEY=
NEXT_PUBLIC_CLIENT_ID=
9 changes: 3 additions & 6 deletions examples/passport/wallets-connect-with-nextjs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,7 @@ yarn dev

browse to `http://localhost:3000` to see the full list of examples.

Available examples include:
## Required Environment Variables

- Connecting with EtherJS Web3Provider `http://localhost:3000/connect-with-etherjs`

- Connecting with EIP-1193 Provider `http://localhost:3000/connect-with-eip1193`

- Connecting with Wagmi `http://localhost:3000/connect-with-wagmi`
- NEXT_PUBLIC_PUBLISHABLE_KEY // replace with your publishable API key from Hub
- NEXT_PUBLIC_CLIENT_ID // replace with your client ID from Hub
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,29 @@ export default function ConnectWithEtherJS() {

// render the view to login/logout and show the connected accounts
return (
<>
<h1>Passport Wallet - Connect with EIP-1193</h1>
<div className="flex flex-col items-center justify-center min-h-screen p-8">
<h1 className="text-3xl font-bold mb-8">Passport Connect with EIP-1193</h1>
{accountsState.length === 0
&& <button onClick={passportLogin} disabled={loading}>Passport Login</button>}
&& (
<button
className="bg-black text-white py-2 px-4 rounded hover:bg-gray-800"
onClick={passportLogin}
disabled={loading}
>
Passport Login
</button>
)}
{accountsState.length >= 1
&& <button onClick={passportLogout} disabled={loading}>Passport Logout</button>}
&& (
<button
className="bg-black text-white py-2 px-4 rounded hover:bg-gray-800"
onClick={passportLogout}
disabled={loading}
>
Passport Logout
</button>
)}
<br />
{loading
? <p>Loading...</p>
: (
Expand All @@ -62,9 +79,8 @@ export default function ConnectWithEtherJS() {
{accountsState.length >= 1 ? accountsState : '(not connected)'}
</p>
)}
<p>
<a href="/">Return to Examples</a>
</p>
</>
<br />
<a href="/" className="underline">Return to Examples</a>
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,29 @@ export default function ConnectWithEtherJS() {

// render the view to login/logout and show the connected accounts
return (
<>
<h1>Passport Wallet - Connect with EtherJS</h1>
<div className="flex flex-col items-center justify-center min-h-screen p-8">
<h1 className="text-3xl font-bold mb-8">Passport Connect with EtherJS</h1>
{accountsState.length === 0
&& <button onClick={passportLogin} disabled={loading} type="button">Passport Login</button>}
&& (
<button
className="bg-black text-white py-2 px-4 rounded hover:bg-gray-800"
onClick={passportLogin}
disabled={loading}
>
Passport Login
</button>
)}
{accountsState.length >= 1
&& <button onClick={passportLogout} disabled={loading} type="button">Passport Logout</button>}
&& (
<button
className="bg-black text-white py-2 px-4 rounded hover:bg-gray-800"
onClick={passportLogout}
disabled={loading}
>
Passport Logout
</button>
)}
<br />
{loading
? <p>Loading...</p>
: (
Expand All @@ -67,9 +84,8 @@ export default function ConnectWithEtherJS() {
{accountsState.length >= 1 ? accountsState : '(not connected)'}
</p>
)}
<p>
<a href="/">Return to Examples</a>
</p>
</>
<br />
<a href="/" className="underline">Return to Examples</a>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {
useAccount, useDisconnect, useEnsAvatar, useEnsName,
useAccount, useDisconnect, useEnsName,
} from 'wagmi';
import { useState } from 'react';
import { passportInstance } from '../utils';
Expand All @@ -8,7 +8,6 @@ export function Account() {
const { address } = useAccount();
const { disconnect } = useDisconnect();
const { data: ensName } = useEnsName({ address });
const { data: ensAvatar } = useEnsAvatar({ name: ensName! });

// setup the loading state to enable/disable buttons when loading
const [loading, setLoadingState] = useState<boolean>(false);
Expand All @@ -24,9 +23,16 @@ export function Account() {

// render the view to show the connected accounts and logout
return (
<div>
<button onClick={() => passportLogout()} disabled={loading} type="button">Passport Logout</button>
{ensAvatar && <img alt="ENS Avatar" src={ensAvatar} />}
<>
<button
className="bg-black text-white py-2 px-4 rounded hover:bg-gray-800"
onClick={() => passportLogout()}
disabled={loading}
type="button"
>
Passport Logout
</button>
<br />
{loading
? <p>Loading...</p>
: (
Expand All @@ -35,6 +41,6 @@ export function Account() {
{address && <span>{ensName ? `${ensName} (${address})` : address}</span>}
</p>
)}
</div>
</>
);
}
Loading

0 comments on commit 18f2a87

Please sign in to comment.