Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
**/*.test.tsx
**/*.test.js
**/*.test.jsx
**/*.spec.ts
**/*.spec.tsx
app/api/gift-exchanges/\[id\]/draw/route.ts
app/api/gift-exchanges/\[id\]/giftSuggestions/route.ts
app/api/gift-exchanges/\[id\]/members/route.ts
Expand Down
2 changes: 1 addition & 1 deletion app/onboarding/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ function Onboarding() {
value={isSubmitted ? 100 : (currentStep / steps.length) * 100}
className="my-4"
/>
<Card>
<Card data-testid="onboarding-card">
<CardHeader>
<CardTitle className="text-center text-2xl font-bold">
{steps[currentStep].title}
Expand Down
9 changes: 6 additions & 3 deletions app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,10 @@ export default function Home() {
<main className="container mx-auto px-4 py-16">
{/* Hero Section */}
<section className="text-center my-12">
<h1 className="text-5xl font-bold text-primary-foreground mb-4">
<h1
className="text-5xl font-bold text-primary-foreground mb-4"
data-testid="hero-title"
>
Make Gift-Giving Magical
</h1>
<p className="text-xl text-primary-foreground/70 mb-8">
Expand All @@ -76,7 +79,7 @@ export default function Home() {
{/* Features Section */}
<section className="grid md:grid-cols-2 lg:grid-cols-4 gap-8 mb-16">
{features.map((feature) => (
<Card key={feature.title}>
<Card key={feature.title} data-testid="feature">
<CardHeader>
<span className="text-red-400">{feature.icon}</span>
<CardTitle>{feature.title}</CardTitle>
Expand Down Expand Up @@ -113,7 +116,7 @@ export default function Home() {
description: 'Exchange gifts and spread joy with your group!',
},
].map((step, index) => (
<div key={index} className="text-center">
<div key={index} className="text-center" data-testid={`step`}>
<div className="w-16 h-16 bg-mutedRed text-white rounded-full flex items-center justify-center text-2xl font-bold mx-auto mb-4">
{step.step}
</div>
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"cmdk": "^1.0.0",
"cross-env": "^7.0.3",
"date-fns": "^3.6.0",
"dotenv": "^16.5.0",
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are the environment variables being setup on the server?

"eslint-plugin-jsdoc": "^50.6.6",
"framer-motion": "^12.6.3",
"lucide-react": "^0.464.0",
Expand Down
18 changes: 9 additions & 9 deletions playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import { defineConfig, devices } from '@playwright/test';
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// import dotenv from 'dotenv';
// import path from 'path';
// dotenv.config({ path: path.resolve(__dirname, '.env') });
import dotenv from 'dotenv';
import path from 'path';
dotenv.config({ path: path.resolve(__dirname, '.env') });

/**
* See https://playwright.dev/docs/test-configuration.
Expand All @@ -29,7 +29,7 @@ export default defineConfig({
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Base URL to use in actions like `await page.goto('/')`. */
// baseURL: 'http://127.0.0.1:3000',
baseURL: 'http://localhost:4000',

/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
Expand Down Expand Up @@ -74,9 +74,9 @@ export default defineConfig({
],

/* Run your local dev server before starting the tests */
// webServer: {
// command: 'npm run start',
// url: 'http://127.0.0.1:3000',
// reuseExistingServer: !process.env.CI,
// },
webServer: {
command: 'pnpm dev --port 4000',
url: 'http://localhost:4000',
reuseExistingServer: !process.env.CI,
},
});
16 changes: 16 additions & 0 deletions tests/tests-examples/loggedIn.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright (c) Gridiron Survivor.
// Licensed under the MIT License.

import { test, expect } from '@playwright/test';
import { getSupabaseClient } from '../utils/auth-setup';
test('Logged in user who hasn’t completed onboarding sees onboarding', async ({
page,
}) => {
await getSupabaseClient(page, 'playwrightuser@test.com');
await page.goto('/');
await expect(page).toHaveURL('/onboarding');
await expect(page.getByTestId('onboarding-card')).toBeVisible();
await expect(
page.getByRole('button', { name: 'Next', exact: true }),
).toBeVisible();
});
22 changes: 22 additions & 0 deletions tests/tests-examples/notLoggedIn.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) Gridiron Survivor.
// Licensed under the MIT License.

import { test, expect } from '@playwright/test';

test('has title', async ({ page }) => {
await page.goto('/');

await expect(page.getByTestId('hero-title')).toBeVisible();
});

test('has 4 features', async ({ page }) => {
await page.goto('/');

await expect(page.getByTestId('feature')).toHaveCount(4);
});

test('has 3 steps', async ({ page }) => {
await page.goto('/');

await expect(page.getByTestId('step')).toHaveCount(3);
});
52 changes: 52 additions & 0 deletions tests/utils/auth-setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright (c) Gridiron Survivor.
// Licensed under the MIT License.

import { createClient } from '@supabase/supabase-js';
import { Page } from '@playwright/test';

/**
* Get a Supabase client with authentication set up for Playwright tests
* @param page - The Playwright page object
* @param userEmail - The email of the user to sign in as
* @returns Promise that resolves when authentication is set up
*/
async function getSupabaseClient(page: Page, userEmail: string): Promise<void> {
const supabaseClient = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
);

const { data, error } = await supabaseClient.auth.signInWithPassword({
email: userEmail,
password: 'password',
});
if (!data.user) {
throw Error(error?.message);
}

const projectRef = process.env
.NEXT_PUBLIC_SUPABASE_URL!.split('//')[1]
.split('.')[0];
await page.context().addCookies([
{
name: `sb-${projectRef}-auth-token`,
value: JSON.stringify({
access_token: data.session.access_token,
refresh_token: data.session.refresh_token,
expires_in: 3600,
expires_at: Math.floor(Date.now() / 1000) + 3600,
token_type: 'bearer',
user: {
id: data.user.id,
email: data.user.email,
},
}),
domain: 'localhost',
path: '/',
httpOnly: false,
secure: false,
},
]);
}

export { getSupabaseClient };