Skip to content

Commit 0febfc8

Browse files
DavertMikDavertMikclaude
authored
fix: join base url and relative path with a single slash (#5738)
Playwright amOnPage produced https://host/app///path whenever the base url ended with a slash, and Puppeteer/WebDriver concatenated without any separator. Route all of them through appendBaseUrl and fix its trimUrl, which never stripped the leading slash. Co-authored-by: DavertMik <davert@testomat.io> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 650f240 commit 0febfc8

5 files changed

Lines changed: 28 additions & 14 deletions

File tree

‎lib/helper/Playwright.js‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import {
2727
normalizeSpacesInString,
2828
normalizePath,
2929
resolveUrl,
30+
appendBaseUrl,
3031
relativeDir,
3132
getMimeType,
3233
base64EncodeFile,
@@ -1365,7 +1366,7 @@ class Playwright extends Helper {
13651366
}
13661367

13671368
if (!/^\w+\:(\/\/|.+)/.test(url)) {
1368-
url = this.options.url + (!this.options.url.endsWith('/') && url.startsWith('/') ? url : `/${url}`)
1369+
url = appendBaseUrl(this.options.url, url)
13691370
this.debug(`Changed URL to base url + relative path: ${url}`)
13701371
}
13711372

@@ -3124,7 +3125,7 @@ class Playwright extends Helper {
31243125

31253126
if (url.startsWith('/')) {
31263127
// local url
3127-
url = this.options.url + url
3128+
url = appendBaseUrl(this.options.url, url)
31283129
this.debugSection('URL', url)
31293130
}
31303131

‎lib/helper/Puppeteer.js‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import {
3030
normalizeSpacesInString,
3131
normalizePath,
3232
resolveUrl,
33+
appendBaseUrl,
3334
getMimeType,
3435
base64EncodeFile,
3536
} from '../utils.js'
@@ -751,7 +752,7 @@ class Puppeteer extends Helper {
751752
*/
752753
async amOnPage(url) {
753754
if (!/^\w+\:\/\//.test(url)) {
754-
url = this.options.url + url
755+
url = appendBaseUrl(this.options.url, url)
755756
}
756757

757758
if (this.options.basicAuth && this.isAuthenticated !== true) {

‎lib/helper/WebDriver.js‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import {
2727
modifierKeys,
2828
normalizePath,
2929
resolveUrl,
30+
appendBaseUrl,
3031
getMimeType,
3132
base64EncodeFile,
3233
} from '../utils.js'
@@ -1063,7 +1064,7 @@ class WebDriver extends Helper {
10631064
let split_url
10641065
if (this.options.basicAuth) {
10651066
if (url.startsWith('/')) {
1066-
url = this.options.url + url
1067+
url = appendBaseUrl(this.options.url, url)
10671068
}
10681069
split_url = url.split('//')
10691070
url = `${split_url[0]}//${this.options.basicAuth.username}:${this.options.basicAuth.password}@${split_url[1]}`

‎lib/utils.js‎

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -372,11 +372,7 @@ function shouldAppendBaseUrl(url) {
372372
}
373373

374374
function trimUrl(url) {
375-
const firstChar = url.substr(1)
376-
if (firstChar === '/') {
377-
url = url.slice(1)
378-
}
379-
return url
375+
return url.replace(/^\/+/, '')
380376
}
381377

382378
function joinUrl(baseUrl, url) {
@@ -390,11 +386,7 @@ export const appendBaseUrl = function (baseUrl = '', oneOrMoreUrls) {
390386
if (!(typeof oneOrMoreUrls === 'string' || Array.isArray(oneOrMoreUrls))) {
391387
throw new Error(`Expected type of Urls is 'string' or 'array', Found '${typeof oneOrMoreUrls}'.`)
392388
}
393-
// Remove '/' if it's at the end of baseUrl
394-
const lastChar = baseUrl.substr(-1)
395-
if (lastChar === '/') {
396-
baseUrl = baseUrl.slice(0, -1)
397-
}
389+
baseUrl = baseUrl.replace(/\/+$/, '')
398390

399391
if (!Array.isArray(oneOrMoreUrls)) {
400392
return joinUrl(baseUrl, oneOrMoreUrls)

‎test/unit/utils_test.js‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,25 @@ describe('utils', () => {
4747
})
4848
})
4949

50+
describe('#appendBaseUrl', () => {
51+
it('should join base url and path with a single slash', () => {
52+
expect(utils.appendBaseUrl('http://localhost', '/login')).equal('http://localhost/login')
53+
expect(utils.appendBaseUrl('http://localhost', 'login')).equal('http://localhost/login')
54+
expect(utils.appendBaseUrl('http://localhost/', '/login')).equal('http://localhost/login')
55+
expect(utils.appendBaseUrl('http://localhost/', 'login')).equal('http://localhost/login')
56+
})
57+
58+
it('should keep the path of the base url', () => {
59+
expect(utils.appendBaseUrl('http://localhost/app/', '/')).equal('http://localhost/app/')
60+
expect(utils.appendBaseUrl('http://localhost/app/', '/login')).equal('http://localhost/app/login')
61+
expect(utils.appendBaseUrl('http://localhost/app', '?q=1')).equal('http://localhost/app/?q=1')
62+
})
63+
64+
it('should not touch absolute urls', () => {
65+
expect(utils.appendBaseUrl('http://localhost', 'https://example.com/a')).equal('https://example.com/a')
66+
})
67+
})
68+
5069
describe('#beautify', () => {
5170
it('should beautify JS code', () => {
5271
expect(utils.beautify('module.exports = function(a, b) { a++; b = a; if (a == b) { return 2 }};')).eql(`module.exports = function(a, b) {

0 commit comments

Comments
 (0)