diff --git a/docs/webapi/dontSeeCurrentPathEquals.mustache b/docs/webapi/dontSeeCurrentPathEquals.mustache new file mode 100644 index 000000000..7142f8560 --- /dev/null +++ b/docs/webapi/dontSeeCurrentPathEquals.mustache @@ -0,0 +1,10 @@ +Checks that current URL path does NOT match the expected path. +Query strings and URL fragments are ignored. + +```js +I.dontSeeCurrentPathEquals('/form'); // fails for '/form', '/form?user=1', '/form#section' +I.dontSeeCurrentPathEquals('/'); // fails for '/', '/?user=ok', '/#top' +``` + +@param {string} path value to check. +@returns {void} automatically synchronized promise through #recorder diff --git a/docs/webapi/seeCurrentPathEquals.mustache b/docs/webapi/seeCurrentPathEquals.mustache new file mode 100644 index 000000000..1b3d8d4d7 --- /dev/null +++ b/docs/webapi/seeCurrentPathEquals.mustache @@ -0,0 +1,10 @@ +Checks that current URL path matches the expected path. +Query strings and URL fragments are ignored. + +```js +I.seeCurrentPathEquals('/info'); // passes for '/info', '/info?user=1', '/info#section' +I.seeCurrentPathEquals('/'); // passes for '/', '/?user=ok', '/#top' +``` + +@param {string} path value to check. +@returns {void} automatically synchronized promise through #recorder diff --git a/lib/helper/Playwright.js b/lib/helper/Playwright.js index 71c48e9db..2ecbf0336 100644 --- a/lib/helper/Playwright.js +++ b/lib/helper/Playwright.js @@ -2405,6 +2405,26 @@ class Playwright extends Helper { urlEquals(this.options.url).negate(url, await this._getPageUrl()) } + /** + * {{> seeCurrentPathEquals }} + */ + async seeCurrentPathEquals(path) { + const currentUrl = await this._getPageUrl() + const baseUrl = this.options.url || 'http://localhost' + const actualPath = new URL(currentUrl, baseUrl).pathname + return equals('url path').assert(path, actualPath) + } + + /** + * {{> dontSeeCurrentPathEquals }} + */ + async dontSeeCurrentPathEquals(path) { + const currentUrl = await this._getPageUrl() + const baseUrl = this.options.url || 'http://localhost' + const actualPath = new URL(currentUrl, baseUrl).pathname + return equals('url path').negate(path, actualPath) + } + /** * {{> see }} * diff --git a/lib/helper/Puppeteer.js b/lib/helper/Puppeteer.js index 5bddc336e..0bf8e465c 100644 --- a/lib/helper/Puppeteer.js +++ b/lib/helper/Puppeteer.js @@ -1684,6 +1684,26 @@ class Puppeteer extends Helper { urlEquals(this.options.url).negate(url, await this._getPageUrl()) } + /** + * {{> seeCurrentPathEquals }} + */ + async seeCurrentPathEquals(path) { + const currentUrl = await this._getPageUrl() + const baseUrl = this.options.url || 'http://localhost' + const actualPath = new URL(currentUrl, baseUrl).pathname + return equals('url path').assert(path, actualPath) + } + + /** + * {{> dontSeeCurrentPathEquals }} + */ + async dontSeeCurrentPathEquals(path) { + const currentUrl = await this._getPageUrl() + const baseUrl = this.options.url || 'http://localhost' + const actualPath = new URL(currentUrl, baseUrl).pathname + return equals('url path').negate(path, actualPath) + } + /** * {{> see }} * diff --git a/lib/helper/WebDriver.js b/lib/helper/WebDriver.js index c602c5dd7..3e31c8928 100644 --- a/lib/helper/WebDriver.js +++ b/lib/helper/WebDriver.js @@ -1844,6 +1844,28 @@ class WebDriver extends Helper { return urlEquals(this.options.url).negate(url, decodeUrl(res)) } + /** + * {{> seeCurrentPathEquals }} + */ + async seeCurrentPathEquals(path) { + const currentUrl = await this.browser.getUrl() + const baseUrl = this.options.url || 'http://localhost' + const actualPath = new URL(currentUrl, baseUrl).pathname + return assert.equal(path, actualPath, `expected url path to be ${path}, but found ${actualPath}`) + } + + /** + * {{> dontSeeCurrentPathEquals }} + */ + async dontSeeCurrentPathEquals(path) { + const currentUrl = await this.browser.getUrl() + const baseUrl = this.options.url || 'http://localhost' + const actualPath = new URL(currentUrl, baseUrl).pathname + const errorMessage = `expected url path not to be ${path}, but found ${actualPath}` + const isEqual = path === actualPath + if (isEqual) throw new Error(errorMessage) + } + /** * Wraps [execute](http://webdriver.io/api/protocol/execute.html) command. * diff --git a/test/helper/webapi.js b/test/helper/webapi.js index 16ba7567e..842a9d81b 100644 --- a/test/helper/webapi.js +++ b/test/helper/webapi.js @@ -75,6 +75,45 @@ export function tests() { const url = await I.grabCurrentUrl() assert.equal(url, `${siteUrl}/info`) }) + + it('should check for equality with query strings', async () => { + await I.amOnPage('/info?user=test') + // Query strings matter for exact equality + await I.seeCurrentUrlEquals('/info?user=test') + await I.dontSeeCurrentUrlEquals('/info') + // But substring check works + await I.seeInCurrentUrl('/info') + await I.seeInCurrentUrl('user=test') + }) + + it('should handle root path with query strings', async () => { + await I.amOnPage('/?user=ok') + // Query strings matter - exact equality requires query string + await I.seeCurrentUrlEquals('/?user=ok') + await I.dontSeeCurrentUrlEquals('/') + // But substring check works for path fragment + await I.seeInCurrentUrl('/') + }) + + it('should check path equality ignoring query strings', async () => { + await I.amOnPage('/info?user=test') + // Path equality ignores query strings + await I.seeCurrentPathEquals('/info') + await I.dontSeeCurrentPathEquals('/form') + await I.dontSeeCurrentPathEquals('/info?user=test') + }) + + it('should check root path equality ignoring query strings', async () => { + await I.amOnPage('/?user=ok') + await I.seeCurrentPathEquals('/') + await I.dontSeeCurrentPathEquals('/info') + }) + + it('should check path equality ignoring hash fragments', async () => { + await I.amOnPage('/info#section') + await I.seeCurrentPathEquals('/info') + await I.dontSeeCurrentPathEquals('/info#section') + }) }) describe('#waitInUrl, #waitUrlEquals', () => {