Skip to content

Commit

Permalink
Refactor Playwright tests (#3614)
Browse files Browse the repository at this point in the history
Signed-off-by: Olga Bulat <obulat@gmail.com>
  • Loading branch information
obulat authored Jan 4, 2024
1 parent cd5a4c6 commit 88e5103
Show file tree
Hide file tree
Showing 20 changed files with 307 additions and 294 deletions.
119 changes: 59 additions & 60 deletions frontend/test/playwright/e2e/attribution.spec.ts
Original file line number Diff line number Diff line change
@@ -1,76 +1,75 @@
import { test, expect } from "@playwright/test"

import { turnOnAnalytics } from "~~/test/playwright/utils/navigation"
import { preparePageForTests } from "~~/test/playwright/utils/navigation"
import {
collectAnalyticsEvents,
expectEventPayloadToMatch,
} from "~~/test/playwright/utils/analytics"

test.describe.configure({ mode: "parallel" })

test.beforeEach(async ({ context }) => {
await context.grantPermissions(["clipboard-read", "clipboard-write"])
})

test("can copy rich text attribution", async ({ page }) => {
await page.goto("image/e9d97a98-621b-4ec2-bf70-f47a74380452")
await page.click('[aria-controls="panel-rich"]')
await page.click('[id="copyattr-rich"]')
const clippedText = await page.evaluate(async () => {
return navigator.clipboard.readText()
test.describe("attribution", () => {
test.beforeEach(async ({ context, page }) => {
await preparePageForTests(page, "xl", { features: { analytics: "on" } })
await context.grantPermissions(["clipboard-read", "clipboard-write"])
})
// The Clipboard API returns a plain-text-ified version of the rich text.
expect(clippedText).toContain('"bubbles in honey" by mutednarayan')
})

test("can copy HTML attribution", async ({ page }) => {
await page.goto("image/e9d97a98-621b-4ec2-bf70-f47a74380452")
await page.click('[aria-controls="panel-html"]')
await page.click('[id="copyattr-html"]')
const clippedText = await page.evaluate(async () => {
return navigator.clipboard.readText()
})
const snippets = [
'<p class="attribution">',
">bubbles in honey</a>",
">mutednarayan</a>",
]
snippets.forEach((snippet) => {
expect(clippedText).toContain(snippet)
test("can copy rich text attribution", async ({ page }) => {
await page.goto("image/e9d97a98-621b-4ec2-bf70-f47a74380452")
await page.click('[aria-controls="panel-rich"]')
await page.click('[id="copyattr-rich"]')
const clippedText = await page.evaluate(async () => {
return navigator.clipboard.readText()
})
// The Clipboard API returns a plain-text-ified version of the rich text.
expect(clippedText).toContain('"bubbles in honey" by mutednarayan')
})
})

test("can copy plain text attribution", async ({ page }) => {
await page.goto("image/e9d97a98-621b-4ec2-bf70-f47a74380452")
await page.click('[aria-controls="panel-plain"]')
await page.click('[id="copyattr-plain"]')
const clippedText = await page.evaluate(async () => {
return navigator.clipboard.readText()
test("can copy HTML attribution", async ({ page }) => {
await page.goto("image/e9d97a98-621b-4ec2-bf70-f47a74380452")
await page.click('[aria-controls="panel-html"]')
await page.click('[id="copyattr-html"]')
const clippedText = await page.evaluate(async () => {
return navigator.clipboard.readText()
})
const snippets = [
'<p class="attribution">',
">bubbles in honey</a>",
">mutednarayan</a>",
]
snippets.forEach((snippet) => {
expect(clippedText).toContain(snippet)
})
})
// Only the plain-text license contains the "To view" bit.
expect(clippedText).toContain("To view a copy of this license")
})

test("sends analytics event on copy", async ({ page }) => {
let copyAttributionEventData: {
id: string
format: string
mediaType: string
} = { id: "", format: "", mediaType: "" }
page.on("request", (req) => {
if (req.method() === "POST") {
const requestData = req.postDataJSON()
if (requestData?.n == "COPY_ATTRIBUTION") {
copyAttributionEventData = JSON.parse(requestData?.p)
}
}
test("can copy plain text attribution", async ({ page }) => {
await page.goto("image/e9d97a98-621b-4ec2-bf70-f47a74380452")
await page.click('[aria-controls="panel-plain"]')
await page.click('[id="copyattr-plain"]')
const clippedText = await page.evaluate(async () => {
return navigator.clipboard.readText()
})
// Only the plain-text license contains the "To view" bit.
expect(clippedText).toContain("To view a copy of this license")
})
const mediaType = "image"
const id = "e9d97a98-621b-4ec2-bf70-f47a74380452"
const format = "rich"

await turnOnAnalytics(page)
test("sends analytics event on copy", async ({ page }) => {
const analyticsEvents = collectAnalyticsEvents(page.context())

await page.goto(`${mediaType}/${id}?ff_analytics=on`)
await page.click(`[id="copyattr-${format}"]`)
const mediaType = "image"
const id = "e9d97a98-621b-4ec2-bf70-f47a74380452"
const format = "rich"

expect(copyAttributionEventData.id).toEqual(id)
expect(copyAttributionEventData.format).toEqual(format)
expect(copyAttributionEventData.mediaType).toEqual(mediaType)
await page.goto(`${mediaType}/${id}?ff_analytics=on`)
await page.click(`[id="copyattr-${format}"]`)

const copyAttributionEvent = analyticsEvents.find(
(event) => event.n === "COPY_ATTRIBUTION"
)
expectEventPayloadToMatch(copyAttributionEvent, {
id,
format,
mediaType,
})
})
})
83 changes: 46 additions & 37 deletions frontend/test/playwright/e2e/collections.spec.ts
Original file line number Diff line number Diff line change
@@ -1,55 +1,64 @@
import { test, expect } from "@playwright/test"

import { setCookies, t } from "~~/test/playwright/utils/navigation"
import { preparePageForTests, t } from "~~/test/playwright/utils/navigation"

test.describe.configure({ mode: "parallel" })

test.beforeEach(async ({ context, page }) => {
await setCookies(context, {
features: { additional_search_views: "on", analytics: "off" },
test.describe("collections", () => {
test.beforeEach(async ({ page }) => {
await preparePageForTests(page, "xl", {
features: {
additional_search_views: "on",
},
})
await page.goto("/image/f9384235-b72e-4f1e-9b05-e1b116262a29?q=cat")
})
await page.goto("/image/f9384235-b72e-4f1e-9b05-e1b116262a29?q=cat")
})
test("can open tags collection page from image page", async ({ page }) => {
// Using the href because there are multiple links with the same text.
await page.click('[href*="/tag/cat"]')

await expect(
page.getByRole("button", { name: t("browsePage.load") })
).toBeEnabled()
test("can open tags collection page from image page", async ({ page }) => {
// Using the href because there are multiple links with the same text.
await page.click('[href*="/tag/cat"]')

await expect(page.getByRole("heading", { name: /cat/i })).toBeVisible()
expect(await page.locator("figure").count()).toEqual(20)
expect(page.url()).toMatch(/image\/tag\/cat/)
})
test("can open source collection page from image page", async ({ page }) => {
const sourcePattern = /flickr/i
await expect(
page.getByRole("button", { name: t("browsePage.load") })
).toBeEnabled()

await page.getByRole("link", { name: sourcePattern }).first().click()
await expect(
page.getByRole("heading", { level: 1, name: /cat/i })
).toBeVisible()
expect(await page.locator("figure").count()).toEqual(20)
expect(page.url()).toMatch(/image\/tag\/cat/)
})
test("can open source collection page from image page", async ({ page }) => {
const sourcePattern = /flickr/i

await expect(
page.getByRole("button", { name: t("browsePage.load") })
).toBeEnabled()
await page.getByRole("link", { name: sourcePattern }).first().click()

await expect(page.getByRole("heading", { name: sourcePattern })).toBeVisible()
await expect(
page.getByRole("button", { name: t("browsePage.load") })
).toBeEnabled()

expect(await page.locator("figure").count()).toEqual(20)
await expect(
page.getByRole("heading", { name: sourcePattern })
).toBeVisible()

expect(page.url()).toMatch(/image\/source\/flickr\/$/)
})
test("can open creator collection page from image page", async ({ page }) => {
const creatorPattern = /strogoscope/i
await page.getByRole("link", { name: creatorPattern }).first().click()
expect(await page.locator("figure").count()).toEqual(20)

await expect(
page.getByRole("button", { name: t("browsePage.load") })
).toBeEnabled()
expect(page.url()).toMatch(/image\/source\/flickr\/$/)
})
test("can open creator collection page from image page", async ({ page }) => {
const creatorPattern = /strogoscope/i
await page.getByRole("link", { name: creatorPattern }).first().click()

await expect(
page.getByRole("button", { name: t("browsePage.load") })
).toBeEnabled()

await expect(
page.getByRole("heading", { name: creatorPattern })
).toBeVisible()
await expect(
page.getByRole("heading", { level: 1, name: creatorPattern })
).toBeVisible()

expect(await page.locator("figure").count()).toEqual(20)
expect(await page.locator("figure").count()).toEqual(20)

expect(page.url()).toMatch(/image\/source\/flickr\/creator\/strogoscope\//)
expect(page.url()).toMatch(/image\/source\/flickr\/creator\/strogoscope\//)
})
})
90 changes: 48 additions & 42 deletions frontend/test/playwright/e2e/external-sources.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,67 +2,73 @@ import { test } from "@playwright/test"

import {
goToSearchTerm,
preparePageForTests,
t,
turnOnAnalytics,
} from "~~/test/playwright/utils/navigation"

import {
collectAnalyticsEvents,
expectEventPayloadToMatch,
} from "~~/test/playwright/utils/analytics"

test("sends VIEW_EXTERNAL_SOURCES analytics events", async ({
page,
context,
}) => {
await turnOnAnalytics(page)
const events = collectAnalyticsEvents(context)
test.describe("analytics", () => {
test.beforeEach(async ({ page }) => {
await preparePageForTests(page, "xl", { features: { analytics: "on" } })
})

test("sends VIEW_EXTERNAL_SOURCES analytics events", async ({
page,
context,
}) => {
const events = collectAnalyticsEvents(context)

await goToSearchTerm(page, "cat", { searchType: "image", mode: "SSR" })
await goToSearchTerm(page, "cat", { searchType: "image", mode: "SSR" })

await page
.getByRole("button", { name: t("externalSources.form.supportedTitle") })
.click()
await page.getByRole("button", { name: /close/i }).click()
await page
.getByRole("button", { name: t("externalSources.form.supportedTitle") })
.click()
await page.getByRole("button", { name: /close/i }).click()

const viewEvent = events.find((event) => event.n === "VIEW_EXTERNAL_SOURCES")
const viewEvent = events.find(
(event) => event.n === "VIEW_EXTERNAL_SOURCES"
)

expectEventPayloadToMatch(viewEvent, {
searchType: "image",
query: "cat",
resultPage: 1,
expectEventPayloadToMatch(viewEvent, {
searchType: "image",
query: "cat",
resultPage: 1,
})
})
})

test("sends SELECT_EXTERNAL_SOURCE analytics events", async ({
page,
context,
}) => {
await turnOnAnalytics(page)
const pagePromise = page.context().waitForEvent("page")
test("sends SELECT_EXTERNAL_SOURCE analytics events", async ({
page,
context,
}) => {
const pagePromise = page.context().waitForEvent("page")

const events = collectAnalyticsEvents(context)
const events = collectAnalyticsEvents(context)

await goToSearchTerm(page, "cat", { searchType: "image", mode: "SSR" })
await goToSearchTerm(page, "cat", { searchType: "image", mode: "SSR" })

await page
.getByRole("button", {
name: new RegExp(t("externalSources.form.supportedTitleSm"), "i"),
})
.click()
await page.getByRole("link", { name: "Centre for Ageing Better" }).click()
await page
.getByRole("button", {
name: new RegExp(t("externalSources.form.supportedTitleSm"), "i"),
})
.click()
await page.getByRole("link", { name: "Centre for Ageing Better" }).click()

const newPage = await pagePromise
await newPage.close()
const newPage = await pagePromise
await newPage.close()

const selectEvent = events.find(
(event) => event.n === "SELECT_EXTERNAL_SOURCE"
)
const selectEvent = events.find(
(event) => event.n === "SELECT_EXTERNAL_SOURCE"
)

expectEventPayloadToMatch(selectEvent, {
name: "Centre For Ageing Better",
mediaType: "image",
query: "cat",
component: "VExternalSourceList",
expectEventPayloadToMatch(selectEvent, {
name: "Centre For Ageing Better",
mediaType: "image",
query: "cat",
component: "VExternalSourceList",
})
})
})
4 changes: 2 additions & 2 deletions frontend/test/playwright/e2e/filters-sidebar-keyboard.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
LanguageDirection,
languageDirections,
pathWithDir,
setBreakpointCookie,
preparePageForTests,
t,
} from "~~/test/playwright/utils/navigation"

Expand Down Expand Up @@ -32,7 +32,7 @@ test.describe.configure({ mode: "parallel" })
for (const dir of languageDirections) {
test.describe(`search header keyboard accessibility test in ${dir}`, () => {
test.beforeEach(async ({ page }) => {
await setBreakpointCookie(page, "lg")
await preparePageForTests(page, "lg", { dismissFilter: false })
/**
* To simplify finding the last focusable element in the filters sidebar,
* we use the image search page. The last element on the all media search
Expand Down
6 changes: 3 additions & 3 deletions frontend/test/playwright/e2e/filters.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
goToSearchTerm,
isPageDesktop,
filters,
dismissAllBannersUsingCookies,
preparePageForTests,
} from "~~/test/playwright/utils/navigation"

import { mockProviderApis } from "~~/test/playwright/utils/route"
Expand Down Expand Up @@ -44,10 +44,10 @@ const FILTER_COUNTS = {
[IMAGE]: 73,
}

breakpoints.describeMobileAndDesktop(() => {
breakpoints.describeMobileAndDesktop(({ breakpoint }) => {
test.beforeEach(async ({ context, page }) => {
await mockProviderApis(context)
await dismissAllBannersUsingCookies(page)
await preparePageForTests(page, breakpoint)
})
for (const searchType of supportedSearchTypes) {
test(`correct total number of filters is displayed for ${searchType}`, async ({
Expand Down
Loading

0 comments on commit 88e5103

Please sign in to comment.