-
Notifications
You must be signed in to change notification settings - Fork 60
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Playwright tests for API and UI integration
- Loading branch information
1 parent
3ada116
commit bac8537
Showing
3 changed files
with
287 additions
and
1 deletion.
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 |
---|---|---|
|
@@ -48,6 +48,13 @@ export function setupAuth(app: Express, provider: AuthProvider) { | |
} | ||
}) | ||
|
||
app.get("/test-callback", async (req, res) => { | ||
const cookies = new Cookies(req, res) | ||
const returnTo = cookies.get("returnTo") || "/" | ||
setAuthenticatedUser(req, res, { domain: null, email: "[email protected]", name: "Ourboard tester" }) | ||
res.redirect(returnTo) | ||
}) | ||
|
||
function parseReturnPath(req: Request) { | ||
return (req.query.returnTo as string) || "/" | ||
} | ||
|
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,279 @@ | ||
import { Browser, Page, expect, test } from "@playwright/test" | ||
import { sleep } from "../../../common/src/sleep" | ||
import { BoardPage, navigateToBoard, navigateToNewBoard, semiUniqueId } from "../pages/BoardPage" | ||
|
||
async function loginAsTester(page: Page) { | ||
await test.step("Login as tester", async () => { | ||
await page.request.get("/test-callback") | ||
}) | ||
} | ||
|
||
async function logout(page: Page) { | ||
await test.step("Logout", async () => { | ||
await page.request.get("/logout") | ||
}) | ||
} | ||
|
||
test.describe("API endpoints", () => { | ||
test("Create and update board", async ({ page, browser }) => { | ||
const { id, accessToken } = await test.step("Create board", async () => { | ||
const response = await page.request.post("/api/v1/board", { | ||
data: { | ||
name: "API test board", | ||
}, | ||
}) | ||
return await response.json() | ||
}) | ||
|
||
const board = await navigateToBoard(page, browser, id) | ||
|
||
await test.step("Check board name", async () => { | ||
await board.assertBoardName("API test board") | ||
const userPageNoteText = `note-${semiUniqueId()}` | ||
await board.createNoteWithText(100, 200, userPageNoteText) | ||
await board.createArea(100, 400, "API notes") | ||
await board.createArea(550, 400, "More API notes") | ||
}) | ||
|
||
await test.step("Set board name", async () => { | ||
const response = await page.request.put(`/api/v1/board/${id}`, { | ||
data: { | ||
name: "Updated board name", | ||
}, | ||
headers: { | ||
API_TOKEN: accessToken, | ||
}, | ||
}) | ||
expect(response.status()).toEqual(200) | ||
await board.assertBoardName("Updated board name") | ||
}) | ||
|
||
const item = await test.step("Add item", async () => { | ||
const response = await page.request.post(`/api/v1/board/${id}/item`, { | ||
data: { | ||
type: "note", | ||
text: "API note", | ||
container: "API notes", | ||
color: "#000000", | ||
}, | ||
headers: { | ||
API_TOKEN: accessToken, | ||
}, | ||
}) | ||
expect(response.status()).toEqual(200) | ||
await expect(board.getNote("API note")).toBeVisible() | ||
return await response.json() | ||
}) | ||
|
||
await test.step("Update item", async () => { | ||
const response = await page.request.put(`/api/v1/board/${id}/item/${item.id}`, { | ||
data: { | ||
type: "note", | ||
text: "Updated item", | ||
color: "#000000", | ||
}, | ||
headers: { | ||
API_TOKEN: accessToken, | ||
}, | ||
}) | ||
expect(response.status()).toEqual(200) | ||
await expect(board.getNote("Updated item")).toBeVisible() | ||
}) | ||
|
||
await test.step("Change item container", async () => { | ||
await board.assertItemPosition(board.getNote("Updated item"), 163, 460) | ||
const response = await page.request.put(`/api/v1/board/${id}/item/${item.id}`, { | ||
data: { | ||
type: "note", | ||
text: "Updated item", | ||
color: "#000000", | ||
container: "More API notes", | ||
}, | ||
headers: { | ||
API_TOKEN: accessToken, | ||
}, | ||
}) | ||
expect(response.status()).toEqual(200) | ||
await sleep(1000) | ||
await board.assertItemPosition(board.getNote("Updated item"), 613, 460) | ||
}) | ||
|
||
await test.step("Get board state", async () => { | ||
const response = await page.request.get(`/api/v1/board/${id}`, { | ||
headers: { | ||
API_TOKEN: accessToken, | ||
}, | ||
}) | ||
const content = await response.json() | ||
expect(content).toEqual({ | ||
board: { | ||
id, | ||
name: "Updated board name", | ||
width: 800, | ||
height: 600, | ||
serial: expect.anything(), | ||
connections: [], | ||
items: expect.anything(), | ||
}, | ||
}) | ||
}) | ||
|
||
await test.step("Get board state hierarchy", async () => { | ||
const response = await page.request.get(`/api/v1/board/${id}/hierarchy`, { | ||
headers: { | ||
API_TOKEN: accessToken, | ||
}, | ||
}) | ||
const content = await response.json() | ||
expect(content).toEqual({ | ||
board: { | ||
id, | ||
name: "Updated board name", | ||
width: 800, | ||
height: 600, | ||
serial: expect.anything(), | ||
connections: [], | ||
items: expect.anything(), | ||
}, | ||
}) | ||
}) | ||
|
||
await test.step("Get board history", async () => { | ||
const response = await page.request.get(`/api/v1/board/${id}/history`, { | ||
headers: { | ||
API_TOKEN: accessToken, | ||
}, | ||
}) | ||
const content = await response.json() | ||
expect(content).toEqual(expect.arrayContaining([])) | ||
}) | ||
|
||
await test.step("Get board as CSV", async () => { | ||
const response = await page.request.get(`/api/v1/board/${id}/csv`, { | ||
headers: { | ||
API_TOKEN: accessToken, | ||
}, | ||
}) | ||
const content = await response.text() | ||
expect(content).toEqual("More API notes,Updated item\n") | ||
}) | ||
|
||
await test.step("Set accessPolicy", async () => { | ||
const response = await page.request.put(`/api/v1/board/${id}`, { | ||
data: { | ||
name: "Updated board name", | ||
accessPolicy: { | ||
allowList: [], | ||
publicRead: false, | ||
publicWrite: false, | ||
}, | ||
}, | ||
headers: { | ||
API_TOKEN: accessToken, | ||
}, | ||
}) | ||
expect(response.status()).toEqual(200) | ||
await page.reload() | ||
await board.assertStatusMessage("This board is for authorized users only. Click here to sign in.") | ||
|
||
expect( | ||
( | ||
await ( | ||
await page.request.get(`/api/v1/board/${id}`, { | ||
headers: { | ||
API_TOKEN: accessToken, | ||
}, | ||
}) | ||
).json() | ||
).board.accessPolicy, | ||
).toEqual({ | ||
allowList: [], | ||
publicRead: false, | ||
publicWrite: false, | ||
}) | ||
}) | ||
|
||
await test.step("Update accessPolicy", async () => { | ||
const newAccessPolicy = { | ||
allowList: [{ email: "[email protected]" }], | ||
publicRead: true, | ||
publicWrite: true, | ||
} | ||
const response = await page.request.put(`/api/v1/board/${id}`, { | ||
data: { | ||
name: "Updated board name", | ||
accessPolicy: newAccessPolicy, | ||
}, | ||
headers: { | ||
API_TOKEN: accessToken, | ||
}, | ||
}) | ||
expect(response.status()).toEqual(200) | ||
await page.reload() | ||
await expect(board.getNote("Updated item")).toBeVisible() | ||
|
||
expect( | ||
( | ||
await ( | ||
await page.request.get(`/api/v1/board/${id}`, { | ||
headers: { | ||
API_TOKEN: accessToken, | ||
}, | ||
}) | ||
).json() | ||
).board.accessPolicy, | ||
).toEqual(newAccessPolicy) | ||
Check failure on line 225 in playwright/src/tests/api.spec.ts
|
||
}) | ||
}) | ||
|
||
test("Create board with accessPolicy", async ({ page, browser }) => { | ||
await test.step("With empty accessPolicy", async () => { | ||
const board = await test.step("Create board and navigate", async () => { | ||
const response = await page.request.post("/api/v1/board", { | ||
data: { | ||
name: "API restricted board", | ||
accessPolicy: { | ||
allowList: [], | ||
}, | ||
}, | ||
}) | ||
const { id, accessToken } = await response.json() | ||
return await navigateToBoard(page, browser, id) | ||
}) | ||
|
||
await test.step("Verify no UI access", async () => { | ||
await board.assertStatusMessage("This board is for authorized users only. Click here to sign in.") | ||
await loginAsTester(page) | ||
await page.reload() | ||
await board.assertStatusMessage("Sorry, access denied. Click here to sign in with another account.") | ||
await logout(page) | ||
}) | ||
}) | ||
|
||
await test.step("With non-empty accessPolicy", async () => { | ||
const board = await test.step("Create board and navigate", async () => { | ||
const response = await page.request.post("/api/v1/board", { | ||
data: { | ||
name: "API restricted board", | ||
accessPolicy: { | ||
allowList: [{ email: "[email protected]" }], | ||
}, | ||
}, | ||
}) | ||
const { id, accessToken } = await response.json() | ||
return await navigateToBoard(page, browser, id) | ||
}) | ||
|
||
await test.step("Verify restricted access", async () => { | ||
await board.assertStatusMessage("This board is for authorized users only. Click here to sign in.") | ||
|
||
await loginAsTester(page) | ||
|
||
await page.reload() | ||
await board.assertBoardName("API restricted board") | ||
}) | ||
}) | ||
}) | ||
|
||
test("Get board contents with CRDT text", async ({ page, browser }) => {}) | ||
}) |