UNPKG

@salesforce/core

Version:

Core libraries to interact with SFDX projects, orgs, and APIs.

527 lines (526 loc) 16.5 kB
/// <reference types="node" /> import { EventEmitter } from 'events'; import * as sinonType from 'sinon'; import { AnyJson, JsonMap, Optional } from '@salesforce/ts-types'; import { ConfigContents } from './config/configStore'; import { Connection } from './org/connection'; import { Logger } from './logger'; import { SfError } from './sfError'; import { CometClient, CometSubscription, Message, StreamingExtension } from './status/streamingClient'; import { AuthFields, SandboxFields } from './org'; import { AliasGroup } from './config/aliasesConfig'; /** * Different parts of the system that are mocked out. They can be restored for * individual tests. Test's stubs should always go on the DEFAULT which is exposed * on the TestContext. */ export interface SandboxTypes { DEFAULT: sinon.SinonSandbox; CRYPTO: sinon.SinonSandbox; CONFIG: sinon.SinonSandbox; PROJECT: sinon.SinonSandbox; CONNECTION: sinon.SinonSandbox; FS: sinonType.SinonSandbox; ORGS: sinonType.SinonSandbox; } /** * Different hooks into {@link ConfigFile} used for testing instead of doing file IO. */ export interface ConfigStub { /** * readFn A function that controls all aspect of {@link ConfigFile.read}. For example, it won't set the contents * unless explicitly done. Only use this if you know what you are doing. Use retrieveContents * instead. */ readFn?: () => Promise<ConfigContents>; /** * A function that controls all aspects of {@link ConfigFile.write}. For example, it won't read the contents unless * explicitly done. Only use this if you know what you are doing. Use updateContents instead. */ writeFn?: (contents?: AnyJson) => Promise<void>; /** * The contents that are used with @{link ConfigFile.readSync} and @{link ConfigFile.read}. If retrieveContents is set, * it will use that instead of @{link ConfigFile.read} but NOT @{link ConfigFile.readSync}. This will also contain the * new config when @{link ConfigFile.write} or @{link ConfigFile.writeSync} is called. This will persist through config instances, * such as {@link Alias.update} and {@link Alias.fetch}. */ contents?: ConfigContents; /** * A function to conditionally read based on the config instance. The `this` value will be the config instance. */ retrieveContents?: () => Promise<JsonMap>; /** * A function to conditionally set based on the config instance. The `this` value will be the config instance. */ updateContents?: () => Promise<JsonMap>; } /** * Different configuration options when running before each */ export interface TestContext { /** * The default sandbox is cleared out before each test run. * * **See** [sinon sandbox]{@link http://sinonjs.org/releases/v1.17.7/sandbox/}. */ SANDBOX: sinonType.SinonSandbox; /** * An object of different sandboxes. Used when * needing to restore parts of the system for customized testing. */ SANDBOXES: SandboxTypes; /** * The test logger that is used when {@link Logger.child} is used anywhere. It uses memory logging. */ TEST_LOGGER: Logger; /** * id A unique id for the test run. */ id: string; /** * A function that returns unique strings. */ uniqid: () => string; /** * An object used in tests that interact with config files. */ configStubs: { [configName: string]: Optional<ConfigStub>; AliasesConfig?: ConfigStub; AuthInfoConfig?: ConfigStub; Config?: ConfigStub; SfProjectJson?: ConfigStub; TokensConfig?: ConfigStub; }; /** * An record of stubs created during instantaion. */ stubs: { configRead?: sinonType.SinonStub; configReadSync?: sinonType.SinonStub; configWriteSync?: sinonType.SinonStub; configWrite?: sinonType.SinonStub; configExists?: sinonType.SinonStub; configRemove?: sinonType.SinonStub; }; /** * A function used when resolving the local path. Calls localPathResolverSync by default. * * @param uid Unique id. */ localPathRetriever: (uid: string) => Promise<string>; /** * A function used when resolving the local path. * * @param uid Unique id. */ localPathRetrieverSync: (uid: string) => string; /** * A function used when resolving the global path. Calls globalPathResolverSync by default. * * @param uid Unique id. */ globalPathRetriever: (uid: string) => Promise<string>; /** * A function used when resolving the global path. * * @param uid Unique id. */ globalPathRetrieverSync: (uid: string) => string; /** * A function used for resolving paths. Calls localPathRetriever and globalPathRetriever. * * @param isGlobal `true` if the config is global. * @param uid user id. */ rootPathRetriever: (isGlobal: boolean, uid?: string) => Promise<string>; /** * A function used for resolving paths. Calls localPathRetrieverSync and globalPathRetrieverSync. * * @param isGlobal `true` if the config is global. * @param uid user id. */ rootPathRetrieverSync: (isGlobal: boolean, uid?: string) => string; /** * Used to mock http request to Salesforce. * * @param request An HttpRequest. * @param options Additional options. * * **See** {@link Connection.request} */ fakeConnectionRequest: (request: AnyJson, options?: AnyJson) => Promise<AnyJson>; /** * Gets a config stub contents by name. * * @param name The name of the config. * @param group If the config supports groups. */ getConfigStubContents(name: string, group?: string): ConfigContents; /** * Sets a config stub contents by name * * @param name The name of the config stub. * @param value The actual stub contents. The Mock data. */ setConfigStubContents(name: string, value: ConfigContents): void; /** * Set stubs for working in the context of a SfProject */ inProject(inProject: boolean): void; /** * Stub salesforce org authorizations. */ stubAuths(...orgs: MockTestOrgData[]): Promise<void>; /** * Stub salesforce sandbox authorizations. */ stubSandboxes(...orgs: MockTestSandboxData[]): Promise<void>; /** * Stub the aliases in the global aliases config file. */ stubAliases(aliases: Record<string, string>, group?: AliasGroup): void; /** * Stub contents in the config file. */ stubConfig(config: Record<string, string>): void; /** * Stub the tokens in the global token config file. */ stubTokens(tokens: Record<string, string>): void; } /** * A function to generate a unique id and return it in the context of a template, if supplied. * * A template is a string that can contain `${%s}` to be replaced with a unique id. * If the template contains the "%s" placeholder, it will be replaced with the unique id otherwise the id will be appended to the template. * * @param options an object with the following properties: * - template: a template string. * - length: the length of the unique id as presented in hexadecimal. */ export declare function uniqid(options?: { template?: string; length?: number; }): string; /** * Instantiate a @salesforce/core test context. This is automatically created by `const $$ = testSetup()` * but is useful if you don't want to have a global stub of @salesforce/core and you want to isolate it to * a single describe. * * **Note:** Call `stubContext` in your beforeEach to have clean stubs of @salesforce/core every test run. * * @example * ``` * const $$ = instantiateContext(); * * beforeEach(() => { * stubContext($$); * }); * * afterEach(() => { * restoreContext($$); * }); * ``` * @param sinon */ export declare const instantiateContext: (sinon?: any) => TestContext; /** * Stub a @salesforce/core test context. This will mock out logging to a file, config file reading and writing, * local and global path resolution, and http request using connection (soon)*. * * This is automatically stubbed in the global beforeEach created by * `const $$ = testSetup()` but is useful if you don't want to have a global stub of @salesforce/core and you * want to isolate it to a single describe. * * **Note:** Always call `restoreContext` in your afterEach. * * @example * ``` * const $$ = instantiateContext(); * * beforeEach(() => { * stubContext($$); * }); * * afterEach(() => { * restoreContext($$); * }); * ``` * @param testContext */ export declare const stubContext: (testContext: TestContext) => Record<string, sinonType.SinonStub>; /** * Restore a @salesforce/core test context. This is automatically stubbed in the global beforeEach created by * `const $$ = testSetup()` but is useful if you don't want to have a global stub of @salesforce/core and you * want to isolate it to a single describe. * * @example * ``` * const $$ = instantiateContext(); * * beforeEach(() => { * stubContext($$); * }); * * afterEach(() => { * restoreContext($$); * }); * ``` * @param testContext */ export declare const restoreContext: (testContext: TestContext) => void; /** * Use to mock out different pieces of sfdx-core to make testing easier. This will mock out * logging to a file, config file reading and writing, local and global path resolution, and * *http request using connection (soon)*. * * **Note:** The testSetup should be outside of the describe. If you need to stub per test, use * `instantiateContext`, `stubContext`, and `restoreContext`. * ``` * // In a mocha tests * import testSetup from '@salesforce/core/lib/testSetup'; * * const $$ = testSetup(); * * describe(() => { * it('test', () => { * // Stub out your own method * $$.SANDBOX.stub(MyClass.prototype, 'myMethod').returnsFake(() => {}); * * // Set the contents that is used when aliases are read. Same for all config files. * $$.stubAliases({ 'myTestAlias': 'user@company.com' }); * * // Will use the contents set above. * const username = (await StateAggregator.getInstance()).aliases.resolveUseranme('myTestAlias'); * expect(username).to.equal('user@company.com'); * }); * }); * ``` */ export declare const testSetup: (sinon?: any) => TestContext; /** * A pre-canned error for try/catch testing. * * **See** {@link shouldThrow} */ export declare const unexpectedResult: SfError; /** * Use for this testing pattern: * ``` * try { * await call() * assert.fail('this should never happen'); * } catch (e) { * ... * } * * Just do this * * try { * await shouldThrow(call()); // If this succeeds unexpectedResultError is thrown. * } catch(e) { * ... * } * ``` * * @param f The async function that is expected to throw. */ export declare function shouldThrow(f: Promise<unknown>, message?: string): Promise<never>; /** * Use for this testing pattern: * ``` * try { * call() * assert.fail('this should never happen'); * } catch (e) { * ... * } * * Just do this * * try { * shouldThrowSync(call); // If this succeeds unexpectedResultError is thrown. * } catch(e) { * ... * } * ``` * * @param f The function that is expected to throw. */ export declare function shouldThrowSync(f: () => unknown, message?: string): never; /** * A helper to determine if a subscription will use callback or errorback. * Enable errback to simulate a subscription failure. */ export declare enum StreamingMockSubscriptionCall { CALLBACK = 0, ERRORBACK = 1 } /** * Additional subscription options for the StreamingMock. */ export interface StreamingMockCometSubscriptionOptions { /** * Target URL. */ url: string; /** * Simple id to associate with this instance. */ id: string; /** * What is the subscription outcome a successful callback or an error?. */ subscriptionCall: StreamingMockSubscriptionCall; /** * If it's an error that states what that error should be. */ subscriptionErrbackError?: SfError; /** * A list of messages to playback for the client. One message per process tick. */ messagePlaylist?: Message[]; } /** * Simulates a comet subscription to a streaming channel. */ export declare class StreamingMockCometSubscription extends EventEmitter implements CometSubscription { static SUBSCRIPTION_COMPLETE: string; static SUBSCRIPTION_FAILED: string; private options; constructor(options: StreamingMockCometSubscriptionOptions); /** * Sets up a streaming subscription callback to occur after the setTimeout event loop phase. * * @param callback The function to invoke. */ callback(callback: () => void): void; /** * Sets up a streaming subscription errback to occur after the setTimeout event loop phase. * * @param callback The function to invoke. */ errback(callback: (error: Error) => void): void; } /** * Simulates a comet client. To the core streaming client this mocks the internal comet impl. * The uses setTimeout(0ms) event loop phase just so the client can simulate actual streaming without the response * latency. */ export declare class StreamingMockCometClient extends CometClient { private readonly options; /** * Constructor * * @param {StreamingMockCometSubscriptionOptions} options Extends the StreamingClient options. */ constructor(options: StreamingMockCometSubscriptionOptions); /** * Fake addExtension. Does nothing. */ addExtension(extension: StreamingExtension): void; /** * Fake disable. Does nothing. */ disable(label: string): void; /** * Fake handshake that invoke callback after the setTimeout event phase. * * @param callback The function to invoke. */ handshake(callback: () => void): void; /** * Fake setHeader. Does nothing, */ setHeader(name: string, value: string): void; /** * Fake subscription that completed after the setTimout event phase. * * @param channel The streaming channel. * @param callback The function to invoke after the subscription completes. */ subscribe(channel: string, callback: (message: Message) => void): CometSubscription; /** * Fake disconnect. Does Nothing. */ disconnect(): Promise<void>; } /** * Mock class for Salesforce Orgs. * * @example * const testOrg = new MockTestOrgData(); * await $$.stubAuths(testOrg) */ export declare class MockTestOrgData { testId: string; aliases?: string[]; configs?: string[]; username: string; devHubUsername?: string; orgId: string; loginUrl: string; instanceUrl: string; clientId: string; clientSecret: string; authcode: string; accessToken: string; refreshToken: string; tracksSource: boolean | undefined; userId: string; redirectUri: string; isDevHub?: boolean; isScratchOrg?: boolean; isExpired?: boolean | 'unknown'; constructor(id?: string, options?: { username: string; }); /** * Add devhub username to properties. */ createDevHubUsername(username: string): void; /** * Mark this org as a devhub. */ makeDevHub(): void; /** * Returns a MockTestOrgData that represents a user created in the org. */ createUser(user: string): MockTestOrgData; /** * Return mock user information based on this org. */ getMockUserInfo(): JsonMap; /** * Return the auth config file contents. */ getConfig(): Promise<AuthFields>; /** * Return the Connection for the org. */ getConnection(): Promise<Connection>; } /** * Mock class for Salesforce Sandboxes. * * @example * const testOrg = new MockTestSandboxData(); * await $$.stubSandboxes(testOrg) */ export declare class MockTestSandboxData { id: string; sandboxOrgId: string; prodOrgUsername: string; sandboxName?: string; username?: string; constructor(id?: string, options?: Partial<{ prodOrgUsername: string; name: string; username: string; }>); /** * Return the auth config file contents. */ getConfig(): Promise<SandboxFields>; }