UNPKG

@sprucelabs/spruce-cli

Version:

Command line interface for building Spruce skills.

403 lines • 16.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 () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const path_1 = __importDefault(require("path")); const globby_1 = __importDefault(require("@sprucelabs/globby")); const mercury_client_1 = require("@sprucelabs/mercury-client"); const schema_1 = require("@sprucelabs/schema"); const spruce_skill_utils_1 = require("@sprucelabs/spruce-skill-utils"); const spruce_templates_1 = require("@sprucelabs/spruce-templates"); const test_utils_1 = __importStar(require("@sprucelabs/test-utils")); const fs_extra_1 = __importDefault(require("fs-extra")); const uuid = __importStar(require("uuid")); const EventFaker_1 = __importDefault(require("../__tests__/support/EventFaker")); const ActionExecuter_1 = __importDefault(require("../features/ActionExecuter")); const ActionFactory_1 = __importDefault(require("../features/ActionFactory")); const EventStore_1 = __importDefault(require("../features/event/stores/EventStore")); const FeatureInstallerFactory_1 = __importDefault(require("../features/FeatureInstallerFactory")); const OnboardingStore_1 = __importDefault(require("../features/onboard/stores/OnboardingStore")); const SkillStore_1 = __importDefault(require("../features/skill/stores/SkillStore")); const GlobalEmitter_1 = __importDefault(require("../GlobalEmitter")); const SpyInterface_1 = __importDefault(require("../interfaces/SpyInterface")); const CommandService_1 = __importDefault(require("../services/CommandService")); const ImportService_1 = __importDefault(require("../services/ImportService")); const LintService_1 = __importDefault(require("../services/LintService")); const ServiceFactory_1 = __importDefault(require("../services/ServiceFactory")); const StoreFactory_1 = __importDefault(require("../stores/StoreFactory")); const WriterFactory_1 = __importDefault(require("../writers/WriterFactory")); const CommandFaker_1 = __importDefault(require("./CommandFaker")); const FeatureFixture_1 = __importDefault(require("./fixtures/FeatureFixture")); const MercuryFixture_1 = __importDefault(require("./fixtures/MercuryFixture")); const OrganizationFixture_1 = __importDefault(require("./fixtures/OrganizationFixture")); const PersonFixture_1 = __importDefault(require("./fixtures/PersonFixture")); const SkillFixture_1 = __importDefault(require("./fixtures/SkillFixture")); const ViewFixture_1 = __importDefault(require("./fixtures/ViewFixture")); const test_utility_1 = __importDefault(require("./utilities/test.utility")); class AbstractCliTest extends test_utils_1.default { static cliRoot = path_1.default.join(__dirname, '..'); static homeDir; static commandFaker; static _ui; static _emitter; static mercuryFixture; static personFixture; static organizationFixture; static skillFixture; static _featureInstaller; static viewFixture; static originalEnv; static _writers; static eventFaker; static async beforeAll() { await super.beforeAll(); await this.cleanTestDirsAndFiles(); LintService_1.default.disableLinting(); ServiceFactory_1.default.reset(); WriterFactory_1.default.reset(); ImportService_1.default.setCacheDir(spruce_skill_utils_1.diskUtil.createRandomTempDir()); ImportService_1.default.enableCaching(); this.eventFaker = new EventFaker_1.default(); process.env.ENABLE_INSTALL_ENTERTAINMENT = 'false'; this.originalEnv = { ...process.env }; } static async beforeEach() { await super.beforeEach(); delete this._writers; ActionFactory_1.default.clearActionOverrides(); //@ts-ignore process.env = { ...this.originalEnv }; test_utility_1.default.startLogTimer(); schema_1.SchemaRegistry.getInstance().forgetAllSchemas(); this.cwd = this.freshTmpDir(); this.homeDir = this.freshTmpDir(); spruce_skill_utils_1.AuthService.homeDir = this.homeDir; this._emitter = undefined; this._featureInstaller = undefined; OnboardingStore_1.default.overrideCwd(spruce_skill_utils_1.diskUtil.createRandomTempDir()); this.ui.reset(); this.ui.invocations = []; this.ui.setCursorPosition({ x: 0, y: 0 }); this.clearFixtures(); ImportService_1.default.clearCache(); SkillStore_1.default.clearCurrentSkill(); EventStore_1.default.clearCache(); CommandService_1.default.clearFakedResponses(); mercury_client_1.MercuryClientFactory.reset(); mercury_client_1.MercuryClientFactory.setIsTestMode(false); this.commandFaker = new CommandFaker_1.default(); } static async afterEach() { await super.afterEach(); await this.organizationFixture?.clearAllOrgs(); await this.mercuryFixture?.disconnectAll(); this.clearFixtures(); if (this._ui?.isWaitingForInput()) { throw new Error(`Terminal interface is waiting for input. Make sure you are invoking this.term.sendInput() as many times as needed.`); } if (spruce_skill_utils_1.diskUtil.doesDirExist(this.cwd) && test_utility_1.default.shouldClearCache()) { spruce_skill_utils_1.diskUtil.deleteDir(this.cwd); } if (spruce_skill_utils_1.diskUtil.doesDirExist(this.homeDir) && test_utility_1.default.shouldClearCache()) { spruce_skill_utils_1.diskUtil.deleteDir(this.homeDir); } if (test_utility_1.default.shouldCleanupAfterEach()) { FeatureFixture_1.default.deleteOldSkillDirs(); } } static async afterAll() { await super.afterAll(); if (test_utility_1.default.shouldCleanupAfterAll()) { FeatureFixture_1.default.deleteOldSkillDirs(); } } static async cleanTestDirsAndFiles() { const pattern = this.resolveTestPath('**/*.d.ts'); const matches = await (0, globby_1.default)(pattern); for (const match of matches) { spruce_skill_utils_1.diskUtil.deleteFile(match); } } static clearFixtures() { this._emitter = undefined; this.mercuryFixture = undefined; this.organizationFixture = undefined; this.personFixture = undefined; this.skillFixture = undefined; this.viewFixture = undefined; } static freshTmpDir() { const tmpDirectory = test_utility_1.default.resolveTestDir(uuid.v4()); fs_extra_1.default.ensureDirSync(tmpDirectory); return tmpDirectory; } static get ui() { if (!this._ui) { this._ui = new SpyInterface_1.default(); } return this._ui; } static get emitter() { if (!this._emitter) { this._emitter = GlobalEmitter_1.default.Emitter(); } return this._emitter; } static set emitter(emitter) { this._emitter = emitter; } static resolveTestPath(...pathAfterTestDirsAndFiles) { return path_1.default.join(this.cliRoot, '__tests__', 'testDirsAndFiles', ...pathAfterTestDirsAndFiles); } static async Cli(options) { return this.FeatureFixture(options).Cli({ cwd: this.cwd, homeDir: this.homeDir, ...(options ?? {}), }); } static async linkLocalPackages() { const fixture = this.FeatureFixture(); await fixture.linkLocalPackages(); } static Service(type, cwd) { const sf = this.ServiceFactory(); return sf.Service(cwd ?? this.cwd, type); } static ServiceFactory() { return new ServiceFactory_1.default(); } static FeatureFixture(options) { return new FeatureFixture_1.default({ cwd: this.cwd, serviceFactory: this.ServiceFactory(), ui: this.ui, apiClientFactory: this.getMercuryFixture().getApiClientFactory(), featureInstaller: this.featureInstaller, emitter: this.emitter, ...options, }); } static getMercuryFixture() { if (!this.mercuryFixture) { this.mercuryFixture = new MercuryFixture_1.default(this.cwd, this.ServiceFactory()); } return this.mercuryFixture; } static get people() { if (!this.personFixture) { this.personFixture = new PersonFixture_1.default(this.getMercuryFixture().getApiClientFactory()); } return this.personFixture; } static getViewFixture() { if (!this.viewFixture) { const viewWriter = this.writers.Writer('view', { fileDescriptions: [], }); this.viewFixture = new ViewFixture_1.default(this.cwd, viewWriter, this.Action('view', 'sync')); } return this.viewFixture; } static get writers() { if (!this._writers) { this._writers = this.WriterFactory(); } return this._writers; } static WriterFactory() { return new WriterFactory_1.default({ templates: spruce_templates_1.templates, ui: this.ui, settings: this.Service('settings'), }); } static async skipInstallSkillPrompts(execute) { const promise = execute?.(); await this.waitForInput(); await this.ui.sendInput('n'); await this.waitForInput(); await this.ui.sendInput(''); const results = await promise; return results; } static getOrganizationFixture() { if (!this.organizationFixture) { this.organizationFixture = new OrganizationFixture_1.default(this.people, this.StoreFactory()); } return this.organizationFixture; } static getSkillFixture() { if (!this.skillFixture) { this.skillFixture = new SkillFixture_1.default(this.people, this.StoreFactory(), this.getMercuryFixture().getApiClientFactory()); } return this.skillFixture; } static resolveHashSprucePath(...filePath) { return spruce_skill_utils_1.diskUtil.resolveHashSprucePath(this.cwd, ...filePath); } static get featureInstaller() { if (!this._featureInstaller) { const installer = this.FeatureInstaller(); this._featureInstaller = installer; } return this._featureInstaller; } static set featureInstaller(installer) { this._featureInstaller = installer; } static FeatureInstaller(options) { const serviceFactory = this.ServiceFactory(); const storeFactory = this.StoreFactory(options); const emitter = options?.emitter ?? this.emitter; const apiClientFactory = this.getMercuryFixture().getApiClientFactory(); const actionExecuter = this.ActionExecuter(); const installer = FeatureInstallerFactory_1.default.WithAllFeatures({ cwd: this.cwd, serviceFactory, storeFactory, ui: this.ui, emitter, apiClientFactory, actionExecuter, ...options, }); return installer; } static StoreFactory(options) { const serviceFactory = this.ServiceFactory(); return new StoreFactory_1.default({ cwd: this.cwd, serviceFactory, homeDir: this.homeDir, apiClientFactory: this.getMercuryFixture().getApiClientFactory(), emitter: this.emitter, ...options, }); } static Store(code, options) { return this.StoreFactory().Store(code, { cwd: this.cwd, ...options, }); } static async waitForInput() { return this.ui.waitForInput(); } static async assertIsFeatureInstalled(code) { const isInstalled = await this.featureInstaller.isInstalled(code); test_utils_1.assert.isTrue(isInstalled); } static async assertValidActionResponseFiles(results) { for (const file of results.files ?? []) { await this.assertFilePassesTypeChecks(file.path); } // await Promise.all( // (results.files ?? []).map((file) => { // const checker = this.Service('typeChecker') // return checker.check(file.path) // }) // ) } static async assertFilePassesTypeChecks(file) { const checker = this.Service('typeChecker'); await checker.check(file); } static async connectToApi(options) { return this.getMercuryFixture().connectToApi(options); } static async openInVsCode(options) { await this.Action('vscode', 'setup').execute({ all: true }); await this.Service('command').execute(`code ${options?.file ?? options?.dir ?? this.cwd}`); await this.wait(options?.timeout ?? 99999999); } static async openInFinder(options) { await this.Service('command').execute(`open ${options?.file ?? options?.dir ?? this.cwd}`); await this.wait(options?.timeout ?? 99999999); } static log(...args) { test_utility_1.default.log(...args); } static Action(featureCode, actionCode, options) { const executer = this.ActionExecuter({ shouldThrowOnListenerError: true, ...options, }).Action(featureCode, actionCode); return executer; } static ActionExecuter(options) { const serviceFactory = this.ServiceFactory(); const actionFactory = new ActionFactory_1.default({ writerFactory: this.writers, ui: this.ui, emitter: this.emitter, apiClientFactory: this.getMercuryFixture().getApiClientFactory(), cwd: this.cwd, serviceFactory, storeFactory: this.StoreFactory(), templates: spruce_templates_1.templates, optionOverrides: { 'sync.schemas': { shouldInstallMissingDependencies: true, }, ...options?.optionOverrides, }, }); const executer = new ActionExecuter_1.default({ ui: this.ui, emitter: this.emitter, actionFactory, featureInstallerFactory: () => { return this.featureInstaller; }, shouldAutoHandleDependencies: false, ...options, }); return executer; } static selectOptionBasedOnLabel(label) { const last = this.ui.getLastInvocation(); test_utils_1.assert.doesInclude(last.options.options.choices, { label, }); const match = last.options.options.choices.find((o) => o.label === label); void this.ui.sendInput(`${match.value}`); } } exports.default = AbstractCliTest; //# sourceMappingURL=AbstractCliTest.js.map