1 | /// <reference types="node" />
|
2 | import { EventEmitter } from 'events';
|
3 | import { SinonSandbox, SinonStatic, SinonStub } from 'sinon';
|
4 | import { AnyJson, JsonMap, Optional } from '@salesforce/ts-types';
|
5 | import { ConfigContents } from './config/configStore';
|
6 | import { Connection } from './org/connection';
|
7 | import { Logger } from './logger';
|
8 | import { SfError } from './sfError';
|
9 | import { CometClient, CometSubscription, Message, StreamingExtension } from './status/streamingClient';
|
10 | import { AuthFields, SandboxFields } from './org';
|
11 | import { AliasGroup } from './config/aliasesConfig';
|
12 | /**
|
13 | * Different parts of the system that are mocked out. They can be restored for
|
14 | * individual tests. Test's stubs should always go on the DEFAULT which is exposed
|
15 | * on the TestContext.
|
16 | */
|
17 | export interface SandboxTypes {
|
18 | DEFAULT: SinonSandbox;
|
19 | CRYPTO: SinonSandbox;
|
20 | CONFIG: SinonSandbox;
|
21 | PROJECT: SinonSandbox;
|
22 | CONNECTION: SinonSandbox;
|
23 | FS: SinonSandbox;
|
24 | ORGS: SinonSandbox;
|
25 | }
|
26 | /**
|
27 | * Different hooks into {@link ConfigFile} used for testing instead of doing file IO.
|
28 | */
|
29 | export interface ConfigStub {
|
30 | /**
|
31 | * readFn A function that controls all aspect of {@link ConfigFile.read}. For example, it won't set the contents
|
32 | * unless explicitly done. Only use this if you know what you are doing. Use retrieveContents
|
33 | * instead.
|
34 | */
|
35 | readFn?: () => Promise<ConfigContents>;
|
36 | /**
|
37 | * A function that controls all aspects of {@link ConfigFile.write}. For example, it won't read the contents unless
|
38 | * explicitly done. Only use this if you know what you are doing. Use updateContents instead.
|
39 | */
|
40 | writeFn?: (contents?: AnyJson) => Promise<void>;
|
41 | /**
|
42 | * The contents that are used with @{link ConfigFile.readSync} and @{link ConfigFile.read}. If retrieveContents is set,
|
43 | * it will use that instead of @{link ConfigFile.read} but NOT @{link ConfigFile.readSync}. This will also contain the
|
44 | * new config when @{link ConfigFile.write} or @{link ConfigFile.writeSync} is called. This will persist through config instances,
|
45 | * such as {@link Alias.update} and {@link Alias.fetch}.
|
46 | */
|
47 | contents?: ConfigContents;
|
48 | /**
|
49 | * A function to conditionally read based on the config instance. The `this` value will be the config instance.
|
50 | */
|
51 | retrieveContents?: () => Promise<JsonMap>;
|
52 | /**
|
53 | * A function to conditionally set based on the config instance. The `this` value will be the config instance.
|
54 | */
|
55 | updateContents?: () => Promise<JsonMap>;
|
56 | }
|
57 | /**
|
58 | * Instantiate a @salesforce/core test context.
|
59 | */
|
60 | export declare class TestContext {
|
61 | /**
|
62 | * The default sandbox is cleared out before each test run.
|
63 | *
|
64 | * **See** [sinon sandbox]{@link https://sinonjs.org/releases/v14/sandbox/}.
|
65 | */
|
66 | SANDBOX: SinonSandbox;
|
67 | /**
|
68 | * An object of different sandboxes. Used when
|
69 | * needing to restore parts of the system for customized testing.
|
70 | */
|
71 | SANDBOXES: SandboxTypes;
|
72 | /**
|
73 | * The test logger that is used when {@link Logger.child} is used anywhere. It uses memory logging.
|
74 | */
|
75 | TEST_LOGGER: Logger;
|
76 | /**
|
77 | * id A unique id for the test run.
|
78 | */
|
79 | id: string;
|
80 | /**
|
81 | * An object used in tests that interact with config files.
|
82 | */
|
83 | configStubs: {
|
84 | [configName: string]: Optional<ConfigStub>;
|
85 | AliasesConfig?: ConfigStub;
|
86 | AuthInfoConfig?: ConfigStub;
|
87 | Config?: ConfigStub;
|
88 | SfProjectJson?: ConfigStub;
|
89 | TokensConfig?: ConfigStub;
|
90 | OrgUsersConfig?: ConfigStub;
|
91 | };
|
92 | /**
|
93 | * A record of stubs created during instantiation.
|
94 | */
|
95 | stubs: Record<string, SinonStub>;
|
96 | constructor(options?: {
|
97 | sinon?: SinonStatic;
|
98 | sandbox?: SinonSandbox;
|
99 | setup?: boolean;
|
100 | });
|
101 | /**
|
102 | * Generate unique string.
|
103 | */
|
104 | uniqid(): string;
|
105 | /**
|
106 | * A function used when resolving the local path. Calls localPathResolverSync by default.
|
107 | *
|
108 | * @param uid Unique id.
|
109 | */
|
110 | localPathRetriever(uid: string): Promise<string>;
|
111 | /**
|
112 | * A function used when resolving the local path.
|
113 | *
|
114 | * @param uid Unique id.
|
115 | */
|
116 | localPathRetrieverSync(uid: string): string;
|
117 | /**
|
118 | * A function used when resolving the global path. Calls globalPathResolverSync by default.
|
119 | *
|
120 | * @param uid Unique id.
|
121 | */
|
122 | globalPathRetriever(uid: string): Promise<string>;
|
123 | /**
|
124 | * A function used when resolving the global path.
|
125 | *
|
126 | * @param uid Unique id.
|
127 | */
|
128 | globalPathRetrieverSync(uid: string): string;
|
129 | /**
|
130 | * A function used for resolving paths. Calls localPathRetriever and globalPathRetriever.
|
131 | *
|
132 | * @param isGlobal `true` if the config is global.
|
133 | * @param uid user id.
|
134 | */
|
135 | rootPathRetriever(isGlobal: boolean, uid?: string): Promise<string>;
|
136 | /**
|
137 | * A function used for resolving paths. Calls localPathRetrieverSync and globalPathRetrieverSync.
|
138 | *
|
139 | * @param isGlobal `true` if the config is global.
|
140 | * @param uid user id.
|
141 | */
|
142 | rootPathRetrieverSync(isGlobal: boolean, uid?: string): string;
|
143 | /**
|
144 | * Used to mock http request to Salesforce.
|
145 | *
|
146 | * @param request An HttpRequest.
|
147 | * @param options Additional options.
|
148 | *
|
149 | * **See** { Connection.request}
|
150 | */
|
151 | fakeConnectionRequest(request: AnyJson, options?: AnyJson): Promise<AnyJson>;
|
152 | /**
|
153 | * Gets a config stub contents by name.
|
154 | *
|
155 | * @param name The name of the config.
|
156 | * @param group If the config supports groups.
|
157 | */
|
158 | getConfigStubContents(name: string, group?: string): ConfigContents;
|
159 | /**
|
160 | * Sets a config stub contents by name
|
161 | *
|
162 | * @param name The name of the config stub.
|
163 | * @param value The actual stub contents. The Mock data.
|
164 | */
|
165 | setConfigStubContents(name: string, value: ConfigContents): void;
|
166 | /**
|
167 | * Set stubs for working in the context of a SfProject
|
168 | */
|
169 | inProject(inProject?: boolean): void;
|
170 | /**
|
171 | * Stub salesforce org authorizations.
|
172 | */
|
173 | stubAuths(...orgs: MockTestOrgData[]): Promise<void>;
|
174 | /**
|
175 | * Stub salesforce user authorizations.
|
176 | *
|
177 | * @param users The users to stub.
|
178 | * 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.
|
179 | * The admin user is excluded from the users array.
|
180 | *
|
181 | */
|
182 | stubUsers(users: Record<string, MockTestOrgData[]>): void;
|
183 | /**
|
184 | * Stub salesforce sandbox authorizations.
|
185 | */
|
186 | stubSandboxes(...sandboxes: MockTestSandboxData[]): Promise<void>;
|
187 | /**
|
188 | * Stub the aliases in the global aliases config file.
|
189 | */
|
190 | stubAliases(aliases: Record<string, string>, group?: AliasGroup): void;
|
191 | /**
|
192 | * Stub contents in the config file.
|
193 | */
|
194 | stubConfig(config: Record<string, string>): Promise<void>;
|
195 | /**
|
196 | * Stub the tokens in the global token config file.
|
197 | */
|
198 | stubTokens(tokens: Record<string, string>): void;
|
199 | restore(): void;
|
200 | init(): void;
|
201 | /**
|
202 | * Add beforeEach and afterEach hooks to init the stubs and restore them.
|
203 | * This is called automatically when the class is instantiated unless the setup option is set to false.
|
204 | */
|
205 | setup(): void;
|
206 | private requireSinon;
|
207 | }
|
208 | /**
|
209 | * A function to generate a unique id and return it in the context of a template, if supplied.
|
210 | *
|
211 | * A template is a string that can contain `${%s}` to be replaced with a unique id.
|
212 | * If the template contains the "%s" placeholder, it will be replaced with the unique id otherwise the id will be appended to the template.
|
213 | *
|
214 | * @param options an object with the following properties:
|
215 | * - template: a template string.
|
216 | * - length: the length of the unique id as presented in hexadecimal.
|
217 | */
|
218 | export declare function uniqid(options?: {
|
219 | template?: string;
|
220 | length?: number;
|
221 | }): string;
|
222 | /**
|
223 | * Instantiate a @salesforce/core test context. This is automatically created by `const $$ = testSetup()`
|
224 | * but is useful if you don't want to have a global stub of @salesforce/core and you want to isolate it to
|
225 | * a single describe.
|
226 | *
|
227 | * **Note:** Call `stubContext` in your beforeEach to have clean stubs of @salesforce/core every test run.
|
228 | *
|
229 | * @example
|
230 | * ```
|
231 | * const $$ = instantiateContext();
|
232 | *
|
233 | * beforeEach(() => {
|
234 | * $$.init()
|
235 | * });
|
236 | *
|
237 | * afterEach(() => {
|
238 | * $$.restore();
|
239 | * });
|
240 | * ```
|
241 | * @param sinon
|
242 | */
|
243 | export declare const instantiateContext: (sinon?: SinonStatic) => TestContext;
|
244 | /**
|
245 | * Stub a @salesforce/core test context. This will mock out logging to a file, config file reading and writing,
|
246 | * local and global path resolution, and http request using connection (soon)*.
|
247 | *
|
248 | * This is automatically stubbed in the global beforeEach created by
|
249 | * `const $$ = testSetup()` but is useful if you don't want to have a global stub of @salesforce/core and you
|
250 | * want to isolate it to a single describe.
|
251 | *
|
252 | * **Note:** Always call `restoreContext` in your afterEach.
|
253 | *
|
254 | * @example
|
255 | * ```
|
256 | * const $$ = instantiateContext();
|
257 | *
|
258 | * beforeEach(() => {
|
259 | * $$.init()
|
260 | * });
|
261 | *
|
262 | * afterEach(() => {
|
263 | * $$.restore();
|
264 | * });
|
265 | * ```
|
266 | * @param testContext
|
267 | */
|
268 | export declare const stubContext: (testContext: TestContext) => Record<string, SinonStub>;
|
269 | /**
|
270 | * Restore a @salesforce/core test context. This is automatically stubbed in the global beforeEach created by
|
271 | * `const $$ = testSetup()` but is useful if you don't want to have a global stub of @salesforce/core and you
|
272 | * want to isolate it to a single describe.
|
273 | *
|
274 | * @example
|
275 | * ```
|
276 | * const $$ = instantiateContext();
|
277 | *
|
278 | * beforeEach(() => {
|
279 | * $$.init()
|
280 | * });
|
281 | *
|
282 | * afterEach(() => {
|
283 | * $$.restore();
|
284 | * });
|
285 | * ```
|
286 | * @param testContext
|
287 | */
|
288 | export declare const restoreContext: (testContext: TestContext) => void;
|
289 | /**
|
290 | * @deprecated Use TestContext instead.
|
291 | * Using testSetup will create globals stubs that could lead to erratic test behavior.
|
292 | *
|
293 | * This example shows you how to use TestContext:
|
294 | * @example
|
295 | * ```
|
296 | * const $$ = new TestContext();
|
297 | *
|
298 | * beforeEach(() => {
|
299 | * $$.init();
|
300 | * });
|
301 | *
|
302 | * afterEach(() => {
|
303 | * $$.restore();
|
304 | * });
|
305 | * ```
|
306 | *
|
307 | * Use to mock out different pieces of sfdx-core to make testing easier. This will mock out
|
308 | * logging to a file, config file reading and writing, local and global path resolution, and
|
309 | * *http request using connection (soon)*.
|
310 | *
|
311 | * **Note:** The testSetup should be outside of the describe. If you need to stub per test, use
|
312 | * `TestContext`.
|
313 | * ```
|
314 | * // In a mocha tests
|
315 | * import testSetup from '@salesforce/core/lib/testSetup';
|
316 | *
|
317 | * const $$ = testSetup();
|
318 | *
|
319 | * describe(() => {
|
320 | * it('test', () => {
|
321 | * // Stub out your own method
|
322 | * $$.SANDBOX.stub(MyClass.prototype, 'myMethod').returnsFake(() => {});
|
323 | *
|
324 | * // Set the contents that is used when aliases are read. Same for all config files.
|
325 | * $$.stubAliases({ 'myTestAlias': 'user@company.com' });
|
326 | *
|
327 | * // Will use the contents set above.
|
328 | * const username = (await StateAggregator.getInstance()).aliases.resolveUsername("myTestAlias");
|
329 | * expect(username).to.equal("user@company.com");
|
330 | * });
|
331 | * });
|
332 | * ```
|
333 | */
|
334 | export declare const testSetup: (sinon?: SinonStatic) => TestContext;
|
335 | /**
|
336 | * A pre-canned error for try/catch testing.
|
337 | *
|
338 | * **See** {@link shouldThrow}
|
339 | */
|
340 | export declare const unexpectedResult: SfError;
|
341 | /**
|
342 | * Use for this testing pattern:
|
343 | * ```
|
344 | * try {
|
345 | * await call()
|
346 | * assert.fail("this should never happen");
|
347 | * } catch (e) {
|
348 | * ...
|
349 | * }
|
350 | *
|
351 | * Just do this
|
352 | *
|
353 | * try {
|
354 | * await shouldThrow(call()); // If this succeeds unexpectedResultError is thrown.
|
355 | * } catch(e) {
|
356 | * ...
|
357 | * }
|
358 | * ```
|
359 | *
|
360 | * @param f The async function that is expected to throw.
|
361 | */
|
362 | export declare function shouldThrow(f: Promise<unknown>, message?: string): Promise<never>;
|
363 | /**
|
364 | * Use for this testing pattern:
|
365 | * ```
|
366 | * try {
|
367 | * call()
|
368 | * assert.fail("this should never happen");
|
369 | * } catch (e) {
|
370 | * ...
|
371 | * }
|
372 | *
|
373 | * Just do this
|
374 | *
|
375 | * try {
|
376 | * shouldThrowSync(call); // If this succeeds unexpectedResultError is thrown.
|
377 | * } catch(e) {
|
378 | * ...
|
379 | * }
|
380 | * ```
|
381 | *
|
382 | * @param f The function that is expected to throw.
|
383 | */
|
384 | export declare function shouldThrowSync(f: () => unknown, message?: string): never;
|
385 | /**
|
386 | * A helper to determine if a subscription will use callback or errorback.
|
387 | * Enable errback to simulate a subscription failure.
|
388 | */
|
389 | export declare enum StreamingMockSubscriptionCall {
|
390 | CALLBACK = 0,
|
391 | ERRORBACK = 1
|
392 | }
|
393 | /**
|
394 | * Additional subscription options for the StreamingMock.
|
395 | */
|
396 | export interface StreamingMockCometSubscriptionOptions {
|
397 | /**
|
398 | * Target URL.
|
399 | */
|
400 | url: string;
|
401 | /**
|
402 | * Simple id to associate with this instance.
|
403 | */
|
404 | id: string;
|
405 | /**
|
406 | * What is the subscription outcome a successful callback or an error?.
|
407 | */
|
408 | subscriptionCall: StreamingMockSubscriptionCall;
|
409 | /**
|
410 | * If it's an error that states what that error should be.
|
411 | */
|
412 | subscriptionErrbackError?: SfError;
|
413 | /**
|
414 | * A list of messages to playback for the client. One message per process tick.
|
415 | */
|
416 | messagePlaylist?: Message[];
|
417 | }
|
418 | /**
|
419 | * Simulates a comet subscription to a streaming channel.
|
420 | */
|
421 | export declare class StreamingMockCometSubscription extends EventEmitter implements CometSubscription {
|
422 | static SUBSCRIPTION_COMPLETE: string;
|
423 | static SUBSCRIPTION_FAILED: string;
|
424 | private options;
|
425 | constructor(options: StreamingMockCometSubscriptionOptions);
|
426 | /**
|
427 | * Sets up a streaming subscription callback to occur after the setTimeout event loop phase.
|
428 | *
|
429 | * @param callback The function to invoke.
|
430 | */
|
431 | callback(callback: () => void): void;
|
432 | /**
|
433 | * Sets up a streaming subscription errback to occur after the setTimeout event loop phase.
|
434 | *
|
435 | * @param callback The function to invoke.
|
436 | */
|
437 | errback(callback: (error: Error) => void): void;
|
438 | }
|
439 | /**
|
440 | * Simulates a comet client. To the core streaming client this mocks the internal comet impl.
|
441 | * The uses setTimeout(0ms) event loop phase just so the client can simulate actual streaming without the response
|
442 | * latency.
|
443 | */
|
444 | export declare class StreamingMockCometClient extends CometClient {
|
445 | private readonly options;
|
446 | /**
|
447 | * Constructor
|
448 | *
|
449 | * @param {StreamingMockCometSubscriptionOptions} options Extends the StreamingClient options.
|
450 | */
|
451 | constructor(options: StreamingMockCometSubscriptionOptions);
|
452 | /**
|
453 | * Fake addExtension. Does nothing.
|
454 | */
|
455 | addExtension(extension: StreamingExtension): void;
|
456 | /**
|
457 | * Fake disable. Does nothing.
|
458 | */
|
459 | disable(label: string): void;
|
460 | /**
|
461 | * Fake handshake that invoke callback after the setTimeout event phase.
|
462 | *
|
463 | * @param callback The function to invoke.
|
464 | */
|
465 | handshake(callback: () => void): void;
|
466 | /**
|
467 | * Fake setHeader. Does nothing,
|
468 | */
|
469 | setHeader(name: string, value: string): void;
|
470 | /**
|
471 | * Fake subscription that completed after the setTimout event phase.
|
472 | *
|
473 | * @param channel The streaming channel.
|
474 | * @param callback The function to invoke after the subscription completes.
|
475 | */
|
476 | subscribe(channel: string, callback: (message: Message) => void): CometSubscription;
|
477 | /**
|
478 | * Fake disconnect. Does Nothing.
|
479 | */
|
480 | disconnect(): Promise<void>;
|
481 | }
|
482 | type MockUserInfo = {
|
483 | Id: string;
|
484 | Username: string;
|
485 | LastName: string;
|
486 | Alias: string;
|
487 | Configs: string[] | undefined;
|
488 | TimeZoneSidKey: string;
|
489 | LocaleSidKey: string;
|
490 | EmailEncodingKey: string;
|
491 | ProfileId: string;
|
492 | LanguageLocaleKey: string;
|
493 | Email: string;
|
494 | };
|
495 | /**
|
496 | * Mock class for Salesforce Orgs.
|
497 | *
|
498 | * @example
|
499 | * ```
|
500 | * const testOrg = new MockTestOrgData();
|
501 | * await $$.stubAuths(testOrg)
|
502 | * ```
|
503 | */
|
504 | export declare class MockTestOrgData {
|
505 | testId: string;
|
506 | aliases?: string[];
|
507 | configs?: string[];
|
508 | username: string;
|
509 | devHubUsername?: string;
|
510 | orgId: string;
|
511 | loginUrl: string;
|
512 | instanceUrl: string;
|
513 | clientId: string;
|
514 | clientSecret: string;
|
515 | authcode: string;
|
516 | accessToken: string;
|
517 | refreshToken: string | undefined;
|
518 | tracksSource: boolean | undefined;
|
519 | userId: string;
|
520 | redirectUri: string;
|
521 | isDevHub?: boolean;
|
522 | isScratchOrg?: boolean;
|
523 | isExpired?: boolean | 'unknown';
|
524 | password?: string;
|
525 | constructor(id?: string, options?: {
|
526 | username: string;
|
527 | });
|
528 | /**
|
529 | * Add devhub username to properties.
|
530 | */
|
531 | createDevHubUsername(username: string): void;
|
532 | /**
|
533 | * Mark this org as a devhub.
|
534 | */
|
535 | makeDevHub(): void;
|
536 | /**
|
537 | * Returns a MockTestOrgData that represents a user created in the org.
|
538 | */
|
539 | createUser(user: string): MockTestOrgData;
|
540 | /**
|
541 | * Return mock user information based on this org.
|
542 | */
|
543 | getMockUserInfo(): MockUserInfo;
|
544 | /**
|
545 | * Return the auth config file contents.
|
546 | */
|
547 | getConfig(): Promise<AuthFields>;
|
548 | /**
|
549 | * Return the Connection for the org.
|
550 | */
|
551 | getConnection(): Promise<Connection>;
|
552 | }
|
553 | /**
|
554 | * Mock class for Salesforce Sandboxes.
|
555 | *
|
556 | * @example
|
557 | * ```
|
558 | * const testOrg = new MockTestSandboxData();
|
559 | * await $$.stubSandboxes(testOrg)
|
560 | * ```
|
561 | */
|
562 | export declare class MockTestSandboxData {
|
563 | id: string;
|
564 | sandboxOrgId: string;
|
565 | prodOrgUsername: string;
|
566 | sandboxName?: string;
|
567 | username?: string;
|
568 | constructor(id?: string, options?: Partial<{
|
569 | prodOrgUsername: string;
|
570 | name: string;
|
571 | username: string;
|
572 | }>);
|
573 | /**
|
574 | * Return the auth config file contents.
|
575 | */
|
576 | getConfig(): Promise<SandboxFields>;
|
577 | }
|
578 | export {};
|