Skip to content

Commit

Permalink
feat: use the new setup domain for lightning pages if available
Browse files Browse the repository at this point in the history
Opening a `/lightning/` setup page on the instance domain caused
multiple server- and client-side redirects to the new setup domain.

This caused errors like:

> failed: Protocol error (DOM.describeNode): Cannot find context with specified id

Now all lightning pages should open using the new setup domain if available
and use the instance URL otherwise.

Example: https://[MyDomainName].my.salesforce-setup.com
  • Loading branch information
amtrack committed Dec 6, 2024
1 parent c0bb950 commit d132451
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 7 deletions.
21 changes: 20 additions & 1 deletion src/browserforce.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ export class Browserforce {
public logger?: Ux;
public browser: Browser;
public page: Page;
public lightningSetupUrl: string;

constructor(org: Org, logger?: Ux) {
this.org = org;
this.logger = logger;
Expand Down Expand Up @@ -62,7 +64,8 @@ export class Browserforce {
const result = await pRetry(
async () => {
page = await this.getNewPage();
const url = `${this.getInstanceUrl()}/${urlPath}`;
const setupUrl = urlPath.startsWith("lightning") ? await this.getLightningSetupUrl() : this.getInstanceUrl();
const url = `${setupUrl}/${urlPath}`;
const response = await page.goto(url, options);
if (response) {
if (!response.ok()) {
Expand Down Expand Up @@ -124,6 +127,22 @@ export class Browserforce {
// sometimes the instanceUrl includes a trailing slash
return this.org.getConnection().instanceUrl?.replace(/\/$/, '');
}

/**
* @returns the setup url (e.g. https://[MyDomainName].my.salesforce-setup.com)
*/
public async getLightningSetupUrl(): Promise<string> {
if (!this.lightningSetupUrl) {
const page = await this.getNewPage();
try {
const lightningResponse = await page.goto(`${this.getInstanceUrl()}/lightning/setup/SetupOneHome/home`, {waitUntil: ["load", "networkidle2"]});
this.lightningSetupUrl = new URL(lightningResponse.url()).origin;
} finally {
await page.close();
}
}
return this.lightningSetupUrl;
}
}

export async function throwPageErrors(page: Page): Promise<void> {
Expand Down
6 changes: 3 additions & 3 deletions src/pages/login.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ export class LoginPage {
throw new Error('login failed');
}
const conn = org.getConnection();
await this.page.goto(
`${conn.instanceUrl}/${PATH}?sid=${conn.accessToken}&retURL=${encodeURIComponent(POST_LOGIN_PATH)}`,
const response = await this.page.goto(
`${conn.instanceUrl.replace(/\/$/, '')}/${PATH}?sid=${conn.accessToken}&retURL=${encodeURIComponent(POST_LOGIN_PATH)}`,
{
// should have waited at least 500ms for network connections, redirects should probably have happened already
waitUntil: ['load', 'networkidle2']
}
);
const url = new URL(this.page.url());
const url = new URL(response.url());
if (url.searchParams.has('startURL')) {
// when query param startURL exists, the login failed
// e.g. /?ec=302&startURL=https...
Expand Down
4 changes: 1 addition & 3 deletions test/browserforce.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,7 @@ describe('Browserforce', function () {
});
describe('waitForSelectorInFrameOrPage()', () => {
it('should query a selector in LEX and Classic UI', async () => {
const page = await global.bf.openPage('lightning/setup/ExternalStrings/home', {
waitUntil: ['load', 'networkidle2']
});
const page = await global.bf.openPage('lightning/setup/ExternalStrings/home');
const frame = await global.bf.waitForSelectorInFrameOrPage(page, 'input[name="edit"]');
const button = await frame.$('input[name="edit"]');
assert.ok(!page.url().includes('/page'));
Expand Down

0 comments on commit d132451

Please sign in to comment.