sfdx-browserforce-plugin 5.2.0-next.5 → 6.0.0-next.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +66 -87
- package/lib/browserforce-command.d.ts +14 -3
- package/lib/browserforce-command.js +117 -17
- package/lib/browserforce-command.js.map +1 -1
- package/lib/browserforce.d.ts +14 -12
- package/lib/browserforce.js +98 -100
- package/lib/browserforce.js.map +1 -1
- package/lib/commands/browserforce/apply.js +17 -12
- package/lib/commands/browserforce/apply.js.map +1 -1
- package/lib/commands/browserforce/playwright.js +9 -3
- package/lib/commands/browserforce/playwright.js.map +1 -1
- package/lib/config-parser.js.map +1 -1
- package/lib/pages/login.d.ts +2 -2
- package/lib/pages/login.js +5 -15
- package/lib/pages/login.js.map +1 -1
- package/lib/plugin.d.ts +0 -2
- package/lib/plugin.js +0 -2
- package/lib/plugin.js.map +1 -1
- package/lib/plugins/activity-settings/index.e2e-spec.js +1 -1
- package/lib/plugins/activity-settings/index.e2e-spec.js.map +1 -1
- package/lib/plugins/activity-settings/index.js +92 -21
- package/lib/plugins/activity-settings/index.js.map +1 -1
- package/lib/plugins/company-information/index.e2e-spec.js +1 -1
- package/lib/plugins/company-information/index.e2e-spec.js.map +1 -1
- package/lib/plugins/company-information/index.js +100 -31
- package/lib/plugins/company-information/index.js.map +1 -1
- package/lib/plugins/customer-portal/available-custom-objects/index.js +161 -73
- package/lib/plugins/customer-portal/available-custom-objects/index.js.map +1 -1
- package/lib/plugins/customer-portal/available-custom-objects/index.test.js +1 -1
- package/lib/plugins/customer-portal/available-custom-objects/index.test.js.map +1 -1
- package/lib/plugins/customer-portal/enabled/index.js +76 -13
- package/lib/plugins/customer-portal/enabled/index.js.map +1 -1
- package/lib/plugins/customer-portal/enabled/index.test.js +1 -1
- package/lib/plugins/customer-portal/enabled/index.test.js.map +1 -1
- package/lib/plugins/customer-portal/index.e2e-spec.js +12 -19
- package/lib/plugins/customer-portal/index.e2e-spec.js.map +1 -1
- package/lib/plugins/customer-portal/index.js +3 -4
- package/lib/plugins/customer-portal/index.js.map +1 -1
- package/lib/plugins/customer-portal/index.test.js +1 -1
- package/lib/plugins/customer-portal/index.test.js.map +1 -1
- package/lib/plugins/customer-portal/portals/index.js +186 -110
- package/lib/plugins/customer-portal/portals/index.js.map +1 -1
- package/lib/plugins/customer-portal/portals/index.test.js +1 -1
- package/lib/plugins/customer-portal/portals/index.test.js.map +1 -1
- package/lib/plugins/density-settings/index.e2e-spec.js +1 -1
- package/lib/plugins/density-settings/index.e2e-spec.js.map +1 -1
- package/lib/plugins/density-settings/index.js +91 -22
- package/lib/plugins/density-settings/index.js.map +1 -1
- package/lib/plugins/email-deliverability/index.e2e-spec.js +1 -1
- package/lib/plugins/email-deliverability/index.e2e-spec.js.map +1 -1
- package/lib/plugins/email-deliverability/index.js +93 -22
- package/lib/plugins/email-deliverability/index.js.map +1 -1
- package/lib/plugins/high-velocity-sales-settings/index.d.ts +1 -1
- package/lib/plugins/high-velocity-sales-settings/index.e2e-spec.js +1 -1
- package/lib/plugins/high-velocity-sales-settings/index.e2e-spec.js.map +1 -1
- package/lib/plugins/high-velocity-sales-settings/index.js +71 -8
- package/lib/plugins/high-velocity-sales-settings/index.js.map +1 -1
- package/lib/plugins/high-velocity-sales-settings/page.d.ts +2 -1
- package/lib/plugins/high-velocity-sales-settings/page.js +2 -6
- package/lib/plugins/high-velocity-sales-settings/page.js.map +1 -1
- package/lib/plugins/history-tracking/index.e2e-spec.js +3 -4
- package/lib/plugins/history-tracking/index.e2e-spec.js.map +1 -1
- package/lib/plugins/history-tracking/index.js +156 -94
- package/lib/plugins/history-tracking/index.js.map +1 -1
- package/lib/plugins/home-page-layouts/index.e2e-spec.js +1 -1
- package/lib/plugins/home-page-layouts/index.e2e-spec.js.map +1 -1
- package/lib/plugins/home-page-layouts/index.js +121 -57
- package/lib/plugins/home-page-layouts/index.js.map +1 -1
- package/lib/plugins/home-page-layouts/index.test.js +1 -1
- package/lib/plugins/home-page-layouts/index.test.js.map +1 -1
- package/lib/plugins/index.d.ts +1 -1
- package/lib/plugins/index.js +1 -1
- package/lib/plugins/index.js.map +1 -1
- package/lib/plugins/lightning-experience-settings/index.e2e-spec.js +1 -1
- package/lib/plugins/lightning-experience-settings/index.e2e-spec.js.map +1 -1
- package/lib/plugins/lightning-experience-settings/index.js +90 -27
- package/lib/plugins/lightning-experience-settings/index.js.map +1 -1
- package/lib/plugins/linkedin-sales-navigator-settings/index.e2e-spec.js +1 -1
- package/lib/plugins/linkedin-sales-navigator-settings/index.e2e-spec.js.map +1 -1
- package/lib/plugins/linkedin-sales-navigator-settings/index.js +84 -6
- package/lib/plugins/linkedin-sales-navigator-settings/index.js.map +1 -1
- package/lib/plugins/linkedin-sales-navigator-settings/page.d.ts +2 -1
- package/lib/plugins/linkedin-sales-navigator-settings/page.js +2 -7
- package/lib/plugins/linkedin-sales-navigator-settings/page.js.map +1 -1
- package/lib/plugins/omni-channel-settings/index.e2e-spec.js +1 -1
- package/lib/plugins/omni-channel-settings/index.e2e-spec.js.map +1 -1
- package/lib/plugins/omni-channel-settings/index.js +87 -14
- package/lib/plugins/omni-channel-settings/index.js.map +1 -1
- package/lib/plugins/opportunity-splits/index.e2e-spec.js +1 -1
- package/lib/plugins/opportunity-splits/index.e2e-spec.js.map +1 -1
- package/lib/plugins/opportunity-splits/index.js +103 -18
- package/lib/plugins/opportunity-splits/index.js.map +1 -1
- package/lib/plugins/opportunity-splits/pages/layout-selection.js.map +1 -1
- package/lib/plugins/opportunity-splits/pages/overview.d.ts +2 -1
- package/lib/plugins/opportunity-splits/pages/overview.js +2 -3
- package/lib/plugins/opportunity-splits/pages/overview.js.map +1 -1
- package/lib/plugins/opportunity-splits/pages/setup.d.ts +2 -1
- package/lib/plugins/opportunity-splits/pages/setup.js +1 -1
- package/lib/plugins/opportunity-splits/pages/setup.js.map +1 -1
- package/lib/plugins/permission-sets/index.e2e-spec.js +1 -1
- package/lib/plugins/permission-sets/index.e2e-spec.js.map +1 -1
- package/lib/plugins/permission-sets/index.js.map +1 -1
- package/lib/plugins/permission-sets/service-presence-status/index.js +106 -53
- package/lib/plugins/permission-sets/service-presence-status/index.js.map +1 -1
- package/lib/plugins/picklists/field-dependencies/index.js +91 -14
- package/lib/plugins/picklists/field-dependencies/index.js.map +1 -1
- package/lib/plugins/picklists/field-dependencies/index.test.js +1 -1
- package/lib/plugins/picklists/field-dependencies/index.test.js.map +1 -1
- package/lib/plugins/picklists/field-dependencies/pages.d.ts +3 -2
- package/lib/plugins/picklists/field-dependencies/pages.js +5 -14
- package/lib/plugins/picklists/field-dependencies/pages.js.map +1 -1
- package/lib/plugins/picklists/index.d.ts +1 -1
- package/lib/plugins/picklists/index.e2e-spec.js +36 -14
- package/lib/plugins/picklists/index.e2e-spec.js.map +1 -1
- package/lib/plugins/picklists/index.js +136 -68
- package/lib/plugins/picklists/index.js.map +1 -1
- package/lib/plugins/picklists/pages.js +13 -28
- package/lib/plugins/picklists/pages.js.map +1 -1
- package/lib/plugins/picklists/standard-value-set.js +2 -2
- package/lib/plugins/picklists/standard-value-set.js.map +1 -1
- package/lib/plugins/record-types/index.e2e-spec.js +2 -3
- package/lib/plugins/record-types/index.e2e-spec.js.map +1 -1
- package/lib/plugins/record-types/index.js +81 -20
- package/lib/plugins/record-types/index.js.map +1 -1
- package/lib/plugins/record-types/pages.js +1 -5
- package/lib/plugins/record-types/pages.js.map +1 -1
- package/lib/plugins/relate-contact-to-multiple-accounts/index.e2e-spec.js +2 -2
- package/lib/plugins/relate-contact-to-multiple-accounts/index.e2e-spec.js.map +1 -1
- package/lib/plugins/relate-contact-to-multiple-accounts/index.js +99 -35
- package/lib/plugins/relate-contact-to-multiple-accounts/index.js.map +1 -1
- package/lib/plugins/reports-and-dashboards/folder-sharing/index.js +100 -37
- package/lib/plugins/reports-and-dashboards/folder-sharing/index.js.map +1 -1
- package/lib/plugins/reports-and-dashboards/index.js +1 -1
- package/lib/plugins/reports-and-dashboards/index.js.map +1 -1
- package/lib/plugins/salesforce-cpq-config/index.e2e-spec.js +1 -1
- package/lib/plugins/salesforce-cpq-config/index.e2e-spec.js.map +1 -1
- package/lib/plugins/salesforce-cpq-config/index.js +213 -167
- package/lib/plugins/salesforce-cpq-config/index.js.map +1 -1
- package/lib/plugins/salesforce-to-salesforce/index.e2e-spec.js +1 -2
- package/lib/plugins/salesforce-to-salesforce/index.e2e-spec.js.map +1 -1
- package/lib/plugins/salesforce-to-salesforce/index.js +93 -23
- package/lib/plugins/salesforce-to-salesforce/index.js.map +1 -1
- package/lib/plugins/security/authentication-configuration/index.e2e-spec.js +2 -3
- package/lib/plugins/security/authentication-configuration/index.e2e-spec.js.map +1 -1
- package/lib/plugins/security/authentication-configuration/index.js +122 -50
- package/lib/plugins/security/authentication-configuration/index.js.map +1 -1
- package/lib/plugins/security/certificate-and-key-management/index.e2e-spec.js +4 -25
- package/lib/plugins/security/certificate-and-key-management/index.e2e-spec.js.map +1 -1
- package/lib/plugins/security/certificate-and-key-management/index.js +141 -65
- package/lib/plugins/security/certificate-and-key-management/index.js.map +1 -1
- package/lib/plugins/security/certificate-and-key-management/index.test.js +1 -1
- package/lib/plugins/security/certificate-and-key-management/index.test.js.map +1 -1
- package/lib/plugins/security/index.js +1 -2
- package/lib/plugins/security/index.js.map +1 -1
- package/lib/plugins/service-channels/capacity/index.js +145 -112
- package/lib/plugins/service-channels/capacity/index.js.map +1 -1
- package/lib/plugins/service-channels/index.e2e-spec.js +5 -6
- package/lib/plugins/service-channels/index.e2e-spec.js.map +1 -1
- package/lib/plugins/service-channels/index.js +1 -2
- package/lib/plugins/service-channels/index.js.map +1 -1
- package/lib/plugins/slack/index.e2e-spec.js +1 -1
- package/lib/plugins/slack/index.e2e-spec.js.map +1 -1
- package/lib/plugins/slack/index.js +97 -28
- package/lib/plugins/slack/index.js.map +1 -1
- package/lib/plugins/user-access-policies/index.e2e-spec.js +3 -5
- package/lib/plugins/user-access-policies/index.e2e-spec.js.map +1 -1
- package/lib/plugins/user-access-policies/index.js +95 -26
- package/lib/plugins/user-access-policies/index.js.map +1 -1
- package/lib/plugins/user-access-policies/page.d.ts +2 -1
- package/lib/plugins/user-access-policies/page.js +1 -7
- package/lib/plugins/user-access-policies/page.js.map +1 -1
- package/lib/plugins/utils.js +2 -7
- package/lib/plugins/utils.js.map +1 -1
- package/oclif.manifest.json +67 -71
- package/package.json +10 -8
- package/lib/commands/browserforce/plan.d.ts +0 -10
- package/lib/commands/browserforce/plan.js +0 -56
- package/lib/commands/browserforce/plan.js.map +0 -1
package/lib/browserforce.js
CHANGED
|
@@ -1,102 +1,113 @@
|
|
|
1
|
+
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
|
|
2
|
+
if (value !== null && value !== void 0) {
|
|
3
|
+
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
|
|
4
|
+
var dispose, inner;
|
|
5
|
+
if (async) {
|
|
6
|
+
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
|
|
7
|
+
dispose = value[Symbol.asyncDispose];
|
|
8
|
+
}
|
|
9
|
+
if (dispose === void 0) {
|
|
10
|
+
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
|
|
11
|
+
dispose = value[Symbol.dispose];
|
|
12
|
+
if (async) inner = dispose;
|
|
13
|
+
}
|
|
14
|
+
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
|
|
15
|
+
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
|
|
16
|
+
env.stack.push({ value: value, dispose: dispose, async: async });
|
|
17
|
+
}
|
|
18
|
+
else if (async) {
|
|
19
|
+
env.stack.push({ async: true });
|
|
20
|
+
}
|
|
21
|
+
return value;
|
|
22
|
+
};
|
|
23
|
+
var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
|
|
24
|
+
return function (env) {
|
|
25
|
+
function fail(e) {
|
|
26
|
+
env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
|
|
27
|
+
env.hasError = true;
|
|
28
|
+
}
|
|
29
|
+
var r, s = 0;
|
|
30
|
+
function next() {
|
|
31
|
+
while (r = env.stack.pop()) {
|
|
32
|
+
try {
|
|
33
|
+
if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
|
|
34
|
+
if (r.dispose) {
|
|
35
|
+
var result = r.dispose.call(r.value);
|
|
36
|
+
if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
|
|
37
|
+
}
|
|
38
|
+
else s |= 1;
|
|
39
|
+
}
|
|
40
|
+
catch (e) {
|
|
41
|
+
fail(e);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
|
|
45
|
+
if (env.hasError) throw env.error;
|
|
46
|
+
}
|
|
47
|
+
return next();
|
|
48
|
+
};
|
|
49
|
+
})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
50
|
+
var e = new Error(message);
|
|
51
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
52
|
+
});
|
|
1
53
|
import pRetry from 'p-retry';
|
|
2
|
-
import { chromium, } from 'playwright';
|
|
3
54
|
import { LoginPage } from './pages/login.js';
|
|
4
55
|
const VF_IFRAME_SELECTOR = 'force-aloha-page iframe[name^=vfFrameId]';
|
|
5
56
|
export class Browserforce {
|
|
6
|
-
|
|
57
|
+
connection;
|
|
58
|
+
browserContext;
|
|
7
59
|
logger;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
this.
|
|
14
|
-
|
|
60
|
+
retryConfig;
|
|
61
|
+
constructor(connection, browserContext, options) {
|
|
62
|
+
this.connection = connection;
|
|
63
|
+
this.browserContext = browserContext;
|
|
64
|
+
this.logger = options?.logger;
|
|
65
|
+
this.retryConfig = options?.retry ?? {
|
|
66
|
+
retries: 0,
|
|
67
|
+
};
|
|
15
68
|
}
|
|
16
69
|
async login() {
|
|
17
|
-
|
|
18
|
-
channel: process.env.CI ? 'chrome' : undefined,
|
|
19
|
-
args: ['--no-sandbox', '--disable-setuid-sandbox'],
|
|
20
|
-
headless: !(process.env.BROWSER_DEBUG === 'true'),
|
|
21
|
-
slowMo: parseInt(process.env.BROWSER_SLOWMO, 10) ?? 0,
|
|
22
|
-
});
|
|
23
|
-
this.context = await this.browser.newContext({
|
|
24
|
-
viewport: { width: 1280, height: 1536 },
|
|
25
|
-
});
|
|
26
|
-
// Start tracing if PLAYWRIGHT_TRACE is set
|
|
27
|
-
if (process.env.PLAYWRIGHT_TRACE === 'true') {
|
|
28
|
-
await this.context.tracing.start({
|
|
29
|
-
screenshots: true,
|
|
30
|
-
snapshots: true,
|
|
31
|
-
sources: true,
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
const page = await this.getNewPage();
|
|
70
|
+
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
35
71
|
try {
|
|
72
|
+
try {
|
|
73
|
+
await this.connection.refreshAuth();
|
|
74
|
+
}
|
|
75
|
+
catch (e) {
|
|
76
|
+
throw new Error('login failed', { cause: e });
|
|
77
|
+
}
|
|
78
|
+
const page = __addDisposableResource(env_1, await this.browserContext.newPage(), true);
|
|
36
79
|
const loginPage = new LoginPage(page);
|
|
37
|
-
await loginPage.login(this.
|
|
80
|
+
await loginPage.login(this.connection);
|
|
81
|
+
return this;
|
|
38
82
|
}
|
|
39
|
-
|
|
40
|
-
|
|
83
|
+
catch (e_1) {
|
|
84
|
+
env_1.error = e_1;
|
|
85
|
+
env_1.hasError = true;
|
|
41
86
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
// Stop tracing and save if it was started
|
|
47
|
-
if (process.env.PLAYWRIGHT_TRACE === 'true') {
|
|
48
|
-
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
49
|
-
const tracePath = `trace-${timestamp}.zip`;
|
|
50
|
-
await this.context.tracing.stop({ path: tracePath });
|
|
51
|
-
if (this.logger) {
|
|
52
|
-
this.logger.log(`Playwright trace saved to: ${tracePath}`);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
await this.browser.close();
|
|
87
|
+
finally {
|
|
88
|
+
const result_1 = __disposeResources(env_1);
|
|
89
|
+
if (result_1)
|
|
90
|
+
await result_1;
|
|
56
91
|
}
|
|
57
|
-
return this;
|
|
58
|
-
}
|
|
59
|
-
async getNewPage() {
|
|
60
|
-
const page = await this.context.newPage();
|
|
61
|
-
page.setDefaultNavigationTimeout(parseInt(process.env.BROWSERFORCE_NAVIGATION_TIMEOUT_MS ?? '90000', 10));
|
|
62
|
-
return page;
|
|
63
92
|
}
|
|
64
93
|
// path instead of url
|
|
65
94
|
async openPage(urlPath) {
|
|
66
95
|
let page;
|
|
67
|
-
const result = await
|
|
68
|
-
page = await this.
|
|
69
|
-
const setupUrl = urlPath.startsWith('lightning')
|
|
70
|
-
|
|
71
|
-
: this.getInstanceUrl();
|
|
72
|
-
const url = `${setupUrl}/${urlPath}`;
|
|
96
|
+
const result = await this.retry(async () => {
|
|
97
|
+
page = await this.browserContext.newPage();
|
|
98
|
+
const setupUrl = urlPath.startsWith('/lightning') ? await this.getLightningSetupUrl() : this.getInstanceUrl();
|
|
99
|
+
const url = `${setupUrl}${urlPath}`;
|
|
73
100
|
const response = await page.goto(url);
|
|
74
101
|
if (response && !response.ok()) {
|
|
75
102
|
await Promise.race([
|
|
76
|
-
waitForPageErrors(page, 5_000),
|
|
77
103
|
(async () => {
|
|
78
|
-
await page.waitForTimeout(
|
|
79
|
-
throw new Error(`${response.status()}: ${response.
|
|
104
|
+
await page.waitForTimeout(5_000);
|
|
105
|
+
throw new Error(`${response.status()}: ${response.url()}`);
|
|
80
106
|
})(),
|
|
107
|
+
waitForPageErrors(page, 6_000),
|
|
81
108
|
]);
|
|
82
109
|
}
|
|
83
110
|
return page;
|
|
84
|
-
}, {
|
|
85
|
-
onFailedAttempt: async (context) => {
|
|
86
|
-
if (this.logger) {
|
|
87
|
-
this.logger.warn(`retrying ${context.retriesLeft} more time(s) because of "${context.error}"`);
|
|
88
|
-
}
|
|
89
|
-
if (page) {
|
|
90
|
-
try {
|
|
91
|
-
await page.close();
|
|
92
|
-
}
|
|
93
|
-
catch (e) {
|
|
94
|
-
// not handled
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
},
|
|
98
|
-
retries: parseInt(process.env.BROWSERFORCE_RETRY_MAX_RETRIES ?? '4', 10),
|
|
99
|
-
minTimeout: parseInt(process.env.BROWSERFORCE_RETRY_TIMEOUT_MS ?? '4000', 10),
|
|
100
111
|
});
|
|
101
112
|
return result;
|
|
102
113
|
}
|
|
@@ -126,31 +137,28 @@ export class Browserforce {
|
|
|
126
137
|
}
|
|
127
138
|
getInstanceUrl() {
|
|
128
139
|
// sometimes the instanceUrl includes a trailing slash
|
|
129
|
-
return this.
|
|
140
|
+
return this.connection.instanceUrl?.replace(/\/$/, '');
|
|
130
141
|
}
|
|
131
142
|
/**
|
|
132
143
|
* @returns the setup url (e.g. https://[MyDomainName].my.salesforce-setup.com)
|
|
133
144
|
*/
|
|
134
145
|
async getLightningSetupUrl() {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
return this.lightningSetupUrl;
|
|
146
|
+
return `https://${this.getMyDomain()}.my.salesforce-setup.com`;
|
|
147
|
+
}
|
|
148
|
+
async retry(input) {
|
|
149
|
+
const res = await pRetry(input, {
|
|
150
|
+
...this.retryConfig,
|
|
151
|
+
onFailedAttempt: (context) => {
|
|
152
|
+
this.logger?.warn(`retrying ${context.retriesLeft} more time(s) because of "${context.error}"`);
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
return res;
|
|
146
156
|
}
|
|
147
157
|
}
|
|
148
158
|
export async function waitForPageErrors(page, timeout = 90_000) {
|
|
149
159
|
const anyErrorsLocator = page.locator(`#error, #errorTitle, #errorDesc, #validationError, div.errorMsg`);
|
|
150
160
|
await anyErrorsLocator.first().waitFor({ state: 'attached', timeout });
|
|
151
|
-
const errorMessages = (await anyErrorsLocator.allInnerTexts())
|
|
152
|
-
.map((t) => t.trim())
|
|
153
|
-
.filter(Boolean);
|
|
161
|
+
const errorMessages = (await anyErrorsLocator.allInnerTexts()).map((t) => t.trim()).filter(Boolean);
|
|
154
162
|
if (errorMessages.length === 1) {
|
|
155
163
|
throw new Error(errorMessages[0]);
|
|
156
164
|
}
|
|
@@ -158,14 +166,4 @@ export async function waitForPageErrors(page, timeout = 90_000) {
|
|
|
158
166
|
throw new Error(errorMessages.join('\n'));
|
|
159
167
|
}
|
|
160
168
|
}
|
|
161
|
-
export async function retry(input) {
|
|
162
|
-
const res = await pRetry(input, {
|
|
163
|
-
onFailedAttempt: (context) => {
|
|
164
|
-
console.warn(`retrying ${context.retriesLeft} more time(s) because of "${context.error}"`);
|
|
165
|
-
},
|
|
166
|
-
retries: parseInt(process.env.BROWSERFORCE_RETRY_MAX_RETRIES ?? '6', 10),
|
|
167
|
-
minTimeout: parseInt(process.env.BROWSERFORCE_RETRY_TIMEOUT_MS ?? '4000', 10),
|
|
168
|
-
});
|
|
169
|
-
return res;
|
|
170
|
-
}
|
|
171
169
|
//# sourceMappingURL=browserforce.js.map
|
package/lib/browserforce.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browserforce.js","sourceRoot":"","sources":["../src/browserforce.ts"],"names":[],"mappings":"AAEA,OAAO,
|
|
1
|
+
{"version":3,"file":"browserforce.js","sourceRoot":"","sources":["../src/browserforce.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { BrowserforceCommand } from '../../browserforce-command.js';
|
|
2
2
|
export class BrowserforceApply extends BrowserforceCommand {
|
|
3
|
-
static description = 'apply a plan from a
|
|
3
|
+
static description = 'apply a plan from a config file';
|
|
4
4
|
static examples = [
|
|
5
5
|
`$ <%= config.bin %> <%= command.id %> -f ./config/currency.json --target-org myOrg@example.com
|
|
6
6
|
logging in... done
|
|
7
|
-
Applying
|
|
7
|
+
Applying config file ./config/currency.json to org myOrg@example.com
|
|
8
8
|
[CompanyInformation] retrieving state... done
|
|
9
9
|
[CompanyInformation] changing 'defaultCurrencyIsoCode' to '"English (South Africa) - ZAR"'... done
|
|
10
10
|
logging out... done
|
|
@@ -12,11 +12,12 @@ export class BrowserforceApply extends BrowserforceCommand {
|
|
|
12
12
|
];
|
|
13
13
|
async run() {
|
|
14
14
|
const { flags } = await this.parse(BrowserforceApply);
|
|
15
|
-
this.log(`Applying
|
|
15
|
+
this.log(`Applying config file ${flags.definitionfile} to org ${flags['target-org'].getUsername()}`);
|
|
16
16
|
for (const setting of this.settings) {
|
|
17
17
|
const driver = setting.Driver;
|
|
18
|
-
const instance = new driver(this.
|
|
18
|
+
const instance = new driver(this.browserforce);
|
|
19
19
|
this.spinner.start(`[${driver.name}] retrieving state`);
|
|
20
|
+
await this.browserforce.browserContext.tracing.group(driver.name);
|
|
20
21
|
let state;
|
|
21
22
|
try {
|
|
22
23
|
state = await instance.retrieve(setting.value);
|
|
@@ -27,20 +28,24 @@ export class BrowserforceApply extends BrowserforceCommand {
|
|
|
27
28
|
}
|
|
28
29
|
this.spinner.stop();
|
|
29
30
|
const diff = instance.diff(state, setting.value);
|
|
31
|
+
const action = flags['dry-run'] ? 'would change' : 'changing';
|
|
30
32
|
if (diff !== undefined) {
|
|
31
33
|
this.spinner.start(`[${driver.name}] ${Object.keys(diff)
|
|
32
34
|
.map((key) => {
|
|
33
|
-
return
|
|
35
|
+
return `${action} '${key}' to '${JSON.stringify(diff[key])}'`;
|
|
34
36
|
})
|
|
35
37
|
.join('\n')}`);
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
if (!flags['dry-run']) {
|
|
39
|
+
try {
|
|
40
|
+
await instance.apply(diff);
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
this.spinner.stop('failed');
|
|
44
|
+
throw err;
|
|
45
|
+
}
|
|
46
|
+
this.spinner.stop();
|
|
38
47
|
}
|
|
39
|
-
|
|
40
|
-
this.spinner.stop('failed');
|
|
41
|
-
throw err;
|
|
42
|
-
}
|
|
43
|
-
this.spinner.stop();
|
|
48
|
+
await this.browserforce.browserContext.tracing.groupEnd();
|
|
44
49
|
}
|
|
45
50
|
else {
|
|
46
51
|
this.log(`[${driver.name}] no action necessary`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apply.js","sourceRoot":"","sources":["../../../src/commands/browserforce/apply.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAMpE,MAAM,OAAO,iBAAkB,SAAQ,mBAA8C;IAC5E,MAAM,CAAC,WAAW,GAAG,
|
|
1
|
+
{"version":3,"file":"apply.js","sourceRoot":"","sources":["../../../src/commands/browserforce/apply.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAMpE,MAAM,OAAO,iBAAkB,SAAQ,mBAA8C;IAC5E,MAAM,CAAC,WAAW,GAAG,iCAAiC,CAAC;IACvD,MAAM,CAAC,QAAQ,GAAG;QACvB;;;;;;GAMD;KACA,CAAC;IAEK,KAAK,CAAC,GAAG;QACd,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QACtD,IAAI,CAAC,GAAG,CAAC,wBAAwB,KAAK,CAAC,cAAc,WAAW,KAAK,CAAC,YAAY,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QACrG,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACpC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YAC9B,MAAM,QAAQ,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAC/C,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,IAAI,oBAAoB,CAAC,CAAC;YACxD,MAAM,IAAI,CAAC,YAAY,CAAC,cAAc,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAClE,IAAI,KAAK,CAAC;YACV,IAAI,CAAC;gBACH,KAAK,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YACjD,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAC5B,MAAM,GAAG,CAAC;YACZ,CAAC;YACD,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YACpB,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;YACjD,MAAM,MAAM,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC;YAC9D,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBACvB,IAAI,CAAC,OAAO,CAAC,KAAK,CAChB,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;qBAClC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;oBACX,OAAO,GAAG,MAAM,KAAK,GAAG,SAAS,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC;gBAChE,CAAC,CAAC;qBACD,IAAI,CAAC,IAAI,CAAC,EAAE,CAChB,CAAC;gBACF,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;oBACtB,IAAI,CAAC;wBACH,MAAM,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBAC7B,CAAC;oBAAC,OAAO,GAAG,EAAE,CAAC;wBACb,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;wBAC5B,MAAM,GAAG,CAAC;oBACZ,CAAC;oBACD,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;gBACtB,CAAC;gBACD,MAAM,IAAI,CAAC,YAAY,CAAC,cAAc,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;YAC5D,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,IAAI,uBAAuB,CAAC,CAAC;YACnD,CAAC;QACH,CAAC;QACD,OAAO;YACL,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC"}
|
|
@@ -1,20 +1,26 @@
|
|
|
1
1
|
import { SfCommand } from '@salesforce/sf-plugins-core';
|
|
2
2
|
import { spawn } from 'child_process';
|
|
3
|
+
import { dirname } from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
3
6
|
export class BrowserforcePlaywrightCommand extends SfCommand {
|
|
4
7
|
static description = 'access the Playwright CLI';
|
|
5
8
|
static examples = [
|
|
6
9
|
`$ <%= config.bin %> <%= command.id %> -- --help`,
|
|
7
10
|
`$ <%= config.bin %> <%= command.id %> -- --version`,
|
|
8
11
|
`$ <%= config.bin %> <%= command.id %> -- install --list`,
|
|
9
|
-
`$ <%= config.bin %> <%= command.id %> -- install
|
|
12
|
+
`$ <%= config.bin %> <%= command.id %> -- install chromium`,
|
|
10
13
|
];
|
|
11
14
|
static strict = false;
|
|
12
15
|
async run() {
|
|
13
16
|
const { argv } = await this.parse(BrowserforcePlaywrightCommand);
|
|
14
17
|
const args = argv;
|
|
15
|
-
const isTest = process.env.NODE_ENV === 'test' ||
|
|
16
|
-
process.env.npm_lifecycle_event === 'test';
|
|
18
|
+
const isTest = process.env.NODE_ENV === 'test' || process.env.npm_lifecycle_event === 'test';
|
|
17
19
|
const child = spawn('npx', ['playwright', ...args], {
|
|
20
|
+
// Run this command wherever browserforce has been installed to.
|
|
21
|
+
// When running npx playwright install in another folder, it needs to be downloaded first
|
|
22
|
+
// AND it could resolve to another playwright version not compatible with sfdx-browserforce-plugin.
|
|
23
|
+
cwd: __dirname,
|
|
18
24
|
stdio: 'pipe',
|
|
19
25
|
});
|
|
20
26
|
return new Promise((resolve, reject) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"playwright.js","sourceRoot":"","sources":["../../../src/commands/browserforce/playwright.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"playwright.js","sourceRoot":"","sources":["../../../src/commands/browserforce/playwright.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAE1D,MAAM,OAAO,6BAA8B,SAAQ,SAAiB;IAC3D,MAAM,CAAC,WAAW,GAAG,2BAA2B,CAAC;IACjD,MAAM,CAAC,QAAQ,GAAG;QACvB,iDAAiD;QACjD,oDAAoD;QACpD,yDAAyD;QACzD,2DAA2D;KAC5D,CAAC;IAEK,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC;IAEtB,KAAK,CAAC,GAAG;QACd,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;QACjE,MAAM,IAAI,GAAG,IAAgB,CAAC;QAC9B,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB,KAAK,MAAM,CAAC;QAC7F,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC,YAAY,EAAE,GAAG,IAAI,CAAC,EAAE;YAClD,gEAAgE;YAChE,yFAAyF;YACzF,mGAAmG;YACnG,GAAG,EAAE,SAAS;YACd,KAAK,EAAE,MAAM;SACd,CAAC,CAAC;QAEH,OAAO,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC7C,IAAI,MAAM,GAAG,EAAE,CAAC;YAChB,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBACnC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YACrC,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;oBAChC,MAAM,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;gBAC7B,CAAC,CAAC,CAAC;YACL,CAAC;YAED,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;gBACzB,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;oBACf,OAAO,CAAC,MAAM,CAAC,CAAC;gBAClB,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;gBAC1B,CAAC;YACH,CAAC,CAAC,CAAC;YAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;gBAC1B,MAAM,CAAC,KAAK,CAAC,CAAC;YAChB,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC"}
|
package/lib/config-parser.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-parser.js","sourceRoot":"","sources":["../src/config-parser.ts"],"names":[],"mappings":"AAgBA,MAAM,OAAO,YAAY;IAChB,MAAM,CAAC,KAAK,CAAC,OAAgB,EAAE,IAAU;QAC9C,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,IAAI,IAAI,EAAE,QAAQ,EAAE,CAAC;YACnB,KAAK,MAAM,UAAU,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACpD,IAAI,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;oBACxB,QAAQ,CAAC,IAAI,CAAC;wBACZ,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC;wBAC3B,GAAG,EAAE,UAAU;wBACf,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;qBACjC,CAAC,CAAC;gBACL,CAAC;qBAAM,CAAC;oBACN,MAAM,IAAI,KAAK,
|
|
1
|
+
{"version":3,"file":"config-parser.js","sourceRoot":"","sources":["../src/config-parser.ts"],"names":[],"mappings":"AAgBA,MAAM,OAAO,YAAY;IAChB,MAAM,CAAC,KAAK,CAAC,OAAgB,EAAE,IAAU;QAC9C,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,IAAI,IAAI,EAAE,QAAQ,EAAE,CAAC;YACnB,KAAK,MAAM,UAAU,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACpD,IAAI,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;oBACxB,QAAQ,CAAC,IAAI,CAAC;wBACZ,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC;wBAC3B,GAAG,EAAE,UAAU;wBACf,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;qBACjC,CAAC,CAAC;gBACL,CAAC;qBAAM,CAAC;oBACN,MAAM,IAAI,KAAK,CAAC,gCAAgC,UAAU,oBAAoB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACxG,CAAC;YACH,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CAAC,+CAA+C,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACzF,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF"}
|
package/lib/pages/login.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type Connection } from '@salesforce/core';
|
|
2
2
|
import { type Page } from 'playwright';
|
|
3
3
|
export declare class LoginPage {
|
|
4
4
|
private page;
|
|
5
5
|
constructor(page: Page);
|
|
6
|
-
login(
|
|
6
|
+
login(connection: Connection): Promise<this>;
|
|
7
7
|
}
|
package/lib/pages/login.js
CHANGED
|
@@ -1,24 +1,14 @@
|
|
|
1
1
|
import { waitForPageErrors } from '../browserforce.js';
|
|
2
|
-
const FRONT_DOOR_PATH = 'secur/frontdoor.jsp';
|
|
3
|
-
const POST_LOGIN_PATH = 'setup/forcecomHomepage.apexp';
|
|
2
|
+
const FRONT_DOOR_PATH = '/secur/frontdoor.jsp';
|
|
3
|
+
const POST_LOGIN_PATH = '/setup/forcecomHomepage.apexp';
|
|
4
4
|
export class LoginPage {
|
|
5
5
|
page;
|
|
6
6
|
constructor(page) {
|
|
7
7
|
this.page = page;
|
|
8
8
|
}
|
|
9
|
-
async login(
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
catch (_) {
|
|
14
|
-
throw new Error('login failed');
|
|
15
|
-
}
|
|
16
|
-
const conn = org.getConnection();
|
|
17
|
-
await this.page.goto(`${conn.instanceUrl.replace(/\/$/, '')}/${FRONT_DOOR_PATH}?sid=${conn.accessToken}&retURL=${encodeURIComponent(POST_LOGIN_PATH)}`);
|
|
18
|
-
await Promise.race([
|
|
19
|
-
this.page.waitForURL((url) => url.pathname === `/${POST_LOGIN_PATH}`),
|
|
20
|
-
waitForPageErrors(this.page),
|
|
21
|
-
]);
|
|
9
|
+
async login(connection) {
|
|
10
|
+
await this.page.goto(`${connection.instanceUrl.replace(/\/$/, '')}${FRONT_DOOR_PATH}?sid=${connection.accessToken}&retURL=${encodeURIComponent(POST_LOGIN_PATH)}`);
|
|
11
|
+
await Promise.race([this.page.waitForURL((url) => url.pathname === POST_LOGIN_PATH), waitForPageErrors(this.page)]);
|
|
22
12
|
return this;
|
|
23
13
|
}
|
|
24
14
|
}
|
package/lib/pages/login.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/pages/login.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEvD,MAAM,eAAe,GAAG,
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/pages/login.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEvD,MAAM,eAAe,GAAG,sBAAsB,CAAC;AAC/C,MAAM,eAAe,GAAG,+BAA+B,CAAC;AAExD,MAAM,OAAO,SAAS;IACZ,IAAI,CAAO;IAEnB,YAAY,IAAU;QACpB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,UAAsB;QAChC,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAClB,GAAG,UAAU,CAAC,WAAW,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,eAAe,QAC5D,UAAU,CAAC,WACb,WAAW,kBAAkB,CAAC,eAAe,CAAC,EAAE,CACjD,CAAC;QACF,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,KAAK,eAAe,CAAC,EAAE,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpH,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
|
package/lib/plugin.d.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import { Org } from '@salesforce/core';
|
|
2
1
|
import { Browserforce } from './browserforce.js';
|
|
3
2
|
export declare abstract class BrowserforcePlugin {
|
|
4
3
|
protected browserforce: Browserforce;
|
|
5
|
-
protected org: Org;
|
|
6
4
|
constructor(browserforce: Browserforce);
|
|
7
5
|
abstract retrieve(definition?: unknown): Promise<unknown>;
|
|
8
6
|
/**
|
package/lib/plugin.js
CHANGED
package/lib/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,MAAM,OAAgB,kBAAkB;IAC5B,YAAY,CAAe;IAErC,YAAmB,YAA0B;QAC3C,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;IACnC,CAAC;IAED;;;;;OAKG;IACI,IAAI,CAAC,KAAc,EAAE,UAAmB;QAC7C,OAAO,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;IACrC,CAAC;IAEM,KAAK,CAAC,GAAG,CAAC,UAAmB;QAClC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QAC1C,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACtC,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,OAAO;YACL,OAAO,EAAE,qBAAqB;SAC/B,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -3,7 +3,7 @@ import { ActivitySettings } from './index.js';
|
|
|
3
3
|
describe(ActivitySettings.name, function () {
|
|
4
4
|
let plugin;
|
|
5
5
|
before(() => {
|
|
6
|
-
plugin = new ActivitySettings(global.
|
|
6
|
+
plugin = new ActivitySettings(global.browserforce);
|
|
7
7
|
});
|
|
8
8
|
describe('allowUsersToRelateMultipleContactsToTasksAndEvents', () => {
|
|
9
9
|
const configEnabled = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.e2e-spec.js","sourceRoot":"","sources":["../../../src/plugins/activity-settings/index.e2e-spec.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9C,QAAQ,CAAC,gBAAgB,CAAC,IAAI,EAAE;IAC9B,IAAI,MAAwB,CAAC;IAC7B,MAAM,CAAC,GAAG,EAAE;QACV,MAAM,GAAG,IAAI,gBAAgB,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"index.e2e-spec.js","sourceRoot":"","sources":["../../../src/plugins/activity-settings/index.e2e-spec.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9C,QAAQ,CAAC,gBAAgB,CAAC,IAAI,EAAE;IAC9B,IAAI,MAAwB,CAAC;IAC7B,MAAM,CAAC,GAAG,EAAE;QACV,MAAM,GAAG,IAAI,gBAAgB,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAClE,MAAM,aAAa,GAAG;YACpB,kDAAkD,EAAE,IAAI;SACzD,CAAC;QACF,MAAM,cAAc,GAAG;YACrB,kDAAkD,EAAE,KAAK;SAC1D,CAAC;QAEF,EAAE,CAAC,eAAe,EAAE,KAAK,IAAI,EAAE;YAC7B,MAAM,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,mBAAmB,EAAE,KAAK,IAAI,EAAE;YACjC,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,QAAQ,EAAE,CAAC;YACpC,MAAM,CAAC,eAAe,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,wBAAwB,EAAE,KAAK,IAAI,EAAE;YACtC,IAAI,GAAG,CAAC;YACR,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;YACrC,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,GAAG,GAAG,CAAC,CAAC;YACV,CAAC;YACD,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE;gBACjB,MAAM,GAAG,CAAC;YACZ,CAAC,EAAE,sBAAsB,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -1,31 +1,102 @@
|
|
|
1
|
+
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
|
|
2
|
+
if (value !== null && value !== void 0) {
|
|
3
|
+
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
|
|
4
|
+
var dispose, inner;
|
|
5
|
+
if (async) {
|
|
6
|
+
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
|
|
7
|
+
dispose = value[Symbol.asyncDispose];
|
|
8
|
+
}
|
|
9
|
+
if (dispose === void 0) {
|
|
10
|
+
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
|
|
11
|
+
dispose = value[Symbol.dispose];
|
|
12
|
+
if (async) inner = dispose;
|
|
13
|
+
}
|
|
14
|
+
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
|
|
15
|
+
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
|
|
16
|
+
env.stack.push({ value: value, dispose: dispose, async: async });
|
|
17
|
+
}
|
|
18
|
+
else if (async) {
|
|
19
|
+
env.stack.push({ async: true });
|
|
20
|
+
}
|
|
21
|
+
return value;
|
|
22
|
+
};
|
|
23
|
+
var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
|
|
24
|
+
return function (env) {
|
|
25
|
+
function fail(e) {
|
|
26
|
+
env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
|
|
27
|
+
env.hasError = true;
|
|
28
|
+
}
|
|
29
|
+
var r, s = 0;
|
|
30
|
+
function next() {
|
|
31
|
+
while (r = env.stack.pop()) {
|
|
32
|
+
try {
|
|
33
|
+
if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
|
|
34
|
+
if (r.dispose) {
|
|
35
|
+
var result = r.dispose.call(r.value);
|
|
36
|
+
if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
|
|
37
|
+
}
|
|
38
|
+
else s |= 1;
|
|
39
|
+
}
|
|
40
|
+
catch (e) {
|
|
41
|
+
fail(e);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
|
|
45
|
+
if (env.hasError) throw env.error;
|
|
46
|
+
}
|
|
47
|
+
return next();
|
|
48
|
+
};
|
|
49
|
+
})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
50
|
+
var e = new Error(message);
|
|
51
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
52
|
+
});
|
|
1
53
|
import { BrowserforcePlugin } from '../../plugin.js';
|
|
2
|
-
const BASE_PATH = 'setup/activitiesSetupPage.apexp';
|
|
54
|
+
const BASE_PATH = '/setup/activitiesSetupPage.apexp';
|
|
3
55
|
const MANY_WHO_PREF_INPUT_SELECTOR = 'input[id="thePage:theForm:theBlock:manyWhoPref"]';
|
|
4
56
|
const SUBMIT_BUTTON_SELECTOR = 'input[id="thePage:theForm:theBlock:buttons:submit"]';
|
|
5
57
|
export class ActivitySettings extends BrowserforcePlugin {
|
|
6
58
|
async retrieve() {
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
.isChecked(),
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
59
|
+
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
60
|
+
try {
|
|
61
|
+
const page = __addDisposableResource(env_1, await this.browserforce.openPage(BASE_PATH), true);
|
|
62
|
+
const response = {
|
|
63
|
+
allowUsersToRelateMultipleContactsToTasksAndEvents: await page.locator(MANY_WHO_PREF_INPUT_SELECTOR).isChecked(),
|
|
64
|
+
};
|
|
65
|
+
return response;
|
|
66
|
+
}
|
|
67
|
+
catch (e_1) {
|
|
68
|
+
env_1.error = e_1;
|
|
69
|
+
env_1.hasError = true;
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
const result_1 = __disposeResources(env_1);
|
|
73
|
+
if (result_1)
|
|
74
|
+
await result_1;
|
|
75
|
+
}
|
|
15
76
|
}
|
|
16
77
|
async apply(config) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
.locator(MANY_WHO_PREF_INPUT_SELECTOR)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
78
|
+
const env_2 = { stack: [], error: void 0, hasError: false };
|
|
79
|
+
try {
|
|
80
|
+
if (config.allowUsersToRelateMultipleContactsToTasksAndEvents === false) {
|
|
81
|
+
throw new Error('`allowUsersToRelateMultipleContactsToTasksAndEvents` can only be disabled with help of the salesforce.com Support team');
|
|
82
|
+
}
|
|
83
|
+
const page = __addDisposableResource(env_2, await this.browserforce.openPage(BASE_PATH), true);
|
|
84
|
+
await page.locator(MANY_WHO_PREF_INPUT_SELECTOR).waitFor();
|
|
85
|
+
await page
|
|
86
|
+
.locator(MANY_WHO_PREF_INPUT_SELECTOR)
|
|
87
|
+
.setChecked(config.allowUsersToRelateMultipleContactsToTasksAndEvents);
|
|
88
|
+
await page.locator(SUBMIT_BUTTON_SELECTOR).click();
|
|
89
|
+
await page.waitForURL((url) => url.pathname === '/ui/setup/Setup');
|
|
90
|
+
}
|
|
91
|
+
catch (e_2) {
|
|
92
|
+
env_2.error = e_2;
|
|
93
|
+
env_2.hasError = true;
|
|
94
|
+
}
|
|
95
|
+
finally {
|
|
96
|
+
const result_2 = __disposeResources(env_2);
|
|
97
|
+
if (result_2)
|
|
98
|
+
await result_2;
|
|
99
|
+
}
|
|
29
100
|
}
|
|
30
101
|
}
|
|
31
102
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/plugins/activity-settings/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErD,MAAM,SAAS,GAAG,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/plugins/activity-settings/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErD,MAAM,SAAS,GAAG,kCAAkC,CAAC;AAErD,MAAM,4BAA4B,GAAG,kDAAkD,CAAC;AACxF,MAAM,sBAAsB,GAAG,qDAAqD,CAAC;AAMrF,MAAM,OAAO,gBAAiB,SAAQ,kBAAkB;IAC/C,KAAK,CAAC,QAAQ;;;YACnB,MAAY,IAAI,kCAAG,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,SAAS,CAAC,OAAA,CAAC;YAC/D,MAAM,QAAQ,GAAG;gBACf,kDAAkD,EAAE,MAAM,IAAI,CAAC,OAAO,CAAC,4BAA4B,CAAC,CAAC,SAAS,EAAE;aACjH,CAAC;YACF,OAAO,QAAQ,CAAC;;;;;;;;;;;KACjB;IAEM,KAAK,CAAC,KAAK,CAAC,MAAc;;;YAC/B,IAAI,MAAM,CAAC,kDAAkD,KAAK,KAAK,EAAE,CAAC;gBACxE,MAAM,IAAI,KAAK,CACb,wHAAwH,CACzH,CAAC;YACJ,CAAC;YACD,MAAY,IAAI,kCAAG,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,SAAS,CAAC,OAAA,CAAC;YAC/D,MAAM,IAAI,CAAC,OAAO,CAAC,4BAA4B,CAAC,CAAC,OAAO,EAAE,CAAC;YAE3D,MAAM,IAAI;iBACP,OAAO,CAAC,4BAA4B,CAAC;iBACrC,UAAU,CAAC,MAAM,CAAC,kDAAkD,CAAC,CAAC;YAEzE,MAAM,IAAI,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAC,KAAK,EAAE,CAAC;YACnD,MAAM,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,KAAK,iBAAiB,CAAC,CAAC;;;;;;;;;;;KACpE;CACF"}
|