rsnext/test/integration/invalid-href/test/index.test.js
JJ Kasper 53e9983d83 Add hydration callback for testing (#10195)
* Add hydration callback for testing

* Update size-limit test
2020-01-21 15:33:58 -05:00

190 lines
5.9 KiB
JavaScript

/* eslint-env jest */
/* global jasmine */
import { join } from 'path'
import webdriver from 'next-webdriver'
import {
findPort,
launchApp,
killApp,
nextStart,
nextBuild,
getReactErrorOverlayContent,
waitFor,
} from 'next-test-utils'
jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 60 * 5
let app
let appPort
const appDir = join(__dirname, '..')
const firstErrorRegex = /Invalid href passed to router: mailto:idk@idk.com.*invalid-href-passed/
const secondErrorRegex = /Invalid href passed to router: .*google\.com.*invalid-href-passed/
const showsError = async (
pathname,
regex,
click = false,
isWarn = false,
cb
) => {
const browser = await webdriver(appPort, pathname)
if (isWarn) {
await browser.eval(`(function() {
window.warnLogs = []
var origWarn = window.console.warn
window.console.warn = function() {
var warnStr = ''
for (var i = 0; i < arguments.length; i++) {
if (i > 0) warnStr += ' ';
warnStr += arguments[i]
}
window.warnLogs.push(warnStr)
origWarn.apply(undefined, arguments)
}
})()`)
}
if (click) {
await browser.elementByCss('a').click()
}
if (isWarn) {
await waitFor(2000)
const warnLogs = await browser.eval('window.warnLogs')
console.log(warnLogs)
expect(warnLogs.some(log => log.match(regex))).toBe(true)
} else {
const errorContent = await getReactErrorOverlayContent(browser)
expect(errorContent).toMatch(regex)
}
if (cb) await cb(browser)
await browser.close()
}
const noError = async (pathname, click = false) => {
const browser = await webdriver(appPort, '/')
await browser.eval(`(function() {
window.caughtErrors = []
window.addEventListener('error', function (error) {
window.caughtErrors.push(error.message || 1)
})
window.addEventListener('unhandledrejection', function (error) {
window.caughtErrors.push(error.message || 1)
})
window.next.router.replace('${pathname}')
})()`)
// wait for page to be built and navigated to
await waitFor(3000)
if (click) {
await browser.elementByCss('a').click()
}
const numErrors = await browser.eval(`window.caughtErrors.length`)
expect(numErrors).toBe(0)
await browser.close()
}
describe('Invalid hrefs', () => {
describe('dev mode', () => {
beforeAll(async () => {
appPort = await findPort()
app = await launchApp(appDir, appPort)
})
afterAll(() => killApp(app))
it('shows error when mailto: is used as href on Link', async () => {
await showsError('/first', firstErrorRegex)
})
it('shows error when mailto: is used as href on router.push', async () => {
await showsError('/first?method=push', firstErrorRegex, true)
})
it('shows error when mailto: is used as href on router.replace', async () => {
await showsError('/first?method=replace', firstErrorRegex, true)
})
it('shows error when https://google.com is used as href on Link', async () => {
await showsError('/second', secondErrorRegex)
})
it('shows error when http://google.com is used as href on router.push', async () => {
await showsError('/second?method=push', secondErrorRegex, true)
})
it('shows error when https://google.com is used as href on router.replace', async () => {
await showsError('/second?method=replace', secondErrorRegex, true)
})
it('shows error when dynamic route mismatch is used on Link', async () => {
await showsError(
'/dynamic-route-mismatch',
/The provided `as` value \(\/blog\/post-1\) is incompatible with the `href` value \(\/\[post\]\)/,
true
)
await showsError(
'/dynamic-route-mismatch',
/Mismatching `as` and `href` failed to manually provide the params: post in the `href`'s `query`/,
true,
true
)
})
it('does not throw error when dynamic route mismatch is used on Link and params are manually provided', async () => {
await noError('/dynamic-route-mismatch-manual', true)
})
})
describe('production mode', () => {
beforeAll(async () => {
await nextBuild(appDir)
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
afterAll(() => killApp())
it('does not show error in production when mailto: is used as href on Link', async () => {
await noError('/first')
})
it('does not show error in production when mailto: is used as href on router.push', async () => {
await noError('/first?method=push', true)
})
it('does not show error in production when mailto: is used as href on router.replace', async () => {
await noError('/first?method=replace', true)
})
it('does not show error in production when https://google.com is used as href on Link', async () => {
await noError('/second')
})
it('does not show error in production when http://google.com is used as href on router.push', async () => {
await noError('/second?method=push', true)
})
it('does not show error in production when https://google.com is used as href on router.replace', async () => {
await noError('/second?method=replace', true)
})
it('shows error when dynamic route mismatch is used on Link', async () => {
const browser = await webdriver(appPort, '/dynamic-route-mismatch')
await browser.eval(`(function() {
window.caughtErrors = []
window.addEventListener('unhandledrejection', (error) => {
window.caughtErrors.push(error.reason.message)
})
})()`)
await browser.elementByCss('a').click()
await waitFor(500)
const errors = await browser.eval('window.caughtErrors')
expect(
errors.find(err =>
err.includes(
'The provided `as` value (/blog/post-1) is incompatible with the `href` value (/[post]). Read more: https://err.sh/zeit/next.js/incompatible-href-as'
)
)
).toBeTruthy()
})
})
})