| | import { nextTestSetup } from 'e2e-utils' |
| | import { browserConfigWithFixedTime, fastForwardTo } from './test-utils' |
| | import { findAllTelemetryEvents } from 'next-test-utils' |
| | import path from 'path' |
| |
|
| | describe('app dir client cache semantics (experimental staleTimes)', () => { |
| | describe('dynamic: 0', () => { |
| | const { next, isNextDev, isNextDeploy } = nextTestSetup({ |
| | files: path.join(__dirname, 'fixtures', 'regular'), |
| | nextConfig: { |
| | experimental: { staleTimes: { dynamic: 0 } }, |
| | }, |
| | env: { |
| | NEXT_TELEMETRY_DEBUG: '1', |
| | }, |
| | }) |
| |
|
| | if (isNextDev) { |
| | |
| | it('should trigger a loading state before fetching the page, followed by fresh data on every subsequent navigation', async () => { |
| | const browser = await next.browser('/', browserConfigWithFixedTime) |
| |
|
| | |
| | await browser.waitForIdleNetwork() |
| |
|
| | |
| | await browser |
| | .elementByCss('[href="/1?timeout=1000"]') |
| | .click() |
| | .waitForElementByCss('#loading') |
| |
|
| | const initialRandomNumber = await browser |
| | .waitForElementByCss('#random-number') |
| | .text() |
| |
|
| | await browser.elementByCss('[href="/"]').click() |
| |
|
| | await browser.eval(fastForwardTo, 5 * 1000) |
| |
|
| | const newRandomNumber = await browser |
| | .elementByCss('[href="/1?timeout=1000"]') |
| | .click() |
| | .waitForElementByCss('#random-number') |
| | .text() |
| |
|
| | expect(initialRandomNumber).not.toBe(newRandomNumber) |
| | }) |
| |
|
| | describe('without a loading boundary', () => { |
| | it('should get fresh data on every subsequent navigation', async () => { |
| | const browser = await next.browser( |
| | '/without-loading', |
| | browserConfigWithFixedTime |
| | ) |
| |
|
| | const initialRandomNumber = await browser |
| | .elementByCss('[href="/without-loading/1?timeout=1000"]') |
| | .click() |
| | .waitForElementByCss('#random-number') |
| | .text() |
| |
|
| | await browser.elementByCss('[href="/without-loading"]').click() |
| |
|
| | const newRandomNumber = await browser |
| | .elementByCss('[href="/without-loading/1?timeout=1000"]') |
| | .click() |
| | .waitForElementByCss('#random-number') |
| | .text() |
| |
|
| | expect(initialRandomNumber).not.toBe(newRandomNumber) |
| | }) |
| | }) |
| |
|
| | return |
| | } |
| |
|
| | describe('prefetch={true}', () => { |
| | it('should re-use the cache for 5 minutes (default "static" time)', async () => { |
| | const browser = await next.browser('/', browserConfigWithFixedTime) |
| |
|
| | |
| | await browser.waitForIdleNetwork() |
| |
|
| | let initialRandomNumber = await browser |
| | .elementByCss('[href="/0?timeout=0"]') |
| | .click() |
| | .waitForElementByCss('#random-number') |
| | .text() |
| |
|
| | await browser.elementByCss('[href="/"]').click() |
| |
|
| | let newRandomNumber = await browser |
| | .elementByCss('[href="/0?timeout=0"]') |
| | .click() |
| | .waitForElementByCss('#random-number') |
| | .text() |
| |
|
| | expect(initialRandomNumber).toBe(newRandomNumber) |
| |
|
| | await browser.eval(fastForwardTo, 30 * 1000) |
| |
|
| | await browser.elementByCss('[href="/"]').click() |
| |
|
| | newRandomNumber = await browser |
| | .elementByCss('[href="/0?timeout=0"]') |
| | .click() |
| | .waitForElementByCss('#random-number') |
| | .text() |
| |
|
| | expect(initialRandomNumber).toBe(newRandomNumber) |
| |
|
| | await browser.eval(fastForwardTo, 5 * 60 * 1000) |
| |
|
| | await browser.elementByCss('[href="/"]').click() |
| |
|
| | newRandomNumber = await browser |
| | .elementByCss('[href="/0?timeout=0"]') |
| | .click() |
| | .waitForElementByCss('#random-number') |
| | .text() |
| |
|
| | expect(initialRandomNumber).not.toBe(newRandomNumber) |
| | }) |
| | }) |
| |
|
| | describe('prefetch={false}', () => { |
| | it('should trigger a loading state before fetching the page, followed by fresh data on every subsequent navigation', async () => { |
| | const browser = await next.browser('/', browserConfigWithFixedTime) |
| |
|
| | |
| | await browser.waitForIdleNetwork() |
| |
|
| | |
| | await browser |
| | .elementByCss('[href="/2?timeout=1000"]') |
| | .click() |
| | .waitForElementByCss('#loading') |
| |
|
| | const initialRandomNumber = await browser |
| | .waitForElementByCss('#random-number') |
| | .text() |
| |
|
| | await browser.elementByCss('[href="/"]').click() |
| |
|
| | await browser.eval(fastForwardTo, 5 * 1000) |
| |
|
| | const newRandomNumber = await browser |
| | .elementByCss('[href="/2?timeout=1000"]') |
| | .click() |
| | .waitForElementByCss('#random-number') |
| | .text() |
| |
|
| | expect(initialRandomNumber).not.toBe(newRandomNumber) |
| | }) |
| |
|
| | describe('without a loading boundary', () => { |
| | it('should get fresh data on every subsequent navigation', async () => { |
| | const browser = await next.browser('/', browserConfigWithFixedTime) |
| |
|
| | const initialRandomNumber = await browser |
| | .elementByCss('[href="/2?timeout=1000"]') |
| | .click() |
| | .waitForElementByCss('#random-number') |
| | .text() |
| |
|
| | await browser.elementByCss('[href="/"]').click() |
| |
|
| | await browser.eval(fastForwardTo, 5 * 1000) |
| |
|
| | const newRandomNumber = await browser |
| | .elementByCss('[href="/2?timeout=1000"]') |
| | .click() |
| | .waitForElementByCss('#random-number') |
| | .text() |
| |
|
| | expect(initialRandomNumber).not.toBe(newRandomNumber) |
| | }) |
| | }) |
| | }) |
| |
|
| | describe('prefetch={undefined} - default', () => { |
| | it('should trigger a loading state before fetching the page, followed by fresh data on every subsequent navigation', async () => { |
| | const browser = await next.browser('/', browserConfigWithFixedTime) |
| |
|
| | |
| | await browser.waitForIdleNetwork() |
| |
|
| | |
| | await browser |
| | .elementByCss('[href="/1?timeout=1000"]') |
| | .click() |
| | .waitForElementByCss('#loading') |
| |
|
| | const initialRandomNumber = await browser |
| | .waitForElementByCss('#random-number') |
| | .text() |
| |
|
| | await browser.elementByCss('[href="/"]').click() |
| |
|
| | await browser.eval(fastForwardTo, 5 * 1000) |
| |
|
| | const newRandomNumber = await browser |
| | .elementByCss('[href="/1?timeout=1000"]') |
| | .click() |
| | .waitForElementByCss('#random-number') |
| | .text() |
| |
|
| | expect(initialRandomNumber).not.toBe(newRandomNumber) |
| | }) |
| |
|
| | describe('without a loading boundary', () => { |
| | it('should get fresh data on every subsequent navigation', async () => { |
| | const browser = await next.browser( |
| | '/without-loading', |
| | browserConfigWithFixedTime |
| | ) |
| |
|
| | const initialRandomNumber = await browser |
| | .elementByCss('[href="/without-loading/1?timeout=1000"]') |
| | .click() |
| | .waitForElementByCss('#random-number') |
| | .text() |
| |
|
| | await browser.elementByCss('[href="/without-loading"]').click() |
| |
|
| | const newRandomNumber = await browser |
| | .elementByCss('[href="/without-loading/1?timeout=1000"]') |
| | .click() |
| | .waitForElementByCss('#random-number') |
| | .text() |
| |
|
| | expect(initialRandomNumber).not.toBe(newRandomNumber) |
| | }) |
| | }) |
| | }) |
| |
|
| | if (!isNextDeploy) { |
| | describe('telemetry', () => { |
| | it('should send staleTimes feature usage event', async () => { |
| | const events = findAllTelemetryEvents( |
| | next.cliOutput, |
| | 'NEXT_CLI_SESSION_STARTED' |
| | ) |
| |
|
| | expect(events).toEqual( |
| | expect.arrayContaining([ |
| | expect.objectContaining({ |
| | staticStaleTime: null, |
| | dynamicStaleTime: 0, |
| | }), |
| | ]) |
| | ) |
| | }) |
| | }) |
| | } |
| | }) |
| |
|
| | describe('static: 180', () => { |
| | const { next, isNextDev, isNextDeploy } = nextTestSetup({ |
| | files: path.join(__dirname, 'fixtures', 'regular'), |
| | nextConfig: { |
| | experimental: { staleTimes: { static: 180 } }, |
| | }, |
| | env: { |
| | NEXT_TELEMETRY_DEBUG: '1', |
| | }, |
| | }) |
| |
|
| | if (isNextDev) { |
| | |
| | |
| | it('should skip dev', () => {}) |
| | return |
| | } |
| |
|
| | describe('prefetch={true}', () => { |
| | it('should use the custom static override time (3 minutes)', async () => { |
| | const browser = await next.browser('/', browserConfigWithFixedTime) |
| |
|
| | |
| | await browser.waitForIdleNetwork() |
| |
|
| | let initialRandomNumber = await browser |
| | .elementByCss('[href="/0?timeout=0"]') |
| | .click() |
| | .waitForElementByCss('#random-number') |
| | .text() |
| |
|
| | await browser.elementByCss('[href="/"]').click() |
| |
|
| | let newRandomNumber = await browser |
| | .elementByCss('[href="/0?timeout=0"]') |
| | .click() |
| | .waitForElementByCss('#random-number') |
| | .text() |
| |
|
| | expect(initialRandomNumber).toBe(newRandomNumber) |
| |
|
| | await browser.eval(fastForwardTo, 30 * 1000) |
| |
|
| | await browser.elementByCss('[href="/"]').click() |
| |
|
| | newRandomNumber = await browser |
| | .elementByCss('[href="/0?timeout=0"]') |
| | .click() |
| | .waitForElementByCss('#random-number') |
| | .text() |
| |
|
| | expect(initialRandomNumber).toBe(newRandomNumber) |
| |
|
| | await browser.eval(fastForwardTo, 3 * 60 * 1000) |
| |
|
| | await browser.elementByCss('[href="/"]').click() |
| |
|
| | newRandomNumber = await browser |
| | .elementByCss('[href="/0?timeout=0"]') |
| | .click() |
| | .waitForElementByCss('#random-number') |
| | .text() |
| |
|
| | expect(initialRandomNumber).not.toBe(newRandomNumber) |
| | }) |
| | }) |
| |
|
| | describe('prefetch={undefined} - default', () => { |
| | it('should re-use the loading boundary for the custom static override time (3 minutes)', async () => { |
| | const browser = await next.browser('/', browserConfigWithFixedTime) |
| |
|
| | |
| | await browser.waitForIdleNetwork() |
| |
|
| | const loadingRandomNumber = await browser |
| | .elementByCss('[href="/1?timeout=1000"]') |
| | .click() |
| | .waitForElementByCss('#loading') |
| | .text() |
| |
|
| | await browser.eval(fastForwardTo, 2 * 60 * 1000) |
| |
|
| | await browser.elementByCss('[href="/"]').click() |
| |
|
| | await browser.waitForElementByCss('[href="/1?timeout=1000"]') |
| | await browser.waitForIdleNetwork() |
| |
|
| | let newLoadingNumber = await browser |
| | .elementByCss('[href="/1?timeout=1000"]') |
| | .click() |
| | .waitForElementByCss('#loading') |
| | .text() |
| |
|
| | expect(loadingRandomNumber).toBe(newLoadingNumber) |
| |
|
| | await browser.eval(fastForwardTo, 2 * 60 * 1000) |
| |
|
| | await browser.elementByCss('[href="/"]').click() |
| |
|
| | |
| | await browser.waitForElementByCss('[href="/1?timeout=1000"]') |
| | await browser.waitForIdleNetwork() |
| |
|
| | newLoadingNumber = await browser |
| | .elementByCss('[href="/1?timeout=1000"]') |
| | .click() |
| | .waitForElementByCss('#loading') |
| | .text() |
| |
|
| | expect(loadingRandomNumber).not.toBe(newLoadingNumber) |
| | }) |
| | }) |
| |
|
| | if (!isNextDeploy) { |
| | describe('telemetry', () => { |
| | it('should send staleTimes feature usage event', async () => { |
| | const events = findAllTelemetryEvents( |
| | next.cliOutput, |
| | 'NEXT_CLI_SESSION_STARTED' |
| | ) |
| | expect(events).toEqual( |
| | expect.arrayContaining([ |
| | expect.objectContaining({ |
| | staticStaleTime: 180, |
| | dynamicStaleTime: null, |
| | }), |
| | ]) |
| | ) |
| | }) |
| | }) |
| | } |
| | }) |
| |
|
| | describe('dynamic: 0, static: 0', () => { |
| | const { next } = nextTestSetup({ |
| | files: path.join(__dirname, 'fixtures', 'regular'), |
| | nextConfig: { |
| | experimental: { staleTimes: { dynamic: 0, static: 0 } }, |
| | }, |
| | env: { |
| | NEXT_TELEMETRY_DEBUG: '1', |
| | }, |
| | }) |
| |
|
| | |
| | it('should trigger a loading state before fetching the page, followed by fresh data on every subsequent navigation', async () => { |
| | const browser = await next.browser('/', browserConfigWithFixedTime) |
| |
|
| | |
| | await browser.waitForIdleNetwork() |
| |
|
| | |
| | await browser |
| | .elementByCss('[href="/1?timeout=1000"]') |
| | .click() |
| | .waitForElementByCss('#loading') |
| |
|
| | const initialRandomNumber = await browser |
| | .waitForElementByCss('#random-number') |
| | .text() |
| |
|
| | await browser.elementByCss('[href="/"]').click() |
| |
|
| | await browser.eval(fastForwardTo, 5 * 1000) |
| |
|
| | const newRandomNumber = await browser |
| | .elementByCss('[href="/1?timeout=1000"]') |
| | .click() |
| | .waitForElementByCss('#random-number') |
| | .text() |
| |
|
| | expect(initialRandomNumber).not.toBe(newRandomNumber) |
| | }) |
| |
|
| | describe('without a loading boundary', () => { |
| | it('should get fresh data on every subsequent navigation', async () => { |
| | const browser = await next.browser( |
| | '/without-loading', |
| | browserConfigWithFixedTime |
| | ) |
| |
|
| | const initialRandomNumber = await browser |
| | .elementByCss('[href="/without-loading/1?timeout=1000"]') |
| | .click() |
| | .waitForElementByCss('#random-number') |
| | .text() |
| |
|
| | await browser.elementByCss('[href="/without-loading"]').click() |
| |
|
| | const newRandomNumber = await browser |
| | .elementByCss('[href="/without-loading/1?timeout=1000"]') |
| | .click() |
| | .waitForElementByCss('#random-number') |
| | .text() |
| |
|
| | expect(initialRandomNumber).not.toBe(newRandomNumber) |
| | }) |
| | }) |
| | }) |
| | }) |
| |
|