Some checks failed
Test examples / Test Examples (20) (push) Has been cancelled
Test examples / Test Examples (22) (push) Has been cancelled
Lock Threads / action (push) Has been cancelled
Trigger Release / start (push) Has been cancelled
Stale issue handler / stale (push) Has been cancelled
Update Font Data / create-pull-request (push) Has been cancelled
build-and-deploy / deploy-target (push) Has been cancelled
build-and-deploy / build (push) Has been cancelled
build-and-deploy / stable - aarch64-unknown-linux-musl - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-unknown-linux-musl - node@16 (push) Has been cancelled
build-and-deploy / stable - aarch64-unknown-linux-gnu - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-unknown-linux-gnu - node@16 (push) Has been cancelled
build-and-deploy / stable - aarch64-pc-windows-msvc - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-pc-windows-msvc - node@16 (push) Has been cancelled
build-and-deploy / stable - aarch64-apple-darwin - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-apple-darwin - node@16 (push) Has been cancelled
build-and-deploy / build-wasm (nodejs) (push) Has been cancelled
build-and-deploy / build-wasm (web) (push) Has been cancelled
build-and-deploy / Deploy preview tarball (push) Has been cancelled
build-and-deploy / Potentially publish release (push) Has been cancelled
build-and-deploy / publish-turbopack-npm-packages (push) Has been cancelled
build-and-deploy / Deploy examples (push) Has been cancelled
build-and-deploy / thank you, build (push) Has been cancelled
build-and-deploy / Upload Turbopack Bytesize metrics to Datadog (push) Has been cancelled
Rspack Next.js development integration tests / Rspack integration tests (push) Has been cancelled
Rspack Next.js production integration tests / Rspack integration tests (push) Has been cancelled
Turbopack Next.js development integration tests / Next.js integration tests (push) Has been cancelled
Turbopack Next.js production integration tests / Next.js integration tests (push) Has been cancelled
Update Rspack test manifest / Update and upload Rspack development test manifest (push) Has been cancelled
Update Rspack test manifest / Update and upload Rspack production test manifest (push) Has been cancelled
Upload bundler test manifests to areweturboyet.com / Upload test results (push) Has been cancelled
Update React / create-pull-request (push) Has been cancelled
test-e2e-project-reset-cron / reset-test-project (push) Has been cancelled
Notify about the top 15 issues/PRs/feature requests (most reacted) in the last 90 days / run (push) Has been cancelled
178 lines
5.3 KiB
TypeScript
178 lines
5.3 KiB
TypeScript
/* eslint-env jest */
|
|
|
|
import { waitFor } from 'next-test-utils'
|
|
import path from 'path'
|
|
import { nextTestSetup } from 'e2e-utils'
|
|
|
|
describe('updating <Head /> while client routing', () => {
|
|
const { next } = nextTestSetup({
|
|
files: path.join(__dirname, 'fixture'),
|
|
})
|
|
|
|
it.each([true, false])(
|
|
'should handle boolean async prop in next/head client-side: %s',
|
|
async (bool) => {
|
|
const browser = await next.browser('/head')
|
|
const value = await browser.eval(
|
|
`document.querySelector('script[src="/test-async-${JSON.stringify(
|
|
bool
|
|
)}.js"]').async`
|
|
)
|
|
|
|
expect(value).toBe(bool)
|
|
}
|
|
)
|
|
|
|
it('should only execute async and defer scripts once', async () => {
|
|
const browser = await next.browser('/head')
|
|
|
|
await browser.waitForElementByCss('h1')
|
|
await waitFor(2000)
|
|
expect(Number(await browser.eval('window.__test_async_executions'))).toBe(1)
|
|
expect(Number(await browser.eval('window.__test_defer_executions'))).toBe(1)
|
|
|
|
await browser.elementByCss('#reverseScriptOrder').click()
|
|
await waitFor(2000)
|
|
|
|
expect(Number(await browser.eval('window.__test_async_executions'))).toBe(1)
|
|
expect(Number(await browser.eval('window.__test_defer_executions'))).toBe(1)
|
|
|
|
await browser.elementByCss('#toggleScript').click()
|
|
await waitFor(2000)
|
|
|
|
expect(Number(await browser.eval('window.__test_async_executions'))).toBe(1)
|
|
expect(Number(await browser.eval('window.__test_defer_executions'))).toBe(1)
|
|
})
|
|
|
|
it('should warn when stylesheets or scripts are in head', async () => {
|
|
const browser = await next.browser('/head')
|
|
|
|
await browser.waitForElementByCss('h1')
|
|
await waitFor(1000)
|
|
const browserLogs = await browser.log()
|
|
let foundStyles = false
|
|
let foundScripts = false
|
|
const logs = []
|
|
browserLogs.forEach(({ message }) => {
|
|
if (message.includes('Do not add stylesheets using next/head')) {
|
|
foundStyles = true
|
|
logs.push(message)
|
|
}
|
|
if (message.includes('Do not add <script> tags using next/head')) {
|
|
foundScripts = true
|
|
logs.push(message)
|
|
}
|
|
})
|
|
|
|
expect(foundStyles).toEqual(true)
|
|
expect(foundScripts).toEqual(true)
|
|
|
|
// Warnings are unique
|
|
expect(logs.length).toEqual(new Set(logs).size)
|
|
})
|
|
|
|
it('should warn when scripts are in head', async () => {
|
|
const browser = await next.browser('/head')
|
|
await browser.waitForElementByCss('h1')
|
|
await waitFor(1000)
|
|
const browserLogs = await browser.log()
|
|
let found = false
|
|
browserLogs.forEach((log) => {
|
|
if (log.message.includes('Use next/script instead')) {
|
|
found = true
|
|
}
|
|
})
|
|
expect(found).toEqual(true)
|
|
})
|
|
|
|
it('should not warn when application/ld+json scripts are in head', async () => {
|
|
const browser = await next.browser('/head-with-json-ld-snippet')
|
|
await browser.waitForElementByCss('h1')
|
|
await waitFor(1000)
|
|
const browserLogs = await browser.log()
|
|
let found = false
|
|
browserLogs.forEach((log) => {
|
|
if (log.message.includes('Use next/script instead')) {
|
|
found = true
|
|
}
|
|
})
|
|
expect(found).toEqual(false)
|
|
})
|
|
|
|
it('should update head during client routing', async () => {
|
|
const browser = await next.browser('/nav/head-1')
|
|
expect(
|
|
await browser
|
|
.elementByCss('meta[name="description"]')
|
|
.getAttribute('content')
|
|
).toBe('Head One')
|
|
|
|
await browser
|
|
.elementByCss('#to-head-2')
|
|
.click()
|
|
.waitForElementByCss('#head-2', 3000)
|
|
expect(
|
|
await browser
|
|
.elementByCss('meta[name="description"]')
|
|
.getAttribute('content')
|
|
).toBe('Head Two')
|
|
|
|
await browser
|
|
.elementByCss('#to-head-1')
|
|
.click()
|
|
.waitForElementByCss('#head-1', 3000)
|
|
expect(
|
|
await browser
|
|
.elementByCss('meta[name="description"]')
|
|
.getAttribute('content')
|
|
).toBe('Head One')
|
|
|
|
await browser
|
|
.elementByCss('#to-head-3')
|
|
.click()
|
|
.waitForElementByCss('#head-3', 3000)
|
|
expect(
|
|
await browser
|
|
.elementByCss('meta[name="description"]')
|
|
.getAttribute('content')
|
|
).toBe('Head Three')
|
|
expect(await browser.eval('document.title')).toBe('')
|
|
|
|
await browser
|
|
.elementByCss('#to-head-1')
|
|
.click()
|
|
.waitForElementByCss('#head-1', 3000)
|
|
expect(
|
|
await browser
|
|
.elementByCss('meta[name="description"]')
|
|
.getAttribute('content')
|
|
).toBe('Head One')
|
|
})
|
|
|
|
it('should update title during client routing', async () => {
|
|
const browser = await next.browser('/nav/head-1')
|
|
expect(await browser.eval('document.title')).toBe('this is head-1')
|
|
|
|
await browser
|
|
.elementByCss('#to-head-2')
|
|
.click()
|
|
.waitForElementByCss('#head-2', 3000)
|
|
expect(await browser.eval('document.title')).toBe('this is head-2')
|
|
|
|
await browser
|
|
.elementByCss('#to-head-1')
|
|
.click()
|
|
.waitForElementByCss('#head-1', 3000)
|
|
expect(await browser.eval('document.title')).toBe('this is head-1')
|
|
})
|
|
|
|
it('should update head when unmounting component', async () => {
|
|
const browser = await next.browser('/head-dynamic')
|
|
expect(await browser.eval('document.title')).toBe('B')
|
|
await browser.elementByCss('button').click()
|
|
expect(await browser.eval('document.title')).toBe('A')
|
|
await browser.elementByCss('button').click()
|
|
expect(await browser.eval('document.title')).toBe('B')
|
|
})
|
|
})
|