1
0
Fork 0
mirror of https://github.com/terribleplan/next.js.git synced 2024-01-19 02:48:18 +00:00

Make onClick Link tests more consistent (#4954)

This commit is contained in:
Tim Neutkens 2018-08-15 12:42:56 -07:00 committed by GitHub
parent 87f5df2454
commit b7e256ba01
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 80 additions and 51 deletions

View file

@ -8,14 +8,14 @@ export default class BuildManifestPlugin {
apply (compiler: any) { apply (compiler: any) {
compiler.hooks.emit.tapAsync('NextJsBuildManifest', (compilation, callback) => { compiler.hooks.emit.tapAsync('NextJsBuildManifest', (compilation, callback) => {
const {chunks} = compilation const {chunks} = compilation
const assetMap = {pages: {}} const assetMap = {devFiles: [], pages: {}}
const mainJsChunk = chunks.find((c) => c.name === CLIENT_STATIC_FILES_RUNTIME_MAIN) const mainJsChunk = chunks.find((c) => c.name === CLIENT_STATIC_FILES_RUNTIME_MAIN)
const mainJsFiles = mainJsChunk && mainJsChunk.files.length > 0 ? mainJsChunk.files.filter((file) => /\.js$/.test(file)) : [] const mainJsFiles = mainJsChunk && mainJsChunk.files.length > 0 ? mainJsChunk.files.filter((file) => /\.js$/.test(file)) : []
for (const filePath of Object.keys(compilation.assets)) { for (const filePath of Object.keys(compilation.assets)) {
if (/^static\/dll\//.test(filePath)) { if (/^static\/dll\//.test(filePath)) {
mainJsFiles.push(filePath) assetMap.devFiles.push(filePath)
} }
} }

View file

@ -199,11 +199,12 @@ export class NextScript extends Component {
} }
render () { render () {
const { staticMarkup, assetPrefix, __NEXT_DATA__ } = this.context._documentProps const { staticMarkup, assetPrefix, devFiles, __NEXT_DATA__ } = this.context._documentProps
const { page, pathname, buildId } = __NEXT_DATA__ const { page, pathname, buildId } = __NEXT_DATA__
const pagePathname = getPagePathname(pathname) const pagePathname = getPagePathname(pathname)
return <Fragment> return <Fragment>
{devFiles ? devFiles.map((file) => <script src={`${assetPrefix}/_next/${file}`} nonce={this.props.nonce} />) : null}
{staticMarkup ? null : <script nonce={this.props.nonce} dangerouslySetInnerHTML={{ {staticMarkup ? null : <script nonce={this.props.nonce} dangerouslySetInnerHTML={{
__html: NextScript.getInlineScriptSource(this.context._documentProps) __html: NextScript.getInlineScriptSource(this.context._documentProps)
}} />} }} />}

View file

@ -84,6 +84,7 @@ async function doRender (req, res, pathname, query, {
const ctx = { err, req, res, pathname, query, asPath } const ctx = { err, req, res, pathname, query, asPath }
const router = new Router(pathname, query, asPath) const router = new Router(pathname, query, asPath)
const props = await loadGetInitialProps(App, {Component, router, ctx}) const props = await loadGetInitialProps(App, {Component, router, ctx})
const devFiles = buildManifest.devFiles
const files = [ const files = [
...new Set([ ...new Set([
...buildManifest.pages[normalizePagePath(page)], ...buildManifest.pages[normalizePagePath(page)],
@ -167,6 +168,7 @@ async function doRender (req, res, pathname, query, {
dir, dir,
staticMarkup, staticMarkup,
buildManifest, buildManifest,
devFiles,
files, files,
dynamicImports, dynamicImports,
assetPrefix, // We always pass assetPrefix as a top level property since _document needs it to render, even though the client side might not need it assetPrefix, // We always pass assetPrefix as a top level property since _document needs it to render, even though the client side might not need it

View file

@ -38,7 +38,7 @@ export default class extends Component {
<Link href='/nav/as-path' as='/as/path'><a id='as-path-link' style={linkStyle}>As Path</a></Link> <Link href='/nav/as-path' as='/as/path'><a id='as-path-link' style={linkStyle}>As Path</a></Link>
<Link href='/nav/as-path'><a id='as-path-link-no-as' style={linkStyle}>As Path (No as)</a></Link> <Link href='/nav/as-path'><a id='as-path-link-no-as' style={linkStyle}>As Path (No as)</a></Link>
<Link href='/nav/as-path-using-router'><a id='as-path-using-router-link' style={linkStyle}>As Path (Using Router)</a></Link> <Link href='/nav/as-path-using-router'><a id='as-path-using-router-link' style={linkStyle}>As Path (Using Router)</a></Link>
<Link href='/nav/on-click'><a id='on-click-link' style={linkStyle}>A element with onClick</a></Link> <Link href='/nav/on-click?count=1'><a id='on-click-link' style={linkStyle}>A element with onClick</a></Link>
<Link href='/nav/about'><a id='target-link' target='_blank'>A element with target</a></Link> <Link href='/nav/about'><a id='target-link' target='_blank'>A element with target</a></Link>
<button <button
onClick={() => this.visitQueryStringPage()} onClick={() => this.visitQueryStringPage()}

View file

@ -1,26 +1,31 @@
import { Component } from 'react' import { Component } from 'react'
import Link from 'next/link' import Link from 'next/link'
let count = 0
export default class OnClick extends Component { export default class OnClick extends Component {
static getInitialProps ({ res }) { static getInitialProps ({ res, query: {count} }) {
if (res) return { count: 0 } return { count: count ? parseInt(count) : 0 }
count += 1 }
return { count } state = {
stateCounter: 0
} }
render () { render () {
const {stateCounter} = this.state
const {count} = this.props
return ( return (
<div id='on-click-page'> <div id='on-click-page'>
<Link href='/nav/on-click'> <Link href={`/nav/on-click?count=${count + 1}`} replace>
<a id='on-click-link' onClick={() => ++count}>Self Reload</a> <a id='on-click-link' onClick={() => this.setState({stateCounter: stateCounter + 1})}>Self Reload</a>
</Link> </Link>
<Link href='/nav/on-click'> <Link href='/nav/on-click'>
<a id='on-click-link-prevent-default' onClick={(e) => { e.preventDefault(); ++count }}>Self Reload</a> <a id='on-click-link-prevent-default' onClick={(e) => {
e.preventDefault()
this.setState({stateCounter: stateCounter + 1})
}}>Self Reload</a>
</Link> </Link>
<p>COUNT: {this.props.count}</p> <p id='query-count'>QUERY COUNT: {count}</p>
<p id='state-count'>STATE COUNT: {stateCounter}</p>
</div> </div>
) )
} }

View file

@ -178,59 +178,79 @@ export default (context, render) => {
describe('with onClick action', () => { describe('with onClick action', () => {
it('should reload the page and perform additional action', async () => { it('should reload the page and perform additional action', async () => {
const browser = await webdriver(context.appPort, '/nav/on-click') let browser
const defaultCount = await browser.elementByCss('p').text() try {
expect(defaultCount).toBe('COUNT: 0') browser = await webdriver(context.appPort, '/nav/on-click')
const defaultCountQuery = await browser.elementByCss('#query-count').text()
const defaultCountState = await browser.elementByCss('#state-count').text()
expect(defaultCountQuery).toBe('QUERY COUNT: 0')
expect(defaultCountState).toBe('STATE COUNT: 0')
const countAfterClicked = await browser await browser.elementByCss('#on-click-link').click()
.elementByCss('#on-click-link').click()
.elementByCss('p').text()
// counts (one click + onClick handler) const countQueryAfterClicked = await browser.elementByCss('#query-count').text()
expect(countAfterClicked).toBe('COUNT: 2') const countStateAfterClicked = await browser.elementByCss('#state-count').text()
browser.close() expect(countQueryAfterClicked).toBe('QUERY COUNT: 1')
expect(countStateAfterClicked).toBe('STATE COUNT: 1')
} finally {
if (browser) {
browser.close()
}
}
}) })
it('should not reload if default was prevented', async () => { it('should not reload if default was prevented', async () => {
const browser = await webdriver(context.appPort, '/nav/on-click') let browser
const defaultCount = await browser.elementByCss('p').text() try {
expect(defaultCount).toBe('COUNT: 0') browser = await webdriver(context.appPort, '/nav/on-click')
const defaultCountQuery = await browser.elementByCss('#query-count').text()
const defaultCountState = await browser.elementByCss('#state-count').text()
expect(defaultCountQuery).toBe('QUERY COUNT: 0')
expect(defaultCountState).toBe('STATE COUNT: 0')
const countAfterClicked = await browser await browser.elementByCss('#on-click-link-prevent-default').click()
.elementByCss('#on-click-link-prevent-default').click()
.elementByCss('p').text()
// counter is increased but there was no reload const countQueryAfterClicked = await browser.elementByCss('#query-count').text()
expect(countAfterClicked).toBe('COUNT: 0') const countStateAfterClicked = await browser.elementByCss('#state-count').text()
expect(countQueryAfterClicked).toBe('QUERY COUNT: 0')
expect(countStateAfterClicked).toBe('STATE COUNT: 1')
const countAfterClickedAndReloaded = await browser await browser.elementByCss('#on-click-link').click()
.elementByCss('#on-click-link').click() // +2
.elementByCss('p').text()
// counts (onClick handler, no reload) const countQueryAfterClickedAgain = await browser.elementByCss('#query-count').text()
expect(countAfterClickedAndReloaded).toBe('COUNT: 3') const countStateAfterClickedAgain = await browser.elementByCss('#state-count').text()
browser.close() expect(countQueryAfterClickedAgain).toBe('QUERY COUNT: 1')
expect(countStateAfterClickedAgain).toBe('STATE COUNT: 2')
} finally {
if (browser) {
browser.close()
}
}
}) })
it('should always replace the state and perform additional action', async () => { it('should always replace the state and perform additional action', async () => {
const browser = await webdriver(context.appPort, '/nav') let browser
try {
browser = await webdriver(context.appPort, '/nav')
const countAfterClicked = await browser await browser.elementByCss('#on-click-link').click().waitForElementByCss('#on-click-page')
.elementByCss('#on-click-link').click() // 1
.waitForElementByCss('#on-click-page')
.elementByCss('#on-click-link').click() // 3
.elementByCss('#on-click-link').click() // 5
.elementByCss('p').text()
// counts (page change + two clicks + onClick handler) const defaultCountQuery = await browser.elementByCss('#query-count').text()
expect(countAfterClicked).toBe('COUNT: 5') expect(defaultCountQuery).toBe('QUERY COUNT: 1')
// Since we replace the state, back button would simply go us back to /nav await browser.elementByCss('#on-click-link').click()
await browser const countQueryAfterClicked = await browser.elementByCss('#query-count').text()
.back() const countStateAfterClicked = await browser.elementByCss('#state-count').text()
.waitForElementByCss('.nav-home') expect(countQueryAfterClicked).toBe('QUERY COUNT: 2')
expect(countStateAfterClicked).toBe('STATE COUNT: 1')
browser.close() // Since we replace the state, back button would simply go us back to /nav
await browser.back().waitForElementByCss('.nav-home')
} finally {
if (browser) {
browser.close()
}
}
}) })
}) })

View file

@ -45,6 +45,7 @@ describe('Basic Features', () => {
renderViaHTTP(context.appPort, '/nav'), renderViaHTTP(context.appPort, '/nav'),
renderViaHTTP(context.appPort, '/nav/about'), renderViaHTTP(context.appPort, '/nav/about'),
renderViaHTTP(context.appPort, '/nav/on-click'),
renderViaHTTP(context.appPort, '/nav/querystring'), renderViaHTTP(context.appPort, '/nav/querystring'),
renderViaHTTP(context.appPort, '/nav/self-reload'), renderViaHTTP(context.appPort, '/nav/self-reload'),
renderViaHTTP(context.appPort, '/nav/hash-changes'), renderViaHTTP(context.appPort, '/nav/hash-changes'),