@salesforce/core 4.0.0 → 4.1.0
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/LICENSE.txt +1 -1
- package/README.md +93 -44
- package/lib/config/authInfoConfig.d.ts +19 -0
- package/lib/config/authInfoConfig.js +35 -0
- package/lib/config/config.d.ts +87 -22
- package/lib/config/config.js +117 -65
- package/lib/config/configAggregator.d.ts +41 -35
- package/lib/config/configAggregator.js +102 -73
- package/lib/config/configFile.d.ts +2 -2
- package/lib/config/configFile.js +38 -29
- package/lib/config/configStore.d.ts +9 -9
- package/lib/config/configStore.js +17 -15
- package/lib/config/envVars.d.ts +15 -9
- package/lib/config/envVars.js +71 -47
- package/lib/config/orgUsersConfig.js +2 -0
- package/lib/config/sandboxOrgConfig.js +2 -0
- package/lib/config/sandboxProcessCache.d.ts +16 -0
- package/lib/config/sandboxProcessCache.js +38 -0
- package/lib/config/tokensConfig.d.ts +10 -0
- package/lib/config/tokensConfig.js +29 -0
- package/lib/config/ttlConfig.d.ts +34 -0
- package/lib/config/ttlConfig.js +50 -0
- package/lib/crypto/crypto.js +15 -22
- package/lib/crypto/keyChain.js +2 -3
- package/lib/crypto/keyChainImpl.d.ts +5 -3
- package/lib/crypto/keyChainImpl.js +58 -61
- package/lib/crypto/secureBuffer.d.ts +1 -1
- package/lib/deviceOauthService.d.ts +3 -3
- package/lib/deviceOauthService.js +27 -25
- package/lib/exported.d.ts +15 -12
- package/lib/exported.js +28 -16
- package/lib/global.d.ts +11 -3
- package/lib/global.js +39 -12
- package/lib/lifecycleEvents.d.ts +1 -1
- package/lib/lifecycleEvents.js +3 -0
- package/lib/logger.d.ts +19 -9
- package/lib/logger.js +112 -86
- package/lib/messages.d.ts +53 -36
- package/lib/messages.js +81 -91
- package/lib/org/authInfo.d.ts +56 -20
- package/lib/org/authInfo.js +232 -131
- package/lib/org/authRemover.d.ts +8 -7
- package/lib/org/authRemover.js +32 -28
- package/lib/org/connection.d.ts +13 -37
- package/lib/org/connection.js +78 -124
- package/lib/org/index.js +5 -1
- package/lib/org/org.d.ts +151 -48
- package/lib/org/org.js +468 -225
- package/lib/org/orgConfigProperties.d.ts +64 -3
- package/lib/org/orgConfigProperties.js +96 -4
- package/lib/org/permissionSetAssignment.js +4 -13
- package/lib/org/scratchOrgCache.d.ts +20 -0
- package/lib/org/scratchOrgCache.js +33 -0
- package/lib/org/scratchOrgCreate.d.ts +28 -17
- package/lib/org/scratchOrgCreate.js +125 -53
- package/lib/org/scratchOrgErrorCodes.d.ts +9 -3
- package/lib/org/scratchOrgErrorCodes.js +34 -17
- package/lib/org/scratchOrgFeatureDeprecation.js +1 -6
- package/lib/org/scratchOrgInfoApi.d.ts +21 -47
- package/lib/org/scratchOrgInfoApi.js +129 -63
- package/lib/org/scratchOrgInfoGenerator.d.ts +6 -5
- package/lib/org/scratchOrgInfoGenerator.js +76 -62
- package/lib/org/scratchOrgLifecycleEvents.d.ts +10 -0
- package/lib/org/scratchOrgLifecycleEvents.js +41 -0
- package/lib/org/scratchOrgSettingsGenerator.d.ts +44 -21
- package/lib/org/scratchOrgSettingsGenerator.js +165 -98
- package/lib/org/scratchOrgTypes.d.ts +43 -0
- package/lib/org/scratchOrgTypes.js +9 -0
- package/lib/org/user.d.ts +1 -1
- package/lib/org/user.js +25 -34
- package/lib/schema/printer.d.ts +6 -0
- package/lib/schema/printer.js +34 -31
- package/lib/schema/validator.d.ts +12 -10
- package/lib/schema/validator.js +56 -76
- package/lib/{sfdxError.d.ts → sfError.d.ts} +12 -20
- package/lib/{sfdxError.js → sfError.js} +40 -30
- package/lib/{sfdxProject.d.ts → sfProject.d.ts} +75 -35
- package/lib/sfProject.js +651 -0
- package/lib/stateAggregator/accessors/aliasAccessor.d.ts +129 -0
- package/lib/stateAggregator/accessors/aliasAccessor.js +263 -0
- package/lib/stateAggregator/accessors/orgAccessor.d.ts +101 -0
- package/lib/stateAggregator/accessors/orgAccessor.js +240 -0
- package/lib/stateAggregator/accessors/sandboxAccessor.d.ts +8 -0
- package/lib/stateAggregator/accessors/sandboxAccessor.js +28 -0
- package/lib/stateAggregator/accessors/tokenAccessor.d.ts +63 -0
- package/lib/stateAggregator/accessors/tokenAccessor.js +80 -0
- package/lib/stateAggregator/index.d.ts +4 -0
- package/lib/stateAggregator/index.js +27 -0
- package/lib/stateAggregator/stateAggregator.d.ts +25 -0
- package/lib/stateAggregator/stateAggregator.js +46 -0
- package/lib/status/myDomainResolver.d.ts +1 -1
- package/lib/status/myDomainResolver.js +4 -4
- package/lib/status/pollingClient.js +4 -4
- package/lib/status/streamingClient.d.ts +2 -2
- package/lib/status/streamingClient.js +58 -63
- package/lib/status/types.d.ts +2 -2
- package/lib/testSetup.d.ts +204 -75
- package/lib/testSetup.js +468 -164
- package/lib/util/cache.d.ts +2 -2
- package/lib/util/cache.js +6 -6
- package/lib/util/checkLightningDomain.js +3 -4
- package/lib/util/directoryWriter.d.ts +12 -0
- package/lib/util/directoryWriter.js +54 -0
- package/lib/util/getJwtAudienceUrl.js +1 -1
- package/lib/util/internal.d.ts +28 -2
- package/lib/util/internal.js +65 -8
- package/lib/util/jsonXmlTools.js +2 -4
- package/lib/util/mapKeys.d.ts +9 -9
- package/lib/util/mapKeys.js +13 -9
- package/lib/util/sfdc.d.ts +51 -51
- package/lib/util/sfdc.js +74 -79
- package/lib/util/sfdcUrl.d.ts +5 -19
- package/lib/util/sfdcUrl.js +40 -49
- package/lib/util/structuredWriter.d.ts +9 -0
- package/lib/util/structuredWriter.js +3 -0
- package/lib/util/zipWriter.d.ts +8 -6
- package/lib/util/zipWriter.js +13 -13
- package/lib/webOAuthServer.d.ts +20 -6
- package/lib/webOAuthServer.js +102 -56
- package/messageTransformer/messageTransformer.ts +93 -0
- package/messages/auth.md +9 -1
- package/messages/config.md +42 -6
- package/messages/connection.md +8 -0
- package/messages/core.md +10 -0
- package/messages/envVars.md +37 -3
- package/messages/org.md +21 -1
- package/messages/scratchOrgCreate.md +2 -6
- package/messages/scratchOrgErrorCodes.md +17 -1
- package/messages/scratchOrgInfoApi.md +9 -0
- package/messages/scratchOrgInfoGenerator.md +9 -1
- package/package.json +123 -46
- package/CHANGELOG.md +0 -1244
- package/lib/config/keychainConfig.d.ts +0 -19
- package/lib/config/keychainConfig.js +0 -43
- package/lib/globalInfo/accessors/aliasAccessor.d.ts +0 -83
- package/lib/globalInfo/accessors/aliasAccessor.js +0 -130
- package/lib/globalInfo/accessors/orgAccessor.d.ts +0 -13
- package/lib/globalInfo/accessors/orgAccessor.js +0 -45
- package/lib/globalInfo/accessors/tokenAccessor.d.ts +0 -13
- package/lib/globalInfo/accessors/tokenAccessor.js +0 -35
- package/lib/globalInfo/globalInfoConfig.d.ts +0 -36
- package/lib/globalInfo/globalInfoConfig.js +0 -105
- package/lib/globalInfo/index.d.ts +0 -6
- package/lib/globalInfo/index.js +0 -29
- package/lib/globalInfo/sfdxDataHandler.d.ts +0 -43
- package/lib/globalInfo/sfdxDataHandler.js +0 -217
- package/lib/globalInfo/types.d.ts +0 -39
- package/lib/globalInfo/types.js +0 -10
- package/lib/sfdxProject.js +0 -557
- package/lib/util/fs.d.ts +0 -201
- package/lib/util/fs.js +0 -378
package/lib/testSetup.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MockTestOrgData = exports.StreamingMockCometClient = exports.StreamingMockCometSubscription = exports.StreamingMockSubscriptionCall = exports.
|
|
3
|
+
exports.MockTestSandboxData = exports.MockTestOrgData = exports.StreamingMockCometClient = exports.StreamingMockCometSubscription = exports.StreamingMockSubscriptionCall = exports.shouldThrowSync = exports.shouldThrow = exports.unexpectedResult = exports.restoreContext = exports.stubContext = exports.instantiateContext = exports.uniqid = exports.TestContext = void 0;
|
|
4
4
|
/*
|
|
5
5
|
* Copyright (c) 2020, salesforce.com, inc.
|
|
6
6
|
* All rights reserved.
|
|
@@ -8,11 +8,16 @@ exports.MockTestOrgData = exports.StreamingMockCometClient = exports.StreamingMo
|
|
|
8
8
|
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
9
9
|
*/
|
|
10
10
|
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
|
11
|
+
/* eslint-disable class-methods-use-this */
|
|
12
|
+
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
13
|
+
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
14
|
+
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
|
15
|
+
const fs = require("node:fs");
|
|
11
16
|
const crypto_1 = require("crypto");
|
|
12
17
|
const events_1 = require("events");
|
|
13
18
|
const os_1 = require("os");
|
|
14
19
|
const path_1 = require("path");
|
|
15
|
-
const
|
|
20
|
+
const util = require("util");
|
|
16
21
|
const ts_sinon_1 = require("@salesforce/ts-sinon");
|
|
17
22
|
const ts_types_1 = require("@salesforce/ts-types");
|
|
18
23
|
const configAggregator_1 = require("./config/configAggregator");
|
|
@@ -21,14 +26,302 @@ const connection_1 = require("./org/connection");
|
|
|
21
26
|
const crypto_2 = require("./crypto/crypto");
|
|
22
27
|
const logger_1 = require("./logger");
|
|
23
28
|
const messages_1 = require("./messages");
|
|
24
|
-
const
|
|
25
|
-
const
|
|
29
|
+
const sfError_1 = require("./sfError");
|
|
30
|
+
const sfProject_1 = require("./sfProject");
|
|
31
|
+
const aliasAccessorEntireFile = require("./stateAggregator/accessors/aliasAccessor");
|
|
26
32
|
const streamingClient_1 = require("./status/streamingClient");
|
|
27
|
-
const
|
|
33
|
+
const stateAggregator_1 = require("./stateAggregator");
|
|
34
|
+
const org_1 = require("./org");
|
|
35
|
+
const sandboxAccessor_1 = require("./stateAggregator/accessors/sandboxAccessor");
|
|
28
36
|
const global_1 = require("./global");
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
37
|
+
/**
|
|
38
|
+
* Instantiate a @salesforce/core test context.
|
|
39
|
+
*/
|
|
40
|
+
class TestContext {
|
|
41
|
+
constructor(options = {}) {
|
|
42
|
+
/**
|
|
43
|
+
* id A unique id for the test run.
|
|
44
|
+
*/
|
|
45
|
+
this.id = uniqid();
|
|
46
|
+
/**
|
|
47
|
+
* An object used in tests that interact with config files.
|
|
48
|
+
*/
|
|
49
|
+
this.configStubs = {};
|
|
50
|
+
/**
|
|
51
|
+
* A record of stubs created during instantiation.
|
|
52
|
+
*/
|
|
53
|
+
this.stubs = {};
|
|
54
|
+
const opts = { setup: true, ...options };
|
|
55
|
+
const sinon = this.requireSinon(opts.sinon);
|
|
56
|
+
// Create a global sinon sandbox and a test logger instance for use within tests.
|
|
57
|
+
this.SANDBOX = opts.sandbox ?? sinon.createSandbox();
|
|
58
|
+
this.SANDBOXES = {
|
|
59
|
+
DEFAULT: this.SANDBOX,
|
|
60
|
+
CONFIG: sinon.createSandbox(),
|
|
61
|
+
PROJECT: sinon.createSandbox(),
|
|
62
|
+
CRYPTO: sinon.createSandbox(),
|
|
63
|
+
CONNECTION: sinon.createSandbox(),
|
|
64
|
+
FS: sinon.createSandbox(),
|
|
65
|
+
ORGS: sinon.createSandbox(),
|
|
66
|
+
};
|
|
67
|
+
this.TEST_LOGGER = new logger_1.Logger({ name: 'SFDX_Core_Test_Logger' }).useMemoryLogging();
|
|
68
|
+
if (opts.setup) {
|
|
69
|
+
this.setup();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Generate unique string.
|
|
74
|
+
*/
|
|
75
|
+
uniqid() {
|
|
76
|
+
return uniqid();
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* A function used when resolving the local path. Calls localPathResolverSync by default.
|
|
80
|
+
*
|
|
81
|
+
* @param uid Unique id.
|
|
82
|
+
*/
|
|
83
|
+
async localPathRetriever(uid) {
|
|
84
|
+
return Promise.resolve(getTestLocalPath(uid));
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* A function used when resolving the local path.
|
|
88
|
+
*
|
|
89
|
+
* @param uid Unique id.
|
|
90
|
+
*/
|
|
91
|
+
localPathRetrieverSync(uid) {
|
|
92
|
+
return getTestLocalPath(uid);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* A function used when resolving the global path. Calls globalPathResolverSync by default.
|
|
96
|
+
*
|
|
97
|
+
* @param uid Unique id.
|
|
98
|
+
*/
|
|
99
|
+
async globalPathRetriever(uid) {
|
|
100
|
+
return Promise.resolve(getTestGlobalPath(uid));
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* A function used when resolving the global path.
|
|
104
|
+
*
|
|
105
|
+
* @param uid Unique id.
|
|
106
|
+
*/
|
|
107
|
+
globalPathRetrieverSync(uid) {
|
|
108
|
+
return getTestGlobalPath(uid);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* A function used for resolving paths. Calls localPathRetriever and globalPathRetriever.
|
|
112
|
+
*
|
|
113
|
+
* @param isGlobal `true` if the config is global.
|
|
114
|
+
* @param uid user id.
|
|
115
|
+
*/
|
|
116
|
+
async rootPathRetriever(isGlobal, uid) {
|
|
117
|
+
return retrieveRootPath(isGlobal, uid);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* A function used for resolving paths. Calls localPathRetrieverSync and globalPathRetrieverSync.
|
|
121
|
+
*
|
|
122
|
+
* @param isGlobal `true` if the config is global.
|
|
123
|
+
* @param uid user id.
|
|
124
|
+
*/
|
|
125
|
+
rootPathRetrieverSync(isGlobal, uid) {
|
|
126
|
+
return retrieveRootPathSync(isGlobal, uid);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Used to mock http request to Salesforce.
|
|
130
|
+
*
|
|
131
|
+
* @param request An HttpRequest.
|
|
132
|
+
* @param options Additional options.
|
|
133
|
+
*
|
|
134
|
+
* **See** {@link Connection.request}
|
|
135
|
+
*/
|
|
136
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
137
|
+
async fakeConnectionRequest(request, options) {
|
|
138
|
+
return defaultFakeConnectionRequest();
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Gets a config stub contents by name.
|
|
142
|
+
*
|
|
143
|
+
* @param name The name of the config.
|
|
144
|
+
* @param group If the config supports groups.
|
|
145
|
+
*/
|
|
146
|
+
getConfigStubContents(name, group) {
|
|
147
|
+
const stub = this.configStubs[name];
|
|
148
|
+
if (stub?.contents) {
|
|
149
|
+
if (group && stub.contents[group]) {
|
|
150
|
+
return (0, ts_types_1.ensureJsonMap)(stub.contents[group]);
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
return stub.contents;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return {};
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Sets a config stub contents by name
|
|
160
|
+
*
|
|
161
|
+
* @param name The name of the config stub.
|
|
162
|
+
* @param value The actual stub contents. The Mock data.
|
|
163
|
+
*/
|
|
164
|
+
setConfigStubContents(name, value) {
|
|
165
|
+
if ((0, ts_types_1.ensureString)(name) && (0, ts_types_1.isJsonMap)(value)) {
|
|
166
|
+
this.configStubs[name] = value;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Set stubs for working in the context of a SfProject
|
|
171
|
+
*/
|
|
172
|
+
inProject(inProject = true) {
|
|
173
|
+
this.SANDBOXES.PROJECT.restore();
|
|
174
|
+
if (inProject) {
|
|
175
|
+
this.SANDBOXES.PROJECT.stub(sfProject_1.SfProject, 'resolveProjectPath').callsFake(() => this.localPathRetriever(this.id));
|
|
176
|
+
this.SANDBOXES.PROJECT.stub(sfProject_1.SfProject, 'resolveProjectPathSync').callsFake(() => this.localPathRetrieverSync(this.id));
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
this.SANDBOXES.PROJECT.stub(sfProject_1.SfProject, 'resolveProjectPath').rejects(new sfError_1.SfError('', 'InvalidProjectWorkspaceError'));
|
|
180
|
+
this.SANDBOXES.PROJECT.stub(sfProject_1.SfProject, 'resolveProjectPathSync').throws(new sfError_1.SfError('', 'InvalidProjectWorkspaceError'));
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Stub salesforce org authorizations.
|
|
185
|
+
*/
|
|
186
|
+
async stubAuths(...orgs) {
|
|
187
|
+
const entries = await Promise.all(orgs.map(async (org) => [org.username, await org.getConfig()]));
|
|
188
|
+
const orgMap = new Map(entries);
|
|
189
|
+
(0, ts_sinon_1.stubMethod)(this.SANDBOX, stateAggregator_1.OrgAccessor.prototype, 'getAllFiles').resolves([...orgMap.keys()].map((o) => `${o}.json`));
|
|
190
|
+
(0, ts_sinon_1.stubMethod)(this.SANDBOX, stateAggregator_1.OrgAccessor.prototype, 'hasFile').callsFake((username) => orgMap.has(username));
|
|
191
|
+
const retrieveContents = async function () {
|
|
192
|
+
const username = (0, path_1.basename)(this.path.replace('.json', ''));
|
|
193
|
+
return Promise.resolve(orgMap.get(username) ?? {});
|
|
194
|
+
};
|
|
195
|
+
this.configStubs.AuthInfoConfig = { retrieveContents };
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Stub salesforce user authorizations.
|
|
199
|
+
*
|
|
200
|
+
* @param users The users to stub.
|
|
201
|
+
* The key is the username of the admin user and it must be included in the users array in order to obtain the orgId key for the remaining users.
|
|
202
|
+
* The admin user is excluded from the users array.
|
|
203
|
+
*
|
|
204
|
+
*/
|
|
205
|
+
stubUsers(users) {
|
|
206
|
+
const mockUsers = Object.values(users).flatMap((orgUsers) => orgUsers.map((user) => {
|
|
207
|
+
const userInfo = user.getMockUserInfo();
|
|
208
|
+
return {
|
|
209
|
+
alias: userInfo.Alias ?? '',
|
|
210
|
+
email: userInfo.Email ?? '',
|
|
211
|
+
emailEncodingKey: userInfo.EmailEncodingKey ?? '',
|
|
212
|
+
id: userInfo.Id ?? '',
|
|
213
|
+
languageLocaleKey: userInfo.LanguageLocaleKey ?? '',
|
|
214
|
+
lastName: userInfo.LastName ?? '',
|
|
215
|
+
localeSidKey: userInfo.LocaleSidKey ?? '',
|
|
216
|
+
profileId: userInfo.ProfileId ?? '',
|
|
217
|
+
timeZoneSidKey: userInfo.TimeZoneSidKey ?? '',
|
|
218
|
+
username: userInfo.Username ?? '',
|
|
219
|
+
};
|
|
220
|
+
}));
|
|
221
|
+
const userOrgsMap = new Map(Object.entries(users).map(([adminUsername, orgs]) => {
|
|
222
|
+
const adminOrg = orgs.find((org) => org.username === adminUsername);
|
|
223
|
+
return adminOrg
|
|
224
|
+
? [adminOrg.orgId, { usernames: orgs.filter((org) => org.username !== adminUsername) }]
|
|
225
|
+
: [undefined, undefined];
|
|
226
|
+
}));
|
|
227
|
+
(0, ts_sinon_1.stubMethod)(this.SANDBOX, org_1.User.prototype, 'retrieve').callsFake((username) => Promise.resolve(mockUsers.find((org) => org.username === username)));
|
|
228
|
+
const retrieveContents = async function () {
|
|
229
|
+
const orgId = (0, path_1.basename)(this.path.replace('.json', ''));
|
|
230
|
+
return Promise.resolve(userOrgsMap.get(orgId) ?? {});
|
|
231
|
+
};
|
|
232
|
+
this.configStubs.OrgUsersConfig = { retrieveContents };
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Stub salesforce sandbox authorizations.
|
|
236
|
+
*/
|
|
237
|
+
async stubSandboxes(...sandboxes) {
|
|
238
|
+
const entries = (await Promise.all(sandboxes.map(async (sandbox) => [sandbox.username, await sandbox.getConfig()])));
|
|
239
|
+
const sandboxMap = new Map(entries);
|
|
240
|
+
(0, ts_sinon_1.stubMethod)(this.SANDBOX, sandboxAccessor_1.SandboxAccessor.prototype, 'getAllFiles').resolves([...sandboxMap.keys()].map((o) => `${o}.sandbox.json`));
|
|
241
|
+
const retrieveContents = async function () {
|
|
242
|
+
const username = (0, path_1.basename)(this.path.replace('.sandbox.json', ''));
|
|
243
|
+
return Promise.resolve(sandboxMap.get(username) ?? {});
|
|
244
|
+
};
|
|
245
|
+
this.configStubs.SandboxOrgConfig = { retrieveContents };
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Stub the aliases in the global aliases config file.
|
|
249
|
+
*/
|
|
250
|
+
stubAliases(aliases, group = aliasAccessorEntireFile.DEFAULT_GROUP) {
|
|
251
|
+
// we don't really "stub" these since they don't use configFile.
|
|
252
|
+
// write the fileContents to location
|
|
253
|
+
fs.mkdirSync((0, path_1.dirname)(getAliasFileLocation()), { recursive: true });
|
|
254
|
+
fs.writeFileSync(getAliasFileLocation(), JSON.stringify({ [group]: aliases }));
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Stub contents in the config file.
|
|
258
|
+
*/
|
|
259
|
+
async stubConfig(config) {
|
|
260
|
+
this.configStubs.Config = { contents: config };
|
|
261
|
+
// configAggregator may have already loaded an instance. We're not sure why this happens.
|
|
262
|
+
// This seems to solve the problem by forcing a load of the new stubbed config.
|
|
263
|
+
await configAggregator_1.ConfigAggregator.create();
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Stub the tokens in the global token config file.
|
|
267
|
+
*/
|
|
268
|
+
stubTokens(tokens) {
|
|
269
|
+
this.configStubs.TokensConfig = { contents: tokens };
|
|
270
|
+
}
|
|
271
|
+
restore() {
|
|
272
|
+
(0, exports.restoreContext)(this);
|
|
273
|
+
}
|
|
274
|
+
init() {
|
|
275
|
+
this.stubs = (0, exports.stubContext)(this);
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Add beforeEach and afterEach hooks to init the stubs and restore them.
|
|
279
|
+
* This is called automatically when the class is instantiated unless the setup option is set to false.
|
|
280
|
+
*/
|
|
281
|
+
setup() {
|
|
282
|
+
beforeEach(() => {
|
|
283
|
+
this.init();
|
|
284
|
+
});
|
|
285
|
+
afterEach(() => {
|
|
286
|
+
this.restore();
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
requireSinon(sinon) {
|
|
290
|
+
if (sinon)
|
|
291
|
+
return sinon;
|
|
292
|
+
try {
|
|
293
|
+
sinon = require('sinon');
|
|
294
|
+
}
|
|
295
|
+
catch (e) {
|
|
296
|
+
throw new Error('The package sinon was not found. Add it to your package.json and pass it in to new TestContext({sinon})');
|
|
297
|
+
}
|
|
298
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
299
|
+
return sinon;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
exports.TestContext = TestContext;
|
|
303
|
+
/**
|
|
304
|
+
* A function to generate a unique id and return it in the context of a template, if supplied.
|
|
305
|
+
*
|
|
306
|
+
* A template is a string that can contain `${%s}` to be replaced with a unique id.
|
|
307
|
+
* If the template contains the "%s" placeholder, it will be replaced with the unique id otherwise the id will be appended to the template.
|
|
308
|
+
*
|
|
309
|
+
* @param options an object with the following properties:
|
|
310
|
+
* - template: a template string.
|
|
311
|
+
* - length: the length of the unique id as presented in hexadecimal.
|
|
312
|
+
*/
|
|
313
|
+
function uniqid(options) {
|
|
314
|
+
const uniqueString = (0, crypto_1.randomBytes)(Math.ceil((options?.length ?? 32) / 2.0))
|
|
315
|
+
.toString('hex')
|
|
316
|
+
.slice(0, options?.length ?? 32);
|
|
317
|
+
if (!options?.template) {
|
|
318
|
+
return uniqueString;
|
|
319
|
+
}
|
|
320
|
+
return options.template.includes('%s')
|
|
321
|
+
? util.format(options.template, uniqueString)
|
|
322
|
+
: `${options.template}${uniqueString}`;
|
|
323
|
+
}
|
|
324
|
+
exports.uniqid = uniqid;
|
|
32
325
|
function getTestLocalPath(uid) {
|
|
33
326
|
return (0, path_1.join)((0, os_1.tmpdir)(), uid, 'sfdx_core', 'local');
|
|
34
327
|
}
|
|
@@ -57,86 +350,16 @@ function defaultFakeConnectionRequest() {
|
|
|
57
350
|
* const $$ = instantiateContext();
|
|
58
351
|
*
|
|
59
352
|
* beforeEach(() => {
|
|
60
|
-
*
|
|
353
|
+
* $$.init()
|
|
61
354
|
* });
|
|
62
355
|
*
|
|
63
356
|
* afterEach(() => {
|
|
64
|
-
*
|
|
357
|
+
* $$.restore();
|
|
65
358
|
* });
|
|
66
359
|
* ```
|
|
67
360
|
* @param sinon
|
|
68
361
|
*/
|
|
69
|
-
|
|
70
|
-
const instantiateContext = (sinon) => {
|
|
71
|
-
if (!sinon) {
|
|
72
|
-
try {
|
|
73
|
-
sinon = require('sinon');
|
|
74
|
-
}
|
|
75
|
-
catch (e) {
|
|
76
|
-
throw new Error('The package sinon was not found. Add it to your package.json and pass it in to testSetup(sinon.sandbox)');
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
// Import all the messages files in the sfdx-core messages dir.
|
|
80
|
-
// Messages.importMessagesDirectory(pathJoin(__dirname, '..', '..'));
|
|
81
|
-
messages_1.Messages.importMessagesDirectory((0, path_1.join)(__dirname));
|
|
82
|
-
// Create a global sinon sandbox and a test logger instance for use within tests.
|
|
83
|
-
const defaultSandbox = sinon.createSandbox();
|
|
84
|
-
const testContext = {
|
|
85
|
-
SANDBOX: defaultSandbox,
|
|
86
|
-
SANDBOXES: {
|
|
87
|
-
DEFAULT: defaultSandbox,
|
|
88
|
-
CONFIG: sinon.createSandbox(),
|
|
89
|
-
PROJECT: sinon.createSandbox(),
|
|
90
|
-
CRYPTO: sinon.createSandbox(),
|
|
91
|
-
CONNECTION: sinon.createSandbox(),
|
|
92
|
-
FS: sinon.createSandbox(),
|
|
93
|
-
},
|
|
94
|
-
TEST_LOGGER: new logger_1.Logger({
|
|
95
|
-
name: 'SFDX_Core_Test_Logger',
|
|
96
|
-
}).useMemoryLogging(),
|
|
97
|
-
id: uniqid(),
|
|
98
|
-
uniqid,
|
|
99
|
-
configStubs: {},
|
|
100
|
-
// eslint-disable-next-line @typescript-eslint/require-await
|
|
101
|
-
localPathRetriever: async (uid) => getTestLocalPath(uid),
|
|
102
|
-
localPathRetrieverSync: getTestLocalPath,
|
|
103
|
-
// eslint-disable-next-line @typescript-eslint/require-await
|
|
104
|
-
globalPathRetriever: async (uid) => getTestGlobalPath(uid),
|
|
105
|
-
globalPathRetrieverSync: getTestGlobalPath,
|
|
106
|
-
rootPathRetriever: retrieveRootPath,
|
|
107
|
-
rootPathRetrieverSync: retrieveRootPathSync,
|
|
108
|
-
fakeConnectionRequest: defaultFakeConnectionRequest,
|
|
109
|
-
getConfigStubContents(name, group) {
|
|
110
|
-
const stub = this.configStubs[name];
|
|
111
|
-
if (stub && stub.contents) {
|
|
112
|
-
if (group && stub.contents[group]) {
|
|
113
|
-
return (0, ts_types_1.ensureJsonMap)(stub.contents[group]);
|
|
114
|
-
}
|
|
115
|
-
else {
|
|
116
|
-
return stub.contents;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
return {};
|
|
120
|
-
},
|
|
121
|
-
setConfigStubContents(name, value) {
|
|
122
|
-
if ((0, ts_types_1.ensureString)(name) && (0, ts_types_1.isJsonMap)(value)) {
|
|
123
|
-
this.configStubs[name] = value;
|
|
124
|
-
}
|
|
125
|
-
},
|
|
126
|
-
inProject(inProject = true) {
|
|
127
|
-
testContext.SANDBOXES.PROJECT.restore();
|
|
128
|
-
if (inProject) {
|
|
129
|
-
testContext.SANDBOXES.PROJECT.stub(sfdxProject_1.SfdxProject, 'resolveProjectPath').callsFake(() => testContext.localPathRetriever(testContext.id));
|
|
130
|
-
testContext.SANDBOXES.PROJECT.stub(sfdxProject_1.SfdxProject, 'resolveProjectPathSync').callsFake(() => testContext.localPathRetrieverSync(testContext.id));
|
|
131
|
-
}
|
|
132
|
-
else {
|
|
133
|
-
testContext.SANDBOXES.PROJECT.stub(sfdxProject_1.SfdxProject, 'resolveProjectPath').rejects(new sfdxError_1.SfdxError('', 'InvalidProjectWorkspaceError'));
|
|
134
|
-
testContext.SANDBOXES.PROJECT.stub(sfdxProject_1.SfdxProject, 'resolveProjectPathSync').throws(new sfdxError_1.SfdxError('', 'InvalidProjectWorkspaceError'));
|
|
135
|
-
}
|
|
136
|
-
},
|
|
137
|
-
};
|
|
138
|
-
return testContext;
|
|
139
|
-
};
|
|
362
|
+
const instantiateContext = (sinon) => new TestContext({ sinon, setup: false });
|
|
140
363
|
exports.instantiateContext = instantiateContext;
|
|
141
364
|
/**
|
|
142
365
|
* Stub a @salesforce/core test context. This will mock out logging to a file, config file reading and writing,
|
|
@@ -153,11 +376,11 @@ exports.instantiateContext = instantiateContext;
|
|
|
153
376
|
* const $$ = instantiateContext();
|
|
154
377
|
*
|
|
155
378
|
* beforeEach(() => {
|
|
156
|
-
*
|
|
379
|
+
* $$.init()
|
|
157
380
|
* });
|
|
158
381
|
*
|
|
159
382
|
* afterEach(() => {
|
|
160
|
-
*
|
|
383
|
+
* $$.restore();
|
|
161
384
|
* });
|
|
162
385
|
* ```
|
|
163
386
|
* @param testContext
|
|
@@ -165,34 +388,33 @@ exports.instantiateContext = instantiateContext;
|
|
|
165
388
|
const stubContext = (testContext) => {
|
|
166
389
|
// Turn off the interoperability feature so that we don't have to mock
|
|
167
390
|
// the old .sfdx config files
|
|
168
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
169
|
-
// @ts-ignore
|
|
170
391
|
global_1.Global.SFDX_INTEROPERABILITY = false;
|
|
392
|
+
const stubs = {};
|
|
171
393
|
// Most core files create a child logger so stub this to return our test logger.
|
|
172
|
-
(0, ts_sinon_1.stubMethod)(testContext.SANDBOX, logger_1.Logger, 'child').
|
|
394
|
+
(0, ts_sinon_1.stubMethod)(testContext.SANDBOX, logger_1.Logger, 'child').resolves(testContext.TEST_LOGGER);
|
|
173
395
|
(0, ts_sinon_1.stubMethod)(testContext.SANDBOX, logger_1.Logger, 'childFromRoot').returns(testContext.TEST_LOGGER);
|
|
174
396
|
testContext.inProject(true);
|
|
175
397
|
testContext.SANDBOXES.CONFIG.stub(configFile_1.ConfigFile, 'resolveRootFolder').callsFake((isGlobal) => testContext.rootPathRetriever(isGlobal, testContext.id));
|
|
176
398
|
testContext.SANDBOXES.CONFIG.stub(configFile_1.ConfigFile, 'resolveRootFolderSync').callsFake((isGlobal) => testContext.rootPathRetrieverSync(isGlobal, testContext.id));
|
|
177
|
-
(0, ts_sinon_1.stubMethod)(testContext.SANDBOXES.PROJECT,
|
|
399
|
+
(0, ts_sinon_1.stubMethod)(testContext.SANDBOXES.PROJECT, sfProject_1.SfProjectJson.prototype, 'doesPackageExist').callsFake(() => true);
|
|
178
400
|
const initStubForRead = (configFile) => {
|
|
179
|
-
const stub = testContext.configStubs[configFile.constructor.name]
|
|
401
|
+
const stub = testContext.configStubs[configFile.constructor.name] ?? {};
|
|
180
402
|
// init calls read calls getPath which sets the path on the config file the first time.
|
|
181
403
|
// Since read is now stubbed, make sure to call getPath to initialize it.
|
|
182
404
|
configFile.getPath();
|
|
183
|
-
// @ts-
|
|
405
|
+
// @ts-expect-error: set this to true to avoid an infinite loop in tests when reading config files.
|
|
184
406
|
configFile.hasRead = true;
|
|
185
407
|
return stub;
|
|
186
408
|
};
|
|
187
409
|
const readSync = function (newContents) {
|
|
188
410
|
const stub = initStubForRead(this);
|
|
189
|
-
this.setContentsFromObject(newContents
|
|
411
|
+
this.setContentsFromObject(newContents ?? stub.contents ?? {});
|
|
190
412
|
return this.getContents();
|
|
191
413
|
};
|
|
192
414
|
const read = async function () {
|
|
193
415
|
const stub = initStubForRead(this);
|
|
194
416
|
if (stub.readFn) {
|
|
195
|
-
return
|
|
417
|
+
return stub.readFn.call(this);
|
|
196
418
|
}
|
|
197
419
|
if (stub.retrieveContents) {
|
|
198
420
|
return readSync.call(this, await stub.retrieveContents.call(this));
|
|
@@ -202,9 +424,9 @@ const stubContext = (testContext) => {
|
|
|
202
424
|
}
|
|
203
425
|
};
|
|
204
426
|
// Mock out all config file IO for all tests. They can restore individually if they need original functionality.
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
testContext.SANDBOXES.CONFIG.stub(configFile_1.ConfigFile.prototype, '
|
|
427
|
+
stubs.configRead = testContext.SANDBOXES.CONFIG.stub(configFile_1.ConfigFile.prototype, 'read').callsFake(read);
|
|
428
|
+
// @ts-expect-error: muting exact type match for stub readSync
|
|
429
|
+
stubs.configReadSync = testContext.SANDBOXES.CONFIG.stub(configFile_1.ConfigFile.prototype, 'readSync').callsFake(readSync);
|
|
208
430
|
const writeSync = function (newContents) {
|
|
209
431
|
if (!testContext.configStubs[this.constructor.name]) {
|
|
210
432
|
testContext.configStubs[this.constructor.name] = {};
|
|
@@ -212,7 +434,7 @@ const stubContext = (testContext) => {
|
|
|
212
434
|
const stub = testContext.configStubs[this.constructor.name];
|
|
213
435
|
if (!stub)
|
|
214
436
|
return;
|
|
215
|
-
this.setContents(newContents
|
|
437
|
+
this.setContents(newContents ?? this.getContents());
|
|
216
438
|
stub.contents = this.toObject();
|
|
217
439
|
};
|
|
218
440
|
const write = async function (newContents) {
|
|
@@ -223,7 +445,7 @@ const stubContext = (testContext) => {
|
|
|
223
445
|
if (!stub)
|
|
224
446
|
return;
|
|
225
447
|
if (stub.writeFn) {
|
|
226
|
-
return
|
|
448
|
+
return stub.writeFn.call(this, newContents);
|
|
227
449
|
}
|
|
228
450
|
if (stub.updateContents) {
|
|
229
451
|
writeSync.call(this, await stub.updateContents.call(this));
|
|
@@ -232,8 +454,8 @@ const stubContext = (testContext) => {
|
|
|
232
454
|
writeSync.call(this);
|
|
233
455
|
}
|
|
234
456
|
};
|
|
235
|
-
(0, ts_sinon_1.stubMethod)(testContext.SANDBOXES.CONFIG, configFile_1.ConfigFile.prototype, 'writeSync').callsFake(writeSync);
|
|
236
|
-
(0, ts_sinon_1.stubMethod)(testContext.SANDBOXES.CONFIG, configFile_1.ConfigFile.prototype, 'write').callsFake(write);
|
|
457
|
+
stubs.configWriteSync = (0, ts_sinon_1.stubMethod)(testContext.SANDBOXES.CONFIG, configFile_1.ConfigFile.prototype, 'writeSync').callsFake(writeSync);
|
|
458
|
+
stubs.configWrite = (0, ts_sinon_1.stubMethod)(testContext.SANDBOXES.CONFIG, configFile_1.ConfigFile.prototype, 'write').callsFake(write);
|
|
237
459
|
(0, ts_sinon_1.stubMethod)(testContext.SANDBOXES.CRYPTO, crypto_2.Crypto.prototype, 'getKeyChain').callsFake(() => Promise.resolve({
|
|
238
460
|
setPassword: () => Promise.resolve(),
|
|
239
461
|
getPassword: (data, cb) => cb(undefined, '12345678901234567890123456789012'),
|
|
@@ -245,10 +467,28 @@ const stubContext = (testContext) => {
|
|
|
245
467
|
}
|
|
246
468
|
return testContext.fakeConnectionRequest.call(this, request, options);
|
|
247
469
|
});
|
|
470
|
+
(0, ts_sinon_1.stubMethod)(testContext.SANDBOX, aliasAccessorEntireFile, 'getFileLocation').returns(getAliasFileLocation());
|
|
471
|
+
stubs.configExists = (0, ts_sinon_1.stubMethod)(testContext.SANDBOXES.ORGS, stateAggregator_1.OrgAccessor.prototype, 'exists').callsFake(async function (username) {
|
|
472
|
+
// @ts-expect-error because private member
|
|
473
|
+
if ([...this.contents.keys()].includes(username))
|
|
474
|
+
return Promise.resolve(true);
|
|
475
|
+
else
|
|
476
|
+
return Promise.resolve(false);
|
|
477
|
+
});
|
|
478
|
+
stubs.configRemove = (0, ts_sinon_1.stubMethod)(testContext.SANDBOXES.ORGS, stateAggregator_1.OrgAccessor.prototype, 'remove').callsFake(async function (username) {
|
|
479
|
+
// @ts-expect-error because private member
|
|
480
|
+
if ([...this.contents.keys()].includes(username))
|
|
481
|
+
return Promise.resolve(true);
|
|
482
|
+
else
|
|
483
|
+
return Promise.resolve(false);
|
|
484
|
+
});
|
|
248
485
|
// Always start with the default and tests beforeEach or it methods can override it.
|
|
249
486
|
testContext.fakeConnectionRequest = defaultFakeConnectionRequest;
|
|
487
|
+
testContext.stubs = stubs;
|
|
488
|
+
return stubs;
|
|
250
489
|
};
|
|
251
490
|
exports.stubContext = stubContext;
|
|
491
|
+
const getAliasFileLocation = () => (0, path_1.join)((0, os_1.tmpdir)(), global_1.Global.SFDX_STATE_FOLDER, aliasAccessorEntireFile.FILENAME);
|
|
252
492
|
/**
|
|
253
493
|
* Restore a @salesforce/core test context. This is automatically stubbed in the global beforeEach created by
|
|
254
494
|
* `const $$ = testSetup()` but is useful if you don't want to have a global stub of @salesforce/core and you
|
|
@@ -259,78 +499,41 @@ exports.stubContext = stubContext;
|
|
|
259
499
|
* const $$ = instantiateContext();
|
|
260
500
|
*
|
|
261
501
|
* beforeEach(() => {
|
|
262
|
-
*
|
|
502
|
+
* $$.init()
|
|
263
503
|
* });
|
|
264
504
|
*
|
|
265
505
|
* afterEach(() => {
|
|
266
|
-
*
|
|
506
|
+
* $$.restore();
|
|
267
507
|
* });
|
|
268
508
|
* ```
|
|
269
509
|
* @param testContext
|
|
270
510
|
*/
|
|
271
511
|
const restoreContext = (testContext) => {
|
|
512
|
+
// Restore the default value for this setting on restore.
|
|
513
|
+
global_1.Global.SFDX_INTEROPERABILITY = true;
|
|
272
514
|
testContext.SANDBOX.restore();
|
|
515
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
273
516
|
Object.values(testContext.SANDBOXES).forEach((theSandbox) => theSandbox.restore());
|
|
274
517
|
testContext.configStubs = {};
|
|
275
|
-
// Give each test run a clean
|
|
276
|
-
|
|
518
|
+
// Give each test run a clean StateAggregator
|
|
519
|
+
stateAggregator_1.StateAggregator.clearInstance();
|
|
520
|
+
// Allow each test to have their own config aggregator
|
|
521
|
+
// @ts-ignore clear for testing.
|
|
522
|
+
delete configAggregator_1.ConfigAggregator.instance;
|
|
277
523
|
};
|
|
278
524
|
exports.restoreContext = restoreContext;
|
|
279
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
280
|
-
const _testSetup = (sinon) => {
|
|
281
|
-
const testContext = (0, exports.instantiateContext)(sinon);
|
|
282
|
-
beforeEach(() => {
|
|
283
|
-
// Allow each test to have their own config aggregator
|
|
284
|
-
// @ts-ignore clear for testing.
|
|
285
|
-
delete configAggregator_1.ConfigAggregator.instance;
|
|
286
|
-
(0, exports.stubContext)(testContext);
|
|
287
|
-
});
|
|
288
|
-
afterEach(() => {
|
|
289
|
-
(0, exports.restoreContext)(testContext);
|
|
290
|
-
});
|
|
291
|
-
return testContext;
|
|
292
|
-
};
|
|
293
|
-
/**
|
|
294
|
-
* Use to mock out different pieces of sfdx-core to make testing easier. This will mock out
|
|
295
|
-
* logging to a file, config file reading and writing, local and global path resolution, and
|
|
296
|
-
* *http request using connection (soon)*.
|
|
297
|
-
*
|
|
298
|
-
* **Note:** The testSetup should be outside of the describe. If you need to stub per test, use
|
|
299
|
-
* `instantiateContext`, `stubContext`, and `restoreContext`.
|
|
300
|
-
* ```
|
|
301
|
-
* // In a mocha tests
|
|
302
|
-
* import testSetup from '@salesforce/core/lib/testSetup';
|
|
303
|
-
*
|
|
304
|
-
* const $$ = testSetup();
|
|
305
|
-
*
|
|
306
|
-
* describe(() => {
|
|
307
|
-
* it('test', () => {
|
|
308
|
-
* // Stub out your own method
|
|
309
|
-
* $$.SANDBOX.stub(MyClass.prototype, 'myMethod').returnsFake(() => {});
|
|
310
|
-
*
|
|
311
|
-
* // Set the contents that is used when aliases are read. Same for all config files.
|
|
312
|
-
* $$.configStubs.Aliases = { contents: { 'myTestAlias': 'user@company.com' } };
|
|
313
|
-
*
|
|
314
|
-
* // Will use the contents set above.
|
|
315
|
-
* const username = Aliases.fetch('myTestAlias');
|
|
316
|
-
* expect(username).to.equal('user@company.com');
|
|
317
|
-
* });
|
|
318
|
-
* });
|
|
319
|
-
* ```
|
|
320
|
-
*/
|
|
321
|
-
exports.testSetup = (0, kit_1.once)(_testSetup);
|
|
322
525
|
/**
|
|
323
526
|
* A pre-canned error for try/catch testing.
|
|
324
527
|
*
|
|
325
528
|
* **See** {@link shouldThrow}
|
|
326
529
|
*/
|
|
327
|
-
exports.unexpectedResult = new
|
|
530
|
+
exports.unexpectedResult = new sfError_1.SfError('This code was expected to fail', 'UnexpectedResult');
|
|
328
531
|
/**
|
|
329
532
|
* Use for this testing pattern:
|
|
330
533
|
* ```
|
|
331
534
|
* try {
|
|
332
535
|
* await call()
|
|
333
|
-
* assert.fail(
|
|
536
|
+
* assert.fail("this should never happen");
|
|
334
537
|
* } catch (e) {
|
|
335
538
|
* ...
|
|
336
539
|
* }
|
|
@@ -346,11 +549,47 @@ exports.unexpectedResult = new sfdxError_1.SfdxError('This code was expected to
|
|
|
346
549
|
*
|
|
347
550
|
* @param f The async function that is expected to throw.
|
|
348
551
|
*/
|
|
349
|
-
async function shouldThrow(f) {
|
|
552
|
+
async function shouldThrow(f, message) {
|
|
350
553
|
await f;
|
|
351
|
-
|
|
554
|
+
if (message) {
|
|
555
|
+
throw new sfError_1.SfError(message, 'UnexpectedResult');
|
|
556
|
+
}
|
|
557
|
+
else {
|
|
558
|
+
throw exports.unexpectedResult;
|
|
559
|
+
}
|
|
352
560
|
}
|
|
353
561
|
exports.shouldThrow = shouldThrow;
|
|
562
|
+
/**
|
|
563
|
+
* Use for this testing pattern:
|
|
564
|
+
* ```
|
|
565
|
+
* try {
|
|
566
|
+
* call()
|
|
567
|
+
* assert.fail("this should never happen");
|
|
568
|
+
* } catch (e) {
|
|
569
|
+
* ...
|
|
570
|
+
* }
|
|
571
|
+
*
|
|
572
|
+
* Just do this
|
|
573
|
+
*
|
|
574
|
+
* try {
|
|
575
|
+
* shouldThrowSync(call); // If this succeeds unexpectedResultError is thrown.
|
|
576
|
+
* } catch(e) {
|
|
577
|
+
* ...
|
|
578
|
+
* }
|
|
579
|
+
* ```
|
|
580
|
+
*
|
|
581
|
+
* @param f The function that is expected to throw.
|
|
582
|
+
*/
|
|
583
|
+
function shouldThrowSync(f, message) {
|
|
584
|
+
f();
|
|
585
|
+
if (message) {
|
|
586
|
+
throw new sfError_1.SfError(message, 'UnexpectedResult');
|
|
587
|
+
}
|
|
588
|
+
else {
|
|
589
|
+
throw exports.unexpectedResult;
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
exports.shouldThrowSync = shouldThrowSync;
|
|
354
593
|
/**
|
|
355
594
|
* A helper to determine if a subscription will use callback or errorback.
|
|
356
595
|
* Enable errback to simulate a subscription failure.
|
|
@@ -472,33 +711,49 @@ class StreamingMockCometClient extends streamingClient_1.CometClient {
|
|
|
472
711
|
}
|
|
473
712
|
exports.StreamingMockCometClient = StreamingMockCometClient;
|
|
474
713
|
/**
|
|
475
|
-
* Mock class for
|
|
714
|
+
* Mock class for Salesforce Orgs.
|
|
715
|
+
*
|
|
716
|
+
* @example
|
|
717
|
+
* ```
|
|
718
|
+
* const testOrg = new MockTestOrgData();
|
|
719
|
+
* await $$.stubAuths(testOrg)
|
|
720
|
+
* ```
|
|
476
721
|
*/
|
|
477
722
|
class MockTestOrgData {
|
|
478
723
|
constructor(id = uniqid(), options) {
|
|
479
724
|
this.testId = id;
|
|
480
725
|
this.userId = `user_id_${this.testId}`;
|
|
481
726
|
this.orgId = `${this.testId}`;
|
|
482
|
-
this.username =
|
|
483
|
-
this.loginUrl = `
|
|
484
|
-
this.instanceUrl = `
|
|
727
|
+
this.username = options?.username ?? `admin_${this.testId}@gb.org`;
|
|
728
|
+
this.loginUrl = `https://login.${this.testId}.salesforce.com`;
|
|
729
|
+
this.instanceUrl = `https://instance.${this.testId}.salesforce.com`;
|
|
485
730
|
this.clientId = `${this.testId}/client_id`;
|
|
486
731
|
this.clientSecret = `${this.testId}/client_secret`;
|
|
487
732
|
this.authcode = `${this.testId}/authcode`;
|
|
488
733
|
this.accessToken = `${this.testId}/accessToken`;
|
|
489
734
|
this.refreshToken = `${this.testId}/refreshToken`;
|
|
490
|
-
this.redirectUri =
|
|
735
|
+
this.redirectUri = 'http://localhost:1717/OauthRedirect';
|
|
491
736
|
}
|
|
737
|
+
/**
|
|
738
|
+
* Add devhub username to properties.
|
|
739
|
+
*/
|
|
492
740
|
createDevHubUsername(username) {
|
|
493
741
|
this.devHubUsername = username;
|
|
494
742
|
}
|
|
743
|
+
/**
|
|
744
|
+
* Mark this org as a devhub.
|
|
745
|
+
*/
|
|
495
746
|
makeDevHub() {
|
|
496
|
-
|
|
747
|
+
this.isDevHub = true;
|
|
497
748
|
}
|
|
749
|
+
/**
|
|
750
|
+
* Returns a MockTestOrgData that represents a user created in the org.
|
|
751
|
+
*/
|
|
498
752
|
createUser(user) {
|
|
499
753
|
const userMock = new MockTestOrgData();
|
|
500
754
|
userMock.username = user;
|
|
501
|
-
userMock.
|
|
755
|
+
userMock.aliases = this.aliases;
|
|
756
|
+
userMock.configs = this.configs;
|
|
502
757
|
userMock.devHubUsername = this.devHubUsername;
|
|
503
758
|
userMock.orgId = this.orgId;
|
|
504
759
|
userMock.loginUrl = this.loginUrl;
|
|
@@ -506,14 +761,23 @@ class MockTestOrgData {
|
|
|
506
761
|
userMock.clientId = this.clientId;
|
|
507
762
|
userMock.clientSecret = this.clientSecret;
|
|
508
763
|
userMock.redirectUri = this.redirectUri;
|
|
764
|
+
userMock.isDevHub = this.isDevHub;
|
|
765
|
+
userMock.isScratchOrg = this.isScratchOrg;
|
|
766
|
+
userMock.isExpired = this.isExpired;
|
|
767
|
+
userMock.password = this.password;
|
|
768
|
+
userMock.accessToken = this.accessToken;
|
|
509
769
|
return userMock;
|
|
510
770
|
}
|
|
771
|
+
/**
|
|
772
|
+
* Return mock user information based on this org.
|
|
773
|
+
*/
|
|
511
774
|
getMockUserInfo() {
|
|
512
775
|
return {
|
|
513
776
|
Id: this.userId,
|
|
514
777
|
Username: this.username,
|
|
515
778
|
LastName: `user_lastname_${this.testId}`,
|
|
516
|
-
Alias: this.
|
|
779
|
+
Alias: this.aliases ? this.aliases[0] : 'user_alias_blah',
|
|
780
|
+
Configs: this.configs,
|
|
517
781
|
TimeZoneSidKey: `user_timezonesidkey_${this.testId}`,
|
|
518
782
|
LocaleSidKey: `user_localesidkey_${this.testId}`,
|
|
519
783
|
EmailEncodingKey: `user_emailencodingkey_${this.testId}`,
|
|
@@ -522,17 +786,20 @@ class MockTestOrgData {
|
|
|
522
786
|
Email: `user_email@${this.testId}.com`,
|
|
523
787
|
};
|
|
524
788
|
}
|
|
789
|
+
/**
|
|
790
|
+
* Return the auth config file contents.
|
|
791
|
+
*/
|
|
525
792
|
async getConfig() {
|
|
526
793
|
const crypto = await crypto_2.Crypto.create();
|
|
527
794
|
const config = {};
|
|
528
795
|
config.orgId = this.orgId;
|
|
796
|
+
config.clientId = this.clientId;
|
|
529
797
|
const accessToken = crypto.encrypt(this.accessToken);
|
|
530
798
|
if (accessToken) {
|
|
531
799
|
config.accessToken = accessToken;
|
|
532
800
|
}
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
config.refreshToken = refreshToken;
|
|
801
|
+
if (this.refreshToken) {
|
|
802
|
+
config.refreshToken = crypto.encrypt(this.refreshToken);
|
|
536
803
|
}
|
|
537
804
|
config.instanceUrl = this.instanceUrl;
|
|
538
805
|
config.loginUrl = this.loginUrl;
|
|
@@ -540,16 +807,53 @@ class MockTestOrgData {
|
|
|
540
807
|
config.createdOrgInstance = 'CS1';
|
|
541
808
|
config.created = '1519163543003';
|
|
542
809
|
config.userId = this.userId;
|
|
543
|
-
|
|
810
|
+
config.tracksSource = this.tracksSource;
|
|
544
811
|
if (this.devHubUsername) {
|
|
545
812
|
config.devHubUsername = this.devHubUsername;
|
|
546
813
|
}
|
|
547
|
-
|
|
548
|
-
if (
|
|
549
|
-
config.
|
|
814
|
+
config.isDevHub = this.isDevHub;
|
|
815
|
+
if (this.password) {
|
|
816
|
+
config.password = crypto.encrypt(this.password);
|
|
550
817
|
}
|
|
551
818
|
return config;
|
|
552
819
|
}
|
|
820
|
+
/**
|
|
821
|
+
* Return the Connection for the org.
|
|
822
|
+
*/
|
|
823
|
+
async getConnection() {
|
|
824
|
+
return (await org_1.Org.create({ aliasOrUsername: this.username })).getConnection();
|
|
825
|
+
}
|
|
553
826
|
}
|
|
554
827
|
exports.MockTestOrgData = MockTestOrgData;
|
|
828
|
+
/**
|
|
829
|
+
* Mock class for Salesforce Sandboxes.
|
|
830
|
+
*
|
|
831
|
+
* @example
|
|
832
|
+
* ```
|
|
833
|
+
* const testOrg = new MockTestSandboxData();
|
|
834
|
+
* await $$.stubSandboxes(testOrg)
|
|
835
|
+
* ```
|
|
836
|
+
*/
|
|
837
|
+
class MockTestSandboxData {
|
|
838
|
+
constructor(id = uniqid(), options) {
|
|
839
|
+
this.id = id;
|
|
840
|
+
this.sandboxOrgId = id;
|
|
841
|
+
this.prodOrgUsername = options?.prodOrgUsername ?? `admin_${id}@gb.org`;
|
|
842
|
+
this.sandboxName = options?.name ?? `sandbox_${id}`;
|
|
843
|
+
this.username = options?.username ?? `${this.prodOrgUsername}.sandbox`;
|
|
844
|
+
}
|
|
845
|
+
/**
|
|
846
|
+
* Return the auth config file contents.
|
|
847
|
+
*/
|
|
848
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
849
|
+
async getConfig() {
|
|
850
|
+
return {
|
|
851
|
+
sandboxOrgId: this.sandboxOrgId,
|
|
852
|
+
prodOrgUsername: this.prodOrgUsername,
|
|
853
|
+
sandboxName: this.sandboxName,
|
|
854
|
+
sandboxUsername: this.username,
|
|
855
|
+
};
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
exports.MockTestSandboxData = MockTestSandboxData;
|
|
555
859
|
//# sourceMappingURL=testSetup.js.map
|