Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
CoCo_Code_Op2
next.js
提交
7dd61b47
N
next.js
项目概览
CoCo_Code_Op2
/
next.js
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
N
next.js
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
7dd61b47
编写于
7月 20, 2020
作者:
J
Jan Potoms
提交者:
GitHub
7月 20, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Fix basepath router events (#14848)
Co-authored-by:
N
Joe Haddad
<
joe.haddad@zeit.co
>
上级
5a00d622
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
315 addition
and
114 deletion
+315
-114
docs/api-reference/next/router.md
docs/api-reference/next/router.md
+2
-0
packages/next/next-server/lib/router/router.ts
packages/next/next-server/lib/router/router.ts
+118
-111
test/integration/basepath/pages/_app.js
test/integration/basepath/pages/_app.js
+52
-0
test/integration/basepath/pages/error-route.js
test/integration/basepath/pages/error-route.js
+8
-0
test/integration/basepath/pages/hello.js
test/integration/basepath/pages/hello.js
+17
-0
test/integration/basepath/pages/index.js
test/integration/basepath/pages/index.js
+2
-1
test/integration/basepath/pages/slow-route.js
test/integration/basepath/pages/slow-route.js
+10
-0
test/integration/basepath/test/index.test.js
test/integration/basepath/test/index.test.js
+101
-0
test/integration/dynamic-routing/test/index.test.js
test/integration/dynamic-routing/test/index.test.js
+5
-2
未找到文件。
docs/api-reference/next/router.md
浏览文件 @
7dd61b47
...
...
@@ -318,6 +318,8 @@ You can listen to different events happening inside the Next.js Router. Here's a
-
`hashChangeComplete(url)`
- Fires when the hash has changed but not the page
> Here `url` is the URL shown in the browser. If you call `router.push(url, as)` (or similar), then the value of `url` will be `as`.
>
> **Note:** If you [configure a `basePath`](/docs/api-reference/next.config.js/basepath.md) then the value of `url` will be `basePath + as`.
#### Usage
...
...
packages/next/next-server/lib/router/router.ts
浏览文件 @
7dd61b47
...
...
@@ -22,6 +22,8 @@ import {
normalizePathTrailingSlash
,
}
from
'
../../../client/normalize-trailing-slash
'
const
ABORTED
=
Symbol
(
'
aborted
'
)
const
basePath
=
(
process
.
env
.
__NEXT_ROUTER_BASEPATH
as
string
)
||
''
export
function
addBasePath
(
path
:
string
):
string
{
...
...
@@ -187,6 +189,7 @@ export default class Router implements BaseRouter {
_wrapApp
:
(
App
:
ComponentType
)
=>
any
isSsr
:
boolean
isFallback
:
boolean
_inFlightRoute
?:
string
static
events
:
MittEmitter
=
mitt
()
...
...
@@ -245,9 +248,7 @@ export default class Router implements BaseRouter {
// until after mount to prevent hydration mismatch
this
.
asPath
=
// @ts-ignore this is temporarily global (attached to window)
isDynamicRoute
(
pathname
)
&&
__NEXT_DATA__
.
autoExport
?
pathname
:
delBasePath
(
as
)
isDynamicRoute
(
pathname
)
&&
__NEXT_DATA__
.
autoExport
?
pathname
:
as
this
.
basePath
=
basePath
this
.
sub
=
subscription
this
.
clc
=
null
...
...
@@ -419,133 +420,140 @@ export default class Router implements BaseRouter {
return
this
.
change
(
'
replaceState
'
,
url
,
as
,
options
)
}
change
(
async
change
(
method
:
HistoryMethod
,
url
:
string
,
as
:
string
,
options
:
any
):
Promise
<
boolean
>
{
return
new
Promise
((
resolve
,
reject
)
=>
{
if
(
!
options
.
_h
)
{
this
.
isSsr
=
false
}
// marking route changes as a navigation start entry
if
(
ST
)
{
performance
.
mark
(
'
routeChange
'
)
}
if
(
!
options
.
_h
)
{
this
.
isSsr
=
false
}
// marking route changes as a navigation start entry
if
(
ST
)
{
performance
.
mark
(
'
routeChange
'
)
}
// Add the ending slash to the paths. So, we can serve the
// "<page>/index.html" directly for the SSR page.
if
(
process
.
env
.
__NEXT_EXPORT_TRAILING_SLASH
)
{
const
rewriteUrlForNextExport
=
require
(
'
./rewrite-url-for-export
'
)
.
rewriteUrlForNextExport
// @ts-ignore this is temporarily global (attached to window)
if
(
__NEXT_DATA__
.
nextExport
)
{
as
=
rewriteUrlForNextExport
(
as
)
}
// Add the ending slash to the paths. So, we can serve the
// "<page>/index.html" directly for the SSR page.
if
(
process
.
env
.
__NEXT_EXPORT_TRAILING_SLASH
)
{
const
rewriteUrlForNextExport
=
require
(
'
./rewrite-url-for-export
'
)
.
rewriteUrlForNextExport
// @ts-ignore this is temporarily global (attached to window)
if
(
__NEXT_DATA__
.
nextExport
)
{
as
=
rewriteUrlForNextExport
(
as
)
}
}
this
.
abortComponentLoad
(
as
)
// If the url change is only related to a hash change
// We should not proceed. We should only change the state.
// WARNING: `_h` is an internal option for handing Next.js client-side
// hydration. Your app should _never_ use this property. It may change at
// any time without notice.
if
(
!
options
.
_h
&&
this
.
onlyAHashChange
(
as
))
{
this
.
asPath
=
as
Router
.
events
.
emit
(
'
hashChangeStart
'
,
as
)
this
.
changeState
(
method
,
url
,
as
,
options
)
this
.
scrollToHash
(
as
)
Router
.
events
.
emit
(
'
hashChangeComplete
'
,
as
)
return
resolve
(
true
)
}
if
(
this
.
_inFlightRoute
)
{
this
.
abortComponentLoad
(
this
.
_inFlightRoute
)
}
const
parsed
=
tryParseRelativeUrl
(
url
)
const
cleanedAs
=
delBasePath
(
as
)
this
.
_inFlightRoute
=
as
// If the url change is only related to a hash change
// We should not proceed. We should only change the state.
// WARNING: `_h` is an internal option for handing Next.js client-side
// hydration. Your app should _never_ use this property. It may change at
// any time without notice.
if
(
!
options
.
_h
&&
this
.
onlyAHashChange
(
cleanedAs
))
{
this
.
asPath
=
cleanedAs
Router
.
events
.
emit
(
'
hashChangeStart
'
,
as
)
this
.
changeState
(
method
,
url
,
as
,
options
)
this
.
scrollToHash
(
cleanedAs
)
Router
.
events
.
emit
(
'
hashChangeComplete
'
,
as
)
return
true
}
if
(
!
parsed
)
return
resolve
(
false
)
const
parsed
=
tryParseRelativeUrl
(
url
)
let
{
pathname
,
searchParams
}
=
parsed
const
query
=
searchParamsToUrlQuery
(
searchParams
)
if
(
!
parsed
)
return
false
// url and as should always be prefixed with basePath by this
// point by either next/link or router.push/replace so strip the
// basePath from the pathname to match the pages dir 1-to-1
pathname
=
pathname
?
removePathTrailingSlash
(
delBasePath
(
pathname
))
:
pathname
let
{
pathname
,
searchParams
}
=
parsed
const
query
=
searchParamsToUrlQuery
(
searchParams
)
const
cleanedAs
=
delBasePath
(
as
)
// url and as should always be prefixed with basePath by this
// point by either next/link or router.push/replace so strip the
// basePath from the pathname to match the pages dir 1-to-1
pathname
=
pathname
?
removePathTrailingSlash
(
delBasePath
(
pathname
))
:
pathname
// If asked to change the current URL we should reload the current page
// (not location.reload() but reload getInitialProps and other Next.js stuffs)
// We also need to set the method = replaceState always
// as this should not go into the history (That's how browsers work)
// We should compare the new asPath to the current asPath, not the url
if
(
!
this
.
urlIsNew
(
cleanedAs
))
{
method
=
'
replaceState
'
}
// If asked to change the current URL we should reload the current page
// (not location.reload() but reload getInitialProps and other Next.js stuffs)
// We also need to set the method = replaceState always
// as this should not go into the history (That's how browsers work)
// We should compare the new asPath to the current asPath, not the url
if
(
!
this
.
urlIsNew
(
cleanedAs
))
{
method
=
'
replaceState
'
}
const
route
=
removePathTrailingSlash
(
pathname
)
const
{
shallow
=
false
}
=
options
if
(
isDynamicRoute
(
route
))
{
const
{
pathname
:
asPathname
}
=
parseRelativeUrl
(
cleanedAs
)
const
routeRegex
=
getRouteRegex
(
route
)
const
routeMatch
=
getRouteMatcher
(
routeRegex
)(
asPathname
)
if
(
!
routeMatch
)
{
const
missingParams
=
Object
.
keys
(
routeRegex
.
groups
).
filter
(
(
param
)
=>
!
query
[
param
]
)
const
route
=
removePathTrailingSlash
(
pathname
)
const
{
shallow
=
false
}
=
options
if
(
missingParams
.
length
>
0
)
{
if
(
process
.
env
.
NODE_ENV
!==
'
production
'
)
{
console
.
warn
(
`Mismatching
\`
as
\`
and
\`
href
\`
failed to manually provide `
+
`the params:
${
missingParams
.
join
(
'
,
'
)}
in the
\`
href
\`
's
\`
query
\`
`
)
}
if
(
isDynamicRoute
(
route
))
{
const
{
pathname
:
asPathname
}
=
parseRelativeUrl
(
cleanedAs
)
const
routeRegex
=
getRouteRegex
(
route
)
const
routeMatch
=
getRouteMatcher
(
routeRegex
)(
asPathname
)
if
(
!
routeMatch
)
{
const
missingParams
=
Object
.
keys
(
routeRegex
.
groups
).
filter
(
(
param
)
=>
!
query
[
param
]
)
return
reject
(
new
Error
(
`The provided
\`
as
\`
value (
${
asPathname
}
) is incompatible with the
\`
href
\`
value (
${
route
}
). `
+
`Read more: https://err.sh/vercel/next.js/incompatible-href-as`
)
if
(
missingParams
.
length
>
0
)
{
if
(
process
.
env
.
NODE_ENV
!==
'
production
'
)
{
console
.
warn
(
`Mismatching
\`
as
\`
and
\`
href
\`
failed to manually provide `
+
`the params:
${
missingParams
.
join
(
'
,
'
)}
in the
\`
href
\`
's
\`
query
\`
`
)
}
}
else
{
// Merge params into `query`, overwriting any specified in search
Object
.
assign
(
query
,
routeMatch
)
throw
new
Error
(
`The provided
\`
as
\`
value (
${
asPathname
}
) is incompatible with the
\`
href
\`
value (
${
route
}
). `
+
`Read more: https://err.sh/vercel/next.js/incompatible-href-as`
)
}
}
else
{
// Merge params into `query`, overwriting any specified in search
Object
.
assign
(
query
,
routeMatch
)
}
}
Router
.
events
.
emit
(
'
routeChangeStart
'
,
as
)
Router
.
events
.
emit
(
'
routeChangeStart
'
,
as
)
// If shallow is true and the route exists in the router cache we reuse the previous result
this
.
getRouteInfo
(
route
,
pathname
,
query
,
as
,
shallow
).
then
(
(
routeInfo
)
=>
{
const
{
error
}
=
routeInfo
// If shallow is true and the route exists in the router cache we reuse the previous result
return
this
.
getRouteInfo
(
route
,
pathname
,
query
,
as
,
shallow
).
then
(
(
routeInfo
)
=>
{
const
{
error
}
=
routeInfo
if
(
error
&&
error
.
cancelled
)
{
return
resolve
(
false
)
}
if
(
error
&&
error
.
cancelled
)
{
// An event already has been fired
return
false
}
Router
.
events
.
emit
(
'
beforeHistoryChange
'
,
as
)
this
.
changeState
(
method
,
url
,
as
,
options
)
if
(
error
&&
error
[
ABORTED
])
{
Router
.
events
.
emit
(
'
routeChangeError
'
,
error
,
as
)
return
false
}
if
(
process
.
env
.
NODE_ENV
!==
'
production
'
)
{
const
appComp
:
any
=
this
.
components
[
'
/_app
'
].
Component
;(
window
as
any
).
next
.
isPrerendered
=
appComp
.
getInitialProps
===
appComp
.
origGetInitialProps
&&
!
(
routeInfo
.
Component
as
any
).
getInitialProps
}
Router
.
events
.
emit
(
'
beforeHistoryChange
'
,
as
)
this
.
changeState
(
method
,
url
,
as
,
options
)
if
(
process
.
env
.
NODE_ENV
!==
'
production
'
)
{
const
appComp
:
any
=
this
.
components
[
'
/_app
'
].
Component
;(
window
as
any
).
next
.
isPrerendered
=
appComp
.
getInitialProps
===
appComp
.
origGetInitialProps
&&
!
(
routeInfo
.
Component
as
any
).
getInitialProps
}
this
.
set
(
route
,
pathname
!
,
query
,
cleanedAs
,
routeInfo
).
then
(()
=>
{
return
this
.
set
(
route
,
pathname
!
,
query
,
cleanedAs
,
routeInfo
).
then
(
()
=>
{
if
(
error
)
{
Router
.
events
.
emit
(
'
routeChangeError
'
,
error
,
a
s
)
Router
.
events
.
emit
(
'
routeChangeError
'
,
error
,
cleanedA
s
)
throw
error
}
...
...
@@ -556,12 +564,11 @@ export default class Router implements BaseRouter {
}
Router
.
events
.
emit
(
'
routeChangeComplete
'
,
as
)
return
resolve
(
true
)
})
},
reject
)
})
return
true
}
)
}
)
}
changeState
(
...
...
@@ -614,7 +621,7 @@ export default class Router implements BaseRouter {
}
const
handleError
=
(
err
:
Error
&
{
code
:
any
;
cancelled
:
boolean
},
err
:
Error
&
{
code
:
any
;
cancelled
:
boolean
;
[
ABORTED
]:
boolean
},
loadErrorFail
?:
boolean
)
=>
{
return
new
Promise
((
resolve
)
=>
{
...
...
@@ -628,8 +635,8 @@ export default class Router implements BaseRouter {
window
.
location
.
href
=
as
// Changing the URL doesn't block executing the current code path.
// So, we need to mark it as a
cancelled error
and stop the routing logic.
err
.
cancelled
=
true
// So, we need to mark it as a
borted
and stop the routing logic.
err
[
ABORTED
]
=
true
// @ts-ignore TODO: fix the control flow here
return
resolve
({
error
:
err
})
}
...
...
test/integration/basepath/pages/_app.js
0 → 100644
浏览文件 @
7dd61b47
import
{
useEffect
}
from
'
react
'
import
{
useRouter
}
from
'
next/router
'
// We use session storage for the event log so that it will survive
// page reloads, which happen for instance during routeChangeError
const
EVENT_LOG_KEY
=
'
router-event-log
'
function
getEventLog
()
{
const
data
=
sessionStorage
.
getItem
(
EVENT_LOG_KEY
)
return
data
?
JSON
.
parse
(
data
)
:
[]
}
function
clearEventLog
()
{
sessionStorage
.
removeItem
(
EVENT_LOG_KEY
)
}
function
addEvent
(
data
)
{
const
eventLog
=
getEventLog
()
eventLog
.
push
(
data
)
sessionStorage
.
setItem
(
EVENT_LOG_KEY
,
JSON
.
stringify
(
eventLog
))
}
if
(
typeof
window
!==
'
undefined
'
)
{
// global functions introduced to interface with the test infrastructure
window
.
_clearEventLog
=
clearEventLog
window
.
_getEventLog
=
getEventLog
}
function
useLoggedEvent
(
event
,
serializeArgs
=
(...
args
)
=>
args
)
{
const
router
=
useRouter
()
useEffect
(()
=>
{
const
logEvent
=
(...
args
)
=>
{
addEvent
([
event
,
...
serializeArgs
(...
args
)])
}
router
.
events
.
on
(
event
,
logEvent
)
return
()
=>
router
.
events
.
off
(
event
,
logEvent
)
},
[
event
,
router
.
events
,
serializeArgs
])
}
function
serializeErrorEventArgs
(
err
,
url
)
{
return
[
err
.
message
,
err
.
cancelled
,
url
]
}
export
default
function
MyApp
({
Component
,
pageProps
})
{
useLoggedEvent
(
'
routeChangeStart
'
)
useLoggedEvent
(
'
routeChangeComplete
'
)
useLoggedEvent
(
'
routeChangeError
'
,
serializeErrorEventArgs
)
useLoggedEvent
(
'
beforeHistoryChange
'
)
useLoggedEvent
(
'
hashChangeStart
'
)
useLoggedEvent
(
'
hashChangeComplete
'
)
return
<
Component
{...
pageProps
}
/
>
}
test/integration/basepath/pages/error-route.js
0 → 100644
浏览文件 @
7dd61b47
export
async
function
getServerSideProps
()
{
// We will use this route to simulate a route change errors
throw
new
Error
(
'
KABOOM!
'
)
}
export
default
function
Page
()
{
return
null
}
test/integration/basepath/pages/hello.js
浏览文件 @
7dd61b47
...
...
@@ -58,6 +58,23 @@ export default () => (
>
click
me
for
error
<
/div
>
<
br
/>
<
div
id
=
"
as-path
"
>
{
useRouter
().
asPath
}
<
/div
>
<
Link
href
=
"
/slow-route
"
>
<
a
id
=
"
slow-route
"
>
<
h1
>
Slow
route
<
/h1
>
<
/a
>
<
/Link
>
<
Link
href
=
"
/error-route
"
>
<
a
id
=
"
error-route
"
>
<
h1
>
Error
route
<
/h1
>
<
/a
>
<
/Link
>
<
Link
href
=
"
/hello#some-hash
"
>
<
a
id
=
"
hash-change
"
>
<
h1
>
Hash
change
<
/h1
>
<
/a
>
<
/Link
>
<
Link
href
=
"
/something-else
"
as
=
"
/hello
"
>
<
a
id
=
"
something-else-link
"
>
to
something
else
<
/a
>
<
/Link
>
...
...
test/integration/basepath/pages/index.js
浏览文件 @
7dd61b47
...
...
@@ -11,7 +11,7 @@ export const getStaticProps = () => {
}
export
default
function
Index
({
hello
,
nested
})
{
const
{
query
,
pathname
}
=
useRouter
()
const
{
query
,
pathname
,
asPath
}
=
useRouter
()
return
(
<>
<
h1
id
=
"
index-page
"
>
index
page
<
/h1
>
...
...
@@ -19,6 +19,7 @@ export default function Index({ hello, nested }) {
<
p
id
=
"
prop
"
>
{
hello
}
world
<
/p
>
<
p
id
=
"
query
"
>
{
JSON
.
stringify
(
query
)}
<
/p
>
<
p
id
=
"
pathname
"
>
{
pathname
}
<
/p
>
<
p
id
=
"
as-path
"
>
{
asPath
}
<
/p
>
<
Link
href
=
"
/hello
"
>
<
a
id
=
"
hello-link
"
>
to
/
hello
<
/a
>
<
/Link
>
...
...
test/integration/basepath/pages/slow-route.js
0 → 100644
浏览文件 @
7dd61b47
export
async
function
getServerSideProps
()
{
// We will use this route to simulate a route cancellation error
// by clicking its link twice in rapid succession
await
new
Promise
((
resolve
)
=>
setTimeout
(
resolve
,
5000
))
return
{
props
:
{}
}
}
export
default
function
Page
()
{
return
null
}
test/integration/basepath/test/index.test.js
浏览文件 @
7dd61b47
...
...
@@ -406,6 +406,24 @@ const runTests = (context, dev = false) => {
}
})
it
(
'
should have correct router paths on first load of /
'
,
async
()
=>
{
const
browser
=
await
webdriver
(
context
.
appPort
,
'
/docs
'
)
await
browser
.
waitForElementByCss
(
'
#pathname
'
)
const
pathname
=
await
browser
.
elementByCss
(
'
#pathname
'
).
text
()
expect
(
pathname
).
toBe
(
'
/
'
)
const
asPath
=
await
browser
.
elementByCss
(
'
#as-path
'
).
text
()
expect
(
asPath
).
toBe
(
'
/
'
)
})
it
(
'
should have correct router paths on first load of /hello
'
,
async
()
=>
{
const
browser
=
await
webdriver
(
context
.
appPort
,
'
/docs/hello
'
)
await
browser
.
waitForElementByCss
(
'
#pathname
'
)
const
pathname
=
await
browser
.
elementByCss
(
'
#pathname
'
).
text
()
expect
(
pathname
).
toBe
(
'
/hello
'
)
const
asPath
=
await
browser
.
elementByCss
(
'
#as-path
'
).
text
()
expect
(
asPath
).
toBe
(
'
/hello
'
)
})
it
(
'
should fetch data for getStaticProps without reloading
'
,
async
()
=>
{
const
browser
=
await
webdriver
(
context
.
appPort
,
'
/docs/hello
'
)
await
browser
.
eval
(
'
window.beforeNavigate = true
'
)
...
...
@@ -490,6 +508,89 @@ const runTests = (context, dev = false) => {
}
})
it
(
'
should use urls with basepath in router events
'
,
async
()
=>
{
const
browser
=
await
webdriver
(
context
.
appPort
,
'
/docs/hello
'
)
try
{
await
browser
.
eval
(
'
window._clearEventLog()
'
)
await
browser
.
elementByCss
(
'
#other-page-link
'
)
.
click
()
.
waitForElementByCss
(
'
#other-page-title
'
)
const
eventLog
=
await
browser
.
eval
(
'
window._getEventLog()
'
)
expect
(
eventLog
).
toEqual
([
[
'
routeChangeStart
'
,
'
/docs/other-page
'
],
[
'
beforeHistoryChange
'
,
'
/docs/other-page
'
],
[
'
routeChangeComplete
'
,
'
/docs/other-page
'
],
])
}
finally
{
await
browser
.
close
()
}
})
it
(
'
should use urls with basepath in router events for hash changes
'
,
async
()
=>
{
const
browser
=
await
webdriver
(
context
.
appPort
,
'
/docs/hello
'
)
try
{
await
browser
.
eval
(
'
window._clearEventLog()
'
)
await
browser
.
elementByCss
(
'
#hash-change
'
).
click
()
const
eventLog
=
await
browser
.
eval
(
'
window._getEventLog()
'
)
expect
(
eventLog
).
toEqual
([
[
'
hashChangeStart
'
,
'
/docs/hello#some-hash
'
],
[
'
hashChangeComplete
'
,
'
/docs/hello#some-hash
'
],
])
}
finally
{
await
browser
.
close
()
}
})
it
(
'
should use urls with basepath in router events for cancelled routes
'
,
async
()
=>
{
const
browser
=
await
webdriver
(
context
.
appPort
,
'
/docs/hello
'
)
try
{
await
browser
.
eval
(
'
window._clearEventLog()
'
)
await
browser
.
elementByCss
(
'
#slow-route
'
)
.
click
()
.
elementByCss
(
'
#other-page-link
'
)
.
click
()
.
waitForElementByCss
(
'
#other-page-title
'
)
const
eventLog
=
await
browser
.
eval
(
'
window._getEventLog()
'
)
expect
(
eventLog
).
toEqual
([
[
'
routeChangeStart
'
,
'
/docs/slow-route
'
],
[
'
routeChangeError
'
,
'
Route Cancelled
'
,
true
,
'
/docs/slow-route
'
],
[
'
routeChangeStart
'
,
'
/docs/other-page
'
],
[
'
beforeHistoryChange
'
,
'
/docs/other-page
'
],
[
'
routeChangeComplete
'
,
'
/docs/other-page
'
],
])
}
finally
{
await
browser
.
close
()
}
})
it
(
'
should use urls with basepath in router events for failed route change
'
,
async
()
=>
{
const
browser
=
await
webdriver
(
context
.
appPort
,
'
/docs/hello
'
)
try
{
await
browser
.
eval
(
'
window._clearEventLog()
'
)
await
browser
.
elementByCss
(
'
#error-route
'
).
click
()
await
waitFor
(
2000
)
const
eventLog
=
await
browser
.
eval
(
'
window._getEventLog()
'
)
expect
(
eventLog
).
toEqual
([
[
'
routeChangeStart
'
,
'
/docs/error-route
'
],
[
'
routeChangeError
'
,
'
Failed to load static props
'
,
null
,
'
/docs/error-route
'
,
],
])
}
finally
{
await
browser
.
close
()
}
})
it
(
'
should allow URL query strings without refresh
'
,
async
()
=>
{
const
browser
=
await
webdriver
(
context
.
appPort
,
'
/docs/hello?query=true
'
)
try
{
...
...
test/integration/dynamic-routing/test/index.test.js
浏览文件 @
7dd61b47
...
...
@@ -98,8 +98,11 @@ function runTests(dev) {
it
(
'
should allow calling Router.push on mount successfully
'
,
async
()
=>
{
const
browser
=
await
webdriver
(
appPort
,
'
/post-1/on-mount-redir
'
)
waitFor
(
2000
)
expect
(
await
browser
.
elementByCss
(
'
h3
'
).
text
()).
toBe
(
'
My blog
'
)
try
{
expect
(
await
browser
.
waitForElementByCss
(
'
h3
'
).
text
()).
toBe
(
'
My blog
'
)
}
finally
{
browser
.
close
()
}
})
it
(
'
should navigate optional dynamic page
'
,
async
()
=>
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录