UNPKG

@salesforce/core

Version:

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

905 lines 34.3 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.MockTestSandboxData = exports.MockTestOrgData = exports.StreamingMockCometClient = exports.StreamingMockCometSubscription = exports.StreamingMockSubscriptionCall = exports.unexpectedResult = exports.restoreContext = exports.stubContext = exports.instantiateContext = exports.TestContext = exports.SecureBuffer = exports.uniqid = void 0; exports.shouldThrow = shouldThrow; exports.shouldThrowSync = shouldThrowSync; /* * Copyright (c) 2020, salesforce.com, inc. * All rights reserved. * Licensed under the BSD 3-Clause license. * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ /* eslint-disable no-param-reassign */ // mutate ALL the THINGS! /* eslint-disable @typescript-eslint/ban-ts-comment */ /* eslint-disable class-methods-use-this */ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable @typescript-eslint/no-unsafe-call */ const fs = __importStar(require("node:fs")); const node_events_1 = require("node:events"); const node_os_1 = require("node:os"); const node_path_1 = require("node:path"); const ts_types_1 = require("@salesforce/ts-types"); const configAggregator_1 = require("./config/configAggregator"); const configFile_1 = require("./config/configFile"); const connection_1 = require("./org/connection"); const crypto_1 = require("./crypto/crypto"); const logger_1 = require("./logger/logger"); const messages_1 = require("./messages"); const sfError_1 = require("./sfError"); const sfProject_1 = require("./sfProject"); const aliasAccessorEntireFile = __importStar(require("./stateAggregator/accessors/aliasAccessor")); const streamingClient_1 = require("./status/streamingClient"); const stateAggregator_1 = require("./stateAggregator/stateAggregator"); const orgAccessor_1 = require("./stateAggregator/accessors/orgAccessor"); const org_1 = require("./org/org"); const user_1 = require("./org/user"); const sandboxAccessor_1 = require("./stateAggregator/accessors/sandboxAccessor"); const global_1 = require("./global"); const uniqid_1 = require("./util/uniqid"); Object.defineProperty(exports, "uniqid", { enumerable: true, get: function () { return uniqid_1.uniqid; } }); // stuff previously imported via /lib/foo and used in unit tests var secureBuffer_1 = require("./crypto/secureBuffer"); Object.defineProperty(exports, "SecureBuffer", { enumerable: true, get: function () { return secureBuffer_1.SecureBuffer; } }); /** * Instantiate a @salesforce/core test context. */ class TestContext { /** * The default sandbox is cleared out before each test run. * * **See** [sinon sandbox]{@link https://sinonjs.org/releases/v14/sandbox/}. */ SANDBOX; /** * An object of different sandboxes. Used when * needing to restore parts of the system for customized testing. */ SANDBOXES; /** * The test logger that is used when {@link Logger.child} is used anywhere. It uses memory logging. */ TEST_LOGGER; /** * id A unique id for the test run. */ id = (0, uniqid_1.uniqid)(); /** * An object used in tests that interact with config files. */ configStubs = {}; /** * A record of stubs created during instantiation. */ stubs = {}; constructor(options = {}) { const opts = { setup: true, ...options }; const sinon = requireSinon(opts.sinon); ; // Create a global sinon sandbox and a test logger instance for use within tests. this.SANDBOX = opts.sandbox ?? sinon.createSandbox(); this.SANDBOXES = { DEFAULT: this.SANDBOX, CONFIG: sinon.createSandbox(), PROJECT: sinon.createSandbox(), CRYPTO: sinon.createSandbox(), CONNECTION: sinon.createSandbox(), FS: sinon.createSandbox(), ORGS: sinon.createSandbox(), }; this.TEST_LOGGER = new logger_1.Logger({ name: 'SFDX_Core_Test_Logger', useMemoryLogger: true }); if (opts.setup) { this.setup(); } } /** * Generate unique string. */ uniqid() { return (0, uniqid_1.uniqid)(); } /** * A function used when resolving the local path. Calls localPathResolverSync by default. * * @param uid Unique id. */ async localPathRetriever(uid) { return Promise.resolve(getTestLocalPath(uid)); } /** * A function used when resolving the local path. * * @param uid Unique id. */ localPathRetrieverSync(uid) { return getTestLocalPath(uid); } /** * A function used when resolving the global path. Calls globalPathResolverSync by default. * * @param uid Unique id. */ async globalPathRetriever(uid) { return Promise.resolve(getTestGlobalPath(uid)); } /** * A function used when resolving the global path. * * @param uid Unique id. */ globalPathRetrieverSync(uid) { return getTestGlobalPath(uid); } /** * A function used for resolving paths. Calls localPathRetriever and globalPathRetriever. * * @param isGlobal `true` if the config is global. * @param uid user id. */ async rootPathRetriever(isGlobal, uid) { return retrieveRootPath(isGlobal, uid); } /** * A function used for resolving paths. Calls localPathRetrieverSync and globalPathRetrieverSync. * * @param isGlobal `true` if the config is global. * @param uid user id. */ rootPathRetrieverSync(isGlobal, uid) { return retrieveRootPathSync(isGlobal, uid); } /** * Used to mock http request to Salesforce. * * @param request An HttpRequest. * @param options Additional options. * * **See** {@link Connection.request} */ // eslint-disable-next-line @typescript-eslint/no-unused-vars async fakeConnectionRequest(request, options) { return defaultFakeConnectionRequest(); } /** * Gets a config stub contents by name. * * @param name The name of the config. * @param group If the config supports groups. */ getConfigStubContents(name, group) { const stub = this.configStubs[name]; if (stub?.contents) { if (group && stub.contents[group]) { return (0, ts_types_1.ensureJsonMap)(stub.contents[group]); } else { return stub.contents; } } return {}; } /** * 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, value) { if ((0, ts_types_1.ensureString)(name) && (0, ts_types_1.isJsonMap)(value)) { this.configStubs[name] = value; } } /** * Set stubs for working in the context of a SfProject */ inProject(inProject = true) { this.SANDBOXES.PROJECT.restore(); if (inProject) { this.SANDBOXES.PROJECT.stub(sfProject_1.SfProject, 'resolveProjectPath').callsFake(() => this.localPathRetriever(this.id)); this.SANDBOXES.PROJECT.stub(sfProject_1.SfProject, 'resolveProjectPathSync').callsFake(() => this.localPathRetrieverSync(this.id)); } else { this.SANDBOXES.PROJECT.stub(sfProject_1.SfProject, 'resolveProjectPath').rejects(new sfError_1.SfError('', 'InvalidProjectWorkspaceError')); this.SANDBOXES.PROJECT.stub(sfProject_1.SfProject, 'resolveProjectPathSync').throws(new sfError_1.SfError('', 'InvalidProjectWorkspaceError')); } } /** * Stub salesforce org authorizations. */ async stubAuths(...orgs) { const entries = await Promise.all(orgs.map(async (org) => [org.username, await org.getConfig()])); const orgMap = new Map(entries); // @ts-expect-error because private method this.SANDBOX.stub(orgAccessor_1.OrgAccessor.prototype, 'getAllFiles').resolves([...orgMap.keys()].map((o) => `${o}.json`)); this.SANDBOX.stub(orgAccessor_1.OrgAccessor.prototype, 'hasFile').callsFake((username) => Promise.resolve(orgMap.has(username))); const retrieveContents = async function () { const username = (0, node_path_1.basename)(this.path.replace('.json', '')); return Promise.resolve(orgMap.get(username) ?? {}); }; this.configStubs.AuthInfoConfig = { retrieveContents }; } /** * Stub salesforce user authorizations. * * @param users The users to stub. * 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. * The admin user is excluded from the users array. * */ stubUsers(users) { const mockUsers = Object.values(users).flatMap((orgUsers) => orgUsers.map((user) => { const userInfo = user.getMockUserInfo(); return { alias: userInfo.Alias ?? '', email: userInfo.Email ?? '', emailEncodingKey: userInfo.EmailEncodingKey ?? '', id: userInfo.Id ?? '', languageLocaleKey: userInfo.LanguageLocaleKey ?? '', lastName: userInfo.LastName ?? '', localeSidKey: userInfo.LocaleSidKey ?? '', profileId: userInfo.ProfileId ?? '', timeZoneSidKey: userInfo.TimeZoneSidKey ?? '', username: userInfo.Username ?? '', }; })); const userOrgsMap = new Map(Object.entries(users).map(([adminUsername, orgs]) => { const adminOrg = orgs.find((org) => org.username === adminUsername); return adminOrg ? [adminOrg.orgId, { usernames: orgs.filter((org) => org.username !== adminUsername) }] : [undefined, undefined]; })); this.SANDBOX.stub(user_1.User.prototype, 'retrieve').callsFake((username) => { const user = mockUsers.find((org) => org.username === username); if (!user) throw new sfError_1.SfError('User not found', 'UserNotFoundError'); return Promise.resolve(user); }); const retrieveContents = async function () { const orgId = (0, node_path_1.basename)(this.path.replace('.json', '')); return Promise.resolve(userOrgsMap.get(orgId) ?? {}); }; this.configStubs.OrgUsersConfig = { retrieveContents }; } /** * Stub salesforce sandbox authorizations. */ async stubSandboxes(...sandboxes) { const entries = (await Promise.all(sandboxes.map(async (sandbox) => [sandbox.username, await sandbox.getConfig()]))); const sandboxMap = new Map(entries); // @ts-expect-error because private method this.SANDBOX.stub(sandboxAccessor_1.SandboxAccessor.prototype, 'getAllFiles').resolves([...sandboxMap.keys()].map((o) => `${o}.sandbox.json`)); const retrieveContents = async function () { const username = (0, node_path_1.basename)(this.path.replace('.sandbox.json', '')); return Promise.resolve(sandboxMap.get(username) ?? {}); }; this.configStubs.SandboxOrgConfig = { retrieveContents }; } /** * Stub the aliases in the global aliases config file. */ stubAliases(aliases, group = aliasAccessorEntireFile.DEFAULT_GROUP) { // we don't really "stub" these since they don't use configFile. // write the fileContents to location fs.mkdirSync((0, node_path_1.dirname)(getAliasFileLocation()), { recursive: true }); fs.writeFileSync(getAliasFileLocation(), JSON.stringify({ [group]: aliases })); } /** * Stub contents in the config file. */ async stubConfig(config) { this.configStubs.Config = { contents: config }; // configAggregator may have already loaded an instance. We're not sure why this happens. // This seems to solve the problem by forcing a load of the new stubbed config. await configAggregator_1.ConfigAggregator.create(); } restore() { (0, exports.restoreContext)(this); } init() { this.stubs = (0, exports.stubContext)(this); } /** * Add beforeEach and afterEach hooks to init the stubs and restore them. * This is called automatically when the class is instantiated unless the setup option is set to false. */ setup() { beforeEach(() => { this.init(); }); afterEach(() => { this.restore(); }); } } exports.TestContext = TestContext; const requireSinon = (sinon) => { if (sinon) return sinon; try { // eslint-disable-next-line @typescript-eslint/no-var-requires, import/no-extraneous-dependencies const newSinon = require('sinon'); return newSinon; } catch (e) { throw new Error('The package sinon was not found. Add it to your package.json and pass it in to new TestContext({sinon})'); } }; function getTestLocalPath(uid) { return (0, node_path_1.join)((0, node_os_1.tmpdir)(), uid, 'sfdx_core', 'local'); } function getTestGlobalPath(uid) { return (0, node_path_1.join)((0, node_os_1.tmpdir)(), uid, 'sfdx_core', 'global'); } function retrieveRootPathSync(isGlobal, uid = (0, uniqid_1.uniqid)()) { return isGlobal ? getTestGlobalPath(uid) : getTestLocalPath(uid); } // eslint-disable-next-line @typescript-eslint/require-await async function retrieveRootPath(isGlobal, uid = (0, uniqid_1.uniqid)()) { return retrieveRootPathSync(isGlobal, uid); } function defaultFakeConnectionRequest() { return Promise.resolve((0, ts_types_1.ensureAnyJson)({ records: [] })); } /** * 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(() => { * $$.init() * }); * * afterEach(() => { * $$.restore(); * }); * ``` * @param sinon */ const instantiateContext = (sinon) => new TestContext({ sinon, setup: false }); exports.instantiateContext = instantiateContext; /** * 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(() => { * $$.init() * }); * * afterEach(() => { * $$.restore(); * }); * ``` * @param testContext */ const stubContext = (testContext) => { // Turn off the interoperability feature so that we don't have to mock // the old .sfdx config files global_1.Global.SFDX_INTEROPERABILITY = false; const stubs = {}; // Most core files create a child logger so stub this to return our test logger. testContext.SANDBOX.stub(logger_1.Logger, 'child').resolves(testContext.TEST_LOGGER); testContext.SANDBOX.stub(logger_1.Logger, 'childFromRoot').returns(testContext.TEST_LOGGER); testContext.inProject(true); testContext.SANDBOXES.CONFIG.stub(configFile_1.ConfigFile, 'resolveRootFolder').callsFake((isGlobal) => testContext.rootPathRetriever(isGlobal, testContext.id)); testContext.SANDBOXES.CONFIG.stub(configFile_1.ConfigFile, 'resolveRootFolderSync').callsFake((isGlobal) => testContext.rootPathRetrieverSync(isGlobal, testContext.id)); // @ts-expect-error using private method testContext.SANDBOXES.PROJECT.stub(sfProject_1.SfProjectJson.prototype, 'doesPackageExist').callsFake(() => true); const initStubForRead = (configFile) => { testContext.configStubs[configFile.constructor.name] ??= {}; const stub = testContext.configStubs[configFile.constructor.name] ?? {}; // init calls read calls getPath which sets the path on the config file the first time. // Since read is now stubbed, make sure to call getPath to initialize it. configFile.getPath(); // @ts-expect-error: set this to true to avoid an infinite loop in tests when reading config files. configFile.hasRead = true; return stub; }; const readSync = function (newContents) { const stub = initStubForRead(this); this.setContentsFromFileContents(newContents ?? stub.contents ?? {}); return this.getContents(); }; const read = async function () { const stub = initStubForRead(this); if (stub.readFn) { return stub.readFn.call(this); } if (stub.retrieveContents) { return readSync.call(this, await stub.retrieveContents.call(this)); } else { return readSync.call(this); } }; // Mock out all config file IO for all tests. They can restore individually if they need original functionality. stubs.configRead = testContext.SANDBOXES.CONFIG.stub(configFile_1.ConfigFile.prototype, 'read').callsFake(read); // @ts-expect-error: muting exact type match for stub readSync stubs.configReadSync = testContext.SANDBOXES.CONFIG.stub(configFile_1.ConfigFile.prototype, 'readSync').callsFake(readSync); const writeSync = function () { testContext.configStubs[this.constructor.name] ??= {}; const stub = testContext.configStubs[this.constructor.name] ?? {}; stub.contents = this.toObject(); }; const write = async function () { testContext.configStubs[this.constructor.name] ??= {}; const stub = testContext.configStubs[this.constructor.name] ?? {}; if (stub.writeFn) { return stub.writeFn.call(this); } writeSync.call(this); }; stubs.configWriteSync = testContext.SANDBOXES.CONFIG.stub(configFile_1.ConfigFile.prototype, 'writeSync').callsFake(writeSync); stubs.configWrite = testContext.SANDBOXES.CONFIG.stub(configFile_1.ConfigFile.prototype, 'write').callsFake(write); // @ts-expect-error: getKeyChain is private testContext.SANDBOXES.CRYPTO.stub(crypto_1.Crypto.prototype, 'getKeyChain').callsFake(() => // @ts-expect-error: not the full type Promise.resolve({ setPassword: () => Promise.resolve(), getPassword: (data, cb) => cb(undefined, '12345678901234567890123456789012'), })); testContext.SANDBOXES.CONNECTION.stub(connection_1.Connection.prototype, 'isResolvable').resolves(true); // @ts-expect-error: just enough of an httpResponse for testing testContext.SANDBOXES.CONNECTION.stub(connection_1.Connection.prototype, 'request').callsFake(function (request, options) { if (request === `${this.instanceUrl}/services/data`) { return Promise.resolve([{ version: '42.0' }]); } return testContext.fakeConnectionRequest.call(this, request, options); }); testContext.SANDBOX.stub(aliasAccessorEntireFile, 'getFileLocation').returns(getAliasFileLocation()); stubs.configExists = testContext.SANDBOXES.ORGS.stub(orgAccessor_1.OrgAccessor.prototype, 'exists').callsFake(async function (username) { // @ts-expect-error because private member if ([...this.contents.keys()].includes(username)) return Promise.resolve(true); else return Promise.resolve(false); }); stubs.configRemove = testContext.SANDBOXES.ORGS.stub(orgAccessor_1.OrgAccessor.prototype, 'remove').callsFake(async function (username) { // @ts-expect-error because private member if ([...this.contents.keys()].includes(username)) return Promise.resolve(); else return Promise.resolve(); }); // Always start with the default and tests beforeEach or it methods can override it. testContext.fakeConnectionRequest = defaultFakeConnectionRequest; testContext.stubs = stubs; return stubs; }; exports.stubContext = stubContext; const getAliasFileLocation = () => (0, node_path_1.join)((0, node_os_1.tmpdir)(), global_1.Global.SFDX_STATE_FOLDER, aliasAccessorEntireFile.FILENAME); /** * 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(() => { * $$.init() * }); * * afterEach(() => { * $$.restore(); * }); * ``` * @param testContext */ const restoreContext = (testContext) => { // Restore the default value for this setting on restore. global_1.Global.SFDX_INTEROPERABILITY = true; testContext.SANDBOX.restore(); // eslint-disable-next-line @typescript-eslint/no-unsafe-return Object.values(testContext.SANDBOXES).forEach((theSandbox) => theSandbox.restore()); testContext.configStubs = {}; // Give each test run a clean StateAggregator stateAggregator_1.StateAggregator.clearInstance(); sfProject_1.SfProject.clearInstances(); // Allow each test to have their own config aggregator // @ts-ignore clear for testing. delete configAggregator_1.ConfigAggregator.instance; }; exports.restoreContext = restoreContext; /** * A pre-canned error for try/catch testing. * * **See** {@link shouldThrow} */ exports.unexpectedResult = new sfError_1.SfError('This code was expected to fail', 'UnexpectedResult'); /** * 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. */ async function shouldThrow(f, message) { await f; if (message) { throw new sfError_1.SfError(message, 'UnexpectedResult'); } else { throw exports.unexpectedResult; } } /** * 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. */ function shouldThrowSync(f, message) { f(); if (message) { throw new sfError_1.SfError(message, 'UnexpectedResult'); } else { throw exports.unexpectedResult; } } /** * A helper to determine if a subscription will use callback or errorback. * Enable errback to simulate a subscription failure. */ var StreamingMockSubscriptionCall; (function (StreamingMockSubscriptionCall) { StreamingMockSubscriptionCall[StreamingMockSubscriptionCall["CALLBACK"] = 0] = "CALLBACK"; StreamingMockSubscriptionCall[StreamingMockSubscriptionCall["ERRORBACK"] = 1] = "ERRORBACK"; })(StreamingMockSubscriptionCall || (exports.StreamingMockSubscriptionCall = StreamingMockSubscriptionCall = {})); /** * Simulates a comet subscription to a streaming channel. */ class StreamingMockCometSubscription extends node_events_1.EventEmitter { static SUBSCRIPTION_COMPLETE = 'subscriptionComplete'; static SUBSCRIPTION_FAILED = 'subscriptionFailed'; options; constructor(options) { super(); this.options = options; } /** * Sets up a streaming subscription callback to occur after the setTimeout event loop phase. * * @param callback The function to invoke. */ callback(callback) { if (this.options.subscriptionCall === StreamingMockSubscriptionCall.CALLBACK) { setTimeout(() => { callback(); super.emit(StreamingMockCometSubscription.SUBSCRIPTION_COMPLETE); }, 0); } } /** * Sets up a streaming subscription errback to occur after the setTimeout event loop phase. * * @param callback The function to invoke. */ errback(callback) { if (this.options.subscriptionCall === StreamingMockSubscriptionCall.ERRORBACK) { const error = this.options.subscriptionErrbackError; if (!error) return; setTimeout(() => { callback(error); super.emit(StreamingMockCometSubscription.SUBSCRIPTION_FAILED); }, 0); } } } exports.StreamingMockCometSubscription = StreamingMockCometSubscription; /** * 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. */ class StreamingMockCometClient extends streamingClient_1.CometClient { options; /** * Constructor * * @param {StreamingMockCometSubscriptionOptions} options Extends the StreamingClient options. */ constructor(options) { super(); this.options = options; if (!this.options.messagePlaylist) { this.options.messagePlaylist = [{ id: this.options.id }]; } } /** * Fake addExtension. Does nothing. */ // eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/no-empty-function addExtension(extension) { } /** * Fake disable. Does nothing. */ // eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/no-empty-function disable(label) { } /** * Fake handshake that invoke callback after the setTimeout event phase. * * @param callback The function to invoke. */ handshake(callback) { setTimeout(() => { callback(); }, 0); } /** * Fake setHeader. Does nothing, */ // eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/no-empty-function setHeader(name, value) { } /** * 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, callback) { const subscription = new StreamingMockCometSubscription(this.options); subscription.on('subscriptionComplete', () => { if (!this.options.messagePlaylist) return; Object.values(this.options.messagePlaylist).forEach((message) => { setTimeout(() => { callback(message); }, 0); }); }); return subscription; } /** * Fake disconnect. Does Nothing. */ disconnect() { return Promise.resolve(); } } exports.StreamingMockCometClient = StreamingMockCometClient; /** * Mock class for Salesforce Orgs. * * @example * ``` * const testOrg = new MockTestOrgData(); * await $$.stubAuths(testOrg) * ``` */ class MockTestOrgData { testId; aliases; configs; username; devHubUsername; orgId; loginUrl; instanceUrl; clientId; clientSecret; authcode; accessToken; refreshToken; tracksSource; userId; redirectUri; isDevHub; isScratchOrg; isExpired; password; namespacePrefix; constructor(id = (0, uniqid_1.uniqid)(), options) { this.testId = id; this.userId = `user_id_${this.testId}`; this.orgId = `${this.testId}`; this.username = options?.username ?? `admin_${this.testId}@gb.org`; this.loginUrl = `https://login.${this.testId}.salesforce.com`; this.instanceUrl = `https://instance.${this.testId}.salesforce.com`; this.clientId = `${this.testId}/client_id`; this.clientSecret = `${this.testId}/client_secret`; this.authcode = `${this.testId}/authcode`; this.accessToken = `${this.testId}/accessToken`; this.refreshToken = `${this.testId}/refreshToken`; this.redirectUri = 'http://localhost:1717/OauthRedirect'; this.namespacePrefix = `acme_${this.testId}`; } /** * Add devhub username to properties. */ createDevHubUsername(username) { this.devHubUsername = username; } /** * Mark this org as a devhub. */ makeDevHub() { this.isDevHub = true; } /** * Returns a MockTestOrgData that represents a user created in the org. */ createUser(user) { const userMock = new MockTestOrgData(); userMock.username = user; userMock.aliases = this.aliases; userMock.configs = this.configs; userMock.devHubUsername = this.devHubUsername; userMock.orgId = this.orgId; userMock.loginUrl = this.loginUrl; userMock.instanceUrl = this.instanceUrl; userMock.clientId = this.clientId; userMock.clientSecret = this.clientSecret; userMock.redirectUri = this.redirectUri; userMock.isDevHub = this.isDevHub; userMock.isScratchOrg = this.isScratchOrg; userMock.isExpired = this.isExpired; userMock.password = this.password; userMock.accessToken = this.accessToken; return userMock; } /** * Return mock user information based on this org. */ getMockUserInfo() { return { Id: this.userId, Username: this.username, LastName: `user_lastname_${this.testId}`, Alias: this.aliases ? this.aliases[0] : 'user_alias_blah', Configs: this.configs, TimeZoneSidKey: `user_timezonesidkey_${this.testId}`, LocaleSidKey: `user_localesidkey_${this.testId}`, EmailEncodingKey: `user_emailencodingkey_${this.testId}`, ProfileId: `user_profileid_${this.testId}`, LanguageLocaleKey: `user_languagelocalekey_${this.testId}`, Email: `user_email@${this.testId}.com`, }; } /** * Return the auth config file contents. */ async getConfig() { const crypto = await crypto_1.Crypto.create(); const config = {}; config.orgId = this.orgId; config.clientId = this.clientId; const accessToken = crypto.encrypt(this.accessToken); if (accessToken) { config.accessToken = accessToken; } if (this.refreshToken) { config.refreshToken = crypto.encrypt(this.refreshToken); } config.instanceUrl = this.instanceUrl; config.loginUrl = this.loginUrl; config.username = this.username; config.createdOrgInstance = 'CS1'; config.created = '1519163543003'; config.userId = this.userId; config.tracksSource = this.tracksSource; if (this.devHubUsername) { config.devHubUsername = this.devHubUsername; } config.isDevHub = this.isDevHub; if (this.password) { config.password = crypto.encrypt(this.password); } // remove "undefined" properties that don't exist in actual files return Object.fromEntries(Object.entries(config).filter(([, v]) => v !== undefined)); } /** * Return the Connection for the org. */ async getConnection() { return (await org_1.Org.create({ aliasOrUsername: this.username })).getConnection(); } } exports.MockTestOrgData = MockTestOrgData; /** * Mock class for Salesforce Sandboxes. * * @example * ``` * const testOrg = new MockTestSandboxData(); * await $$.stubSandboxes(testOrg) * ``` */ class MockTestSandboxData { id; sandboxOrgId; prodOrgUsername; sandboxName; username; constructor(id = (0, uniqid_1.uniqid)(), options) { this.id = id; this.sandboxOrgId = id; this.prodOrgUsername = options?.prodOrgUsername ?? `admin_${id}@gb.org`; this.sandboxName = options?.name ?? `sandbox_${id}`; this.username = options?.username ?? `${this.prodOrgUsername}.sandbox`; } /** * Return the auth config file contents. */ // eslint-disable-next-line @typescript-eslint/require-await async getConfig() { return { sandboxOrgId: this.sandboxOrgId, prodOrgUsername: this.prodOrgUsername, sandboxName: this.sandboxName, sandboxUsername: this.username, }; } } exports.MockTestSandboxData = MockTestSandboxData; //# sourceMappingURL=testSetup.js.map