UNPKG

@sprucelabs/spruce-cli

Version:

Command line interface for building Spruce skills.

156 lines (133 loc) 4.86 kB
import { eventResponseUtil } from '@sprucelabs/spruce-event-utils' import { diskUtil } from '@sprucelabs/spruce-skill-utils' import SpruceError from '../../errors/SpruceError' import PkgService from '../../services/PkgService' import { NpmPackage } from '../../types/cli.types' import tsConfigUtil from '../../utilities/tsConfig.utility' import AbstractFeature, { FeatureDependency } from '../AbstractFeature' import ParentTestFinder from '../error/ParentTestFinder' import { FeatureCode } from '../features.types' export interface ParentClassCandidate { name: string label: string path?: string import?: string isDefaultExport: boolean featureCode?: FeatureCode } export default class TestFeature extends AbstractFeature { public nameReadable = 'Testing' public description = 'Test first. Test everything! 💪' public code: FeatureCode = 'test' public dependencies: FeatureDependency[] = [ { code: 'skill', isRequired: false }, { code: 'node', isRequired: true }, ] public packageDependencies: NpmPackage[] = [ { name: '@sprucelabs/test@latest', isDev: true }, { name: '@sprucelabs/test-utils@latest', isDev: true }, { name: '@sprucelabs/jest-json-reporter@latest', isDev: true }, { name: 'jest-circus', isDev: true }, { name: 'jest', isDev: true }, ] public actionsDir = diskUtil.resolvePath(__dirname, 'actions') public async afterPackageInstall() { const service = this.Service('pkg') this.configureJest(service) this.configureScripts(service) this.configureTsConfig() return {} } private configureTsConfig() { try { const tsConfig = tsConfigUtil.readConfig(this.cwd) if (!tsConfig.compilerOptions.experimentalDecorators) { tsConfig.compilerOptions.experimentalDecorators = true tsConfigUtil.setCompilerOption( this.cwd, 'experimentalDecorators', true ) } } catch (err) { //@ts-ignore } } private configureScripts(service: PkgService) { let scripts = service.get('scripts') as Record<string, any> | undefined if (!scripts) { scripts = {} } if (!scripts.test) { scripts.test = 'jest' scripts['watch.tests'] = 'jest --watch' service.set({ path: 'scripts', value: scripts }) } } private configureJest(service: PkgService) { const jestConfig = { testRunner: 'jest-circus/runner', maxWorkers: 4, testTimeout: 120000, testEnvironment: 'node', testPathIgnorePatterns: [ '<rootDir>/tmp/', '<rootDir>/src/', '<rootDir>/node_modules/', '<rootDir>/build/__tests__/testDirsAndFiles/', ], testMatch: ['**/__tests__/**/*.test.js?(x)'], moduleNameMapper: { '^#spruce/(.*)$': '<rootDir>/build/.spruce/$1', }, } const existingJest = service.get('jest') as Record<string, any> if (!existingJest) { service.set({ path: 'jest', value: jestConfig }) } } public async buildParentClassCandidates(): Promise<ParentClassCandidate[]> { const parentFinder = new ParentTestFinder(this.cwd) const candidates: ParentClassCandidate[] = ( await parentFinder.findAbstractTests() ).map((a) => ({ ...a, label: a.name })) const results = await this.emitter.emit( 'test.register-abstract-test-classes' ) const { payloads } = eventResponseUtil.getAllResponsePayloadsAndErrors( results, SpruceError ) for (const payload of payloads) { const { abstractClasses } = payload for (const ac of abstractClasses) { const a = { ...ac, isDefaultExport: false } if (ac.featureCode) { const isInstalled = await this.features.isInstalled( ac.featureCode as any ) if (!isInstalled) { a.label = `${a.label} (requires install)` } } candidates.push(a as any) } } candidates.sort((a, b) => { if (a.label > b.label) { return 1 } else { return -1 } }) return candidates } } declare module '../../features/features.types' { interface FeatureMap { test: TestFeature } interface FeatureOptionsMap { test: undefined } }