UNPKG

@sprucelabs/spruce-cli

Version:

Command line interface for building Spruce skills.

340 lines (339 loc) • 18.8 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; 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 spruce_skill_utils_1 = require("@sprucelabs/spruce-skill-utils"); const spruce_skill_utils_2 = require("@sprucelabs/spruce-skill-utils"); const spruce_skill_utils_3 = require("@sprucelabs/spruce-skill-utils"); const test_utils_1 = require("@sprucelabs/test-utils"); const test_utils_2 = require("@sprucelabs/test-utils"); const SchemaStore_1 = require("../../../features/schema/stores/SchemaStore"); const AbstractSchemaTest_1 = __importDefault(require("../../../tests/AbstractSchemaTest")); const test_utility_1 = __importDefault(require("../../../tests/utilities/test.utility")); //TODO rethink how to check for count of files and results or where it may make sense to move this test const TYPE_FILE_COUNT = 2; // (only fieldMap and field.types... schema.types checked by +1 in tests) const SYNC_FILE_COUNT = Object.keys(SchemaStore_1.coreSchemas).length + TYPE_FILE_COUNT; const MOCK_CORE_SYNC_FILE_COUNT = 4 + TYPE_FILE_COUNT; class KeepsSchemasInSyncTest extends AbstractSchemaTest_1.default { static coreSyncOptions = { shouldGenerateCoreSchemaTypes: true, }; static async hasSyncSchemaAction() { await this.Cli(); test_utils_1.assert.isFunction(this.Action('schema', 'sync').execute); } static async failsBecauseSchemasIsNotInstalled() { await this.Cli(); const err = await test_utils_1.assert.doesThrowAsync(() => this.Action('schema', 'sync').execute({})); test_utils_2.errorAssert.assertError(err, 'FEATURE_NOT_INSTALLED'); } static async syncingWithNoSchemasSucceeds() { await this.installSchemaFeature('schemas'); const results = await this.Action('schema', 'sync').execute({}); test_utils_1.assert.isFalsy(results.errors); //TODO determine better way to count files test_utility_1.default.assertCountsByAction(results.files, { updated: 0, generated: SYNC_FILE_COUNT, skipped: 0, }); } static async syncingWithNoSchemasAndFetchCoreSchemasFalseSucceeds() { await this.installSchemaFeature('schemas'); const results = await this.Action('schema', 'sync').execute({ shouldFetchCoreSchemas: false, }); test_utils_1.assert.isFalsy(results.errors); test_utility_1.default.assertCountsByAction(results.files, { updated: 0, generated: TYPE_FILE_COUNT, skipped: 0, }); } static async syncingCleansUpTempFiles() { await this.installSchemaFeature('schemas'); const results = await this.Action('schema', 'sync').execute({}); test_utils_1.assert.isFalsy(results.errors); const tmpFile = this.resolveHashSprucePath('schemas', 'tmp', 'valueType.tmp.ts'); test_utils_1.assert.isFalse(spruce_skill_utils_2.diskUtil.doesFileExist(tmpFile)); } static async syncingCoreSchemasGeneratesTypesFile() { await this.installSchemaFeature('schemas'); await this.copyMockCoreSchemas(); const results = await this.Action('schema', 'sync').execute(this.coreSyncOptions); test_utils_1.assert.isUndefined(results.errors); test_utils_1.assert.isTruthy(results.files); test_utils_1.assert.isLength(results.files, MOCK_CORE_SYNC_FILE_COUNT); test_utility_1.default.assertCountsByAction(results.files, { generated: MOCK_CORE_SYNC_FILE_COUNT, skipped: 0, updated: 0, }); test_utils_1.assert.isTrue(spruce_skill_utils_2.diskUtil.doesFileExist(this.coreSchemaTypesFile)); await this.assertTypesFileGeneratesArraySelect(this.coreSchemaTypesFile); } static async syncSchemasTwiceSkipsFiles() { await this.syncSchemas('schemas', this.coreSyncOptions); const results = await this.Action('schema', 'sync').execute(this.coreSyncOptions); test_utils_1.assert.isFalsy(results.errors); test_utils_1.assert.isAbove(results.files?.length, 0); test_utility_1.default.assertCountsByAction(results.files, { generated: 0, skipped: results.files?.length ?? 0, updated: 0, }); } static async makeSureSchemaTypesAreVersioned() { await this.installSchemaFeature('schemas'); await this.copyMockCoreSchemas(); const results = await this.Action('schema', 'sync').execute(this.coreSyncOptions); test_utils_1.assert.isFalsy(results.errors); const typesContents = spruce_skill_utils_2.diskUtil.readFile(this.coreSchemaTypesFile); test_utils_1.assert.doesInclude(typesContents, new RegExp(`SpruceSchemas.${spruce_skill_utils_3.CORE_NAMESPACE}.${spruce_skill_utils_3.CORE_SCHEMA_VERSION.constValue}(.*?)interface Person`, 'gis')); } static async shouldGenerateCoreSchemaTypesGeneratesValidFiles() { await this.installSchemaFeature('schemas'); await this.copyMockCoreSchemas(); const results = await this.Action('schema', 'sync').execute(this.coreSyncOptions); test_utils_1.assert.isFalsy(results.errors); test_utils_1.assert.isTruthy(results.files); await this.assertValidActionResponseFiles(results); const typesContents = spruce_skill_utils_2.diskUtil.readFile(this.coreSchemaTypesFile); test_utils_1.assert.doesNotInclude(typesContents, /@sprucelabs\/spruce-core-schemas/gi); test_utils_1.assert.doesInclude(typesContents, new RegExp(`export declare namespace ${spruce_skill_utils_3.DEFAULT_GLOBAL_SCHEMA_NAMESPACE}.${spruce_skill_utils_3.CORE_NAMESPACE}.${spruce_skill_utils_3.CORE_SCHEMA_VERSION.constValue}`, 'gis')); const orgSchema = test_utility_1.default.assertFileByNameInGeneratedFiles('organization.schema.ts', results.files); const locationSchemaContents = spruce_skill_utils_2.diskUtil.readFile(orgSchema); test_utils_1.assert.doesInclude(locationSchemaContents, 'SchemaRegistry'); } static async generateCoreSchemaInCoreSchemasModule() { await this.installSchemaFeature('schemas'); const pkg = this.Service('pkg'); pkg.set({ path: 'name', value: '@sprucelabs/spruce-core-schemas' }); await this.copyMockCoreSchemas(); const results = await this.Action('schema', 'sync').execute({}); test_utils_1.assert.isFalsy(results.errors); test_utils_1.assert.isTruthy(results.files); const typesContents = spruce_skill_utils_2.diskUtil.readFile(this.coreSchemaTypesFile); test_utils_1.assert.doesNotInclude(typesContents, /@sprucelabs\/spruce-core-schemas/gi); test_utils_1.assert.doesInclude(typesContents, new RegExp(`export declare namespace ${spruce_skill_utils_3.DEFAULT_GLOBAL_SCHEMA_NAMESPACE}.${spruce_skill_utils_3.CORE_NAMESPACE}.${spruce_skill_utils_3.CORE_SCHEMA_VERSION.constValue}`, 'gis')); const orgSchema = test_utility_1.default.assertFileByNameInGeneratedFiles('organization.schema.ts', results.files); const locationSchemaContents = spruce_skill_utils_2.diskUtil.readFile(orgSchema); test_utils_1.assert.doesInclude(locationSchemaContents, 'SchemaRegistry'); } static async canHandleHyphenSchemaIds() { await this.syncSchemas('schemas'); const createResponse = await this.Action('schema', 'create').execute({ nameReadable: 'Test schema', nameCamel: 'testSchema', }); test_utils_1.assert.isFalsy(createResponse.errors); const builderPath = test_utility_1.default.assertFileByNameInGeneratedFiles('testSchema.builder.ts', createResponse.files); const contents = spruce_skill_utils_2.diskUtil .readFile(builderPath) .replace("id: 'testSchema'", "id: 'test-schema'"); spruce_skill_utils_2.diskUtil.writeFile(builderPath, contents); const syncResults = await this.Action('schema', 'sync').execute({}); const testSchema = test_utility_1.default.assertFileByNameInGeneratedFiles('test-schema.schema.ts', syncResults.files); const testSchemaContents = spruce_skill_utils_2.diskUtil.readFile(testSchema); test_utils_1.assert.doesInclude(testSchemaContents, 'SchemaRegistry'); await this.assertValidActionResponseFiles(syncResults); } static async coreSchemasPullFromCoreSchemasModuleDuringNormalGeneration() { await this.syncSchemas('schemas'); const createResponse = await this.Action('schema', 'create').execute({ nameReadable: 'Test schema', nameCamel: 'testSchema', }); for (const schema of Object.values(SchemaStore_1.coreSchemas)) { const id = schema.id; const match = test_utility_1.default.assertFileByNameInGeneratedFiles(`${id}.schema.ts`, createResponse.files); const contents = spruce_skill_utils_2.diskUtil.readFile(match); test_utils_1.assert.doesInclude(contents, `export { ${id}Schema as default } from '@sprucelabs/spruce-core-schemas'`); } } static async schemasStayInSyncWhenBuildersAreDeleted() { await this.syncSchemas('schemas'); const version = spruce_skill_utils_1.versionUtil.generateVersion(); const typeChecker = this.Service('typeChecker'); const createAction = this.Action('schema', 'create'); const matcher = new RegExp(`SpruceSchemas.TestingSchemas.${version.constValue}(.*?)interface TestSchema`, 'gis'); test_utils_1.assert.isTrue(spruce_skill_utils_2.diskUtil.doesFileExist(path_1.default.dirname(this.schemaTypesFile))); const createResponse = await createAction.execute({ nameReadable: 'Test schema', nameCamel: 'testSchema', }); const builderFile = test_utility_1.default.assertFileByNameInGeneratedFiles(/testSchema\.builder/, createResponse.files); // make sure builder is versioned test_utils_1.assert.doesInclude(builderFile, version.dirValue); const schemaFile = test_utility_1.default.assertFileByNameInGeneratedFiles(/testSchema\.schema/, createResponse.files); // make sure this path is versioned test_utils_1.assert.doesInclude(schemaFile, version.dirValue); test_utils_1.assert.doesInclude(schemaFile, '/testingSchemas/'); // schema types should be good await typeChecker.check(this.schemaTypesFile); // the types should include our test schema let typesContents = spruce_skill_utils_2.diskUtil.readFile(this.schemaTypesFile); test_utils_1.assert.doesInclude(typesContents, matcher); // the schema file should exist test_utils_1.assert.isTrue(spruce_skill_utils_2.diskUtil.doesFileExist(schemaFile)); // DELETE builder and make sure we are cleaned up spruce_skill_utils_2.diskUtil.deleteFile(builderFile); // this should cleanup types and schema files await this.Action('schema', 'sync').execute({}); test_utils_1.assert.isTrue(spruce_skill_utils_2.diskUtil.doesFileExist(this.schemaTypesFile)); // and the schema should have been deleted test_utils_1.assert.isFalse(spruce_skill_utils_2.diskUtil.doesFileExist(schemaFile)); // and the namespace folder should have been deleted const namespaceFolder = this.resolveHashSprucePath('schemas', 'testingSChemas'); test_utils_1.assert.isFalse(spruce_skill_utils_2.diskUtil.doesDirExist(namespaceFolder)); } static async canSyncSchemasWhenOnlyNodeModuleIsInstalledAfterDecliningToInstallSkill() { await this.FeatureFixture().installCachedFeatures('schemasInNodeModule'); const promise = this.Action('schema', 'sync').execute({}); await this.waitForInput(); await this.ui.sendInput('n'); await this.waitForInput(); await this.ui.sendInput(''); const results = await promise; test_utils_1.assert.isFalsy(results.errors); await this.assertValidActionResponseFiles(results); } static async syncsExpectedFields() { await this.syncSchemas('schemas'); const schemasDir = this.resolvePath('src', 'schemas'); await spruce_skill_utils_2.diskUtil.copyDir(this.resolveTestPath('test_builders'), schemasDir); const results = await this.Action('schema', 'sync').execute({}); const schema = await this.importSchema(results, 'schemaTwo.schema.ts'); test_utils_1.assert.isUndefined(schema.fields.phone.minArrayLength); test_utils_1.assert.isEqual(schema.fields.favoriteColors.minArrayLength, 3); test_utils_1.assert.isEqual(schema.fields.permissions.minArrayLength, 0); } static async canChangeSkillNamespace() { await this.syncSchemas('schemas'); await this.Action('schema', 'create').execute({ nameReadable: 'Test schema', nameCamel: 'testSchema', }); const beforeFolder = this.resolveHashSprucePath('schemas', 'testingSchemas'); const afterFolder = this.resolveHashSprucePath('schemas', 'newNamespace'); test_utils_1.assert.isTrue(spruce_skill_utils_2.diskUtil.doesFileExist(beforeFolder)); test_utils_1.assert.isFalse(spruce_skill_utils_2.diskUtil.doesFileExist(afterFolder)); await this.Store('skill').setCurrentSkillsNamespace('new-namespace'); await this.Action('schema', 'sync').execute({}); test_utils_1.assert.isFalse(spruce_skill_utils_2.diskUtil.doesFileExist(beforeFolder)); test_utils_1.assert.isTrue(spruce_skill_utils_2.diskUtil.doesFileExist(afterFolder)); } static async generatedSchemasRetainImportsAndTypeSuffix() { await this.installSchemaFeature('schemas'); const results = await this.Action('schema', 'create').execute({ nameReadable: 'Test schema', nameCamel: 'testSchema', }); const testSchemaPath = test_utility_1.default.assertFileByNameInGeneratedFiles('testSchema.builder.ts', results.files); spruce_skill_utils_2.diskUtil.writeFile(testSchemaPath, `import { buildSchema } from '@sprucelabs/schema' export default buildSchema({ id: 'testSchema', name: 'Test schema', description: '', importsWhenLocal: ['import * as Local from "@sprucelabs/schema"'], importsWhenRemote: ['import * as Remote from "@sprucelabs/schema"'], typeSuffix: '<S extends Record<string, any> = Record<string, any>>', fields: { fieldName1: { type: 'text', label: 'First Field', isRequired: true, }, fieldName2: { type: 'number', label: 'Second Field', isRequired: true, hint: 'A hint', }, }, }) `); const syncResults = await this.Action('schema', 'sync').execute({}); const schemaPath = test_utility_1.default.assertFileByNameInGeneratedFiles('testSchema.schema.ts', syncResults.files); const imported = await this.Service('import').importDefault(schemaPath); test_utils_1.assert.doesInclude(imported, { importsWhenRemote: ['import * as Remote from "@sprucelabs/schema"'], typeSuffix: '<S extends Record<string, any> = Record<string, any>>', }); } static async importSchema(results, filename) { const file = test_utility_1.default.assertFileByNameInGeneratedFiles(filename, results.files); const schema = await this.Service('import').importDefault(file); return schema; } static async assertTypesFileGeneratesArraySelect(typesFile) { const contents = spruce_skill_utils_2.diskUtil.readFile(typesFile); test_utils_1.assert.doesInclude(contents, `'favoriteColors'?: ("blue" | "red")[]`); } static async copyMockCoreSchemas() { const source = this.resolveTestPath('mock_core_builders'); const destination = this.resolvePath('src', 'schemas'); await spruce_skill_utils_2.diskUtil.copyDir(source, destination); } } exports.default = KeepsSchemasInSyncTest; __decorate([ (0, test_utils_1.test)() ], KeepsSchemasInSyncTest, "hasSyncSchemaAction", null); __decorate([ (0, test_utils_1.test)() ], KeepsSchemasInSyncTest, "failsBecauseSchemasIsNotInstalled", null); __decorate([ (0, test_utils_1.test)() ], KeepsSchemasInSyncTest, "syncingWithNoSchemasSucceeds", null); __decorate([ (0, test_utils_1.test)() ], KeepsSchemasInSyncTest, "syncingWithNoSchemasAndFetchCoreSchemasFalseSucceeds", null); __decorate([ (0, test_utils_1.test)() ], KeepsSchemasInSyncTest, "syncingCleansUpTempFiles", null); __decorate([ (0, test_utils_1.test)() ], KeepsSchemasInSyncTest, "syncingCoreSchemasGeneratesTypesFile", null); __decorate([ (0, test_utils_1.test)() ], KeepsSchemasInSyncTest, "syncSchemasTwiceSkipsFiles", null); __decorate([ (0, test_utils_1.test)() ], KeepsSchemasInSyncTest, "makeSureSchemaTypesAreVersioned", null); __decorate([ (0, test_utils_1.test)() ], KeepsSchemasInSyncTest, "shouldGenerateCoreSchemaTypesGeneratesValidFiles", null); __decorate([ (0, test_utils_1.test)() ], KeepsSchemasInSyncTest, "generateCoreSchemaInCoreSchemasModule", null); __decorate([ (0, test_utils_1.test)() ], KeepsSchemasInSyncTest, "canHandleHyphenSchemaIds", null); __decorate([ (0, test_utils_1.test)() ], KeepsSchemasInSyncTest, "coreSchemasPullFromCoreSchemasModuleDuringNormalGeneration", null); __decorate([ (0, test_utils_1.test)() ], KeepsSchemasInSyncTest, "schemasStayInSyncWhenBuildersAreDeleted", null); __decorate([ (0, test_utils_1.test)() ], KeepsSchemasInSyncTest, "canSyncSchemasWhenOnlyNodeModuleIsInstalledAfterDecliningToInstallSkill", null); __decorate([ (0, test_utils_1.test)('syncs minArrayLength, importsWhenRemote') ], KeepsSchemasInSyncTest, "syncsExpectedFields", null); __decorate([ (0, test_utils_1.test)() ], KeepsSchemasInSyncTest, "canChangeSkillNamespace", null); __decorate([ (0, test_utils_1.test)() ], KeepsSchemasInSyncTest, "generatedSchemasRetainImportsAndTypeSuffix", null); //# sourceMappingURL=KeepingSchemasInSync.test.js.map