Skip to content

Commit 6fcbd27

Browse files
committed
chore: add unit tests for cy url, hash, location, title, reload, and go changes to make it easier to test minor behavior changes
1 parent 55b61cf commit 6fcbd27

File tree

10 files changed

+1663
-404
lines changed

10 files changed

+1663
-404
lines changed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
export class UrlNotYetAvailableError extends Error {
2+
constructor () {
3+
const message = 'URL is not yet available'
4+
5+
super(message)
6+
this.name = 'UrlNotYetAvailableError'
7+
}
8+
}
9+
10+
export function getUrlFromAutomation (Cypress: Cypress.Cypress, options: Partial<Cypress.Loggable & Cypress.Timeoutable> = {}) {
11+
const timeout = options.timeout ?? Cypress.config('defaultCommandTimeout') as number
12+
13+
this.set('timeout', timeout)
14+
15+
let fullUrlObj: any = null
16+
let automationPromise: Promise<void> | null = null
17+
// need to set a valid type on this
18+
let mostRecentError = new UrlNotYetAvailableError()
19+
20+
const getUrlFromAutomation = () => {
21+
if (automationPromise) {
22+
return automationPromise
23+
}
24+
25+
fullUrlObj = null
26+
27+
automationPromise = Cypress.automation('get:aut:url', {})
28+
.timeout(timeout)
29+
.then((url) => {
30+
const fullUrlObject = new URL(url)
31+
32+
fullUrlObj = {
33+
hash: fullUrlObject.hash,
34+
host: fullUrlObject.host,
35+
hostname: fullUrlObject.hostname,
36+
href: fullUrlObject.href,
37+
origin: fullUrlObject.origin,
38+
pathname: fullUrlObject.pathname,
39+
port: fullUrlObject.port,
40+
protocol: fullUrlObject.protocol,
41+
search: fullUrlObject.search,
42+
searchParams: fullUrlObject.searchParams,
43+
}
44+
})
45+
.catch((err) => {
46+
mostRecentError.name = err.name
47+
mostRecentError.message = err.message
48+
})
49+
.catch((err) => mostRecentError = err)
50+
// Pass or fail, we always clear the automationPromise, so future retries know there's no live request to the server.
51+
.finally(() => automationPromise = null)
52+
53+
return automationPromise
54+
}
55+
56+
this.set('onFail', (err) => {
57+
// if we are actively retrying or the assertion failed, we want to retry
58+
if (err.name === 'UrlNotYetAvailableError' || err.name === 'AssertionError') {
59+
// tslint:disable-next-line no-floating-promises
60+
getUrlFromAutomation()
61+
} else {
62+
throw err
63+
}
64+
})
65+
66+
return () => {
67+
if (fullUrlObj) {
68+
return fullUrlObj
69+
}
70+
71+
// tslint:disable-next-line no-floating-promises
72+
getUrlFromAutomation()
73+
74+
throw mostRecentError
75+
}
76+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
export class TitleNotYetAvailableError extends Error {
2+
constructor () {
3+
const message = 'document.title is not yet available'
4+
5+
super(message)
6+
this.name = 'TitleNotYetAvailableError'
7+
}
8+
}
9+
10+
export function getTitleFromAutomation (Cypress: Cypress.Cypress, options: Partial<Cypress.Loggable & Cypress.Timeoutable> = {}) {
11+
const timeout = options.timeout ?? Cypress.config('defaultCommandTimeout') as number
12+
13+
this.set('timeout', timeout)
14+
15+
let documentTitle: any = null
16+
let automationPromise: Promise<void> | null = null
17+
// need to set a valid type on this
18+
let mostRecentError = new TitleNotYetAvailableError()
19+
20+
const getTitleFromAutomation = () => {
21+
if (automationPromise) {
22+
return automationPromise
23+
}
24+
25+
documentTitle = null
26+
27+
automationPromise = Cypress.automation('get:aut:title', {})
28+
.timeout(timeout)
29+
.then((returnedDocumentTitle) => {
30+
documentTitle = returnedDocumentTitle
31+
})
32+
.catch((err) => {
33+
mostRecentError.name = err.name
34+
mostRecentError.message = err.message
35+
})
36+
.catch((err) => mostRecentError = err)
37+
// Pass or fail, we always clear the automationPromise, so future retries know there's no live request to the server.
38+
.finally(() => automationPromise = null)
39+
40+
return automationPromise
41+
}
42+
43+
this.set('onFail', (err, timedOut) => {
44+
// if we are actively retrying or the assertion failed, we want to retry
45+
if (err.name === 'TitleNotYetAvailableError' || err.name === 'AssertionError') {
46+
// tslint:disable-next-line no-floating-promises
47+
getTitleFromAutomation()
48+
} else {
49+
throw err
50+
}
51+
})
52+
53+
return () => {
54+
if (documentTitle !== null) {
55+
return documentTitle
56+
}
57+
58+
// tslint:disable-next-line no-floating-promises
59+
getTitleFromAutomation()
60+
61+
throw mostRecentError
62+
}
63+
}

0 commit comments

Comments
 (0)