Skip to content

Commit

Permalink
WIP e2e test env
Browse files Browse the repository at this point in the history
  • Loading branch information
alexeh committed Oct 10, 2024
1 parent f8ef226 commit 152f5fa
Show file tree
Hide file tree
Showing 10 changed files with 129 additions and 112 deletions.
5 changes: 3 additions & 2 deletions api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@
"@nestjs/platform-express": "^10.0.0",
"@nestjs/typeorm": "^10.0.2",
"@ts-rest/nest": "^3.51.0",
"@types/multer": "^1.4.12",
"bcrypt": "catalog:",
"class-transformer": "catalog:",
"dotenv": "16.4.5",
"lodash": "^4.17.21",
"nodemailer": "^6.9.15",
"passport": "^0.7.0",
Expand All @@ -38,8 +40,7 @@
"rxjs": "^7.8.1",
"typeorm": "catalog:",
"xlsx": "^0.18.5",
"zod": "catalog:",
"@types/multer": "^1.4.12"
"zod": "catalog:"
},
"devDependencies": {
"@nestjs/cli": "^10.0.0",
Expand Down
2 changes: 2 additions & 0 deletions api/src/modules/config/app-config.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { DatabaseModule } from '@api/modules/config/database/database.module';
import { resolveConfigPath } from '@api/modules/config/path-resolver';
import { JwtConfigHandler } from '@api/modules/config/auth-config.handler';

const DEFAULT_RELATIVE_PATH = '../../../../../../';

@Global()
@Module({
imports: [
Expand Down
7 changes: 2 additions & 5 deletions api/src/modules/config/path-resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,9 @@ const TEST_RELATIVE_PATH = '../../../../';
const DEFAULT_RELATIVE_PATH = '../../../../../../';

/**
* @description: Resolve the path of the config file depending on the environment
* @description: Resolve the path of the dotenv config file relative to shared folder
*/
export function resolveConfigPath(relativePath: string): string {
const rootDir =
process.env.NODE_ENV === 'test'
? TEST_RELATIVE_PATH
: DEFAULT_RELATIVE_PATH;
const rootDir = DEFAULT_RELATIVE_PATH;
return join(__dirname, rootDir, relativePath);
}
3 changes: 2 additions & 1 deletion client/.env.development
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
NEXTAUTH_URL=http://localhost:$PORT
NEXTAUTH_SECRET=WAzjpS46vFxp17TsRDU3FXo+TF0vrfy6uhCXwGMBUE8=
NEXT_PUBLIC_API_URL=https://dev.blue-carbon-cost-tool.dev-vizzuality.com/api
#NEXT_PUBLIC_API_URL=https://dev.blue-carbon-cost-tool.dev-vizzuality.com/api
NEXT_PUBLIC_API_URL=http://localhost:4000
2 changes: 1 addition & 1 deletion client/.env.test
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
NEXTAUTH_URL=http://localhost:$PORT
NEXTAUTH_SECRET=WAzjpS46vFxp17TsRDU3FXo+TF0vrfy6uhCXwGMBUE8=
NEXT_PUBLIC_API_URL=https://dev.blue-carbon-cost-tool.dev-vizzuality.com/api
NEXT_PUBLIC_API_URL=http://localhost:4000
4 changes: 3 additions & 1 deletion e2e/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
"pretest": "tsc && tsc-alias",
"test": "playwright test -c ./dist/e2e",
"test:ui": "pnpm pretest && playwright test --ui -c ./dist/e2e",
"codegen": "pnpm --filter api start:dev & pnpm --filter client dev & playwright codegen localhost:3000"
"codegen": "pnpm --filter api start:dev & pnpm --filter client dev & playwright codegen localhost:3000",
"codegen:prod": "pnpm --filter api run build & NODE_ENV=test pnpm --filter api run start:prod & NODE_ENV=test pnpm --filter client run build & NODE_ENV=test pnpm --filter client run start & playwright codegen localhost:3000",
"test2": "playwright test"
}
}
83 changes: 43 additions & 40 deletions e2e/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,51 @@
import { defineConfig, devices } from '@playwright/test';
import { defineConfig, devices } from "@playwright/test";

const API_URL = 'http://localhost:4000';
const APP_URL = 'http://localhost:3000';
//
const API_URL = "http://localhost:4000";
const APP_URL = "http://localhost:3000";

/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
/* Run your local dev server before starting the tests */
webServer: [
{
command: 'pnpm --filter api run build && NODE_ENV=test pnpm --filter api run start:prod',
url: API_URL,
reuseExistingServer: !process.env.CI,
},
{
command: 'NODE_ENV=test pnpm --filter client run build && NODE_ENV=test pnpm --filter client run start',
url: APP_URL,
reuseExistingServer: !process.env.CI,
},
],
testDir: './tests',
/* Run tests in files in parallel */
fullyParallel: false,
workers: 1,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: process.env.CI ? 'list' : 'html',
/* 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: APP_URL,
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
/* Run your local dev server before starting the tests */
webServer: [
{
command:
"pnpm --filter api run build && NODE_ENV=test pnpm --filter api run start:prod",
url: API_URL,
reuseExistingServer: !process.env.CI,
},
/* Configure projects for major browsers */
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
],
{
command:
"NODE_ENV=test pnpm --filter client run build && NODE_ENV=test pnpm --filter client run start",
url: APP_URL,
reuseExistingServer: !process.env.CI,
},
],
testDir: "./tests",
/* Run tests in files in parallel */
fullyParallel: false,
workers: 1,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: process.env.CI ? "list" : "html",
/* 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: APP_URL,
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: "on-first-retry",
},
/* Configure projects for major browsers */
projects: [
{
name: "chromium",
use: { ...devices["Desktop Chrome"] },
},
],
});
76 changes: 52 additions & 24 deletions e2e/tests/auth/auth.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { test, expect, Page } from '@playwright/test';
import { E2eTestManager } from '@shared/lib/e2e-test-manager';
import { User } from '@shared/entities/users/user.entity';
import { test, expect, Page } from "@playwright/test";
import { E2eTestManager } from "@shared/lib/e2e-test-manager";
import { User } from "@shared/entities/users/user.entity";

let testManager: E2eTestManager;
let page: Page;
Expand All @@ -15,48 +15,76 @@ test.beforeEach(async () => {
});

test.afterEach(async () => {
await testManager.clearDatabase();
//await testManager.clearDatabase();
});

test.afterAll(async () => {
await testManager.logout();
await testManager.close();
});

// test('an user signs up successfully', async ({ page }) => {
// const user: Pick<User, 'email' | 'password'> = {
// email: '[email protected]',
// password: 'password',
// test("an user signs up successfully", async ({ page }) => {
// const user: Pick<User, "email" | "password"> = {
// email: "[email protected]",
// password: "password",
// };
//
// await page.goto('/auth/signup');
// await page.goto("/auth/signup");
//
// await page.getByLabel('Email').fill(user.email);
// await page.getByLabel("Email").fill(user.email);
// await page.locator('input[type="password"]').fill(user.password);
// await page.getByRole('checkbox').check();
// await page.getByRole("checkbox").check();
//
// await page.getByRole('button', { name: /sign up/i }).click();
// await page.getByRole("button", { name: /sign up/i }).click();
//
// await page.waitForURL('/auth/signin');
// await page.waitForURL("/auth/signin");
//
// await page.getByLabel('Email').fill(user.email);
// await page.getByLabel("Email").fill(user.email);
// await page.locator('input[type="password"]').fill(user.password);
//
// await page.getByRole('button', { name: /log in/i }).click();
// await page.getByRole("button", { name: /log in/i }).click();
//
// await page.waitForURL('/profile');
// await page.waitForURL("/profile");
// await expect(await page.locator('input[type="email"]')).toHaveValue(
// user.email
// user.email,
// );
// });

test('an user signs in successfully', async ({ page }) => {
const user: Pick<User, 'email' | 'password' | 'partnerName'> = {
email: '[email protected]',
password: '12345678',
partnerName: 'partner-test'
test("an user signs in successfully", async ({ page }) => {
const user: Pick<User, "email" | "password" | "partnerName"> = {
email: "[email protected]",
password: "12345678",
partnerName: "admin",
};

await testManager.mocks().createUser(user);
await testManager.login(user as User)
await expect(page.getByText(`Email: ${user.email}`)).toBeVisible();
await page.goto("/auth/signin");
await page.getByLabel("Email").fill(user.email);
await page.locator('input[type="password"]').fill(user.password);
await page.getByRole("button", { name: /log in/i }).click();
});

test("test", async ({ page }) => {
await page.goto("http://localhost:3000/");
await page.getByRole("link", { name: "Sign in" }).click();
await page.getByPlaceholder("Enter your email").click();
await page.getByPlaceholder("Enter your email").fill("[email protected]");
await page.getByPlaceholder("*******").click();
await page.getByPlaceholder("*******").fill("12345678");
await page.getByRole("button", { name: "Log in" }).click();
});
// test("test", async ({ page }) => {
// const user: Pick<User, "email" | "password" | "partnerName"> = {
// email: "[email protected]",
// password: "12345678",
// partnerName: "admin",
// };
// await page.goto("http://localhost:3000/");
// await page.getByRole("link", { name: "Sign in" }).click();
// await page.getByPlaceholder("Enter your email").click();
// await page.getByPlaceholder("Enter your email").fill(user.email);
// await page.getByPlaceholder("*******").click();
// await page.getByPlaceholder("*******").fill(user.password);
// await page.getByRole("button", { name: "Log in" }).click();
// await expect(page.getByText(`Email: ${user.email}`)).toBeVisible();
// });
21 changes: 3 additions & 18 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 18 additions & 20 deletions shared/lib/e2e-test-manager.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
import { DataSource } from 'typeorm';
import { DataSource } from "typeorm";
import { User } from "@shared/entities/users/user.entity";
import {
createUser,
} from '@shared/lib/entity-mocks';
import { clearTestDataFromDatabase } from '@shared/lib/db-helpers';
import { DB_ENTITIES } from '@shared/lib/db-entities';
import { sign } from 'jsonwebtoken';
import { createUser } from "@shared/lib/entity-mocks";
import { clearTestDataFromDatabase } from "@shared/lib/db-helpers";
import { DB_ENTITIES } from "@shared/lib/db-entities";
import { sign } from "jsonwebtoken";

const AppDataSource = new DataSource({
type: 'postgres',
host: 'localhost',
type: "postgres",
host: "localhost",
port: 5432,
username: 'blue-carbon-cost',
password: 'blue-carbon-cost',
database: 'blc',
username: "blue-carbon-cost",
password: "blue-carbon-cost",
database: "blc",
entities: DB_ENTITIES,
});

Expand Down Expand Up @@ -59,29 +57,29 @@ export class E2eTestManager {
}

getPage() {
if (!this.page) throw new Error('Playwright Page is not initialized');
if (!this.page) throw new Error("Playwright Page is not initialized");
return this.page;
}

async login(user?: User) {
if (!user) {
user = await this.mocks().createUser();
}
await this.page.goto('/auth/signin');
await this.page.getByLabel('Email').fill(user.email);
await this.page.goto("/auth/signin");
await this.page.getByLabel("Email").fill(user.email);
await this.page.locator('input[type="password"]').fill(user.password);
await this.page.getByRole('button', { name: /log in/i }).click();
await this.page.waitForURL('/profile');
await this.page.getByRole("button", { name: /log in/i }).click();
await this.page.waitForURL("/profile");
return user;
}

async logout() {
await this.page.goto('/auth/api/signout');
await this.page.getByRole('button', { name: 'Sign out' }).click();
await this.page.goto("/auth/api/signout");
await this.page.getByRole("button", { name: "Sign out" }).click();
}

async generateToken(user: User) {
// the secret must match the provided for the api when built for e2e tests
return sign({ id: user.id }, 'mysupersecretfortests');
return sign({ id: user.id }, "mysupersecretfortests");
}
}

0 comments on commit 152f5fa

Please sign in to comment.