diff --git a/packages/webdriver-utils/src/playwrightDriver.js b/packages/webdriver-utils/src/playwrightDriver.js index c1fb01e6c..8f930b07d 100644 --- a/packages/webdriver-utils/src/playwrightDriver.js +++ b/packages/webdriver-utils/src/playwrightDriver.js @@ -27,7 +27,8 @@ export default class PlaywrightDriver { command.script = `/* percy_automate_script */ \n ${command.script}`; } const options = this.requestPostOptions(command); - const baseUrl = `https://cdp.browserstack.com/wd/hub/session/${this.sessionId}/execute`; + const cdpDomain = process.env.PERCY_CDP_DOMAIN || 'cdp.browserstack.com'; + const baseUrl = `https://${cdpDomain}/wd/hub/session/${this.sessionId}/execute`; const response = JSON.parse((await request(baseUrl, options)).body); return response; } diff --git a/packages/webdriver-utils/src/providers/automateProvider.js b/packages/webdriver-utils/src/providers/automateProvider.js index eb0ded8aa..eab956812 100644 --- a/packages/webdriver-utils/src/providers/automateProvider.js +++ b/packages/webdriver-utils/src/providers/automateProvider.js @@ -106,9 +106,10 @@ export default class AutomateProvider extends GenericProvider { async setDebugUrl() { if (!this.driver) throw new Error('Driver is null, please initialize driver with createDriver().'); + const automateDomain = process.env.PERCY_AUTOMATE_DOMAIN || 'automate.browserstack.com'; this.debugUrl = await Cache.withCache(Cache.bstackSessionDetails, this.driver.sessionId, async () => { - return `https://automate.browserstack.com/builds/${this.automateResults.buildHash}/sessions/${this.automateResults.sessionHash}`; + return `https://${automateDomain}/builds/${this.automateResults.buildHash}/sessions/${this.automateResults.sessionHash}`; }); } diff --git a/packages/webdriver-utils/src/providers/genericProvider.js b/packages/webdriver-utils/src/providers/genericProvider.js index 65ff1a0f3..01a1a5dc1 100644 --- a/packages/webdriver-utils/src/providers/genericProvider.js +++ b/packages/webdriver-utils/src/providers/genericProvider.js @@ -96,6 +96,9 @@ export default class GenericProvider { async browserstackExecutor(action, args) { if (!this.driver) throw new Error('Driver is null, please initialize driver with createDriver().'); + if (action === 'percyScreenshot' && process.env.PERCY_ENABLE_DEV === 'true') { + args = { ...args, projectId: 'percy-dev' }; + } let options = args ? { action, arguments: args } : { action }; let res = await this.driver.executeScript({ script: `browserstack_executor: ${JSON.stringify(options)}`, args: [] }); return res; diff --git a/packages/webdriver-utils/src/providers/playwrightProvider.js b/packages/webdriver-utils/src/providers/playwrightProvider.js index 47e4c9c19..5c5b50149 100644 --- a/packages/webdriver-utils/src/providers/playwrightProvider.js +++ b/packages/webdriver-utils/src/providers/playwrightProvider.js @@ -35,7 +35,8 @@ export default class PlaywrightProvider extends GenericProvider { } async setDebugUrl() { - this.debugUrl = `https://automate.browserstack.com/builds/${this.automateResults.buildHash}/sessions/${this.automateResults.sessionHash}`; + const automateDomain = process.env.PERCY_AUTOMATE_DOMAIN || 'automate.browserstack.com'; + this.debugUrl = `https://${automateDomain}/builds/${this.automateResults.buildHash}/sessions/${this.automateResults.sessionHash}`; } async screenshot(name, options) { diff --git a/packages/webdriver-utils/test/playwrightDriver.test.js b/packages/webdriver-utils/test/playwrightDriver.test.js index f4cb7f654..579abd610 100644 --- a/packages/webdriver-utils/test/playwrightDriver.test.js +++ b/packages/webdriver-utils/test/playwrightDriver.test.js @@ -86,6 +86,18 @@ describe('PlaywrightDriver', () => { expect(response).toEqual({ value: 'mockVal' }); }); + it('should use PERCY_CDP_DOMAIN when set', async () => { + process.env.PERCY_CDP_DOMAIN = 'cdp-k8s-devpercyplat.bsstag.com'; + try { + const command = { script: 'console.log("Hello, World!")', args: [] }; + await driver.executeScript(command); + const baseUrl = `https://cdp-k8s-devpercyplat.bsstag.com/wd/hub/session/${sessionId}/execute`; + expect(requestSpy).toHaveBeenCalledWith(baseUrl, jasmine.any(Object)); + } finally { + delete process.env.PERCY_CDP_DOMAIN; + } + }); + it('should handle request error and re-throw', async () => { requestSpy.and.returnValue(Promise.reject(new Error('Request failed'))); const command = { script: 'console.log("Hello, World!")', args: [] }; diff --git a/packages/webdriver-utils/test/providers/automateProvider.test.js b/packages/webdriver-utils/test/providers/automateProvider.test.js index afe491665..ad7573d74 100644 --- a/packages/webdriver-utils/test/providers/automateProvider.test.js +++ b/packages/webdriver-utils/test/providers/automateProvider.test.js @@ -50,6 +50,19 @@ describe('AutomateProvider', () => { expect(automateProvider.debugUrl).toEqual('https://automate.browserstack.com/builds/12e3/sessions/abc1d'); }); + it('uses PERCY_AUTOMATE_DOMAIN when set', async () => { + Cache.reset(); + process.env.PERCY_AUTOMATE_DOMAIN = 'automate-k8s-mobile.bsstag.com'; + try { + let automateProvider = new AutomateProvider(args); + await automateProvider.createDriver(); + await automateProvider.screenshot('abc', { }); + expect(automateProvider.debugUrl).toEqual('https://automate-k8s-mobile.bsstag.com/builds/12e3/sessions/abc1d'); + } finally { + delete process.env.PERCY_AUTOMATE_DOMAIN; + } + }); + it('throws error if driver is not initialized', async () => { let automateProvider = new AutomateProvider(args); await expectAsync(automateProvider.setDebugUrl()) diff --git a/packages/webdriver-utils/test/providers/genericProvider.test.js b/packages/webdriver-utils/test/providers/genericProvider.test.js index 834fad1b9..8e283cf8f 100644 --- a/packages/webdriver-utils/test/providers/genericProvider.test.js +++ b/packages/webdriver-utils/test/providers/genericProvider.test.js @@ -1262,6 +1262,38 @@ describe('GenericProvider', () => { expect(executeScriptSpy) .toHaveBeenCalledWith({ script: 'browserstack_executor: {"action":"getSessionDetails","arguments":"new"}', args: [] }); }); + + describe('with PERCY_ENABLE_DEV', () => { + afterEach(() => { + delete process.env.PERCY_ENABLE_DEV; + }); + + it('injects projectId: percy-dev into percyScreenshot payloads when enabled', async () => { + process.env.PERCY_ENABLE_DEV = 'true'; + let provider = new GenericProvider(args); + await provider.createDriver(); + await provider.browserstackExecutor('percyScreenshot', { state: 'begin' }); + expect(executeScriptSpy) + .toHaveBeenCalledWith({ script: 'browserstack_executor: {"action":"percyScreenshot","arguments":{"state":"begin","projectId":"percy-dev"}}', args: [] }); + }); + + it('does not inject projectId for non-percyScreenshot actions when enabled', async () => { + process.env.PERCY_ENABLE_DEV = 'true'; + let provider = new GenericProvider(args); + await provider.createDriver(); + await provider.browserstackExecutor('getSessionDetails', { foo: 'bar' }); + expect(executeScriptSpy) + .toHaveBeenCalledWith({ script: 'browserstack_executor: {"action":"getSessionDetails","arguments":{"foo":"bar"}}', args: [] }); + }); + + it('does not inject projectId when disabled (byte-identical to prod)', async () => { + let provider = new GenericProvider(args); + await provider.createDriver(); + await provider.browserstackExecutor('percyScreenshot', { state: 'begin' }); + expect(executeScriptSpy) + .toHaveBeenCalledWith({ script: 'browserstack_executor: {"action":"percyScreenshot","arguments":{"state":"begin"}}', args: [] }); + }); + }); }); describe('getTag', () => { diff --git a/packages/webdriver-utils/test/providers/playwrightProvider.test.js b/packages/webdriver-utils/test/providers/playwrightProvider.test.js index 0317fa07a..78328c38d 100644 --- a/packages/webdriver-utils/test/providers/playwrightProvider.test.js +++ b/packages/webdriver-utils/test/providers/playwrightProvider.test.js @@ -49,6 +49,22 @@ describe('PlaywrightProvider', () => { 'https://automate.browserstack.com/builds/buildHash/sessions/sessionHash' ); }); + + it('uses PERCY_AUTOMATE_DOMAIN when set', async () => { + process.env.PERCY_AUTOMATE_DOMAIN = 'automate-k8s-mobile.bsstag.com'; + try { + provider.automateResults = { + buildHash: 'buildHash', + sessionHash: 'sessionHash' + }; + await provider.setDebugUrl(); + expect(provider.debugUrl).toBe( + 'https://automate-k8s-mobile.bsstag.com/builds/buildHash/sessions/sessionHash' + ); + } finally { + delete process.env.PERCY_AUTOMATE_DOMAIN; + } + }); }); describe('screenshot', () => {