Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Playwright Integration Testing #335

Merged
merged 26 commits into from
May 14, 2024
Merged
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: 1 addition & 1 deletion .github/workflows/changesets.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- name: setup node.js
uses: actions/setup-node@v3
with:
node-version: 20
node-version: 20.13.1
- name: install pnpm
run: npm i pnpm@latest -g
- name: setup npmrc
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 20
node-version: 20.13.1

- name: Install pnpm
uses: pnpm/action-setup@v3
Expand Down
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v20.6.0
v20.13.1
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# If you need more help, visit the Dockerfile reference guide at
# https://docs.docker.com/go/dockerfile-reference/

ARG NODE_VERSION=20.6.0
ARG NODE_VERSION=20.13.1

ARG PACKAGE
ARG PORT=3000
Expand Down
27 changes: 27 additions & 0 deletions core/.github/workflows/playwright.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Playwright Tests
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: lts/*
- name: Install dependencies
run: npm install -g pnpm && pnpm install
- name: Install Playwright Browsers
run: pnpm exec playwright install --with-deps
- name: Run Playwright tests
run: pnpm exec playwright test
- uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
path: playwright-report/
retention-days: 30
7 changes: 7 additions & 0 deletions core/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
node_modules/
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/

playwright/.auth
1 change: 1 addition & 0 deletions core/app/c/[communitySlug]/stages/components/Assign.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ export default function Assign(props: Props) {
size="sm"
variant="outline"
role="combobox"
name="Assign"
aria-expanded={open}
className="w-[150px] justify-between"
>
Expand Down
3 changes: 3 additions & 0 deletions core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
"version": "0.0.0",
"private": true,
"scripts": {
"playwright:test": "playwright test",
"playwright:ui": "playwright test --ui",
"dev": "next dev -p 3000 --turbo | pino-pretty",
"build": "SKIP_VALIDATION=true next build",
"invite-users": "dotenv -e .env.local -e .env.development tsx scripts/invite.ts",
Expand Down Expand Up @@ -81,6 +83,7 @@
"zod": "^3.22.4"
},
"devDependencies": {
"@playwright/test": "^1.43.1",
"@preconstruct/next": "^4.0.0",
"@pubpub/eslint-config": "workspace:*",
"@pubpub/prettier-config": "workspace:*",
Expand Down
77 changes: 77 additions & 0 deletions core/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { defineConfig, devices } from "@playwright/test";

/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// require('dotenv').config();

/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: "./playwright",
/* Run tests in files in parallel */
fullyParallel: true,
/* 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. */
workers: process.env.CI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: "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: "http://localhost:3000",

/* 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"] },
},

{
name: "firefox",
use: { ...devices["Desktop Firefox"] },
},
/* Test against WebKit on macOS is failing for me */
// {
// name: "webkit",
// use: { ...devices["Desktop Safari"] },
// },

/* Test against mobile viewports. */
// {
// name: 'Mobile Chrome',
// use: { ...devices['Pixel 5'] },
// },
// {
// name: 'Mobile Safari',
// use: { ...devices['iPhone 12'] },
// },

/* Test against branded browsers. */
// {
// name: 'Microsoft Edge',
// use: { ...devices['Desktop Edge'], channel: 'msedge' },
// },
// {
// name: 'Google Chrome',
// use: { ...devices['Desktop Chrome'], channel: 'chrome' },
// },
],

/* Run your local dev server before starting the tests */
// webServer: {
// command: "pnpm dev",
// url: "http://127.0.0.1:3000",
// reuseExistingServer: !process.env.CI,
// },
});
16 changes: 16 additions & 0 deletions core/playwright/assign.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { expect, test } from "@playwright/test";

const authFile = "playwright/.auth/user.json";

test("Assigning members to a pub", async ({ page }) => {
await page.goto("/login");
await page.getByLabel("email").fill("[email protected]");
await page.getByRole("textbox", { name: "password" }).fill("pubpub-all");
await page.getByRole("button", { name: "Sign in" }).click();

await page.waitForURL("/c/unjournal/stages");
await page.getByRole("combobox").click();
await page.getByRole("option", { name: "Jill Admin" }).click();
await expect(page.getByText("Success", { exact: true })).toBeVisible();
await page.context().storageState({ path: authFile });
});
26 changes: 26 additions & 0 deletions core/playwright/login.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { expect, test } from "@playwright/test";

const authFile = "playwright/.auth/user.json";

test("Login", async ({ page }) => {
await page.goto("/login");
await page.getByLabel("email").fill("[email protected]");
await page.getByRole("textbox", { name: "password" }).fill("pubpub-all");
await page.getByRole("button", { name: "Sign in" }).click();
await page.waitForURL("/c/unjournal/stages");
await expect(page.getByRole("link", { name: "Stages" })).toBeVisible();
await page.context().storageState({ path: authFile });
});

test("Logout", async ({ page }) => {
// should replace login with startup and and eventual db actions with teardown steps
await page.goto("/login");
await page.getByLabel("email").fill("[email protected]");
await page.getByRole("textbox", { name: "password" }).fill("pubpub-all");
await page.getByRole("button", { name: "Sign in" }).click();
await page.waitForURL("/c/unjournal/stages");
await expect(page.getByRole("button", { name: "Logout" })).toBeVisible();
await page.getByRole("button", { name: "Logout" }).click();
await page.waitForURL("/login");
await page.context().storageState({ path: authFile });
});
10 changes: 2 additions & 8 deletions core/prisma/exampleCommunitySeeds/croccroc.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,16 @@
import { faker } from "@faker-js/faker";
import { PubType } from "@prisma/client";
import { v4 as uuidv4, v4 } from "uuid";

import { logger } from "logger";

import type { CommunitiesId } from "~/kysely/types/public/Communities";
import type { PubTypesId } from "~/kysely/types/public/PubTypes";
import { registerCorePubField } from "~/actions/_lib/init";
import { corePubFields } from "~/actions/corePubFields";
// import { PrismaClient } from "@prisma/client";
import { type db as kyselyDb } from "~/kysely/database";
import { env } from "../../lib/env/env.mjs";

// import { FileUpload } from "../../lib/fields/fileUpload";
import { db } from "~/kysely/database";

export const crocCrocId = "758ba348-92c7-46ec-9612-7afda81e2d70" as CommunitiesId;

export default async function main(db: typeof kyselyDb, communityUUID: CommunitiesId) {
export default async function main(communityUUID: CommunitiesId) {
logger.info("Registering core fields");
for (const corePubField of corePubFields) {
logger.info(`Registering core field ${corePubField.slug}`);
Expand Down
73 changes: 44 additions & 29 deletions core/prisma/exampleCommunitySeeds/unjournal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ import { faker } from "@faker-js/faker";
import { PrismaClient } from "@prisma/client";
import { v4 as uuidv4 } from "uuid";

import type { CommunitiesId } from "~/kysely/types/public/Communities";
import type { PubTypesId } from "~/kysely/types/public/PubTypes";
import { corePubFields } from "~/actions/corePubFields";
import { db } from "~/kysely/database";
import { StagesId } from "~/kysely/types/public/Stages";
import { env } from "../../lib/env/env.mjs";
import { FileUpload } from "../../lib/fields/fileUpload";

Expand Down Expand Up @@ -627,7 +632,45 @@ export default async function main(prisma: PrismaClient, communityUUID: string)
},
},
});

const corePubSlugs = corePubFields.map((field) => field.slug);
const persistedCorePubFields = await db
.selectFrom("pub_fields")
.selectAll()
.where("pub_fields.slug", "in", corePubSlugs)
.execute();
await db
.with("new_pubs", (db) =>
db
.insertInto("pubs")
.values({
community_id: communityUUID as CommunitiesId,
pub_type_id: submissionTypeId as PubTypesId,
})
.returning("id")
)
.with("pubs_in_stages", (db) =>
db.insertInto("PubsInStages").values((eb) => [
{
pubId: eb.selectFrom("new_pubs").select("id"),
stageId: stageIds[3] as StagesId,
},
])
)
.insertInto("pub_values")
.values((eb) => [
{
pub_id: eb.selectFrom("new_pubs").select("new_pubs.id"),
field_id: persistedCorePubFields.find((field) => field.slug === "pubpub:title")!.id,
value: '"It Aint Ease Bein Cheese"',
},
{
pub_id: eb.selectFrom("new_pubs").select("new_pubs.id"),
field_id: persistedCorePubFields.find((field) => field.slug === "pubpub:content")!
.id,
value: '"# Abstract"',
},
])
.execute();
// await prisma.pub.update({
// where: { id: submission.id },
// data: {
Expand Down Expand Up @@ -776,32 +819,4 @@ export default async function main(prisma: PrismaClient, communityUUID: string)
});
})
);

// const pubIds = [...Array(7)].map((x) => uuidv4());
// const submissionToEvaluate = await prisma.pub.create({
// data: {
// pubTypeId: submissionTypeId,
// communityId: communityUUID,
// stages: { connect: { id: stageIds[3] } },

// values: {
// createMany: {
// data: [
// {
// fieldId: fieldIds[0],
// value: "When Celebrities Speak: A Nationwide Twitter Experiment Promoting Vaccination In Indonesia",
// },
// {
// fieldId: fieldIds[1],
// value: "Celebrity endorsements are often sought to influence public opinion. We ask whether celebrity endorsement per se has an effect beyond the fact that their statements are seen by many, and whether on net their statements actually lead people to change their beliefs. To do so, we conducted a nationwide Twitter experiment in Indonesia with 46 high-profile celebrities and organizations, with a total of 7.8 million followers, who agreed to let us randomly tweet or retweet content promoting immunization from their accounts. Our design exploits the structure of what information is passed on along a retweet chain on Twitter to parse reach versus endorsement effects. Endorsements matter: tweets that users can identify as being originated by a celebrity are far more likely to be liked or retweeted by users than similar tweets seen by the same users but without the celebrities' imprimatur. By contrast, explicitly citing sources in the tweets actually reduces diffusion. By randomizing which celebrities tweeted when, we find suggestive evidence that overall exposure to the campaign may influence beliefs about vaccination and knowledge of immunization-seeking behavior by one's network. Taken together, the findings suggest an important role for celebrity endorsement.",
// },
// {
// fieldId: fieldIds[8],
// value: "10.3386/w25589",
// },
// ],
// },
// },
// },
// });
}
2 changes: 1 addition & 1 deletion core/prisma/seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ async function main() {
];

logger.info("build crocroc");
await buildCrocCroc(db, crocCrocId);
await buildCrocCroc(crocCrocId);
logger.info("build unjournal");
await buildUnjournal(prisma, unJournalId);

Expand Down
8 changes: 8 additions & 0 deletions core/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,13 @@ export default defineConfig({
plugins: [react(), tsconfigPaths()],
test: {
environment: "jsdom",
exclude: [
"**/playwright/**",
"**/node_modules/**",
"**/dist/**",
"**/cypress/**",
"**/.{idea,git,cache,output,temp}/**",
"**/{karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress,tsup,build}.config.*",
],
},
});
Loading