Skip to content

Commit

Permalink
test: wait for nuxt to be hydrated before interacting with elements
Browse files Browse the repository at this point in the history
  • Loading branch information
danielroe committed Dec 14, 2023
1 parent ea51071 commit a71fb31
Show file tree
Hide file tree
Showing 12 changed files with 61 additions and 38 deletions.
9 changes: 9 additions & 0 deletions .e2e/augments.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { useNuxtApp } from 'nuxt/app'

declare global {
interface Window {
useNuxtApp?: typeof useNuxtApp
}
}

export {}
2 changes: 2 additions & 0 deletions .e2e/tests/advanced/error-handling.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ test('Clicking on the "Trigger fatal error" button navigates to the error page a
await page.goto("/")

const appErrorHookPromise = waitForAppErrorHookToRan(page)
await page.waitForFunction(() => window.useNuxtApp?.().isHydrating === false)
await page.getByRole("button", { name: "Trigger fatal error" }).click()
await appErrorHookPromise

Expand All @@ -99,6 +100,7 @@ test("Triggering non-fatal error with button runs the global error handler and v
const globalErrorHandlerPromise = waitForGlobalErrorHandlerToRan(page)
const vueErrorHookPromise = waitForVueErrorHookToRan(page)

await page.waitForFunction(() => window.useNuxtApp?.().isHydrating === false)
await page.getByRole("button", { name: "Trigger non-fatal error" }).click()
await globalErrorHandlerPromise
await vueErrorHookPromise
Expand Down
1 change: 1 addition & 0 deletions .e2e/tests/advanced/locale.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { test, expect } from "@playwright/test"
test.use(getSettingsForDeployment('locale'))
test.beforeEach(async ({ page }) => {
await page.goto("/")
await page.waitForFunction(() => window.useNuxtApp?.().isHydrating === false)
})

test.describe("British Locale", () => {
Expand Down
1 change: 1 addition & 0 deletions .e2e/tests/advanced/module-extend-pages.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { test, expect } from "@playwright/test"
test.use(getSettingsForDeployment('module-extend-pages'))
test.beforeEach(async ({ page }) => {
await page.goto("/")
await page.waitForFunction(() => window.useNuxtApp?.().isHydrating === false)
})

test("Page that has been added by a module works", async ({ page }) => {
Expand Down
19 changes: 8 additions & 11 deletions .e2e/tests/advanced/use-cookie.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { withoutProtocol } from "ufo"
import { getSettingsForDeployment } from "@/utils"
import { addCookies, addForcedCookie, getSettingsForDeployment, wait } from "@/utils"
import { test, expect } from "@playwright/test"

test.use(getSettingsForDeployment('use-cookie'))
Expand All @@ -11,6 +11,7 @@ test("Login screen shows by default", async ({ page }) => {

test("Logging in multiple times increases counter", async ({ page }) => {
await page.goto("/")
await page.waitForFunction(() => window.useNuxtApp?.().isHydrating === false)

await page.getByPlaceholder("Enter your name...").fill("Nuxt")
await page.getByRole("button", { name: "Log in" }).click()
Expand All @@ -33,40 +34,36 @@ test("Logging in multiple times increases counter", async ({ page }) => {
})

test("Automatic login with existing cookies", async ({ context, page }) => {
const domain = withoutProtocol(process.env.DEPLOY_URL || `https://use-cookie.example.nuxt.space/`)
await context.addCookies([
await addCookies(context, 'use-cookie', [
{
name: "user",
value: '{"name":"Nuxt"}',
domain,
path: "/",
},
{
name: "logins",
value: "1",
domain,
path: "/",
},
])

await page.goto("/")

await expect(
page.getByRole("heading", { name: "Welcome, Nuxt! 👋" })
).toBeVisible()
await expect(page.getByRole("heading", { name: "Welcome, Nuxt! 👋" })).toBeVisible()
await expect(page.getByText("You have logged in 1 times!")).toBeVisible()
})

test("Clearing cookies resets the timer", async ({ context, page }) => {
await page.goto("/")
await page.waitForFunction(() => window.useNuxtApp?.().isHydrating === false)

await page.getByPlaceholder("Enter your name...").fill("Nuxt")
await page.getByRole("button", { name: "Log in" }).click()
await expect(page.getByText("You have logged in 1 times!")).toBeVisible()
await page.getByRole("button", { name: "Log out" }).click()

await context.clearCookies()
await page.reload()
await addForcedCookie(context, "use-cookie")
await page.reload({ waitUntil: "load" })
await page.waitForFunction(() => window.useNuxtApp?.().isHydrating === false)

await page.getByPlaceholder("Enter your name...").fill("Nuxt")
await page.getByRole("button", { name: "Log in" }).click()
Expand Down
1 change: 1 addition & 0 deletions .e2e/tests/features/auto-imports.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { test, expect } from "@playwright/test"
test.use(getSettingsForDeployment('auto-imports'))
test.beforeEach(async ({ page }) => {
await page.goto("/")
await page.waitForFunction(() => window.useNuxtApp?.().isHydrating === false)
})

test("Heading is visible", async ({ page }) => {
Expand Down
2 changes: 2 additions & 0 deletions .e2e/tests/features/meta-tags.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ test.describe("Moving from index to about, and back to the index page", () => {
page,
}) => {
await page.goto("/")
await page.waitForFunction(() => window.useNuxtApp?.().isHydrating === false)
await expect(page.locator("body.my-body-class")).toBeVisible()

await page.getByRole("link", { name: "About page" }).click()
Expand All @@ -82,6 +83,7 @@ test.describe("Moving from index to about, and back to the index page", () => {

test("Title and description changes", async ({ page }) => {
await page.goto("/")
await page.waitForFunction(() => window.useNuxtApp?.().isHydrating === false)
await expect(page.locator('meta[name="description"]')).toHaveAttribute(
"content",
INDEX_DEFAULT_DESCRIPTION
Expand Down
1 change: 1 addition & 0 deletions .e2e/tests/features/state-management.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { test, expect, type Page } from "@playwright/test"
test.use(getSettingsForDeployment("state-management"))
test.beforeEach(async ({ page }) => {
await page.goto("/")
await page.waitForFunction(() => window.useNuxtApp?.().isHydrating === false)
})

test("Same value is displayed on load for both counters", async ({ page }) => {
Expand Down
24 changes: 8 additions & 16 deletions .e2e/tests/routing/middleware.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getSettingsForDeployment, wait } from "@/utils"
import { addForcedCookie, getSettingsForDeployment, wait } from "@/utils"
import { test, expect } from "@playwright/test"

test.use(getSettingsForDeployment('middleware'))
Expand All @@ -10,9 +10,7 @@ test("Global middleware is being registered", async ({ page }) => {

await page.goto("/")
await globalMiddlewareMessageLoggedPromise
await expect(
page.getByText("Current route: /", { exact: true })
).toBeVisible()
await expect(page.getByText("Current route: /", { exact: true })).toBeVisible()
})

test("Global middleware from plugin is being registered", async ({ page }) => {
Expand All @@ -23,9 +21,7 @@ test("Global middleware from plugin is being registered", async ({ page }) => {

await page.goto("/")
await globalMiddlewareMessageLoggedPromise
await expect(
page.getByText("Current route: /", { exact: true })
).toBeVisible()
await expect(page.getByText("Current route: /", { exact: true })).toBeVisible()
})

test('Inline middleware on the "forbidden" page cancels navigation', async ({
Expand All @@ -36,18 +32,16 @@ test('Inline middleware on the "forbidden" page cancels navigation', async ({
const strictlyForbiddenLoggedPromise = page.waitForEvent("console", {
predicate: (message) => message.text() === "Strictly forbidden.",
})
await page.waitForFunction(() => window.useNuxtApp?.().isHydrating === false)
await page.getByRole("link", { name: "Forbidden" }).click()
await strictlyForbiddenLoggedPromise
await wait(500)

await expect(
page.getByText("Current route: /", { exact: true })
).toBeVisible()
await expect(page.getByText("Current route: /", { exact: true })).toBeVisible()
})

test('Middleware redirects from the "/redirect" page to the "/secret" page', async ({
page,
}) => {
test('Middleware redirects from the "/redirect" page to the "/secret" page', async ({ page, context }) => {
await addForcedCookie(context, "middleware")
await page.goto("/redirect")
await expect(page.getByText("You should never see this page")).toBeHidden()
await expect(page).toHaveURL("/secret")
Expand All @@ -61,7 +55,5 @@ test("Named middleware is registered on the secret page", async ({ page }) => {

await page.goto("/secret")
await namedMiddlewareLoggedPromise
await expect(
page.getByText("You've landed on a page that wasn't in the menu!")
).toBeVisible()
await expect(page.getByText("You've landed on a page that wasn't in the menu!")).toBeVisible()
})
1 change: 1 addition & 0 deletions .e2e/tests/routing/pages.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ test.use(getSettingsForDeployment('pages'))
test.describe("Linked pages", () => {
test.beforeEach(async ({ page }) => {
await page.goto("/")
await page.waitForFunction(() => window.useNuxtApp?.().isHydrating === false)
})

test("Home page is shown", async ({ page }) => {
Expand Down
17 changes: 8 additions & 9 deletions .e2e/tests/routing/universal-router.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getSettingsForDeployment } from "@/utils"
import { addForcedCookie, getSettingsForDeployment } from "@/utils"
import { test, expect } from "@playwright/test"

test.use(getSettingsForDeployment('universal-router'))
Expand All @@ -10,21 +10,19 @@ test("Global middleware is being registered", async ({ page }) => {

await page.goto("/")
await globalMiddlewareMessageLoggedPromise
await expect(
page.getByText("Current route: /", { exact: true })
).toBeVisible()
await expect(page.getByText("Current route: /", { exact: true })).toBeVisible()
})

test("Timer is shows during client-side navigation", async ({ page }) => {
await page.goto("/", { waitUntil: "networkidle" })
await page.goto("/")
await page.waitForFunction(() => window.useNuxtApp?.().isHydrating === false)
await page.getByRole("link", { name: "Home" }).click()
await expect(page.getByText("A page... Processing navigation")).toBeVisible()
await expect(page.getByText("A page... Processing navigation")).toBeHidden()
})

test('Middleware redirects from the "/redirect" page to the "/secret" page', async ({
page,
}) => {
test('Middleware redirects from the "/redirect" page to the "/secret" page', async ({ page, context }) => {
await addForcedCookie(context, "middleware")
await page.goto("/redirect")
await expect(page.getByText("You should never see this page")).toBeHidden()
await expect(page).toHaveURL("/secret")
Expand All @@ -33,7 +31,8 @@ test('Middleware redirects from the "/redirect" page to the "/secret" page', asy
test('Middleware redirects from the "/redirect" page to the "/secret" page using custom NuxtLink', async ({
page,
}) => {
await page.goto("/", { waitUntil: "networkidle" })
await page.goto("/")
await page.waitForFunction(() => window.useNuxtApp?.().isHydrating === false)
await page.getByRole("button", { name: "Custom: /redirect" }).click()
await expect(page).toHaveURL("/secret")
})
21 changes: 19 additions & 2 deletions .e2e/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,24 @@
import { BrowserContext, Fixtures, PlaywrightTestArgs, PlaywrightTestOptions, PlaywrightWorkerArgs } from "@playwright/test"
import { withoutProtocol } from "ufo"

export const wait = (ms: number) =>
new Promise((resolve) => setTimeout(resolve, ms))

export const getSettingsForDeployment = (slug: string) => ({
export const getSettingsForDeployment = (slug: string): Fixtures<{}, {}, PlaywrightTestArgs & PlaywrightTestOptions, PlaywrightWorkerArgs> => ({
baseURL: process.env.DEPLOY_URL || `https://${slug}.example.nuxt.space/`,
extraHTTPHeaders: { 'cookie': `forced=${slug}` }
extraHTTPHeaders: { 'cookie': `forced=${slug}` },
})

export async function addForcedCookie (context: BrowserContext, slug: string) {
return addCookies(context, slug, [{ name: "forced", value: slug }])
}

export async function addCookies (context: BrowserContext, slug: string, cookies: Array<{ name: string, value: string }>) {
const domain = withoutProtocol(process.env.DEPLOY_URL || `https://${slug}.example.nuxt.space`)
await context.addCookies(cookies.map(c => ({
name: c.name,
value: c.value,
domain,
path: "/",
})).concat([{ name: "forced", value: slug, domain, path: "/" }]))
}

0 comments on commit a71fb31

Please sign in to comment.