generated from trywilco/Anythink-Market-Base
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e9b0ea6
commit cfc3e10
Showing
9 changed files
with
1,072 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
name: Playwright Tests | ||
on: | ||
pull_request: | ||
|
||
jobs: | ||
test: | ||
timeout-minutes: 6 | ||
runs-on: ubuntu-20.04 | ||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v3 | ||
with: | ||
ref: ${{ github.head_ref }} | ||
- name: Run checks | ||
uses: actions/setup-node@v3 | ||
with: | ||
node-version: "16" | ||
cache: "yarn" | ||
cache-dependency-path: .framework/react/frontend | ||
|
||
- name: Install dependencies | ||
run: yarn install | ||
working-directory: .framework/react/frontend | ||
|
||
- name: Run frontend client | ||
run: WILCO_ID=0 REACT_APP_BACKEND_URL=http://localhost:3001 yarn start >& /dev/null & | ||
working-directory: .framework/react/frontend | ||
|
||
- name: Install test deps | ||
run: yarn install | ||
working-directory: tests/frontend | ||
|
||
- name: Run Playwright tests | ||
run: yarn test | ||
working-directory: tests/frontend |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
module.exports = async (config) => { | ||
process.env.REACT_APP_URL = "http://localhost:3000"; | ||
process.env.BACKEND_URL = "http://localhost:3001"; | ||
process.env.BACKEND_API_URL = `${process.env.BACKEND_URL}/api`; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"name": "frontend", | ||
"version": "1.0.0", | ||
"main": "index.js", | ||
"license": "MIT", | ||
"dependencies": { | ||
"@playwright/test": "^1.30.0", | ||
"eslint": "^8.34.0", | ||
"playwright": "^1.30.0", | ||
"prettier": "^2.8.4", | ||
"uid": "^2.0.1" | ||
}, | ||
"scripts": { | ||
"test": "playwright test --config=playwright.config.js", | ||
"format": "yarn prettier --write ." | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
// @ts-check | ||
const { defineConfig, devices } = require("@playwright/test"); | ||
|
||
/** | ||
* Read environment variables from file. | ||
* https://github.com/motdotla/dotenv | ||
*/ | ||
// require('dotenv').config(); | ||
|
||
/** | ||
* @see https://playwright.dev/docs/test-configuration | ||
*/ | ||
module.exports = defineConfig({ | ||
globalSetup: "./global-setup.js", | ||
testDir: "./tests", | ||
/* Maximum time one test can run for. */ | ||
timeout: 30 * 1000, | ||
expect: { | ||
/** | ||
* Maximum time expect() should wait for the condition to be met. | ||
* For example in `await expect(locator).toHaveText();` | ||
*/ | ||
timeout: 5000, | ||
}, | ||
/* 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: { | ||
/* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ | ||
actionTimeout: 0, | ||
/* 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'] }, | ||
// }, | ||
], | ||
|
||
/* Folder for test artifacts such as screenshots, videos, traces, etc. */ | ||
// outputDir: 'test-results/', | ||
|
||
/* Run your local dev server before starting the tests */ | ||
// webServer: { | ||
// command: 'npm run start', | ||
// port: 3000, | ||
// }, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
const EventEmitter = require("events"); | ||
const { sleep } = require("../utils"); | ||
const { expect } = require("@playwright/test"); | ||
const { uid } = require("uid"); | ||
|
||
const eventEmitter = new EventEmitter(); | ||
|
||
const dispatch = (type) => { | ||
eventEmitter.emit(type); | ||
}; | ||
|
||
const subscribe = (type, callback) => { | ||
eventEmitter.on(type, callback); | ||
}; | ||
|
||
const unsubscribe = (type, callback) => { | ||
eventEmitter.removeListener(type, callback); | ||
}; | ||
|
||
const wrapWithRequestId = (func) => { | ||
return () => { | ||
const requestId = uid(); | ||
func(requestId); | ||
return requestId; | ||
}; | ||
}; | ||
|
||
const listenAndTriggerRequest = async ( | ||
requestListenerCallback, | ||
requestTrigger | ||
) => { | ||
const requestId = await requestListenerCallback(); | ||
await execAndWaitForRequest(requestId, requestTrigger); | ||
}; | ||
|
||
const execAndWaitForRequest = async (requestId, func, maxTime = 500) => { | ||
let eventPromise; | ||
const eventCallback = () => { | ||
eventPromise(`The event ${requestId} was sent to Wilco`); | ||
}; | ||
|
||
const subscribePromiseAndExec = new Promise(async (resolve) => { | ||
subscribe(requestId, eventCallback); | ||
eventPromise = resolve; | ||
await func(); | ||
}); | ||
|
||
try { | ||
const result = await Promise.race([ | ||
new Promise((resolve) => setTimeout(resolve, maxTime)), | ||
subscribePromiseAndExec, | ||
]); | ||
expect(result).toBe(`The event ${requestId} was sent to Wilco`); | ||
} catch { | ||
throw new Error(`The event ${requestId} was not sent to Wilco`); | ||
} finally { | ||
unsubscribe(requestId, eventCallback); | ||
} | ||
}; | ||
|
||
module.exports = { | ||
dispatch, | ||
subscribe, | ||
unsubscribe, | ||
wrapWithRequestId, | ||
listenAndTriggerRequest, | ||
execAndWaitForRequest, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import { expect, test } from "@playwright/test"; | ||
|
||
import { | ||
dispatch, | ||
listenAndTriggerRequest, | ||
wrapWithRequestId, | ||
} from "../requestValidator"; | ||
|
||
const title = "title"; | ||
const description = "description"; | ||
const imageUrl = | ||
"https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png"; | ||
|
||
const item = { | ||
item: { | ||
slug: `xxxxx-${title}`, | ||
title: title, | ||
description: description, | ||
image: imageUrl, | ||
createdAt: "2023-02-21T19:33:06.752Z", | ||
updatedAt: "2023-02-21T19:33:06.752Z", | ||
tagList: [], | ||
favorited: false, | ||
favoritesCount: 0, | ||
seller: { | ||
username: "username", | ||
image: "https://static.productionready.io/images/smiley-cyrus.jpg", | ||
}, | ||
}, | ||
}; | ||
const wrapExpectCreateItem = (page, title, description, image) => { | ||
return wrapWithRequestId((requestId) => { | ||
page.on("request", (request) => { | ||
if ( | ||
request.url() === `${process.env.BACKEND_API_URL}/items` && | ||
request.method() === "POST" | ||
) { | ||
expect(JSON.parse(request.postData())?.item?.title).toEqual(title); | ||
expect(JSON.parse(request.postData())?.item?.description).toEqual( | ||
description | ||
); | ||
expect(JSON.parse(request.postData())?.item?.image).toEqual(image); | ||
dispatch(requestId); | ||
} | ||
}); | ||
})(); | ||
}; | ||
|
||
test.beforeEach(async ({ page }) => { | ||
await page.route(`${process.env.BACKEND_API_URL}/items`, async (route) => { | ||
const json = item; | ||
await route.fulfill({ json, contentType: "application/json", status: 200 }); | ||
}); | ||
}); | ||
|
||
test("Creating an item trigger a request", async ({ page }) => { | ||
const title = "title"; | ||
const description = "description"; | ||
const imageUrl = | ||
"https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png"; | ||
await page.goto(`${process.env.REACT_APP_URL}/editor`); | ||
await page.getByPlaceholder("Item Title").fill(title); | ||
await page.getByPlaceholder("What's this item about?").fill(description); | ||
await page.getByPlaceholder("Image url").fill(imageUrl); | ||
await listenAndTriggerRequest( | ||
async () => wrapExpectCreateItem(page, title, description, imageUrl), | ||
async () => await page.getByRole("button", { name: "Publish Item" }).click() | ||
); | ||
}); | ||
|
||
test("Creating an item redirects to the item page", async ({ page }) => { | ||
await page.goto(`${process.env.REACT_APP_URL}/editor`); | ||
await page.getByPlaceholder("Item Title").fill(title); | ||
await page.getByPlaceholder("What's this item about?").fill(description); | ||
await page.getByPlaceholder("Image url").fill(imageUrl); | ||
await page.getByRole("button", { name: "Publish Item" }).click(); | ||
await page.waitForURL(`${process.env.REACT_APP_URL}/item/*`); | ||
expect(page.url()).toEqual( | ||
`${process.env.REACT_APP_URL}/item/${item.item.slug}` | ||
); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
import { expect, test } from "@playwright/test"; | ||
|
||
import { | ||
dispatch, | ||
listenAndTriggerRequest, | ||
wrapWithRequestId, | ||
} from "../requestValidator"; | ||
import { uid } from "uid"; | ||
|
||
const username = `user${(Math.random() + 1).toString(36).substring(7)}`; | ||
const email = `${username}@email.com`; | ||
const password = `pass${(Math.random() + 1).toString(36).substring(7)}`; | ||
const token = | ||
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjYzZWE2MjAxZjg3MjE1OGMzMTE1YWI0ZSIsInVzZXJuYW1lIjoidXNlcjJ3d3FlIiwiZXhwIjoxNjgxNDg1Mjk3LCJpYXQiOjE2NzYzMDQ4OTd9.Z45FqelGgXLU4q6xkhw_fTHZ5GXoVsx0vI_HoI3ccDo"; | ||
|
||
const wrapExpectCreateUser = (page, username, email, password) => { | ||
return wrapWithRequestId((requestId) => { | ||
page.on("request", (request) => { | ||
if ( | ||
request.url() === `${process.env.BACKEND_API_URL}/users` && | ||
request.method() === "POST" | ||
) { | ||
expect(JSON.parse(request.postData())?.user?.username).toEqual( | ||
username | ||
); | ||
expect(JSON.parse(request.postData())?.user?.email).toEqual(email); | ||
expect(JSON.parse(request.postData())?.user?.password).toEqual( | ||
password | ||
); | ||
dispatch(requestId); | ||
} | ||
}); | ||
})(); | ||
}; | ||
|
||
test.beforeEach(async ({ page }) => { | ||
await page.route(`${process.env.BACKEND_API_URL}/users`, async (route) => { | ||
const json = { | ||
user: { | ||
username: username, | ||
email: email, | ||
token: token, | ||
role: "user", | ||
}, | ||
}; | ||
await route.fulfill({ json, contentType: "application/json", status: 200 }); | ||
}); | ||
|
||
await page.route( | ||
`${process.env.BACKEND_API_URL}/profiles/${username}`, | ||
async (route) => { | ||
const json = { | ||
profile: { | ||
username: username, | ||
image: "https://static.productionready.io/images/smiley-cyrus.jpg", | ||
following: false, | ||
}, | ||
}; | ||
await route.fulfill({ | ||
json, | ||
headers: { "Content-Type": "application/json" }, | ||
}); | ||
} | ||
); | ||
|
||
await page.route( | ||
`${process.env.BACKEND_API_URL}/items?seller=${username}**`, | ||
async (route) => { | ||
const json = { items: [], itemsCount: 0 }; | ||
await route.fulfill({ | ||
json, | ||
headers: { "Content-Type": "application/json" }, | ||
}); | ||
} | ||
); | ||
}); | ||
|
||
test("User creation redirects to profile page ", async ({ page }) => { | ||
await page.goto(`${process.env.REACT_APP_URL}`); | ||
await page.getByRole("link", { name: "Sign up" }).click(); | ||
await page.getByPlaceholder("Username").fill(username); | ||
await page.getByPlaceholder("Password").fill(password); | ||
await page.getByPlaceholder("Email").fill(email); | ||
await page.getByRole("button", { name: "SIGN UP" }).click(); | ||
await page.waitForSelector(`[href="/@${username}"]`); | ||
expect(page.url()).toBe(`${process.env.REACT_APP_URL}/@${username}`); | ||
}); | ||
|
||
test("Creating a user triggers a request", async ({ page }) => { | ||
await page.goto(`${process.env.REACT_APP_URL}`); | ||
await page.getByRole("link", { name: "Sign up" }).click(); | ||
await page.getByPlaceholder("Username").fill(username); | ||
await page.getByPlaceholder("Password").fill(password); | ||
await page.getByPlaceholder("Email").fill(email); | ||
await listenAndTriggerRequest( | ||
async () => wrapExpectCreateUser(page, username, email, password), | ||
async () => await page.getByRole("button", { name: "SIGN UP" }).click() | ||
); | ||
}); |
Oops, something went wrong.