diff --git a/jest.config.js b/jest.config.js index 598cf10e..77989a00 100644 --- a/jest.config.js +++ b/jest.config.js @@ -5,7 +5,6 @@ module.exports = { preset: 'ts-jest', testEnvironment: 'node', moduleDirectories: ['node_modules', 'src'], - setupFilesAfterEnv: ['/src/test-tool/jest.setup.ts'], transform: { '\\.sh$': '/src/test-tool/jest-raw-loader.js', '\\.yml$': '/src/test-tool/jest-raw-loader.js' diff --git a/package-lock.json b/package-lock.json index eeda6460..5c0d9ec1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,14 +33,12 @@ "eslint-plugin-prettier": "^4.0.0", "glob": "^8.0.3", "husky": "^8.0.1", - "inversify": "^6.0.1", "jest": "^29.2.2", "jest-raw-loader": "^1.0.1", "js-yaml": "^4.1.0", "npm-run-all": "^4.1.5", "prettier": "^2.6.1", "raw-loader": "^4.0.2", - "reflect-metadata": "^0.1.13", "shellcheck": "^1.1.0", "ts-jest": "^29.0.3", "ts-loader": "^9.2.8", @@ -4354,12 +4352,6 @@ "node": ">= 0.10" } }, - "node_modules/inversify": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/inversify/-/inversify-6.0.1.tgz", - "integrity": "sha512-B3ex30927698TJENHR++8FfEaJGqoWOgI6ZY5Ht/nLUsFCwHn6akbwtnUAPCgUepAnTpe2qHxhDNjoKLyz6rgQ==", - "dev": true - }, "node_modules/is-arguments": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", @@ -7220,12 +7212,6 @@ "node": ">= 0.10" } }, - "node_modules/reflect-metadata": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", - "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", - "dev": true - }, "node_modules/regexp.prototype.flags": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", @@ -11942,12 +11928,6 @@ "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", "dev": true }, - "inversify": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/inversify/-/inversify-6.0.1.tgz", - "integrity": "sha512-B3ex30927698TJENHR++8FfEaJGqoWOgI6ZY5Ht/nLUsFCwHn6akbwtnUAPCgUepAnTpe2qHxhDNjoKLyz6rgQ==", - "dev": true - }, "is-arguments": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", @@ -14109,12 +14089,6 @@ "resolve": "^1.9.0" } }, - "reflect-metadata": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", - "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", - "dev": true - }, "regexp.prototype.flags": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", diff --git a/package.json b/package.json index d84ffa29..f60798e7 100644 --- a/package.json +++ b/package.json @@ -305,14 +305,12 @@ "eslint-plugin-prettier": "^4.0.0", "glob": "^8.0.3", "husky": "^8.0.1", - "inversify": "^6.0.1", "jest": "^29.2.2", "jest-raw-loader": "^1.0.1", "js-yaml": "^4.1.0", "npm-run-all": "^4.1.5", "prettier": "^2.6.1", "raw-loader": "^4.0.2", - "reflect-metadata": "^0.1.13", "shellcheck": "^1.1.0", "ts-jest": "^29.0.3", "ts-loader": "^9.2.8", diff --git a/src/CompositionRoot.ts b/src/CompositionRoot.ts new file mode 100644 index 00000000..4abb6882 --- /dev/null +++ b/src/CompositionRoot.ts @@ -0,0 +1,236 @@ +import ChildProcessGateway from 'gateway/ChildProcessGateway'; +import EditorGateway from 'gateway/EditorGateway'; +import EnvVar from 'process/EnvVar'; +import FsGateway from 'gateway/FsGateway'; +import HttpGateway from 'gateway/HttpGateway'; +import OsGateway from 'gateway/OsGateway'; +import ProcessGateway from 'gateway/ProcessGateway'; +import ReporterGateway from 'gateway/ReporterGateway'; +import AllConfigFiles from 'config/AllConfigFiles'; +import AllJobs from 'job/AllJobs'; +import BuildAgentSettings from 'config/BuildAgentSettings'; +import Children from 'job/Children'; +import Images from 'containerization/Images'; +import CommandDecorators from 'terminal/CommandDecorators'; +import CommandFactory from 'job/ComandFactory'; +import Complain from 'command/Complain'; +import Config from 'config/Config'; +import ConfigFile from 'config/ConfigFile'; +import CreateConfigFile from 'command/CreateConfigFile'; +import DebugRepo from 'command/DebugRepo'; +import Docker from 'containerization/Docker'; +import Email from 'license/Email'; +import EnterLicense from 'command/EnterLicense'; +import EnterToken from 'command/EnterToken'; +import EnvPath from 'common/EnvPath'; +import ExitAllJobs from 'command/ExitAllJobs'; +import ExitJob from 'command/ExitJob'; +import FinalTerminal from 'terminal/FinalTerminal'; +import FirstActivation from 'job/FirstActivation'; +import GetLicense from 'command/GetLicense'; +import Help from 'command/Help'; +import JobFactory from 'job/JobFactory'; +import JobListener from 'job/JobListener'; +import JobProviderFactory from 'job/JobProviderFactory'; +import JobRunner from 'job/JobRunner'; +import JobTerminals from 'terminal/JobTerminals'; +import LatestCommittedImage from 'containerization/LatestCommittedImage'; +import LocalCi from './common/LocalCi'; +import License from 'license/License'; +import LicenseInput from 'license/LicenseInput'; +import LicensePresenter from 'license/LicensePresenter'; +import LicenseProviderFactory from 'license/LicenseProviderFactory'; +import LogFactory from 'log/LogFactory'; +import LogFile from 'log/LogFile'; +import LogProviderFactory from 'log/LogProviderFactory'; +import NativeCommandFactory from 'job/NativeComandFactory'; +import ParsedConfig from 'config/ParsedConfig'; +import Persistence from 'process/Persistence'; +import PipelineParameter from 'config/PipelineParameter'; +import ProcessFile from 'process/ProcessFile'; +import Refresh from 'command/Refresh'; +import RefreshLicenseTree from 'command/RefreshLicenseTree'; +import RegistrarFactory from 'common/RegistrarFactory'; +import ReRunJob from 'command/ReRunJob'; +import Retryer from 'job/Retryer'; +import RunJob from 'command/RunJob'; +import RunningContainer from 'containerization/RunningContainer'; +import RunWalkthroughJob from 'command/RunWalkthroughJob'; +import SelectRepo from 'command/SelectRepo'; +import ShowLogFile from 'command/ShowLogFile'; +import Spawn from 'common/Spawn'; +import StartDocker from 'command/StartDocker'; +import TryProcessAgain from 'command/TryProcessAgain'; +import UncommittedFile from 'containerization/UncommittedFile'; +import Volume from 'containerization/Volume'; +import WarningCommandFactory from 'job/WarningCommandFactory'; +import WarningFactory from 'job/WarningFactory'; +import Workspace from 'common/Workspace'; + +const childProcessGateway = new ChildProcessGateway(); +const editorGateway = new EditorGateway(); +const fsGateway = new FsGateway(); +const httpGateway = new HttpGateway(); +const osGateway = new OsGateway(); +const processGateway = new ProcessGateway(); +const reporterGateway = new ReporterGateway(editorGateway); + +const parsedConfig = new ParsedConfig(fsGateway); +const allJobs = new AllJobs(parsedConfig); +const envPath = new EnvPath(osGateway, processGateway); +const workspace = new Workspace(editorGateway); +const commandFactory = new CommandFactory(editorGateway); +const jobFactory = new JobFactory(editorGateway); +const logFactory = new LogFactory(editorGateway); +const warningFactory = new WarningFactory(editorGateway); +const warningCommandFactory = new WarningCommandFactory(warningFactory); +const spawn = new Spawn(envPath, processGateway, workspace); +const buildAgentSettings = new BuildAgentSettings( + childProcessGateway, + osGateway, + spawn +); +const children = new Children( + commandFactory, + editorGateway, + jobFactory, + logFactory, + new NativeCommandFactory(), + warningCommandFactory, + warningFactory +); +const pipelineParameter = new PipelineParameter(fsGateway); +const envVar = new EnvVar(childProcessGateway, spawn); +const volume = new Volume(fsGateway); +const persistence = new Persistence(volume); +const processFile = new ProcessFile(envVar, fsGateway, persistence); + +const config = new Config( + childProcessGateway, + editorGateway, + fsGateway, + pipelineParameter, + processFile, + spawn +); +const allConfigFiles = new AllConfigFiles(editorGateway); +const configFile = new ConfigFile( + allConfigFiles, + editorGateway, + reporterGateway +); + +const createConfigFile = new CreateConfigFile(editorGateway, reporterGateway); +const debugRepo = new DebugRepo(editorGateway, reporterGateway); +const docker = new Docker(childProcessGateway, spawn); +const email = new Email(editorGateway, httpGateway, reporterGateway); +const enterToken = new EnterToken(editorGateway); +const images = new Images(childProcessGateway, spawn); +const exitAllJobs = new ExitAllJobs(images, editorGateway, reporterGateway); +const finalTerminal = new FinalTerminal( + childProcessGateway, + editorGateway, + spawn +); +const logFile = new LogFile(editorGateway); +const jobListener = new JobListener( + childProcessGateway, + images, + configFile, + editorGateway, + fsGateway, + logFile, + parsedConfig, + spawn +); + +const latestCommittedImage = new LatestCommittedImage( + spawn, + childProcessGateway +); +const runningContainer = new RunningContainer(spawn, childProcessGateway); +const uncommittedFile = new UncommittedFile( + childProcessGateway, + editorGateway, + spawn +); + +const jobRunner = new JobRunner( + buildAgentSettings, + new CommandDecorators(editorGateway), + configFile, + editorGateway, + finalTerminal, + fsGateway, + images, + jobFactory, + jobListener, + latestCommittedImage, + parsedConfig, + runningContainer, + uncommittedFile +); +const jobTerminals = new JobTerminals(editorGateway); +const exitJob = new ExitJob(jobFactory, jobRunner, jobTerminals); +const getLicense = new GetLicense(editorGateway); +const license = new License(editorGateway, httpGateway); +const retryer = new Retryer(); +const jobProviderFactory = new JobProviderFactory( + allConfigFiles, + children, + configFile, + commandFactory, + docker, + editorGateway, + fsGateway, + license, + config, + jobFactory, + logFactory, + reporterGateway, + retryer, + warningFactory, + allJobs +); + +const licenseInput = new LicenseInput(editorGateway, license); +const licensePresenter = new LicensePresenter(license); +const licenseProviderFactory = new LicenseProviderFactory( + license, + licenseInput, + licensePresenter, + editorGateway +); +const registrarFactory = new RegistrarFactory( + new Complain(editorGateway), + configFile, + createConfigFile, + debugRepo, + new EnterLicense(licenseInput), + enterToken, + exitAllJobs, + exitJob, + new FirstActivation(editorGateway, reporterGateway, email), + getLicense, + new Help(editorGateway, reporterGateway), + licenseInput, + new LogProviderFactory(fsGateway), + new Refresh(), + new RefreshLicenseTree(editorGateway), + new ReRunJob(editorGateway, jobRunner, jobTerminals, reporterGateway), + new RunJob(editorGateway, jobRunner, reporterGateway), + new RunWalkthroughJob(config, configFile, editorGateway, reporterGateway), + new SelectRepo(allConfigFiles, images, editorGateway, reporterGateway), + new ShowLogFile(logFile), + new StartDocker(childProcessGateway, envPath, spawn), + new TryProcessAgain(configFile, fsGateway), + editorGateway +); + +export const app = new LocalCi( + fsGateway, + jobProviderFactory, + licenseProviderFactory, + registrarFactory, + reporterGateway +); diff --git a/src/command/Complain.ts b/src/command/Complain.ts index dec59ee1..7fcc9a98 100644 --- a/src/command/Complain.ts +++ b/src/command/Complain.ts @@ -1,17 +1,11 @@ -import { inject, injectable } from 'inversify'; import type { Command } from '.'; -import Types from 'common/Types'; import EditorGateway from 'gateway/EditorGateway'; import { COMPLAIN_COMMAND, COMPLAIN_URL } from 'constant'; -@injectable() export default class Complain implements Command { - @inject(Types.IEditorGateway) - editorGateway!: EditorGateway; - commandName: string; - constructor() { + constructor(public editorGateway: EditorGateway) { this.commandName = COMPLAIN_COMMAND; } diff --git a/src/command/CreateConfigFile.ts b/src/command/CreateConfigFile.ts index 39ff12e9..46393cde 100644 --- a/src/command/CreateConfigFile.ts +++ b/src/command/CreateConfigFile.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from 'inversify'; import * as path from 'path'; import type vscode from 'vscode'; import type { Command } from './'; @@ -6,20 +5,15 @@ import EditorGateway from 'gateway/EditorGateway'; import getStarterConfig from 'config/getStarterConfig'; import JobProvider from 'job/JobProvider'; import ReporterGateway from 'gateway/ReporterGateway'; -import Types from 'common/Types'; import { CREATE_CONFIG_FILE_COMMAND } from 'constant'; -@injectable() export default class CreateConfigFile implements Command { - @inject(Types.IEditorGateway) - editorGateway!: EditorGateway; - - @inject(Types.IReporterGateway) - reporterGateway!: ReporterGateway; - commandName: string; - constructor() { + constructor( + public editorGateway: EditorGateway, + public reporterGateway: ReporterGateway + ) { this.commandName = CREATE_CONFIG_FILE_COMMAND; } diff --git a/src/command/DebugRepo.ts b/src/command/DebugRepo.ts index e1f8c47a..11ff49c9 100644 --- a/src/command/DebugRepo.ts +++ b/src/command/DebugRepo.ts @@ -1,22 +1,16 @@ -import { inject, injectable } from 'inversify'; import type vscode from 'vscode'; -import Types from 'common/Types'; import EditorGateway from 'gateway/EditorGateway'; import JobProvider from 'job/JobProvider'; import ReporterGateway from 'gateway/ReporterGateway'; import { SELECTED_CONFIG_PATH } from 'constant'; -@injectable() export default class DebugRepo { - @inject(Types.IEditorGateway) - editorGateway!: EditorGateway; - - @inject(Types.IReporterGateway) - reporterGateway!: ReporterGateway; - commandName: string; - constructor() { + constructor( + public editorGateway: EditorGateway, + public reporterGateway: ReporterGateway + ) { this.commandName = 'local-ci.debug.repo'; } diff --git a/src/command/EnterLicense.ts b/src/command/EnterLicense.ts index b02ad41b..7b02ac5a 100644 --- a/src/command/EnterLicense.ts +++ b/src/command/EnterLicense.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from 'inversify'; import type vscode from 'vscode'; import type { Command } from '.'; import JobProvider from 'job/JobProvider'; @@ -6,14 +5,10 @@ import LicenseInput from 'license/LicenseInput'; import LicenseProvider from 'license/LicenseProvider'; import { ENTER_LICENSE_COMMAND } from 'constant'; -@injectable() export default class EnterLicense implements Command { - @inject(LicenseInput) - licenseInput!: LicenseInput; - commandName: string; - constructor() { + constructor(public licenseInput: LicenseInput) { this.commandName = ENTER_LICENSE_COMMAND; } diff --git a/src/command/EnterToken.ts b/src/command/EnterToken.ts index 189bbeca..03212901 100644 --- a/src/command/EnterToken.ts +++ b/src/command/EnterToken.ts @@ -1,19 +1,13 @@ -import { inject, injectable } from 'inversify'; import type vscode from 'vscode'; import type { Command } from '.'; import { getBinaryPath } from '../../node/binary'; import EditorGateway from 'gateway/EditorGateway'; -import Types from 'common/Types'; import { JOB_TREE_VIEW_ID } from 'constant'; -@injectable() export default class EnterToken implements Command { - @inject(Types.IEditorGateway) - editorGateway!: EditorGateway; - commandName: string; - constructor() { + constructor(public editorGateway: EditorGateway) { this.commandName = `${JOB_TREE_VIEW_ID}.enterToken`; } diff --git a/src/command/ExitAllJobs.ts b/src/command/ExitAllJobs.ts index 6a0ff89d..11471029 100644 --- a/src/command/ExitAllJobs.ts +++ b/src/command/ExitAllJobs.ts @@ -1,27 +1,19 @@ -import { inject, injectable } from 'inversify'; import type vscode from 'vscode'; import type { Command } from '.'; -import Types from 'common/Types'; import Images from 'containerization/Images'; import EditorGateway from 'gateway/EditorGateway'; import JobProvider from 'job/JobProvider'; import ReporterGateway from 'gateway/ReporterGateway'; import { COMMITTED_IMAGE_NAMESPACE, JOB_TREE_VIEW_ID } from 'constant'; -@injectable() export default class ExitAllJobs implements Command { - @inject(Images) - images!: Images; - - @inject(Types.IEditorGateway) - editorGateway!: EditorGateway; - - @inject(Types.IReporterGateway) - reporterGateway!: ReporterGateway; - commandName: string; - constructor() { + constructor( + public images: Images, + public editorGateway: EditorGateway, + public reporterGateway: ReporterGateway + ) { this.commandName = `${JOB_TREE_VIEW_ID}.exitAllJobs`; } diff --git a/src/command/ExitJob.ts b/src/command/ExitJob.ts index 3f9b4429..747107bd 100644 --- a/src/command/ExitJob.ts +++ b/src/command/ExitJob.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from 'inversify'; import type vscode from 'vscode'; import type { Command } from '.'; import JobFactory from 'job/JobFactory'; @@ -8,20 +7,14 @@ import JobTerminals from 'terminal/JobTerminals'; import JobTreeItem from 'job/JobTreeItem'; import { EXIT_JOB_COMMAND } from 'constant'; -@injectable() export default class ExitJob implements Command { - @inject(JobFactory) - jobFactory!: JobFactory; - - @inject(JobRunner) - jobRunner!: JobRunner; - - @inject(JobTerminals) - jobTerminals!: JobTerminals; - commandName: string; - constructor() { + constructor( + public jobFactory: JobFactory, + public jobRunner: JobRunner, + public jobTerminals: JobTerminals + ) { this.commandName = EXIT_JOB_COMMAND; } diff --git a/src/command/GetLicense.ts b/src/command/GetLicense.ts index e7b79f4d..51b4b7c8 100644 --- a/src/command/GetLicense.ts +++ b/src/command/GetLicense.ts @@ -1,17 +1,11 @@ -import { inject, injectable } from 'inversify'; import type { Command } from '.'; -import Types from 'common/Types'; import EditorGateway from 'gateway/EditorGateway'; import { GET_LICENSE_COMMAND, GET_LICENSE_KEY_URL } from 'constant'; -@injectable() export default class GetLicense implements Command { - @inject(Types.IEditorGateway) - editorGateway!: EditorGateway; - commandName: string; - constructor() { + constructor(public editorGateway: EditorGateway) { this.commandName = GET_LICENSE_COMMAND; } diff --git a/src/command/Help.ts b/src/command/Help.ts index d920694e..0490cbde 100644 --- a/src/command/Help.ts +++ b/src/command/Help.ts @@ -1,21 +1,15 @@ -import { inject, injectable } from 'inversify'; import type { Command } from '.'; -import Types from 'common/Types'; import EditorGateway from 'gateway/EditorGateway'; import ReporterGateway from 'gateway/ReporterGateway'; import { HELP_URL, JOB_TREE_VIEW_ID } from 'constant'; -@injectable() export default class Help implements Command { - @inject(Types.IEditorGateway) - editorGateway!: EditorGateway; - - @inject(Types.IReporterGateway) - reporterGateway!: ReporterGateway; - commandName: string; - constructor() { + constructor( + public editorGateway: EditorGateway, + public reporterGateway: ReporterGateway + ) { this.commandName = `${JOB_TREE_VIEW_ID}.help`; } diff --git a/src/command/ReRunJob.ts b/src/command/ReRunJob.ts index cbe82560..1d151138 100644 --- a/src/command/ReRunJob.ts +++ b/src/command/ReRunJob.ts @@ -1,7 +1,5 @@ -import { inject, injectable } from 'inversify'; import type vscode from 'vscode'; import type { Command } from '.'; -import Types from 'common/Types'; import EditorGateway from 'gateway/EditorGateway'; import JobProvider from 'job/JobProvider'; import ReporterGateway from 'gateway/ReporterGateway'; @@ -10,23 +8,15 @@ import JobTerminals from 'terminal/JobTerminals'; import JobTreeItem from 'job/JobTreeItem'; import { DO_NOT_CONFIRM_RUN_JOB, RERUN_JOB_COMMAND } from 'constant'; -@injectable() export default class ReRunJob implements Command { - @inject(Types.IEditorGateway) - editorGateway!: EditorGateway; - - @inject(JobRunner) - jobRunner!: JobRunner; - - @inject(JobTerminals) - jobTerminals!: JobTerminals; - - @inject(Types.IReporterGateway) - reporterGateway!: ReporterGateway; - commandName: string; - constructor() { + constructor( + public editorGateway: EditorGateway, + public jobRunner: JobRunner, + public jobTerminals: JobTerminals, + public reporterGateway: ReporterGateway + ) { this.commandName = RERUN_JOB_COMMAND; } diff --git a/src/command/Refresh.ts b/src/command/Refresh.ts index 99877144..9895cad9 100644 --- a/src/command/Refresh.ts +++ b/src/command/Refresh.ts @@ -1,10 +1,8 @@ -import { injectable } from 'inversify'; import type vscode from 'vscode'; import type { Command } from '.'; import JobProvider from 'job/JobProvider'; import { JOB_TREE_VIEW_ID } from 'constant'; -@injectable() export default class Refresh implements Command { commandName: string; @@ -12,7 +10,7 @@ export default class Refresh implements Command { this.commandName = `${JOB_TREE_VIEW_ID}.refresh`; } - getCallback(context: vscode.ExtensionContext, jobProvider: JobProvider) { + getCallback(_context: vscode.ExtensionContext, jobProvider: JobProvider) { return () => { jobProvider.hardRefresh(); }; diff --git a/src/command/RefreshLicenseTree.ts b/src/command/RefreshLicenseTree.ts index 2b5c01d2..06b083f7 100644 --- a/src/command/RefreshLicenseTree.ts +++ b/src/command/RefreshLicenseTree.ts @@ -1,20 +1,14 @@ -import { inject, injectable } from 'inversify'; import type vscode from 'vscode'; import type { Command } from '.'; import EditorGateway from 'gateway/EditorGateway'; import JobProvider from 'job/JobProvider'; import LicenseProvider from 'license/LicenseProvider'; -import Types from 'common/Types'; import { LICENSE_TREE_VIEW_ID } from 'constant'; -@injectable() export default class RefreshLicenseTree implements Command { - @inject(Types.IEditorGateway) - editorGateway!: EditorGateway; - commandName: string; - constructor() { + constructor(public editorGateway: EditorGateway) { this.commandName = `${LICENSE_TREE_VIEW_ID}.refresh`; } diff --git a/src/command/RunJob.ts b/src/command/RunJob.ts index 5a7fe137..03e43e47 100644 --- a/src/command/RunJob.ts +++ b/src/command/RunJob.ts @@ -1,7 +1,5 @@ -import { inject, injectable } from 'inversify'; import type vscode from 'vscode'; import type { Command } from '.'; -import Types from 'common/Types'; import EditorGateway from 'gateway/EditorGateway'; import JobProvider from 'job/JobProvider'; import JobRunner from 'job/JobRunner'; @@ -9,20 +7,14 @@ import JobTreeItem from 'job/JobTreeItem'; import ReporterGateway from 'gateway/ReporterGateway'; import { DO_NOT_CONFIRM_RUN_JOB, RUN_JOB_COMMAND } from 'constant'; -@injectable() export default class RunJob implements Command { - @inject(Types.IEditorGateway) - editorGateway!: EditorGateway; - - @inject(JobRunner) - jobRunner!: JobRunner; - - @inject(Types.IReporterGateway) - reporterGateway!: ReporterGateway; - commandName: string; - constructor() { + constructor( + public editorGateway: EditorGateway, + public jobRunner: JobRunner, + public reporterGateway: ReporterGateway + ) { this.commandName = RUN_JOB_COMMAND; } diff --git a/src/command/RunWalkthroughJob.ts b/src/command/RunWalkthroughJob.ts index 4f4c0dfa..e36ba334 100644 --- a/src/command/RunWalkthroughJob.ts +++ b/src/command/RunWalkthroughJob.ts @@ -1,6 +1,4 @@ -import { inject, injectable } from 'inversify'; import type vscode from 'vscode'; -import Types from 'common/Types'; import Config from 'config/Config'; import ConfigFile from 'config/ConfigFile'; import EditorGateway from 'gateway/EditorGateway'; @@ -13,23 +11,15 @@ import ReporterGateway from 'gateway/ReporterGateway'; import { RUN_JOB_COMMAND } from 'constant'; -@injectable() export default class RunWalkthroughJob { - @inject(Config) - config!: Config; - - @inject(ConfigFile) - configFile!: ConfigFile; - - @inject(Types.IEditorGateway) - editorGateway!: EditorGateway; - - @inject(Types.IReporterGateway) - reporterGateway!: ReporterGateway; - commandName: string; - constructor() { + constructor( + public config: Config, + public configFile: ConfigFile, + public editorGateway: EditorGateway, + public reporterGateway: ReporterGateway + ) { this.commandName = 'local-ci.runWalkthroughJob'; } diff --git a/src/command/SelectRepo.ts b/src/command/SelectRepo.ts index 1446b338..dc367569 100644 --- a/src/command/SelectRepo.ts +++ b/src/command/SelectRepo.ts @@ -1,7 +1,5 @@ -import { inject, injectable } from 'inversify'; import type vscode from 'vscode'; import type { Command } from '.'; -import Types from 'common/Types'; import AllConfigFiles from 'config/AllConfigFiles'; import Images from 'containerization/Images'; import EditorGateway from 'gateway/EditorGateway'; @@ -14,23 +12,15 @@ import { SELECTED_CONFIG_PATH, } from 'constant'; -@injectable() export default class SelectRepo implements Command { - @inject(AllConfigFiles) - allConfigFiles!: AllConfigFiles; - - @inject(Images) - images!: Images; - - @inject(Types.IEditorGateway) - editorGateway!: EditorGateway; - - @inject(Types.IReporterGateway) - reporterGateway!: ReporterGateway; - commandName: string; - constructor() { + constructor( + public allConfigFiles: AllConfigFiles, + public images: Images, + public editorGateway: EditorGateway, + public reporterGateway: ReporterGateway + ) { this.commandName = `${JOB_TREE_VIEW_ID}.selectRepo`; } diff --git a/src/command/ShowLogFile.ts b/src/command/ShowLogFile.ts index 92df6cbd..caa589a5 100644 --- a/src/command/ShowLogFile.ts +++ b/src/command/ShowLogFile.ts @@ -1,16 +1,11 @@ -import { inject, injectable } from 'inversify'; import type { Command } from '.'; import LogFile from 'log/LogFile'; import { SHOW_LOG_FILE_COMMAND } from 'constant'; -@injectable() export default class ShowLogFile implements Command { - @inject(LogFile) - logFile!: LogFile; - commandName: string; - constructor() { + constructor(public logFile: LogFile) { this.commandName = SHOW_LOG_FILE_COMMAND; } diff --git a/src/command/StartDocker.ts b/src/command/StartDocker.ts index eac2e4f4..32bb2a4a 100644 --- a/src/command/StartDocker.ts +++ b/src/command/StartDocker.ts @@ -1,28 +1,20 @@ -import { inject, injectable } from 'inversify'; import type vscode from 'vscode'; import type { Command } from '.'; import { START_DOCKER_COMMAND } from 'constant'; -import Types from 'common/Types'; import ChildProcessGateway from 'gateway/ChildProcessGateway'; import CommandTreeItem from 'job/CommandTreeItem'; import Spawn from 'common/Spawn'; import EnvPath from 'common/EnvPath'; import JobProvider from 'job/JobProvider'; -@injectable() export default class StartDocker implements Command { - @inject(Types.IChildProcessGateway) - childProcessGateway!: ChildProcessGateway; - - @inject(EnvPath) - envPath!: EnvPath; - - @inject(Spawn) - spawn!: Spawn; - commandName: string; - constructor() { + constructor( + public childProcessGateway: ChildProcessGateway, + public envPath: EnvPath, + public spawn: Spawn + ) { this.commandName = START_DOCKER_COMMAND; } diff --git a/src/command/TryProcessAgain.ts b/src/command/TryProcessAgain.ts index 6824b04a..45a430bf 100644 --- a/src/command/TryProcessAgain.ts +++ b/src/command/TryProcessAgain.ts @@ -1,24 +1,15 @@ -import { inject, injectable } from 'inversify'; import type { Command } from '.'; import type vscode from 'vscode'; import ConfigFile from 'config/ConfigFile'; import FsGateway from 'gateway/FsGateway'; import getDynamicConfigPath from 'config/getDynamicConfigPath'; import JobProvider from 'job/JobProvider'; -import Types from 'common/Types'; import { PROCESS_TRY_AGAIN_COMMAND } from 'constant'; -@injectable() export default class TryProcessAgain implements Command { - @inject(ConfigFile) - configFile!: ConfigFile; - - @inject(Types.IFsGateway) - fsGateway!: FsGateway; - commandName: string; - constructor() { + constructor(public configFile: ConfigFile, public fsGateway: FsGateway) { this.commandName = PROCESS_TRY_AGAIN_COMMAND; } diff --git a/src/command/test/Complain.spec.ts b/src/command/test/Complain.spec.ts index cbb86eeb..4823f664 100644 --- a/src/command/test/Complain.spec.ts +++ b/src/command/test/Complain.spec.ts @@ -1,22 +1,12 @@ -import AppTestHarness from 'test-tool/helper/AppTestHarness'; -import FakeEditorGateway from 'gateway/FakeEditorGateway'; -import Complain from 'command/Complain'; - -let complain: Complain; -let editorGateway: FakeEditorGateway; +import getContainer from 'test-tool/TestRoot'; describe('Complain command', () => { - beforeEach(() => { - const testHarness = new AppTestHarness(); - testHarness.init(); - complain = testHarness.container.get(Complain); - editorGateway = testHarness.editorGateway; - }); - test('opens the complain email url', () => { + const { complain, editorGateway } = getContainer(); const editorSpy = jest.fn(); editorGateway.editor.env.openExternal = editorSpy; const stubUri = 'emailto:ryan@getlocalci.com'; + // @ts-expect-error stub is the wrong type. editorGateway.editor.Uri.parse = () => stubUri; complain.getCallback()(); diff --git a/src/command/test/CreateConfigFile.spec.ts b/src/command/test/CreateConfigFile.spec.ts index c9eade39..3c59940a 100644 --- a/src/command/test/CreateConfigFile.spec.ts +++ b/src/command/test/CreateConfigFile.spec.ts @@ -1,30 +1,19 @@ -import AppTestHarness from 'test-tool/helper/AppTestHarness'; -import CreateConfigFile from 'command/CreateConfigFile'; -import FakeEditorGateway from 'gateway/FakeEditorGateway'; -import FakeReporterGateway from 'gateway/FakeReporterGateway'; import getContextStub from 'test-tool/helper/getContextStub'; -import JobProviderFactory from 'job/JobProviderFactory'; - -let createConfigFile: CreateConfigFile; -let editorGateway: FakeEditorGateway; -let jobProviderFactory: JobProviderFactory; -let reporterGateway: FakeReporterGateway; +import getContainer from 'test-tool/TestRoot'; describe('CreateConfigFile command', () => { - beforeEach(() => { - const testHarness = new AppTestHarness(); - testHarness.init(); - createConfigFile = testHarness.container.get(CreateConfigFile); - editorGateway = testHarness.editorGateway; - reporterGateway = testHarness.reporterGateway; - jobProviderFactory = testHarness.container.get(JobProviderFactory); - }); - test('creates the config when there is a workspace folder', async () => { + const { + createConfigFile, + editorGateway, + reporterGateway, + jobProviderFactory, + } = getContainer(); const reporterSpy = jest.fn(); reporterGateway.reporter.sendTelemetryEvent = reporterSpy; const uri = 'foo/baz/'; + // @ts-expect-error read-only property. editorGateway.editor.workspace.workspaceFolders = [ { uri: { diff --git a/src/command/test/DebugRepo.spec.ts b/src/command/test/DebugRepo.spec.ts index f1b8e37b..ee1265af 100644 --- a/src/command/test/DebugRepo.spec.ts +++ b/src/command/test/DebugRepo.spec.ts @@ -1,20 +1,10 @@ -import AppTestHarness from 'test-tool/helper/AppTestHarness'; -import DebugRepo from 'command/DebugRepo'; import getContextStub from 'test-tool/helper/getContextStub'; -import JobProviderFactory from 'job/JobProviderFactory'; - -let debugRepo: DebugRepo; -let jobProviderFactory: JobProviderFactory; +import getContainer from 'test-tool/TestRoot'; describe('DebugRepo command', () => { - beforeEach(() => { - const testHarness = new AppTestHarness(); - testHarness.init(); - jobProviderFactory = testHarness.container.get(JobProviderFactory); - debugRepo = testHarness.container.get(DebugRepo); - }); - test('selects the repo if there is a path', () => { + const { jobProviderFactory, debugRepo } = getContainer(); + const updateSpy = jest.fn().mockImplementationOnce(async () => null); const contextStub = { ...getContextStub(), diff --git a/src/command/test/Help.spec.ts b/src/command/test/Help.spec.ts index c22dd759..e140df2f 100644 --- a/src/command/test/Help.spec.ts +++ b/src/command/test/Help.spec.ts @@ -1,22 +1,8 @@ -import AppTestHarness from 'test-tool/helper/AppTestHarness'; -import FakeEditorGateway from 'gateway/FakeEditorGateway'; -import FakeReporterGateway from 'gateway/FakeReporterGateway'; -import Help from 'command/Help'; - -let help: Help; -let editorGateway: FakeEditorGateway; -let reporterGateway: FakeReporterGateway; +import getContainer from 'test-tool/TestRoot'; describe('Help command', () => { - beforeEach(() => { - const testHarness = new AppTestHarness(); - testHarness.init(); - help = testHarness.container.get(Help); - editorGateway = testHarness.editorGateway; - reporterGateway = testHarness.reporterGateway; - }); - test('calls the reporter event', () => { + const { help, reporterGateway } = getContainer(); const reporterSpy = jest.fn(); reporterGateway.reporter.sendTelemetryEvent = reporterSpy; @@ -26,9 +12,11 @@ describe('Help command', () => { }); test('opens an external link', () => { + const { editorGateway, help } = getContainer(); const editorSpy = jest.fn(); editorGateway.editor.env.openExternal = editorSpy; const stubUri = 'https://example.com/stub'; + // @ts-expect-error stubUri is the wrong type. editorGateway.editor.Uri.parse = () => stubUri; help.getCallback()(); diff --git a/src/common/AppIoc.ts b/src/common/AppIoc.ts deleted file mode 100644 index 5a073e1a..00000000 --- a/src/common/AppIoc.ts +++ /dev/null @@ -1,30 +0,0 @@ -import 'reflect-metadata'; -import BaseIoc from 'common/BaseIoc'; -import ChildProcessGateway from 'gateway/ChildProcessGateway'; -import EditorGateway from 'gateway/EditorGateway'; -import EnvVar from 'process/EnvVar'; -import FsGateway from 'gateway/FsGateway'; -import HttpGateway from 'gateway/HttpGateway'; -import OsGateway from 'gateway/OsGateway'; -import ProcessGateway from 'gateway/ProcessGateway'; -import ReporterGateway from 'gateway/ReporterGateway'; -import Types from 'common/Types'; -import Volume from 'containerization/Volume'; - -export const iocContainer = new BaseIoc().buildBaseTemplate(); - -iocContainer - .bind(Types.IChildProcessGateway) - .to(ChildProcessGateway) - .inSingletonScope(); -iocContainer.bind(Types.IEditorGateway).to(EditorGateway).inSingletonScope(); -iocContainer.bind(Types.IEnvVar).to(EnvVar).inSingletonScope(); -iocContainer.bind(Types.IFsGateway).to(FsGateway).inSingletonScope(); -iocContainer.bind(Types.IHttpGateway).to(HttpGateway).inSingletonScope(); -iocContainer.bind(Types.IOsGateway).to(OsGateway).inSingletonScope(); -iocContainer.bind(Types.IProcessGateway).to(ProcessGateway).inSingletonScope(); -iocContainer - .bind(Types.IReporterGateway) - .to(ReporterGateway) - .inSingletonScope(); -iocContainer.bind(Types.IVolume).to(Volume).inSingletonScope(); diff --git a/src/common/BaseIoc.ts b/src/common/BaseIoc.ts deleted file mode 100644 index d80704dd..00000000 --- a/src/common/BaseIoc.ts +++ /dev/null @@ -1,120 +0,0 @@ -import { Container as IocContainer } from 'inversify'; -import AllConfigFiles from 'config/AllConfigFiles'; -import AllJobs from 'job/AllJobs'; -import BuildAgentSettings from 'config/BuildAgentSettings'; -import Children from 'job/Children'; -import Images from 'containerization/Images'; -import CommandFactory from 'job/ComandFactory'; -import Config from 'config/Config'; -import ConfigFile from 'config/ConfigFile'; -import CreateConfigFile from 'command/CreateConfigFile'; -import DebugRepo from 'command/DebugRepo'; -import Docker from 'containerization/Docker'; -import Email from 'license/Email'; -import EnterToken from 'command/EnterToken'; -import EnvPath from 'common/EnvPath'; -import ExitAllJobs from 'command/ExitAllJobs'; -import ExitJob from 'command/ExitJob'; -import FinalTerminal from 'terminal/FinalTerminal'; -import GetLicense from 'command/GetLicense'; -import JobFactory from 'job/JobFactory'; -import JobProviderFactory from 'job/JobProviderFactory'; -import JobRunner from 'job/JobRunner'; -import JobListener from 'job/JobListener'; -import JobTerminals from 'terminal/JobTerminals'; -import LatestCommittedImage from 'containerization/LatestCommittedImage'; -import License from 'license/License'; -import LicenseInput from 'license/LicenseInput'; -import LicenseProviderFactory from 'license/LicenseProviderFactory'; -import LogFactory from 'log/LogFactory'; -import LogFile from 'log/LogFile'; -import LogProviderFactory from 'log/LogProviderFactory'; -import NativeCommandFactory from 'job/NativeComandFactory'; -import ParsedConfig from 'config/ParsedConfig'; -import Persistence from 'process/Persistence'; -import PipelineParameter from 'config/PipelineParameter'; -import ProcessFile from 'process/ProcessFile'; -import Refresh from 'command/Refresh'; -import RegistrarFactory from 'common/RegistrarFactory'; -import ReRunJob from 'command/ReRunJob'; -import Retryer from 'job/Retryer'; -import RunJob from 'command/RunJob'; -import RunningContainer from 'containerization/RunningContainer'; -import RunWalkthroughJob from 'command/RunWalkthroughJob'; -import SelectRepo from 'command/SelectRepo'; -import Spawn from 'common/Spawn'; -import TryProcessAgain from 'command/TryProcessAgain'; -import UncommittedFile from 'containerization/UncommittedFile'; -import WarningCommandFactory from 'job/WarningCommandFactory'; -import WarningFactory from 'job/WarningFactory'; -import Workspace from 'common/Workspace'; - -/** - * Main dependency injection class. - * - * For classes that are the same in production and unit tests. - */ -export default class BaseIoc { - container: IocContainer; - - constructor() { - this.container = new IocContainer({ - autoBindInjectable: true, - defaultScope: 'Transient', - }); - } - - buildBaseTemplate(): IocContainer { - this.container.bind(AllConfigFiles).toSelf(); - this.container.bind(AllJobs).toSelf(); - this.container.bind(BuildAgentSettings).toSelf(); - this.container.bind(Children).toSelf(); - this.container.bind(CommandFactory).toSelf(); - this.container.bind(Images).toSelf(); - this.container.bind(Config).toSelf(); - this.container.bind(ConfigFile).toSelf(); - this.container.bind(CreateConfigFile).toSelf(); - this.container.bind(DebugRepo).toSelf(); - this.container.bind(Docker).toSelf(); - this.container.bind(Email).toSelf(); - this.container.bind(EnterToken).toSelf(); - this.container.bind(EnvPath).toSelf(); - this.container.bind(ExitAllJobs).toSelf(); - this.container.bind(ExitJob).toSelf(); - this.container.bind(FinalTerminal).toSelf(); - this.container.bind(GetLicense).toSelf(); - this.container.bind(JobFactory).toSelf(); - this.container.bind(JobListener).toSelf(); - this.container.bind(JobProviderFactory).toSelf(); - this.container.bind(JobRunner).toSelf(); - this.container.bind(JobTerminals).toSelf(); - this.container.bind(LogFactory).toSelf(); - this.container.bind(LogFile).toSelf(); - this.container.bind(LatestCommittedImage).toSelf(); - this.container.bind(License).toSelf(); - this.container.bind(LicenseInput).toSelf(); - this.container.bind(LicenseProviderFactory).toSelf(); - this.container.bind(LogProviderFactory).toSelf(); - this.container.bind(NativeCommandFactory).toSelf(); - this.container.bind(ParsedConfig).toSelf(); - this.container.bind(Persistence).toSelf(); - this.container.bind(PipelineParameter).toSelf(); - this.container.bind(ProcessFile).toSelf(); - this.container.bind(Refresh).toSelf(); - this.container.bind(RegistrarFactory).toSelf(); - this.container.bind(ReRunJob).toSelf(); - this.container.bind(Retryer).toSelf(); - this.container.bind(RunWalkthroughJob).toSelf(); - this.container.bind(RunJob).toSelf(); - this.container.bind(RunningContainer).toSelf(); - this.container.bind(SelectRepo).toSelf(); - this.container.bind(Spawn).toSelf(); - this.container.bind(TryProcessAgain).toSelf(); - this.container.bind(UncommittedFile).toSelf(); - this.container.bind(WarningCommandFactory).toSelf(); - this.container.bind(WarningFactory).toSelf(); - this.container.bind(Workspace).toSelf(); - - return this.container; - } -} diff --git a/src/common/EnvPath.ts b/src/common/EnvPath.ts index 5e0c9984..5dac195e 100644 --- a/src/common/EnvPath.ts +++ b/src/common/EnvPath.ts @@ -1,15 +1,11 @@ -import { inject, injectable } from 'inversify'; import OsGateway from 'gateway/OsGateway'; import ProcessGateway from 'gateway/ProcessGateway'; -import Types from './Types'; -@injectable() export default class EnvPath { - @inject(Types.IOsGateway) - osGateway!: OsGateway; - - @inject(Types.IProcessGateway) - processGateway!: ProcessGateway; + constructor( + public osGateway: OsGateway, + public processGateway: ProcessGateway + ) {} /** * Gets the environment path. diff --git a/src/common/LocalCi.ts b/src/common/LocalCi.ts index 41772eb5..4e499792 100644 --- a/src/common/LocalCi.ts +++ b/src/common/LocalCi.ts @@ -1,6 +1,4 @@ -import { inject, injectable } from 'inversify'; import type vscode from 'vscode'; -import Types from './Types'; import FsGateway from 'gateway/FsGateway'; import JobProviderFactory from 'job/JobProviderFactory'; import LicenseProviderFactory from 'license/LicenseProviderFactory'; @@ -8,22 +6,14 @@ import RegistrarFactory from './RegistrarFactory'; import ReporterGateway from 'gateway/ReporterGateway'; import { HOST_TMP_DIRECTORY } from 'constant'; -@injectable() export default class LocalCi { - @inject(Types.IFsGateway) - fsGateway!: FsGateway; - - @inject(JobProviderFactory) - jobProviderFactory!: JobProviderFactory; - - @inject(LicenseProviderFactory) - licenseProviderFactory!: LicenseProviderFactory; - - @inject(RegistrarFactory) - registrarFactory!: RegistrarFactory; - - @inject(Types.IReporterGateway) - reporterGateway!: ReporterGateway; + constructor( + public fsGateway: FsGateway, + public jobProviderFactory: JobProviderFactory, + public licenseProviderFactory: LicenseProviderFactory, + public registrarFactory: RegistrarFactory, + public reporterGateway: ReporterGateway + ) {} activate(context: vscode.ExtensionContext) { this.reporterGateway.reporter.sendTelemetryEvent('activate'); diff --git a/src/common/RegistrarFactory.ts b/src/common/RegistrarFactory.ts index a22a28fe..731670c7 100644 --- a/src/common/RegistrarFactory.ts +++ b/src/common/RegistrarFactory.ts @@ -1,6 +1,4 @@ -import { inject, injectable } from 'inversify'; import type vscode from 'vscode'; -import Types from 'common/Types'; import Complain from 'command/Complain'; import ConfigFile from 'config/ConfigFile'; import CreateConfigFile from 'command/CreateConfigFile'; @@ -28,32 +26,31 @@ import ShowLogFile from 'command/ShowLogFile'; import StartDocker from 'command/StartDocker'; import TryProcessAgain from '../command/TryProcessAgain'; -@injectable() export default class RegistrarFactory { constructor( - @inject(Complain) private complain: Complain, - @inject(ConfigFile) private configFile: ConfigFile, - @inject(CreateConfigFile) private createConfigFile: CreateConfigFile, - @inject(DebugRepo) private debugRepo: DebugRepo, - @inject(EnterLicense) private enterLicense: EnterLicense, - @inject(EnterToken) private enterToken: EnterToken, - @inject(ExitAllJobs) private exitAllJobs: ExitAllJobs, - @inject(ExitJob) private exitJob: ExitJob, - @inject(FirstActivation) private firstActivation: FirstActivation, - @inject(GetLicense) private getLicense: GetLicense, - @inject(Help) private help: Help, - @inject(LicenseInput) private licenseInput: LicenseInput, - @inject(LogProviderFactory) private logProviderFactory: LogProviderFactory, - @inject(Refresh) private refresh: Refresh, - @inject(RefreshLicenseTree) private refreshLicenseTree: RefreshLicenseTree, - @inject(ReRunJob) private reRunJob: ReRunJob, - @inject(RunJob) private runJob: RunJob, - @inject(RunWalkthroughJob) private runWalkthroughJob: RunWalkthroughJob, - @inject(SelectRepo) private selectRepo: SelectRepo, - @inject(ShowLogFile) private showLogFile: ShowLogFile, - @inject(StartDocker) private startDocker: StartDocker, - @inject(TryProcessAgain) private tryProcessAgain: TryProcessAgain, - @inject(Types.IEditorGateway) private editorGateway: EditorGateway + private complain: Complain, + private configFile: ConfigFile, + private createConfigFile: CreateConfigFile, + private debugRepo: DebugRepo, + private enterLicense: EnterLicense, + private enterToken: EnterToken, + private exitAllJobs: ExitAllJobs, + private exitJob: ExitJob, + private firstActivation: FirstActivation, + private getLicense: GetLicense, + private help: Help, + private licenseInput: LicenseInput, + private logProviderFactory: LogProviderFactory, + private refresh: Refresh, + private refreshLicenseTree: RefreshLicenseTree, + private reRunJob: ReRunJob, + private runJob: RunJob, + private runWalkthroughJob: RunWalkthroughJob, + private selectRepo: SelectRepo, + private showLogFile: ShowLogFile, + private startDocker: StartDocker, + private tryProcessAgain: TryProcessAgain, + private editorGateway: EditorGateway ) {} create( diff --git a/src/common/Spawn.ts b/src/common/Spawn.ts index b141905f..c19ed425 100644 --- a/src/common/Spawn.ts +++ b/src/common/Spawn.ts @@ -1,18 +1,13 @@ -import { inject, injectable } from 'inversify'; import EnvPath from './EnvPath'; import ProcessGateway from 'gateway/ProcessGateway'; import Workspace from './Workspace'; -@injectable() export default class Spawn { - @inject(EnvPath) - envPath!: EnvPath; - - @inject(ProcessGateway) - processGateway!: ProcessGateway; - - @inject(Workspace) - workspace!: Workspace; + constructor( + public envPath: EnvPath, + public processGateway: ProcessGateway, + public workspace: Workspace + ) {} getOptions(cwd?: string): SpawnOptions { return { diff --git a/src/common/Workspace.ts b/src/common/Workspace.ts index f97b4f49..92339994 100644 --- a/src/common/Workspace.ts +++ b/src/common/Workspace.ts @@ -1,11 +1,7 @@ -import { inject, injectable } from 'inversify'; -import Types from 'common/Types'; import EditorGateway from 'gateway/EditorGateway'; -@injectable() export default class Workspace { - @inject(Types.IEditorGateway) - editorGateway!: EditorGateway; + constructor(public editorGateway: EditorGateway) {} /** * Gets the absolute path to the 1st VS Code workspace folder. diff --git a/src/common/test/EnvPath.spec.ts b/src/common/test/EnvPath.spec.ts index a100a48f..c49ec0dd 100644 --- a/src/common/test/EnvPath.spec.ts +++ b/src/common/test/EnvPath.spec.ts @@ -1,24 +1,9 @@ -import AppTestHarness from 'test-tool/helper/AppTestHarness'; -import EnvPath from 'common/EnvPath'; -import FakeOsGateway from 'gateway/FakeOsGateway'; -import FakeProcessGateway from 'gateway/FakeProcessGateway'; - -let testHarness: AppTestHarness; -let envPath: EnvPath; -let osGateway: FakeOsGateway; -let processGateway: FakeProcessGateway; +import getContainer from 'test-tool/TestRoot'; describe('EnvPath', () => { - beforeEach(() => { - testHarness = new AppTestHarness(); - testHarness.init(); - envPath = testHarness.container.get(EnvPath); - osGateway = testHarness.osGateway; - processGateway = testHarness.processGateway; - }); - describe('get', () => { test('on Linux', () => { + const { envPath, osGateway, processGateway } = getContainer(); osGateway.os.type = jest.fn().mockImplementationOnce(() => 'Linux'); processGateway.process.env = { PATH: '' }; @@ -26,6 +11,7 @@ describe('EnvPath', () => { }); test('on Mac without the bin path', () => { + const { envPath, osGateway, processGateway } = getContainer(); osGateway.os.type = jest.fn().mockImplementationOnce(() => 'Darwin'); processGateway.process.env = { PATH: 'Users/Foo/' }; @@ -33,6 +19,7 @@ describe('EnvPath', () => { }); test('on Mac with the bin path', () => { + const { envPath, osGateway, processGateway } = getContainer(); osGateway.os.type = jest.fn().mockImplementationOnce(() => 'Darwin'); processGateway.process.env = { PATH: 'Users/Foo/:/usr/local/bin' }; @@ -42,16 +29,19 @@ describe('EnvPath', () => { describe('isMac', () => { test('mac', () => { + const { envPath, osGateway } = getContainer(); osGateway.os.type = () => 'Darwin'; expect(envPath.isMac()); }); test('linux', () => { + const { envPath, osGateway } = getContainer(); osGateway.os.type = () => 'Linux'; expect(envPath.isMac()).toEqual(false); }); test('windows', () => { + const { envPath, osGateway } = getContainer(); osGateway.os.type = () => 'Windows_NT'; expect(envPath.isMac()).toEqual(false); }); diff --git a/src/common/test/LocalCi.spec.ts b/src/common/test/LocalCi.spec.ts index be3ae6c1..8532c107 100644 --- a/src/common/test/LocalCi.spec.ts +++ b/src/common/test/LocalCi.spec.ts @@ -1,24 +1,9 @@ -import AppTestHarness from 'test-tool/helper/AppTestHarness'; -import FakeEditorGateway from 'gateway/FakeEditorGateway'; -import FakeFsGateway from 'gateway/FakeFsGateway'; import getContextStub from 'test-tool/helper/getContextStub'; -import LocalCi from 'common/LocalCi'; - -let editorGateway: FakeEditorGateway; -let fsGateway: FakeFsGateway; -let localCi: LocalCi; -let testHarness: AppTestHarness; +import getContainer from 'test-tool/TestRoot'; describe('LocalCi', () => { - beforeEach(() => { - testHarness = new AppTestHarness(); - testHarness.init(); - localCi = testHarness.container.get(LocalCi); - editorGateway = testHarness.editorGateway; - fsGateway = testHarness.fsGateway; - }); - test('activate registers commands', () => { + const { localCi, editorGateway } = getContainer(); const expectedCommands = [ 'local-ci.email.complain', 'local-ci.create.config', @@ -60,6 +45,7 @@ describe('LocalCi', () => { }); test('deactivate removes the tmp/ file', () => { + const { localCi, fsGateway } = getContainer(); fsGateway.fs.rmSync = jest.fn(); localCi.deactivate(); diff --git a/src/common/test/Spawn.spec.ts b/src/common/test/Spawn.spec.ts index a0cc0c84..9a53e2fa 100644 --- a/src/common/test/Spawn.spec.ts +++ b/src/common/test/Spawn.spec.ts @@ -1,26 +1,11 @@ -import AppTestHarness from 'test-tool/helper/AppTestHarness'; -import FakeEditorGateway from 'gateway/FakeEditorGateway'; -import FakeOsGateway from 'gateway/FakeOsGateway'; -import Spawn from 'common/Spawn'; - -let editorGateway: FakeEditorGateway; -let osGateway: FakeOsGateway; -let spawn: Spawn; -let testHarness: AppTestHarness; +import getContainer from 'test-tool/TestRoot'; describe('Spawn', () => { - beforeEach(() => { - testHarness = new AppTestHarness(); - testHarness.init(); - editorGateway = testHarness.editorGateway; - - osGateway = testHarness.osGateway; - spawn = testHarness.container.get(Spawn); - }); - test('has working directory', () => { + const { editorGateway, osGateway, spawn } = getContainer(); osGateway.os.platform = () => 'darwin'; const path = 'example'; + // @ts-expect-error read-only property. editorGateway.editor.workspace.workspaceFolders = [ { uri: { path }, @@ -31,11 +16,14 @@ describe('Spawn', () => { }); test('has bin directory', () => { + const { osGateway, spawn } = getContainer(); osGateway.os.platform = () => 'darwin'; expect(spawn.getOptions().env.PATH.includes('/usr/local/bin')); }); test('with cwd argument', () => { + const { spawn } = getContainer(); + expect(spawn.getOptions('/foo/baz').cwd).toEqual('/foo/baz'); }); }); diff --git a/src/common/test/Workspace.spec.ts b/src/common/test/Workspace.spec.ts index 654e2bcd..a356693e 100644 --- a/src/common/test/Workspace.spec.ts +++ b/src/common/test/Workspace.spec.ts @@ -1,26 +1,18 @@ -import AppTestHarness from 'test-tool/helper/AppTestHarness'; -import FakeEditorGateway from 'gateway/FakeEditorGateway'; -import Workspace from 'common/Workspace'; - -let editorGateway: FakeEditorGateway; -let testHarness: AppTestHarness; -let workspace: Workspace; +import getContainer from 'test-tool/TestRoot'; describe('Workspace', () => { - beforeEach(() => { - testHarness = new AppTestHarness(); - testHarness.init(); - workspace = testHarness.container.get(Workspace); - editorGateway = testHarness.editorGateway; - }); - test('with no workspaceFolders', () => { + const { editorGateway, workspace } = getContainer(); + + // @ts-expect-error read-only property. editorGateway.editor.workspace.workspaceFolders = []; expect(workspace.getFirstWorkspaceRootPath()).toEqual(''); }); - test('Wwith workspaceFolders', () => { + test('with workspaceFolders', () => { + const { editorGateway, workspace } = getContainer(); const path = 'example'; + // @ts-expect-error read-only property. editorGateway.editor.workspace.workspaceFolders = [ { uri: { path }, diff --git a/src/config/AllConfigFiles.ts b/src/config/AllConfigFiles.ts index f9841d57..abd83670 100644 --- a/src/config/AllConfigFiles.ts +++ b/src/config/AllConfigFiles.ts @@ -1,15 +1,10 @@ -import { inject, injectable } from 'inversify'; import type vscode from 'vscode'; -import Types from 'common/Types'; import EditorGateway from 'gateway/EditorGateway'; import getRepoBasename from 'common/getRepoBasename'; import { SELECTED_CONFIG_PATH } from 'constant'; -@injectable() export default class AllConfigFiles { - @inject(Types.IEditorGateway) - editorGateway!: EditorGateway; - + constructor(public editorGateway: EditorGateway) {} /** * Gets all of the paths to .circleci/config.yml files * diff --git a/src/config/BuildAgentSettings.ts b/src/config/BuildAgentSettings.ts index 9f775841..79db8bf1 100644 --- a/src/config/BuildAgentSettings.ts +++ b/src/config/BuildAgentSettings.ts @@ -1,20 +1,14 @@ -import { inject, injectable } from 'inversify'; import ChildProcessGateway from 'gateway/ChildProcessGateway'; import OsGateway from 'gateway/OsGateway'; import Spawn from 'common/Spawn'; -import Types from 'common/Types'; import { writeBuildAgentSettings } from 'script'; -@injectable() export default class BuildAgentSettings { - @inject(Types.IChildProcessGateway) - childProcessGateway!: ChildProcessGateway; - - @inject(Types.IOsGateway) - osGateway!: OsGateway; - - @inject(Spawn) - spawn!: Spawn; + constructor( + public childProcessGateway: ChildProcessGateway, + public osGateway: OsGateway, + public spawn: Spawn + ) {} set() { if (!this.isIntelMac()) { diff --git a/src/config/Config.ts b/src/config/Config.ts index 04cfe0ec..3aba2895 100644 --- a/src/config/Config.ts +++ b/src/config/Config.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from 'inversify'; import * as path from 'path'; import PipelineParameter from './PipelineParameter'; import ChildProcessGateway from 'gateway/ChildProcessGateway'; @@ -12,28 +11,17 @@ import getProcessFilePath from 'process/getProcessFilePath'; import ProcessFile from 'process/ProcessFile'; import ReporterGateway from 'gateway/ReporterGateway'; import Spawn from 'common/Spawn'; -import Types from 'common/Types'; import { RERUN_JOB_COMMAND } from 'constant'; -@injectable() export default class Config { - @inject(Types.IChildProcessGateway) - childProcessGateway!: ChildProcessGateway; - - @inject(Types.IEditorGateway) - editorGateway!: EditorGateway; - - @inject(Types.IFsGateway) - fsGateway!: FsGateway; - - @inject(PipelineParameter) - pipelineParameter!: PipelineParameter; - - @inject(ProcessFile) - processFile!: ProcessFile; - - @inject(Spawn) - spawn!: Spawn; + constructor( + public childProcessGateway: ChildProcessGateway, + public editorGateway: EditorGateway, + public fsGateway: FsGateway, + public pipelineParameter: PipelineParameter, + public processFile: ProcessFile, + public spawn: Spawn + ) {} process( configFilePath: string, diff --git a/src/config/ConfigFile.ts b/src/config/ConfigFile.ts index 60011451..7747d041 100644 --- a/src/config/ConfigFile.ts +++ b/src/config/ConfigFile.ts @@ -1,6 +1,4 @@ -import { inject, injectable } from 'inversify'; import type vscode from 'vscode'; -import Types from 'common/Types'; import AllConfigFiles from './AllConfigFiles'; import EditorGateway from 'gateway/EditorGateway'; import ReporterGateway from 'gateway/ReporterGateway'; @@ -10,16 +8,12 @@ import { SELECT_REPO_COMMAND, } from 'constant'; -@injectable() export default class ConfigFile { - @inject(AllConfigFiles) - allConfigFiles!: AllConfigFiles; - - @inject(Types.IEditorGateway) - editorGateway!: EditorGateway; - - @inject(Types.IReporterGateway) - reporterGateway!: ReporterGateway; + constructor( + public allConfigFiles: AllConfigFiles, + public editorGateway: EditorGateway, + public reporterGateway: ReporterGateway + ) {} /** * Gets the absolute path of the selected .circleci/config.yml to run the jobs on. diff --git a/src/config/ParsedConfig.ts b/src/config/ParsedConfig.ts index 21504592..3fd54b66 100644 --- a/src/config/ParsedConfig.ts +++ b/src/config/ParsedConfig.ts @@ -1,12 +1,8 @@ -import { inject, injectable } from 'inversify'; -import Types from 'common/Types'; import FsGateway from 'gateway/FsGateway'; import getConfig from './getConfig'; -@injectable() export default class ParsedConfig { - @inject(Types.IFsGateway) - fsGateway!: FsGateway; + constructor(public fsGateway: FsGateway) {} get(configFilePath: string): CiConfig { return this.fsGateway.fs.existsSync(configFilePath) diff --git a/src/config/PipelineParameter.ts b/src/config/PipelineParameter.ts index 6d58f9e8..9af1ae88 100644 --- a/src/config/PipelineParameter.ts +++ b/src/config/PipelineParameter.ts @@ -1,10 +1,7 @@ -import { inject, injectable } from 'inversify'; import FsGateway from 'gateway/FsGateway'; -@injectable() export default class PipelineParameter { - @inject(FsGateway) - fsGateway!: FsGateway; + constructor(public fsGateway: FsGateway) {} replace(parametersPath: string, configFilePath: string): void { if ( diff --git a/src/config/test/AllConfigFiles.spec.ts b/src/config/test/AllConfigFiles.spec.ts index 635c0528..34ef4e6f 100644 --- a/src/config/test/AllConfigFiles.spec.ts +++ b/src/config/test/AllConfigFiles.spec.ts @@ -1,8 +1,6 @@ -import Types from 'common/Types'; -import AllConfigFiles from 'config/AllConfigFiles'; -import AppTestHarness from 'test-tool/helper/AppTestHarness'; -import FakeEditorGateway from 'gateway/FakeEditorGateway'; import getContextStub from 'test-tool/helper/getContextStub'; +import getContainer from 'test-tool/TestRoot'; +import type { Uri } from 'vscode'; function getMockContext(filePath: string) { const initialContext = getContextStub(); @@ -19,26 +17,18 @@ function getMockContext(filePath: string) { }; } -let testHarness: AppTestHarness; -let allConfigFiles: AllConfigFiles; -let editorGateway: FakeEditorGateway; - describe('AllConfigFiles', () => { - beforeEach(() => { - testHarness = new AppTestHarness(); - testHarness.init(); - allConfigFiles = testHarness.container.get(AllConfigFiles); - editorGateway = testHarness.container.get(Types.IEditorGateway); - }); - test('stored config file', async () => { + const { allConfigFiles, editorGateway } = getContainer(); const selectedFilePath = '/baz/bar/ex'; editorGateway.editor.workspace.findFiles = () => + // @ts-expect-error type of stub is wrong. Promise.resolve([ { fsPath: '/path/to/here' }, { fsPath: selectedFilePath }, ]); - editorGateway.editor.workspace.asRelativePath = (path: string) => path; + editorGateway.editor.workspace.asRelativePath = (pathOrUri: string | Uri) => + String(pathOrUri); const actual = await allConfigFiles.getPaths( getMockContext(selectedFilePath) diff --git a/src/config/test/BuildAgentSettings.spec.ts b/src/config/test/BuildAgentSettings.spec.ts index cd4cf540..55ee3ba2 100644 --- a/src/config/test/BuildAgentSettings.spec.ts +++ b/src/config/test/BuildAgentSettings.spec.ts @@ -1,23 +1,9 @@ -import AppTestHarness from 'test-tool/helper/AppTestHarness'; -import BuildAgentSettings from 'config/BuildAgentSettings'; -import FakeChildProcessGateway from 'gateway/FakeChildProcessGateway'; -import FakeOsGateway from 'gateway/FakeOsGateway'; - -let buildAgentSettings: BuildAgentSettings; -let childProcessGateway: FakeChildProcessGateway; -let osGateway: FakeOsGateway; -let testHarness: AppTestHarness; +import getContainer from 'test-tool/TestRoot'; describe('BuildAgentSettings', () => { - beforeEach(() => { - testHarness = new AppTestHarness(); - testHarness.init(); - buildAgentSettings = testHarness.container.get(BuildAgentSettings); - osGateway = testHarness.osGateway; - childProcessGateway = testHarness.childProcessGateway; - }); - test('should not set the settings on a Linux machine', () => { + const { buildAgentSettings, childProcessGateway, osGateway } = + getContainer(); const spawnSpy = jest.fn(); osGateway.os.type = jest.fn().mockImplementationOnce(() => 'Intel'); osGateway.os.arch = jest.fn().mockImplementationOnce(() => 'x64'); @@ -28,6 +14,8 @@ describe('BuildAgentSettings', () => { }); test('should not set the settings on an M1 Mac machine', () => { + const { buildAgentSettings, childProcessGateway, osGateway } = + getContainer(); const spawnSpy = jest.fn(); osGateway.os.type = jest.fn().mockImplementationOnce(() => 'Darwin'); osGateway.os.arch = jest.fn().mockImplementationOnce(() => 'arm64'); @@ -38,6 +26,8 @@ describe('BuildAgentSettings', () => { }); test('should set the settings on an Intel Mac machine', () => { + const { buildAgentSettings, childProcessGateway, osGateway } = + getContainer(); const spawnSpy = jest.fn(); osGateway.os.type = jest.fn().mockImplementationOnce(() => 'Darwin'); osGateway.os.arch = jest.fn().mockImplementationOnce(() => 'x64'); diff --git a/src/config/test/ConfigFile.spec.ts b/src/config/test/ConfigFile.spec.ts index ef0e1b94..f427e5e5 100644 --- a/src/config/test/ConfigFile.spec.ts +++ b/src/config/test/ConfigFile.spec.ts @@ -1,7 +1,4 @@ -import ConfigFile from 'config/ConfigFile'; -import AppTestHarness from 'test-tool/helper/AppTestHarness'; -import EditorGateway from 'gateway/EditorGateway'; -import Types from 'common/Types'; +import getContainer from 'test-tool/TestRoot'; import getContextStub from 'test-tool/helper/getContextStub'; function getMockContext(filePath: string) { @@ -19,19 +16,9 @@ function getMockContext(filePath: string) { }; } -let testHarness: AppTestHarness; -let configFile: ConfigFile; -let editorGateway: EditorGateway; - describe('ConfigFile', () => { - beforeEach(() => { - testHarness = new AppTestHarness(); - testHarness.init(); - configFile = testHarness.container.get(ConfigFile); - editorGateway = testHarness.container.get(Types.IEditorGateway); - }); - test('stored config file', async () => { + const { configFile, editorGateway } = getContainer(); editorGateway.editor.workspace.getWorkspaceFolder = jest .fn() .mockImplementationOnce(() => ({ name: 'example' })); diff --git a/src/config/test/ParsedConfig.spec.ts b/src/config/test/ParsedConfig.spec.ts index b1ff4ecf..2e192d5a 100644 --- a/src/config/test/ParsedConfig.spec.ts +++ b/src/config/test/ParsedConfig.spec.ts @@ -1,21 +1,9 @@ -import AppTestHarness from 'test-tool/helper/AppTestHarness'; -import FakeFsGateway from 'gateway/FakeFsGateway'; import onlyJobsYml from 'test-tool/fixture/only-jobs.yml'; -import ParsedConfig from 'config/ParsedConfig'; - -let fsGateway: FakeFsGateway; -let parsedConfig: ParsedConfig; -let testHarness: AppTestHarness; +import getContainer from 'test-tool/TestRoot'; describe('ParsedConfig', () => { - beforeEach(() => { - testHarness = new AppTestHarness(); - testHarness.init(); - parsedConfig = testHarness.container.get(ParsedConfig); - fsGateway = testHarness.fsGateway; - }); - test('no config', () => { + const { fsGateway, parsedConfig } = getContainer(); const existsSyncSpy = jest.fn().mockImplementationOnce(() => false); fsGateway.fs.existsSync = existsSyncSpy; @@ -23,6 +11,7 @@ describe('ParsedConfig', () => { }); test('with config', () => { + const { fsGateway, parsedConfig } = getContainer(); const existsSyncSpy = jest.fn().mockImplementationOnce(() => true); const readFileSyncSpy = jest.fn().mockImplementationOnce(() => onlyJobsYml); diff --git a/src/containerization/Docker.ts b/src/containerization/Docker.ts index 593508a7..c1493288 100644 --- a/src/containerization/Docker.ts +++ b/src/containerization/Docker.ts @@ -1,15 +1,11 @@ -import { inject, injectable } from 'inversify'; import ChildProcessGateway from 'gateway/ChildProcessGateway'; import Spawn from 'common/Spawn'; -import Types from 'common/Types'; -@injectable() class Docker { - @inject(Types.IChildProcessGateway) - childProcessGateway!: ChildProcessGateway; - - @inject(Spawn) - spawn!: Spawn; + constructor( + public childProcessGateway: ChildProcessGateway, + public spawn: Spawn + ) {} getError(): string { try { diff --git a/src/containerization/FakeVolume.ts b/src/containerization/FakeVolume.ts index 6d899a05..1f1076e5 100644 --- a/src/containerization/FakeVolume.ts +++ b/src/containerization/FakeVolume.ts @@ -1,6 +1,3 @@ -import { injectable } from 'inversify'; - -@injectable() export default class FakeVolume { isEmpty = () => false; } diff --git a/src/containerization/Images.ts b/src/containerization/Images.ts index 400f6227..483ef7dd 100644 --- a/src/containerization/Images.ts +++ b/src/containerization/Images.ts @@ -1,16 +1,12 @@ -import { inject, injectable } from 'inversify'; import ChildProcessGateway from 'gateway/ChildProcessGateway'; import Spawn from 'common/Spawn'; -import Types from 'common/Types'; import { cleanUpImages } from 'script'; -@injectable() export default class Images { - @inject(Types.IChildProcessGateway) - childProcessGateway!: ChildProcessGateway; - - @inject(Spawn) - spawn!: Spawn; + constructor( + public childProcessGateway: ChildProcessGateway, + public spawn: Spawn + ) {} cleanUp(imagePattern: string, imageIdToExclude?: string): void { this.childProcessGateway.cp.spawn( diff --git a/src/containerization/LatestCommittedImage.ts b/src/containerization/LatestCommittedImage.ts index 998eeda0..81109b3a 100644 --- a/src/containerization/LatestCommittedImage.ts +++ b/src/containerization/LatestCommittedImage.ts @@ -1,15 +1,11 @@ -import { inject, injectable } from 'inversify'; import ChildProcessGateway from 'gateway/ChildProcessGateway'; import Spawn from 'common/Spawn'; -import Types from 'common/Types'; -@injectable() export default class LatestCommittedImage { - @inject(Spawn) - spawn!: Spawn; - - @inject(Types.IChildProcessGateway) - childProcessGateway!: ChildProcessGateway; + constructor( + public spawn: Spawn, + public childProcessGateway: ChildProcessGateway + ) {} get(committedImageName: string): Promise { const { stdout, stderr } = this.childProcessGateway.cp.spawn( diff --git a/src/containerization/RunningContainer.ts b/src/containerization/RunningContainer.ts index f9d2ffe7..b2c3998d 100644 --- a/src/containerization/RunningContainer.ts +++ b/src/containerization/RunningContainer.ts @@ -1,16 +1,12 @@ -import { inject, injectable } from 'inversify'; import ChildProcessGateway from 'gateway/ChildProcessGateway'; import Spawn from 'common/Spawn'; -import Types from 'common/Types'; import { commitContainer, getRunningContainerFunction } from 'script'; -@injectable() export default class RunningContainer { - @inject(Spawn) - spawn!: Spawn; - - @inject(Types.IChildProcessGateway) - childProcessGateway!: ChildProcessGateway; + constructor( + public spawn: Spawn, + public childProcessGateway: ChildProcessGateway + ) {} /** * Commits the latest container so that this can open an interactive session when it finishes. diff --git a/src/containerization/UncommittedFile.ts b/src/containerization/UncommittedFile.ts index fe95eb5f..5e19896a 100644 --- a/src/containerization/UncommittedFile.ts +++ b/src/containerization/UncommittedFile.ts @@ -1,21 +1,15 @@ -import { inject, injectable } from 'inversify'; import type vscode from 'vscode'; import ChildProcessGateway from 'gateway/ChildProcessGateway'; import EditorGateway from 'gateway/EditorGateway'; import Spawn from 'common/Spawn'; -import Types from 'common/Types'; import { SUPPRESS_UNCOMMITTED_FILE_WARNING } from 'constant'; -@injectable() export default class UncommittedFile { - @inject(Types.IChildProcessGateway) - childProcess!: ChildProcessGateway; - - @inject(Types.IEditorGateway) - editorGateway!: EditorGateway; - - @inject(Spawn) - spawn!: Spawn; + constructor( + public childProcess: ChildProcessGateway, + public editorGateway: EditorGateway, + public spawn: Spawn + ) {} /** * Shows a warning if there are uncommitted files in the repo. diff --git a/src/containerization/Volume.ts b/src/containerization/Volume.ts index 8f535ece..e7051b8e 100644 --- a/src/containerization/Volume.ts +++ b/src/containerization/Volume.ts @@ -1,17 +1,9 @@ -import { inject, injectable } from 'inversify'; -import Types from 'common/Types'; -import ConfigFile from '../config/ConfigFile'; import FsGateway from 'gateway/FsGateway'; import getLocalVolumePath from 'containerization/getLocalVolumePath'; import { DYNAMIC_CONFIG_FILE_NAME } from 'constant'; -@injectable() export default class Volume { - @inject(Types.IFsGateway) - fsGateway!: FsGateway; - - @inject(ConfigFile) - configFile!: ConfigFile; + constructor(public fsGateway: FsGateway) {} isEmpty(configFilePath: string): boolean { const localConfigFile = getLocalVolumePath(configFilePath); diff --git a/src/containerization/test/Docker.spec.ts b/src/containerization/test/Docker.spec.ts index 3c039442..0cb23650 100644 --- a/src/containerization/test/Docker.spec.ts +++ b/src/containerization/test/Docker.spec.ts @@ -1,22 +1,9 @@ -import AppTestHarness from 'test-tool/helper/AppTestHarness'; -import ChildProcessGateway from 'gateway/ChildProcessGateway'; -import Docker from 'containerization/Docker'; -import Types from 'common/Types'; - -let childProcessGateway: ChildProcessGateway; -let docker: Docker; -let testHarness: AppTestHarness; +import getContainer from 'test-tool/TestRoot'; describe('Docker', () => { - beforeEach(() => { - testHarness = new AppTestHarness(); - testHarness.init(); - docker = testHarness.container.get(Docker); - childProcessGateway = testHarness.container.get(Types.IChildProcessGateway); - }); - describe('getError', () => { test('no error', () => { + const { childProcessGateway, docker } = getContainer(); const execSyncSpy = jest.fn(); childProcessGateway.cp.execSync = execSyncSpy; expect(docker.getError()).toEqual(''); @@ -24,6 +11,7 @@ describe('Docker', () => { }); test('with error', () => { + const { childProcessGateway, docker } = getContainer(); const message = 'Cannot connect to the Docker daemon'; const execSyncSpy = jest.fn().mockImplementationOnce(() => { @@ -37,6 +25,7 @@ describe('Docker', () => { describe('isRunning', () => { test('is not running', () => { + const { childProcessGateway, docker } = getContainer(); const execSyncSpy = jest.fn().mockImplementationOnce(() => { throw new Error('Cannot connect to the Docker daemon'); }); @@ -45,6 +34,7 @@ describe('Docker', () => { }); test('is running', () => { + const { childProcessGateway, docker } = getContainer(); childProcessGateway.cp.execSync = jest.fn(); expect(docker.isRunning()).toEqual(true); }); diff --git a/src/containerization/test/Images.spec.ts b/src/containerization/test/Images.spec.ts index 1036aeeb..d432978e 100644 --- a/src/containerization/test/Images.spec.ts +++ b/src/containerization/test/Images.spec.ts @@ -1,20 +1,8 @@ -import AppTestHarness from 'test-tool/helper/AppTestHarness'; -import Images from 'containerization/Images'; -import FakeChildProcessGateway from 'gateway/FakeChildProcessGateway'; - -let childProcessGateway: FakeChildProcessGateway; -let images: Images; -let testHarness: AppTestHarness; +import getContainer from 'test-tool/TestRoot'; describe('Images', () => { - beforeEach(() => { - testHarness = new AppTestHarness(); - testHarness.init(); - images = testHarness.container.get(Images); - childProcessGateway = testHarness.childProcessGateway; - }); - test('no error', () => { + const { images, childProcessGateway } = getContainer(); const spawnSpy = jest.fn(); childProcessGateway.cp.spawn = spawnSpy; diff --git a/src/containerization/test/UncommittedFile.spec.ts b/src/containerization/test/UncommittedFile.spec.ts index 94b48a16..599cd4f2 100644 --- a/src/containerization/test/UncommittedFile.spec.ts +++ b/src/containerization/test/UncommittedFile.spec.ts @@ -1,8 +1,5 @@ -import AppTestHarness from 'test-tool/helper/AppTestHarness'; -import FakeChildProcessGateway from 'gateway/FakeChildProcessGateway'; -import FakeEditorGateway from 'gateway/FakeEditorGateway'; +import getContainer from 'test-tool/TestRoot'; import getContextStub from 'test-tool/helper/getContextStub'; -import UncommittedFile from 'containerization/UncommittedFile'; function getMockContext(isSuppressed: boolean) { const initialContext = getContextStub(); @@ -17,28 +14,19 @@ function getMockContext(isSuppressed: boolean) { }; } -let childProcessGateway: FakeChildProcessGateway; -let editorGateway: FakeEditorGateway; -let uncommittedFile: UncommittedFile; -let testHarness: AppTestHarness; - describe('uncommittedWarning', () => { - beforeEach(() => { - testHarness = new AppTestHarness(); - testHarness.init(); - uncommittedFile = testHarness.container.get(UncommittedFile); - childProcessGateway = testHarness.childProcessGateway; - editorGateway = testHarness.editorGateway; - }); - test('warning is suppressed', async () => { + const { editorGateway, uncommittedFile } = getContainer(); const showWarningMessageSpy = jest.fn(); (editorGateway.editor.window.showWarningMessage = showWarningMessageSpy), uncommittedFile.warn(getMockContext(true), '/foo/baz', 'build', []); + expect(showWarningMessageSpy).not.toHaveBeenCalled(); }); test('no uncommitted file', async () => { + const { childProcessGateway, editorGateway, uncommittedFile } = + getContainer(); const showWarningMessageSpy = jest.fn(); editorGateway.editor.window.showWarningMessage = (message: string) => { return new Promise(() => { @@ -60,6 +48,8 @@ describe('uncommittedWarning', () => { }); test('only an uncommitted config file should not show a warning', async () => { + const { childProcessGateway, editorGateway, uncommittedFile } = + getContainer(); const showWarningMessageSpy = jest.fn(); editorGateway.editor.window.showWarningMessage = (message: string) => { return new Promise(() => { @@ -81,6 +71,8 @@ describe('uncommittedWarning', () => { }); test('with uncommitted files', async () => { + const { childProcessGateway, editorGateway, uncommittedFile } = + getContainer(); const showWarningMessageSpy = jest.fn(); editorGateway.editor.window.showWarningMessage = (message: string) => { return new Promise(() => { @@ -102,6 +94,8 @@ describe('uncommittedWarning', () => { }); test('not a checkout job', async () => { + const { childProcessGateway, editorGateway, uncommittedFile } = + getContainer(); const showWarningMessageSpy = jest.fn(); editorGateway.editor.window.showWarningMessage = (message: string) => { return new Promise(() => { diff --git a/src/extension.ts b/src/extension.ts index 466c486f..357b7c27 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,11 +1,10 @@ -import { iocContainer } from 'common/AppIoc'; +import { app } from 'CompositionRoot'; import type vscode from 'vscode'; -import LocalCi from 'common/LocalCi'; export function activate(context: vscode.ExtensionContext) { - iocContainer.get(LocalCi).activate(context); + app.activate(context); } export function deactivate() { - iocContainer.get(LocalCi).deactivate(); + app.deactivate(); } diff --git a/src/gateway/ChildProcessGateway.ts b/src/gateway/ChildProcessGateway.ts index 2eeab910..f40459ad 100644 --- a/src/gateway/ChildProcessGateway.ts +++ b/src/gateway/ChildProcessGateway.ts @@ -1,7 +1,5 @@ import * as cp from 'child_process'; -import { injectable } from 'inversify'; -@injectable() export default class ChildProcessGateway { cp = cp; } diff --git a/src/gateway/EditorGateway.ts b/src/gateway/EditorGateway.ts index a2f85d9b..1b4db400 100644 --- a/src/gateway/EditorGateway.ts +++ b/src/gateway/EditorGateway.ts @@ -1,7 +1,5 @@ import * as vscode from 'vscode'; -import { injectable } from 'inversify'; -@injectable() export default class EditorGateway { editor = vscode; } diff --git a/src/gateway/FakeChildProcessGateway.ts b/src/gateway/FakeChildProcessGateway.ts index 9925d983..9952d174 100644 --- a/src/gateway/FakeChildProcessGateway.ts +++ b/src/gateway/FakeChildProcessGateway.ts @@ -1,7 +1,3 @@ -import { injectable } from 'inversify'; - -/** Stub class for cp. */ -@injectable() export default class FakeChildProcessGateway { cp = { spawn: () => null, diff --git a/src/gateway/FakeEditorGateway.ts b/src/gateway/FakeEditorGateway.ts index ed79e786..2da11f1d 100644 --- a/src/gateway/FakeEditorGateway.ts +++ b/src/gateway/FakeEditorGateway.ts @@ -1,8 +1,5 @@ /* eslint-disable @typescript-eslint/no-empty-function */ -import { injectable } from 'inversify'; -/** Stub class for the editor. */ -@injectable() export default class FakeEditorGateway { editor = { commands: { diff --git a/src/gateway/FakeFsGateway.ts b/src/gateway/FakeFsGateway.ts index 1441a843..ffc2dd07 100644 --- a/src/gateway/FakeFsGateway.ts +++ b/src/gateway/FakeFsGateway.ts @@ -1,7 +1,3 @@ -import { injectable } from 'inversify'; - -/** Stub class for filesystem. */ -@injectable() export default class FakeFsGateway { fs = { existsSync: () => null, diff --git a/src/gateway/FakeHttpGateway.ts b/src/gateway/FakeHttpGateway.ts index 798403cc..9b3f8031 100644 --- a/src/gateway/FakeHttpGateway.ts +++ b/src/gateway/FakeHttpGateway.ts @@ -1,6 +1,3 @@ -import { injectable } from 'inversify'; - -@injectable() export default class FakeHttpGateway { get = async () => null; post = async () => null; diff --git a/src/gateway/FakeOsGateway.ts b/src/gateway/FakeOsGateway.ts index 72879b51..aa81289b 100644 --- a/src/gateway/FakeOsGateway.ts +++ b/src/gateway/FakeOsGateway.ts @@ -1,7 +1,3 @@ -import { injectable } from 'inversify'; - -/** Stub class for operating system. */ -@injectable() export default class FakeOsGateway { os = { arch: () => '', diff --git a/src/gateway/FakeProcessGateway.ts b/src/gateway/FakeProcessGateway.ts index ba5210df..7834ed0b 100644 --- a/src/gateway/FakeProcessGateway.ts +++ b/src/gateway/FakeProcessGateway.ts @@ -1,7 +1,3 @@ -import { injectable } from 'inversify'; - -/** Stub class for process. */ -@injectable() export default class FakeProcessGateway { process = { env: { PATH: 'example/here/' }, diff --git a/src/gateway/FakeReporterGateway.ts b/src/gateway/FakeReporterGateway.ts index f2353455..27dbdb21 100644 --- a/src/gateway/FakeReporterGateway.ts +++ b/src/gateway/FakeReporterGateway.ts @@ -1,6 +1,3 @@ -import { injectable } from 'inversify'; - -@injectable() export default class FakeReporterGateway { reporter = { sendTelemetryEvent: () => null, diff --git a/src/gateway/FsGateway.ts b/src/gateway/FsGateway.ts index 1ff4713f..f48059e3 100644 --- a/src/gateway/FsGateway.ts +++ b/src/gateway/FsGateway.ts @@ -1,7 +1,4 @@ import * as fs from 'fs'; -import { injectable } from 'inversify'; - -@injectable() export default class FsGateway { fs = fs; } diff --git a/src/gateway/HttpGateway.ts b/src/gateway/HttpGateway.ts index 87910c2c..b0b75d5c 100644 --- a/src/gateway/HttpGateway.ts +++ b/src/gateway/HttpGateway.ts @@ -1,7 +1,5 @@ -import { injectable } from 'inversify'; import axios from 'axios'; -@injectable() export default class HttpGateway { async get(url: string, config: Record) { return await axios.get(url, config); diff --git a/src/gateway/LoggingChildProcessGateway.ts b/src/gateway/LoggingChildProcessGateway.ts index 31d7d164..62e17ed3 100644 --- a/src/gateway/LoggingChildProcessGateway.ts +++ b/src/gateway/LoggingChildProcessGateway.ts @@ -1,5 +1,4 @@ import * as cp from 'child_process'; -import { inject, injectable } from 'inversify'; import EditorGateway from './EditorGateway'; /** @@ -8,13 +7,12 @@ import EditorGateway from './EditorGateway'; * To debug the bash commands run with ChildProcessGateway.cp.spawn(), * replaces ChildProcessGateway with this file in AppIoc.ts. */ -@injectable() export default class LoggingChildProcessGateway { cp; outputChannel; outputChannelId = 'Local CI'; - constructor(@inject(EditorGateway) private editorGateway: EditorGateway) { + constructor(private editorGateway: EditorGateway) { this.cp = { ...cp, spawn: ( diff --git a/src/gateway/OsGateway.ts b/src/gateway/OsGateway.ts index d4c70d2b..7e98844f 100644 --- a/src/gateway/OsGateway.ts +++ b/src/gateway/OsGateway.ts @@ -1,7 +1,5 @@ -import { injectable } from 'inversify'; import * as os from 'os'; -@injectable() export default class OsGateway { os = os; } diff --git a/src/gateway/ProcessGateway.ts b/src/gateway/ProcessGateway.ts index 7ae4c92a..29d851ef 100644 --- a/src/gateway/ProcessGateway.ts +++ b/src/gateway/ProcessGateway.ts @@ -1,6 +1,3 @@ -import { injectable } from 'inversify'; - -@injectable() export default class ProcessGateway { process = process; } diff --git a/src/gateway/ReporterGateway.ts b/src/gateway/ReporterGateway.ts index 00e81aa9..6a60899e 100644 --- a/src/gateway/ReporterGateway.ts +++ b/src/gateway/ReporterGateway.ts @@ -1,16 +1,11 @@ -import { inject, injectable } from 'inversify'; -import Types from 'common/Types'; import EditorGateway from './EditorGateway'; import TelemetryReporter from '@vscode/extension-telemetry'; import { EXTENSION_ID, TELEMETRY_KEY } from 'constant'; -@injectable() export default class ReporterGateway { reporter: TelemetryReporter; - constructor( - @inject(Types.IEditorGateway) private editorGateway: EditorGateway - ) { + constructor(private editorGateway: EditorGateway) { this.reporter = new TelemetryReporter( EXTENSION_ID, this.editorGateway.editor.extensions.getExtension( diff --git a/src/job/AllJobs.ts b/src/job/AllJobs.ts index cf3dba1b..17a4a272 100644 --- a/src/job/AllJobs.ts +++ b/src/job/AllJobs.ts @@ -1,13 +1,10 @@ -import { inject, injectable } from 'inversify'; import getConfig from 'config/getConfig'; import getDynamicConfigPath from 'config/getDynamicConfigPath'; import getJobs from './getJobs'; import ParsedConfig from 'config/ParsedConfig'; -@injectable() export default class AllJobs { - @inject(ParsedConfig) - parsedConfig!: ParsedConfig; + constructor(public parsedConfig: ParsedConfig) {} get( processedConfig: string, diff --git a/src/job/Children.ts b/src/job/Children.ts index 62a2fad8..04d4bca2 100644 --- a/src/job/Children.ts +++ b/src/job/Children.ts @@ -1,6 +1,4 @@ import * as path from 'path'; -import { inject, injectable } from 'inversify'; -import Types from 'common/Types'; import { JobError } from './JobProvider'; import LogFactory from 'log/LogFactory'; import type vscode from 'vscode'; @@ -25,28 +23,16 @@ import { type Logs = Record; type JobDependencies = Map | undefined; -@injectable() export default class Children { - @inject(CommandFactory) - commandFactory!: CommandFactory; - - @inject(Types.IEditorGateway) - editorGateway!: EditorGateway; - - @inject(JobFactory) - jobFactory!: JobFactory; - - @inject(LogFactory) - logFactory!: LogFactory; - - @inject(NativeCommandFactory) - nativeCommandFactory!: NativeCommandFactory; - - @inject(WarningCommandFactory) - warningCommandFactory!: WarningCommandFactory; - - @inject(WarningFactory) - warningFactory!: WarningFactory; + constructor( + public commandFactory: CommandFactory, + public editorGateway: EditorGateway, + public jobFactory: JobFactory, + public logFactory: LogFactory, + public nativeCommandFactory: NativeCommandFactory, + public warningCommandFactory: WarningCommandFactory, + public warningFactory: WarningFactory + ) {} get( jobs: string[], diff --git a/src/job/ComandFactory.ts b/src/job/ComandFactory.ts index 6506107f..3c219c6a 100644 --- a/src/job/ComandFactory.ts +++ b/src/job/ComandFactory.ts @@ -1,12 +1,8 @@ -import { inject, injectable } from 'inversify'; import EditorGateway from 'gateway/EditorGateway'; -import Types from 'common/Types'; import CommandTreeItem from './CommandTreeItem'; -@injectable() export default class CommandFactory { - @inject(Types.IEditorGateway) - editorGateway!: EditorGateway; + constructor(public editorGateway: EditorGateway) {} create(label: string, command: string) { return new CommandTreeItem(this.editorGateway, label, command); diff --git a/src/job/FirstActivation.ts b/src/job/FirstActivation.ts index 689c7e02..db6792c2 100644 --- a/src/job/FirstActivation.ts +++ b/src/job/FirstActivation.ts @@ -1,21 +1,15 @@ -import { inject, injectable } from 'inversify'; import type vscode from 'vscode'; -import Types from 'common/Types'; import EditorGateway from 'gateway/EditorGateway'; import Email from 'license/Email'; import ReporterGateway from 'gateway/ReporterGateway'; import { EXTENSION_ID, TRIAL_STARTED_TIMESTAMP } from 'constant'; -@injectable() export default class FirstActivation { - @inject(Types.IEditorGateway) - editorGateway!: EditorGateway; - - @inject(Types.IReporterGateway) - reporterGateway!: ReporterGateway; - - @inject(Email) - email!: Email; + constructor( + public editorGateway: EditorGateway, + public reporterGateway: ReporterGateway, + public email: Email + ) {} handle(context: vscode.ExtensionContext) { if (!context.globalState.get(TRIAL_STARTED_TIMESTAMP)) { diff --git a/src/job/JobFactory.ts b/src/job/JobFactory.ts index 8a91903d..68e6af41 100644 --- a/src/job/JobFactory.ts +++ b/src/job/JobFactory.ts @@ -1,12 +1,8 @@ -import { inject, injectable } from 'inversify'; -import Types from 'common/Types'; import EditorGateway from 'gateway/EditorGateway'; import JobTreeItem from './JobTreeItem'; -@injectable() export default class JobFactory { - @inject(Types.IEditorGateway) - editorGateway!: EditorGateway; + constructor(public editorGateway: EditorGateway) {} create(label: string, isRunning: boolean, hasChildJob: boolean) { return new JobTreeItem(this.editorGateway, label, isRunning, hasChildJob); diff --git a/src/job/JobListener.ts b/src/job/JobListener.ts index 5b3ae5ff..02adf4b7 100644 --- a/src/job/JobListener.ts +++ b/src/job/JobListener.ts @@ -1,6 +1,4 @@ -import { inject, injectable } from 'inversify'; import type vscode from 'vscode'; -import Types from 'common/Types'; import ChildProcessGateway from 'gateway/ChildProcessGateway'; import Images from 'containerization/Images'; import ConfigFile from 'config/ConfigFile'; @@ -18,31 +16,17 @@ import { } from 'constant'; import { getPicardContainerFunction } from 'script'; -@injectable() export default class JobListener { - @inject(Types.IChildProcessGateway) - childProcessGateway!: ChildProcessGateway; - - @inject(Images) - images!: Images; - - @inject(ConfigFile) - configFile!: ConfigFile; - - @inject(Types.IEditorGateway) - editorGateway!: EditorGateway; - - @inject(FsGateway) - fsGateway!: FsGateway; - - @inject(LogFile) - logFile!: LogFile; - - @inject(ParsedConfig) - parsedConfig!: ParsedConfig; - - @inject(Spawn) - spawn!: Spawn; + constructor( + public childProcessGateway: ChildProcessGateway, + public images: Images, + public configFile: ConfigFile, + public editorGateway: EditorGateway, + public fsGateway: FsGateway, + public logFile: LogFile, + public parsedConfig: ParsedConfig, + public spawn: Spawn + ) {} listen( context: vscode.ExtensionContext, diff --git a/src/job/JobProvider.ts b/src/job/JobProvider.ts index 4daef9c3..a7b601ac 100644 --- a/src/job/JobProvider.ts +++ b/src/job/JobProvider.ts @@ -1,4 +1,3 @@ -import { injectable } from 'inversify'; import * as path from 'path'; import type vscode from 'vscode'; import type Retryer from './Retryer'; @@ -27,7 +26,6 @@ export enum JobError { ProcessFile, } -@injectable() export default class JobProvider implements vscode.TreeDataProvider { diff --git a/src/job/JobProviderFactory.ts b/src/job/JobProviderFactory.ts index 6ac7a389..4ed364ab 100644 --- a/src/job/JobProviderFactory.ts +++ b/src/job/JobProviderFactory.ts @@ -1,6 +1,4 @@ -import { inject, injectable } from 'inversify'; import type vscode from 'vscode'; -import Types from 'common/Types'; import AllConfigFiles from 'config/AllConfigFiles'; import AllJobs from './AllJobs'; import Children from './Children'; @@ -18,52 +16,24 @@ import ReporterGateway from 'gateway/ReporterGateway'; import WarningFactory from './WarningFactory'; import Retryer from './Retryer'; -@injectable() export default class JobProviderFactory { - @inject(AllConfigFiles) - allConfigFiles!: AllConfigFiles; - - @inject(Children) - children!: Children; - - @inject(ConfigFile) - configFile!: ConfigFile; - - @inject(CommandFactory) - commandFactory!: CommandFactory; - - @inject(Docker) - docker!: Docker; - - @inject(Types.IEditorGateway) - editorGateway!: EditorGateway; - - @inject(Types.IFsGateway) - fsGateway!: FsGateway; - - @inject(License) - license!: License; - - @inject(Config) - config!: Config; - - @inject(JobFactory) - jobFactory!: JobFactory; - - @inject(LogFactory) - logFactory!: LogFactory; - - @inject(Types.IReporterGateway) - reporterGateway!: ReporterGateway; - - @inject(Retryer) - retryer!: Retryer; - - @inject(WarningFactory) - warningFactory!: WarningFactory; - - @inject(AllJobs) - allJobs!: AllJobs; + constructor( + public allConfigFiles: AllConfigFiles, + public children: Children, + public configFile: ConfigFile, + public commandFactory: CommandFactory, + public docker: Docker, + public editorGateway: EditorGateway, + public fsGateway: FsGateway, + public license: License, + public config: Config, + public jobFactory: JobFactory, + public logFactory: LogFactory, + public reporterGateway: ReporterGateway, + public retryer: Retryer, + public warningFactory: WarningFactory, + public allJobs: AllJobs + ) {} create( context: vscode.ExtensionContext, diff --git a/src/job/JobRunner.ts b/src/job/JobRunner.ts index 5c7ead44..dfe630fd 100644 --- a/src/job/JobRunner.ts +++ b/src/job/JobRunner.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from 'inversify'; import * as path from 'path'; import type vscode from 'vscode'; import { getBinaryPath } from '../../node/binary'; @@ -27,7 +26,6 @@ import JobTreeItem from './JobTreeItem'; import LatestCommittedImage from 'containerization/LatestCommittedImage'; import ParsedConfig from 'config/ParsedConfig'; import RunningContainer from 'containerization/RunningContainer'; -import Types from 'common/Types'; import UncommittedFile from '../containerization/UncommittedFile'; import { COMMITTED_IMAGE_NAMESPACE, @@ -39,46 +37,22 @@ import { getRunningContainerFunction, } from 'script'; -@injectable() export default class JobRunner { - @inject(BuildAgentSettings) - buildAgentSettings!: BuildAgentSettings; - - @inject(CommandDecorators) - commandDecorators!: CommandDecorators; - - @inject(ConfigFile) - configFile!: ConfigFile; - - @inject(Types.IEditorGateway) - editorGateway!: EditorGateway; - - @inject(FinalTerminal) - finalTerminal!: FinalTerminal; - - @inject(Types.IFsGateway) - fsGateway!: FsGateway; - - @inject(Images) - images!: Images; - - @inject(JobFactory) - jobFactory!: JobFactory; - - @inject(JobListener) - jobListener!: JobListener; - - @inject(LatestCommittedImage) - latestCommittedImage!: LatestCommittedImage; - - @inject(ParsedConfig) - parsedConfig!: ParsedConfig; - - @inject(RunningContainer) - runningContainer!: RunningContainer; - - @inject(UncommittedFile) - uncommittedFile!: UncommittedFile; + constructor( + public buildAgentSettings: BuildAgentSettings, + public commandDecorators: CommandDecorators, + public configFile: ConfigFile, + public editorGateway: EditorGateway, + public finalTerminal: FinalTerminal, + public fsGateway: FsGateway, + public images: Images, + public jobFactory: JobFactory, + public jobListener: JobListener, + public latestCommittedImage: LatestCommittedImage, + public parsedConfig: ParsedConfig, + public runningContainer: RunningContainer, + public uncommittedFile: UncommittedFile + ) {} async run( context: vscode.ExtensionContext, diff --git a/src/job/NativeComandFactory.ts b/src/job/NativeComandFactory.ts index 16e7d31e..3dbab55f 100644 --- a/src/job/NativeComandFactory.ts +++ b/src/job/NativeComandFactory.ts @@ -1,7 +1,5 @@ -import { injectable } from 'inversify'; import NativeCommandTreeItem from './NativeCommandTreeItem'; -@injectable() export default class NativeCommandFactory { create(label: string, command: string) { return new NativeCommandTreeItem(label, command); diff --git a/src/job/Retryer.ts b/src/job/Retryer.ts index 1616e0cb..b8365679 100644 --- a/src/job/Retryer.ts +++ b/src/job/Retryer.ts @@ -1,7 +1,5 @@ -import { injectable } from 'inversify'; import Delayer from './Delayer'; -@injectable() export default class Retryer { delayer?: Delayer; delayLength = 5000; diff --git a/src/job/WarningCommandFactory.ts b/src/job/WarningCommandFactory.ts index e8f78d9d..493f7196 100644 --- a/src/job/WarningCommandFactory.ts +++ b/src/job/WarningCommandFactory.ts @@ -1,11 +1,8 @@ -import { inject, injectable } from 'inversify'; import type vscode from 'vscode'; import WarningFactory from './WarningFactory'; -@injectable() export default class WarningCommandFactory { - @inject(WarningFactory) - warningFactory!: WarningFactory; + constructor(public warningFactory: WarningFactory) {} create(label: string, command: string): vscode.TreeItem { return { diff --git a/src/job/WarningFactory.ts b/src/job/WarningFactory.ts index 2136153b..7edcb65a 100644 --- a/src/job/WarningFactory.ts +++ b/src/job/WarningFactory.ts @@ -1,12 +1,8 @@ -import { inject, injectable } from 'inversify'; import type vscode from 'vscode'; -import Types from 'common/Types'; import EditorGateway from 'gateway/EditorGateway'; -@injectable() export default class WarningFactory { - @inject(Types.IEditorGateway) - editorGateway!: EditorGateway; + constructor(public editorGateway: EditorGateway) {} create(label: string): vscode.TreeItem { const warning = new this.editorGateway.editor.TreeItem( diff --git a/src/job/test/JobFactory.spec.ts b/src/job/test/JobFactory.spec.ts index 095ef9dc..326e3211 100644 --- a/src/job/test/JobFactory.spec.ts +++ b/src/job/test/JobFactory.spec.ts @@ -1,20 +1,8 @@ -import AppTestHarness from 'test-tool/helper/AppTestHarness'; -import FakeEditorGateway from 'gateway/FakeEditorGateway'; -import JobFactory from 'job/JobFactory'; - -let editorGateway: FakeEditorGateway; -let jobFactory: JobFactory; -let testHarness: AppTestHarness; +import getContainer from 'test-tool/TestRoot'; describe('Job', () => { - beforeEach(() => { - testHarness = new AppTestHarness(); - testHarness.init(); - jobFactory = testHarness.container.get(JobFactory); - editorGateway = testHarness.editorGateway; - }); - test('no element passed', () => { + const { jobFactory } = getContainer(); const jobName = 'this-is-your-job'; expect(jobFactory.create(jobName, false, false).getJobName()).toEqual( jobName @@ -22,6 +10,7 @@ describe('Job', () => { }); test('is running', () => { + const { jobFactory } = getContainer(); expect(jobFactory.create('example-job', false, false).contextValue).toEqual( undefined ); @@ -32,6 +21,7 @@ describe('Job', () => { }); test('is success', () => { + const { jobFactory } = getContainer(); const job = jobFactory.create('example', false, false); job.setIsSuccess(); expect(job.description).toEqual('✅'); @@ -41,6 +31,7 @@ describe('Job', () => { }); test('is expanded', () => { + const { editorGateway, jobFactory } = getContainer(); const job = jobFactory.create('example', false, false); job.setExpanded(); diff --git a/src/job/test/JobProvider.spec.ts b/src/job/test/JobProvider.spec.ts index 7525a1a0..10666627 100644 --- a/src/job/test/JobProvider.spec.ts +++ b/src/job/test/JobProvider.spec.ts @@ -1,28 +1,17 @@ -import AppTestHarness from 'test-tool/helper/AppTestHarness'; -import getContextStub from 'test-tool/helper/getContextStub'; -import JobProviderFactory from 'job/JobProviderFactory'; -import JobFactory from 'job/JobFactory'; import JobTreeItem from 'job/JobTreeItem'; - -let testHarness: AppTestHarness; -let jobProviderFactory: JobProviderFactory; -let jobFactory: JobFactory; +import getContextStub from 'test-tool/helper/getContextStub'; +import getContainer from 'test-tool/TestRoot'; describe('JobProvider', () => { - beforeEach(() => { - testHarness = new AppTestHarness(); - testHarness.init(); - jobFactory = testHarness.container.get(JobFactory); - jobProviderFactory = testHarness.container.get(JobProviderFactory); - }); - test('no element passed', () => { + const { jobProviderFactory } = getContainer(); expect(jobProviderFactory.create(getContextStub()).getChildren()).toEqual( [] ); }); test('no child', () => { + const { jobFactory, jobProviderFactory } = getContainer(); const provider = jobProviderFactory.create(getContextStub()); expect( provider.getChildren(jobFactory.create('foo', false, false)) @@ -30,6 +19,7 @@ describe('JobProvider', () => { }); test('two children', () => { + const { jobFactory, jobProviderFactory } = getContainer(); const allJobs = new Map(); allJobs.set('foo', []); allJobs.set('baz', ['foo']); diff --git a/src/license/Email.ts b/src/license/Email.ts index 8cf849b6..62c4dc0d 100644 --- a/src/license/Email.ts +++ b/src/license/Email.ts @@ -1,20 +1,14 @@ -import { inject, injectable } from 'inversify'; -import Types from 'common/Types'; import EditorGateway from 'gateway/EditorGateway'; import HttpGateway from 'gateway/HttpGateway'; import ReporterGateway from 'gateway/ReporterGateway'; import { EMAIL_ENDPOINT, EXTENSION_ID } from 'constant'; -@injectable() export default class Email { - @inject(Types.IEditorGateway) - editorGateway!: EditorGateway; - - @inject(Types.IHttpGateway) - httpGateway!: HttpGateway; - - @inject(Types.IReporterGateway) - repoterGateway!: ReporterGateway; + constructor( + public editorGateway: EditorGateway, + public httpGateway: HttpGateway, + public repoterGateway: ReporterGateway + ) {} async askForEmail(): Promise { const enteredEmail = await this.editorGateway.editor.window.showInputBox({ diff --git a/src/license/License.ts b/src/license/License.ts index 5ac28770..a9cf472c 100644 --- a/src/license/License.ts +++ b/src/license/License.ts @@ -1,6 +1,4 @@ -import { inject, injectable } from 'inversify'; import type vscode from 'vscode'; -import Types from 'common/Types'; import EditorGateway from 'gateway/EditorGateway'; import getHash from './getHash'; import HttpGateway from 'gateway/HttpGateway'; @@ -15,13 +13,11 @@ import { const licenseValidationEndpoint = 'https://getlocalci.com'; const fiveMinutesInMilliseconds = 300000; -@injectable() export default class License { - @inject(Types.IEditorGateway) - editorGateway!: EditorGateway; - - @inject(Types.IHttpGateway) - httpGateway!: HttpGateway; + constructor( + public editorGateway: EditorGateway, + public httpGateway: HttpGateway + ) {} async isValid( context: vscode.ExtensionContext, diff --git a/src/license/LicenseInput.ts b/src/license/LicenseInput.ts index 76c8a086..629263bf 100644 --- a/src/license/LicenseInput.ts +++ b/src/license/LicenseInput.ts @@ -1,19 +1,12 @@ -import { inject, injectable } from 'inversify'; import type vscode from 'vscode'; -import Types from 'common/Types'; import EditorGateway from 'gateway/EditorGateway'; import getLicenseErrorMessage from 'license/getLicenseErrorMessage'; import License from './License'; import sanitizeLicenseKey from './sanitizeLicenseKey'; import { LICENSE_ERROR, GET_LICENSE_KEY_URL, LICENSE_KEY } from 'constant'; -@injectable() export default class LicenseInput { - @inject(Types.IEditorGateway) - editorGateway!: EditorGateway; - - @inject(License) - license!: License; + constructor(public editorGateway: EditorGateway, public license: License) {} async show( context: vscode.ExtensionContext, diff --git a/src/license/LicensePresenter.ts b/src/license/LicensePresenter.ts index 2868b5df..80089b43 100644 --- a/src/license/LicensePresenter.ts +++ b/src/license/LicensePresenter.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from 'inversify'; import type vscode from 'vscode'; import getLicenseErrorMessage from './getLicenseErrorMessage'; import getTimeRemainingInTrial from './getTimeRemainingInTrial'; @@ -15,10 +14,8 @@ import { TRIAL_STARTED_TIMESTAMP, } from 'constant'; -@injectable() export default class LicensePresenter { - @inject(License) - license!: License; + constructor(public license: License) {} async getView(context: vscode.ExtensionContext): Promise { context.secrets.delete(LICENSE_VALIDITY); diff --git a/src/license/LicenseProviderFactory.ts b/src/license/LicenseProviderFactory.ts index 66fb898f..375468ab 100644 --- a/src/license/LicenseProviderFactory.ts +++ b/src/license/LicenseProviderFactory.ts @@ -1,25 +1,17 @@ -import { inject, injectable } from 'inversify'; import type vscode from 'vscode'; -import Types from 'common/Types'; import EditorGateway from 'gateway/EditorGateway'; import License from './License'; import LicenseInput from './LicenseInput'; import LicensePresenter from './LicensePresenter'; import LicenseProvider from './LicenseProvider'; -@injectable() export default class LicenseProviderFactory { - @inject(License) - license!: License; - - @inject(LicenseInput) - licenseInput!: LicenseInput; - - @inject(LicensePresenter) - licensePresenter!: LicensePresenter; - - @inject(Types.IEditorGateway) - editorGateway!: EditorGateway; + constructor( + public license: License, + public licenseInput: LicenseInput, + public licensePresenter: LicensePresenter, + public editorGateway: EditorGateway + ) {} create(context: vscode.ExtensionContext, licenseSuccessCallback: () => void) { return new LicenseProvider( diff --git a/src/license/test/Email.spec.ts b/src/license/test/Email.spec.ts index 588c830b..e079adf4 100644 --- a/src/license/test/Email.spec.ts +++ b/src/license/test/Email.spec.ts @@ -1,21 +1,9 @@ -import AppTestHarness from 'test-tool/helper/AppTestHarness'; -import Email from 'license/Email'; -import FakeHttpGateway from 'gateway/FakeHttpGateway'; import { EMAIL_ENDPOINT } from 'constant'; - -let email: Email; -let httpGateway: FakeHttpGateway; -let testHarness: AppTestHarness; +import getContainer from 'test-tool/TestRoot'; describe('Email', () => { - beforeEach(() => { - testHarness = new AppTestHarness(); - testHarness.init(); - email = testHarness.container.get(Email); - httpGateway = testHarness.httpGateway; - }); - test('only email', async () => { + const { email, httpGateway } = getContainer(); const emailAddress = 'a@example.com'; const postSpy = jest.fn(); @@ -30,6 +18,7 @@ describe('Email', () => { }); test('all fields', async () => { + const { email, httpGateway } = getContainer(); const emailAddress = 'a@example.com'; const name = 'Jane'; const optedIn = true; diff --git a/src/license/test/License.spec.ts b/src/license/test/License.spec.ts index a0ff21aa..495f782a 100644 --- a/src/license/test/License.spec.ts +++ b/src/license/test/License.spec.ts @@ -1,23 +1,15 @@ -import AppTestHarness from 'test-tool/helper/AppTestHarness'; import getContextStub from 'test-tool/helper/getContextStub'; -import License from 'license/License'; import { LICENSE_VALIDITY, LICENSE_VALIDITY_CACHE_EXPIRATION } from 'constant'; - -let testHarness: AppTestHarness; -let license: License; +import getContainer from 'test-tool/TestRoot'; describe('License', () => { - beforeEach(() => { - testHarness = new AppTestHarness(); - testHarness.init(); - license = testHarness.container.get(License); - }); - test('no license key', async () => { + const { license } = getContainer(); expect(await license.isValid(getContextStub(), true, '')).toBe(false); }); test('cached license validation', async () => { + const { license } = getContainer(); const mockContext = getContextStub(); expect( diff --git a/src/license/test/LicenseInput.spec.ts b/src/license/test/LicenseInput.spec.ts index 6a413089..c82a0cf0 100644 --- a/src/license/test/LicenseInput.spec.ts +++ b/src/license/test/LicenseInput.spec.ts @@ -1,18 +1,9 @@ -import AppTestHarness from 'test-tool/helper/AppTestHarness'; import getContextStub from 'test-tool/helper/getContextStub'; -import LicenseInput from 'license/LicenseInput'; - -let testHarness: AppTestHarness; -let licenseInput: LicenseInput; +import getContainer from 'test-tool/TestRoot'; describe('LicenseInput', () => { - beforeEach(() => { - testHarness = new AppTestHarness(); - testHarness.init(); - licenseInput = testHarness.container.get(LicenseInput); - }); - test('license is not valid', async () => { + const { licenseInput } = getContainer(); const completedCallbackSpy = jest.fn(); const successCallbackSpy = jest.fn(); await licenseInput.show( diff --git a/src/license/test/LicensePresenter.spec.ts b/src/license/test/LicensePresenter.spec.ts index 8cc8f8b3..0f8f646b 100644 --- a/src/license/test/LicensePresenter.spec.ts +++ b/src/license/test/LicensePresenter.spec.ts @@ -1,8 +1,7 @@ /* eslint-disable @typescript-eslint/no-empty-function */ -import AppTestHarness from 'test-tool/helper/AppTestHarness'; -import LicensePresenter from 'license/LicensePresenter'; import { LICENSE_VALIDITY, LICENSE_VALIDITY_CACHE_EXPIRATION } from 'constant'; import getContextStub from 'test-tool/helper/getContextStub'; +import getContainer from 'test-tool/TestRoot'; function getMockContext(licenseKey: string, cachedValidity: boolean) { const initialContext = getContextStub(); @@ -32,17 +31,9 @@ function getMockContext(licenseKey: string, cachedValidity: boolean) { }; } -let licensePresenter: LicensePresenter; -let testHarness: AppTestHarness; - describe('LicensePresenter', () => { - beforeEach(() => { - testHarness = new AppTestHarness(); - testHarness.init(); - licensePresenter = testHarness.container.get(LicensePresenter); - }); - test('no license', async () => { + const { licensePresenter } = getContainer(); expect( (await licensePresenter.getView(getMockContext('', false))).includes( 'Enter license key' @@ -51,6 +42,7 @@ describe('LicensePresenter', () => { }); test('cached valid license', async () => { + const { licensePresenter } = getContainer(); const actual = await licensePresenter.getView( getMockContext('123456789', true) ); diff --git a/src/log/LogFactory.ts b/src/log/LogFactory.ts index d2748909..7f9b9367 100644 --- a/src/log/LogFactory.ts +++ b/src/log/LogFactory.ts @@ -1,13 +1,9 @@ -import { inject, injectable } from 'inversify'; import type vscode from 'vscode'; import EditorGateway from 'gateway/EditorGateway'; -import Types from 'common/Types'; import { SHOW_LOG_FILE_COMMAND } from 'constant'; -@injectable() export default class LogFactory { - @inject(Types.IEditorGateway) - editorGateway!: EditorGateway; + constructor(public editorGateway: EditorGateway) {} create(label: string, filePath: string): vscode.TreeItem { const log = new this.editorGateway.editor.TreeItem(label); diff --git a/src/log/LogFile.ts b/src/log/LogFile.ts index e6033595..7f11c5bc 100644 --- a/src/log/LogFile.ts +++ b/src/log/LogFile.ts @@ -1,12 +1,8 @@ -import { inject, injectable } from 'inversify'; -import Types from 'common/Types'; import EditorGateway from 'gateway/EditorGateway'; import { LOG_FILE_SCHEME } from 'constant'; -@injectable() export default class LogFile { - @inject(Types.IEditorGateway) - editorGateway!: EditorGateway; + constructor(public editorGateway: EditorGateway) {} async show(logFilePath: string): Promise { await this.editorGateway.editor.window.showTextDocument( diff --git a/src/log/LogProviderFactory.ts b/src/log/LogProviderFactory.ts index 4d5a9275..13d9c01b 100644 --- a/src/log/LogProviderFactory.ts +++ b/src/log/LogProviderFactory.ts @@ -1,12 +1,8 @@ -import { inject, injectable } from 'inversify'; -import Types from 'common/Types'; import FsGateway from 'gateway/FsGateway'; import LogProvider from './LogProvider'; -@injectable() export default class LogProviderFactory { - @inject(Types.IFsGateway) - fsGateway!: FsGateway; + constructor(public fsGateway: FsGateway) {} create() { return new LogProvider(this.fsGateway); diff --git a/src/process/EnvVar.ts b/src/process/EnvVar.ts index 63c27c02..c3c648fd 100644 --- a/src/process/EnvVar.ts +++ b/src/process/EnvVar.ts @@ -1,16 +1,12 @@ -import { injectable, inject } from 'inversify'; -import Types from 'common/Types'; import { addEnvVars } from 'script'; import ChildProcessGateway from 'gateway/ChildProcessGateway'; import Spawn from 'common/Spawn'; -@injectable() export default class EnvVar { - @inject(Types.IChildProcessGateway) - childProcessGateway!: ChildProcessGateway; - - @inject(Spawn) - spawn!: Spawn; + constructor( + public childProcessGateway: ChildProcessGateway, + public spawn: Spawn + ) {} getStep(repoPath: string) { let command; diff --git a/src/process/FakeEnvVar.ts b/src/process/FakeEnvVar.ts index 444e5504..47df8e99 100644 --- a/src/process/FakeEnvVar.ts +++ b/src/process/FakeEnvVar.ts @@ -1,6 +1,3 @@ -import { injectable } from 'inversify'; - -@injectable() export default class FakeEnvVar { getStep() { return { diff --git a/src/process/Persistence.ts b/src/process/Persistence.ts index 578cf2ad..4f17e1e2 100644 --- a/src/process/Persistence.ts +++ b/src/process/Persistence.ts @@ -1,4 +1,3 @@ -import { inject, injectable } from 'inversify'; import * as path from 'path'; import getAttachWorkspaceCommand from 'config/getAttachWorkspaceCommand'; import getRestoreCacheCommand from 'cache/getRestoreCacheCommand'; @@ -11,13 +10,10 @@ import { DYNAMIC_CONFIG_PATH_IN_CONTAINER, } from 'constant'; import getJobs from 'job/getJobs'; -import Types from 'common/Types'; import Volume from 'containerization/Volume'; -@injectable() export default class Persistence { - @inject(Types.IVolume) - volume!: Volume; + constructor(public volume: Volume) {} simulateAttachWorkspace( config: NonNullable, diff --git a/src/process/ProcessFile.ts b/src/process/ProcessFile.ts index 5299b5b6..6da46847 100644 --- a/src/process/ProcessFile.ts +++ b/src/process/ProcessFile.ts @@ -1,5 +1,3 @@ -import { injectable, inject } from 'inversify'; -import Types from 'common/Types'; import * as path from 'path'; import * as yaml from 'js-yaml'; import FsGateway from 'gateway/FsGateway'; @@ -9,16 +7,12 @@ import Persistence from './Persistence'; import { CONTAINER_STORAGE_DIRECTORY } from 'constant'; import EnvVar from './EnvVar'; -@injectable() export default class ProcessFile { - @inject(Types.IEnvVar) - envVar!: EnvVar; - - @inject(Types.IFsGateway) - fsGateway!: FsGateway; - - @inject(Persistence) - persistence!: Persistence; + constructor( + public envVar: EnvVar, + public fsGateway: FsGateway, + public persistence: Persistence + ) {} /** * Overwrites parts of the process.yml file. diff --git a/src/process/test/ProcessFile.spec.ts b/src/process/test/ProcessFile.spec.ts index 4ed797ed..b87b4166 100644 --- a/src/process/test/ProcessFile.spec.ts +++ b/src/process/test/ProcessFile.spec.ts @@ -1,25 +1,18 @@ import * as yaml from 'js-yaml'; -import Types from 'common/Types'; -import AppTestHarness from 'test-tool/helper/AppTestHarness'; import dynamicConfigExpected from 'test-tool/expected/dynamic-config.yml'; import dyanamicConfigFixture from 'test-tool/fixture/dynamic-config.yml'; import getConfig from 'config/getConfig'; -import ProcessFile from 'process/ProcessFile'; import normalize from 'test-tool/helper/normalize'; import simulatedAttachWorkspaceExpected from 'test-tool/expected/simulated-attach-workspace.yml'; import simulatedAttachWorkspaceFixture from 'test-tool/fixture/simulated-attach-workspace.yml'; import withCacheExpected from 'test-tool/expected/with-cache.yml'; import withCacheFixture from 'test-tool/fixture/with-cache.yml'; +import getContainer from 'test-tool/TestRoot'; import Volume from 'containerization/Volume'; - -let testHarness: AppTestHarness; +import Persistence from 'process/Persistence'; +import ProcessFile from 'process/ProcessFile'; describe('ProcessFile', () => { - beforeEach(() => { - testHarness = new AppTestHarness(); - testHarness.init(); - }); - it.each` fixture | expected | name ${withCacheFixture} | ${withCacheExpected} | ${'withCache'} @@ -27,7 +20,11 @@ describe('ProcessFile', () => { `( 'converts $name from \n $fixture \n …to: \n\n $expected', ({ fixture, expected }) => { - const processFile = testHarness.container.get(ProcessFile); + const { envVar, fsGateway } = getContainer(); + const volume = new Volume(fsGateway); + volume.isEmpty = jest.fn(() => false); + const persistence = new Persistence(volume); + const processFile = new ProcessFile(envVar, fsGateway, persistence); expect( normalize( @@ -43,10 +40,11 @@ describe('ProcessFile', () => { ); test('simulates attach_workspace', () => { - const volume: Volume = testHarness.container.get(Types.IVolume); + const { envVar, fsGateway } = getContainer(); + const volume = new Volume(fsGateway); volume.isEmpty = jest.fn(() => true); - - const processFile = testHarness.container.get(ProcessFile); + const persistence = new Persistence(volume); + const processFile = new ProcessFile(envVar, fsGateway, persistence); expect( normalize( diff --git a/src/terminal/CommandDecorators.ts b/src/terminal/CommandDecorators.ts index 2d9b1747..8ec29988 100644 --- a/src/terminal/CommandDecorators.ts +++ b/src/terminal/CommandDecorators.ts @@ -1,11 +1,7 @@ -import Types from 'common/Types'; import EditorGateway from 'gateway/EditorGateway'; -import { inject, injectable } from 'inversify'; -@injectable() export default class CommandDecorators { - @inject(Types.IEditorGateway) - editorGateway!: EditorGateway; + constructor(public editorGateway: EditorGateway) {} get() { const isPreCommand = this.editorGateway.editor.workspace diff --git a/src/terminal/FinalTerminal.ts b/src/terminal/FinalTerminal.ts index c4ec5ac6..61089761 100644 --- a/src/terminal/FinalTerminal.ts +++ b/src/terminal/FinalTerminal.ts @@ -1,19 +1,13 @@ -import { inject, injectable } from 'inversify'; -import Types from 'common/Types'; import ChildProcessGateway from 'gateway/ChildProcessGateway'; import EditorGateway from 'gateway/EditorGateway'; import Spawn from 'common/Spawn'; -@injectable() export default class FinalTerminal { - @inject(Types.IChildProcessGateway) - childProcessGateway!: ChildProcessGateway; - - @inject(Types.IEditorGateway) - editorGateway!: EditorGateway; - - @inject(Spawn) - spawn!: Spawn; + constructor( + public childProcessGateway: ChildProcessGateway, + public editorGateway: EditorGateway, + public spawn: Spawn + ) {} // @todo: this isn't working. // It probably needs to run the logic to get the latest image again. diff --git a/src/terminal/JobTerminals.ts b/src/terminal/JobTerminals.ts index 6d205c0a..158cfbaa 100644 --- a/src/terminal/JobTerminals.ts +++ b/src/terminal/JobTerminals.ts @@ -1,14 +1,10 @@ -import { inject, injectable } from 'inversify'; -import Types from 'common/Types'; import getDebuggingTerminalName from './getDebuggingTerminalName'; import getTerminalName from './getTerminalName'; import getFinalTerminalName from './getFinalTerminalName'; import EditorGateway from 'gateway/EditorGateway'; -@injectable() export default class JobTerminals { - @inject(Types.IEditorGateway) - editorGateway!: EditorGateway; + constructor(public editorGateway: EditorGateway) {} /** Closes VS Code terminals for a job. */ dispose(jobName: string): void { diff --git a/src/terminal/test/CommandDecorators.spec.ts b/src/terminal/test/CommandDecorators.spec.ts index 2e1d4b91..bc8ba2d4 100644 --- a/src/terminal/test/CommandDecorators.spec.ts +++ b/src/terminal/test/CommandDecorators.spec.ts @@ -1,20 +1,8 @@ -import FakeEditorGateway from 'gateway/FakeEditorGateway'; -import AppTestHarness from 'test-tool/helper/AppTestHarness'; -import CommandDecorators from '../CommandDecorators'; - -let editorGateway: FakeEditorGateway; -let testHarness: AppTestHarness; -let commandDecorators: CommandDecorators; +import getContainer from 'test-tool/TestRoot'; describe('CommandDecorators', () => { - beforeEach(() => { - testHarness = new AppTestHarness(); - testHarness.init(); - editorGateway = testHarness.editorGateway; - commandDecorators = testHarness.container.get(CommandDecorators); - }); - test('neither pre nor post command enabled', () => { + const { commandDecorators } = getContainer(); expect(commandDecorators.get()).toEqual({ getPreCommand: '', getPostCommand: '', @@ -24,6 +12,9 @@ describe('CommandDecorators', () => { }); test('both pre and post command enabled', () => { + const { commandDecorators, editorGateway } = getContainer(); + + // @ts-expect-error stub is missing properties. editorGateway.editor.workspace.getConfiguration = jest.fn(() => { return { get: (configuration: string) => { diff --git a/src/terminal/test/FinalTerminal.spec.ts b/src/terminal/test/FinalTerminal.spec.ts index 959d6063..51c40f5a 100644 --- a/src/terminal/test/FinalTerminal.spec.ts +++ b/src/terminal/test/FinalTerminal.spec.ts @@ -1,23 +1,9 @@ -import AppTestHarness from 'test-tool/helper/AppTestHarness'; -import FakeChildProcessGateway from 'gateway/FakeChildProcessGateway'; -import FakeEditorGateway from 'gateway/FakeEditorGateway'; -import FinalTerminal from '../FinalTerminal'; - -let childProcessGateway: FakeChildProcessGateway; -let editorGateway: FakeEditorGateway; -let finalTerminal: FinalTerminal; -let testHarness: AppTestHarness; +import getContainer from 'test-tool/TestRoot'; describe('FinalTerminal', () => { - beforeEach(() => { - testHarness = new AppTestHarness(); - testHarness.init(); - finalTerminal = testHarness.container.get(FinalTerminal); - childProcessGateway = testHarness.childProcessGateway; - editorGateway = testHarness.editorGateway; - }); - test('no helper message', async () => { + const { childProcessGateway, editorGateway, finalTerminal } = + getContainer(); const showInformationMessageSpy = jest.fn(); editorGateway.editor.window.showInformationMessage = showInformationMessageSpy; @@ -38,6 +24,8 @@ describe('FinalTerminal', () => { }); test('with helper message', async () => { + const { childProcessGateway, editorGateway, finalTerminal } = + getContainer(); const showInformationMessageSpy = jest.fn(); editorGateway.editor.window.showInformationMessage = showInformationMessageSpy; diff --git a/src/terminal/test/JobTerminals.spec.ts b/src/terminal/test/JobTerminals.spec.ts index 6991e4ea..723ce9cf 100644 --- a/src/terminal/test/JobTerminals.spec.ts +++ b/src/terminal/test/JobTerminals.spec.ts @@ -1,22 +1,11 @@ -import AppTestHarness from 'test-tool/helper/AppTestHarness'; -import FakeEditorGateway from 'gateway/FakeEditorGateway'; -import JobTerminals from 'terminal/JobTerminals'; - -let editorGateway: FakeEditorGateway; -let jobTerminals: JobTerminals; -let testHarness: AppTestHarness; +import getContainer from 'test-tool/TestRoot'; describe('JobTerminals', () => { - beforeEach(() => { - testHarness = new AppTestHarness(); - testHarness.init(); - jobTerminals = testHarness.container.get(JobTerminals); - editorGateway = testHarness.editorGateway; - }); - test('terminal is not disposed', async () => { + const { editorGateway, jobTerminals } = getContainer(); const jobName = 'build'; const disposeSpy = jest.fn(); + // @ts-expect-error read-only property. editorGateway.editor.window.terminals = [ { name: `Terminal unrelated to this extension `, @@ -29,8 +18,10 @@ describe('JobTerminals', () => { }); test('terminal is disposed', async () => { + const { editorGateway, jobTerminals } = getContainer(); const jobName = 'build'; const disposeSpy = jest.fn(); + // @ts-expect-error read-only property. editorGateway.editor.window.terminals = [ { name: `Local CI ${jobName}`, diff --git a/src/test-tool/TestRoot.ts b/src/test-tool/TestRoot.ts new file mode 100644 index 00000000..9ccb0192 --- /dev/null +++ b/src/test-tool/TestRoot.ts @@ -0,0 +1,291 @@ +import FakeChildProcessGateway from 'gateway/FakeChildProcessGateway'; +import FakeEditorGateway from 'gateway/FakeEditorGateway'; +import FakeEnvVar from 'process/FakeEnvVar'; +import FakeFsGateway from 'gateway/FakeFsGateway'; +import FakeHttpGateway from 'gateway/FakeHttpGateway'; +import FakeOsGateway from 'gateway/FakeOsGateway'; +import FakeProcessGateway from 'gateway/FakeProcessGateway'; +import FakeReporterGateway from 'gateway/FakeReporterGateway'; +import AllConfigFiles from 'config/AllConfigFiles'; +import AllJobs from 'job/AllJobs'; +import BuildAgentSettings from 'config/BuildAgentSettings'; +import Children from 'job/Children'; +import Images from 'containerization/Images'; +import ChildProcessGateway from 'gateway/ChildProcessGateway'; +import CommandDecorators from 'terminal/CommandDecorators'; +import CommandFactory from 'job/ComandFactory'; +import Complain from 'command/Complain'; +import Config from 'config/Config'; +import ConfigFile from 'config/ConfigFile'; +import CreateConfigFile from 'command/CreateConfigFile'; +import DebugRepo from 'command/DebugRepo'; +import Docker from 'containerization/Docker'; +import EditorGateway from 'gateway/EditorGateway'; +import Email from 'license/Email'; +import EnterLicense from 'command/EnterLicense'; +import EnterToken from 'command/EnterToken'; +import EnvPath from 'common/EnvPath'; +import EnvVar from 'process/EnvVar'; +import ExitAllJobs from 'command/ExitAllJobs'; +import ExitJob from 'command/ExitJob'; +import FinalTerminal from 'terminal/FinalTerminal'; +import FirstActivation from 'job/FirstActivation'; +import FsGateway from 'gateway/FsGateway'; +import GetLicense from 'command/GetLicense'; +import Help from 'command/Help'; +import HttpGateway from 'gateway/HttpGateway'; +import JobFactory from 'job/JobFactory'; +import JobListener from 'job/JobListener'; +import JobProviderFactory from 'job/JobProviderFactory'; +import JobRunner from 'job/JobRunner'; +import JobTerminals from 'terminal/JobTerminals'; +import LatestCommittedImage from 'containerization/LatestCommittedImage'; +import License from 'license/License'; +import LicenseInput from 'license/LicenseInput'; +import LicensePresenter from 'license/LicensePresenter'; +import LicenseProviderFactory from 'license/LicenseProviderFactory'; +import LocalCi from '../common/LocalCi'; +import LogFactory from 'log/LogFactory'; +import LogFile from 'log/LogFile'; +import LogProviderFactory from 'log/LogProviderFactory'; +import NativeCommandFactory from 'job/NativeComandFactory'; +import OsGateway from 'gateway/OsGateway'; +import ParsedConfig from 'config/ParsedConfig'; +import Persistence from 'process/Persistence'; +import PipelineParameter from 'config/PipelineParameter'; +import ProcessFile from 'process/ProcessFile'; +import ProcessGateway from 'gateway/ProcessGateway'; +import Refresh from 'command/Refresh'; +import RegistrarFactory from 'common/RegistrarFactory'; +import ReRunJob from 'command/ReRunJob'; +import Retryer from 'job/Retryer'; +import RunJob from 'command/RunJob'; +import RunningContainer from 'containerization/RunningContainer'; +import RunWalkthroughJob from 'command/RunWalkthroughJob'; +import SelectRepo from 'command/SelectRepo'; +import Spawn from 'common/Spawn'; +import TryProcessAgain from 'command/TryProcessAgain'; +import UncommittedFile from 'containerization/UncommittedFile'; +import WarningCommandFactory from 'job/WarningCommandFactory'; +import WarningFactory from 'job/WarningFactory'; +import Workspace from 'common/Workspace'; +import RefreshLicenseTree from 'command/RefreshLicenseTree'; +import ShowLogFile from 'command/ShowLogFile'; +import StartDocker from 'command/StartDocker'; +import ReporterGateway from 'gateway/ReporterGateway'; +import Volume from 'containerization/Volume'; + +export default function getContainer() { + const childProcessGateway = + new FakeChildProcessGateway() as unknown as ChildProcessGateway; + const editorGateway = new FakeEditorGateway() as unknown as EditorGateway; + const envVar = new FakeEnvVar() as unknown as EnvVar; + const fsGateway = new FakeFsGateway() as unknown as FsGateway; + const httpGateway = new FakeHttpGateway() as unknown as HttpGateway; + const osGateway = new FakeOsGateway() as unknown as OsGateway; + const processGateway = new FakeProcessGateway() as unknown as ProcessGateway; + const reporterGateway = + new FakeReporterGateway() as unknown as ReporterGateway; + const volume = new Volume(fsGateway); + + const parsedConfig = new ParsedConfig(fsGateway); + + const allJobs = new AllJobs(parsedConfig); + const envPath = new EnvPath(osGateway, processGateway); + const workspace = new Workspace(editorGateway); + + const spawn = new Spawn(envPath, processGateway, workspace); + const buildAgentSettings = new BuildAgentSettings( + childProcessGateway, + osGateway, + spawn + ); + const commandFactory = new CommandFactory(editorGateway); + const jobFactory = new JobFactory(editorGateway); + const logFactory = new LogFactory(editorGateway); + const warningFactory = new WarningFactory(editorGateway); + const warningCommandFactory = new WarningCommandFactory(warningFactory); + + const children = new Children( + commandFactory, + editorGateway, + jobFactory, + logFactory, + new NativeCommandFactory(), + warningCommandFactory, + warningFactory + ); + const pipelineParameter = new PipelineParameter(fsGateway); + const persistence = new Persistence(volume); + + const processFile = new ProcessFile(envVar, fsGateway, persistence); + + const config = new Config( + childProcessGateway, + editorGateway, + fsGateway, + pipelineParameter, + processFile, + spawn + ); + const allConfigFiles = new AllConfigFiles(editorGateway); + const configFile = new ConfigFile( + allConfigFiles, + editorGateway, + reporterGateway + ); + const createConfigFile = new CreateConfigFile(editorGateway, reporterGateway); + const debugRepo = new DebugRepo(editorGateway, reporterGateway); + const docker = new Docker(childProcessGateway, spawn); + const email = new Email(editorGateway, httpGateway, reporterGateway); + const enterToken = new EnterToken(editorGateway); + const images = new Images(childProcessGateway, spawn); + const exitAllJobs = new ExitAllJobs(images, editorGateway, reporterGateway); + const finalTerminal = new FinalTerminal( + childProcessGateway, + editorGateway, + spawn + ); + const logFile = new LogFile(editorGateway); + const jobListener = new JobListener( + childProcessGateway, + images, + configFile, + editorGateway, + fsGateway, + logFile, + parsedConfig, + spawn + ); + + const latestCommittedImage = new LatestCommittedImage( + spawn, + childProcessGateway + ); + const runningContainer = new RunningContainer(spawn, childProcessGateway); + const uncommittedFile = new UncommittedFile( + childProcessGateway, + editorGateway, + spawn + ); + + const commandDecorators = new CommandDecorators(editorGateway); + const jobRunner = new JobRunner( + buildAgentSettings, + commandDecorators, + configFile, + editorGateway, + finalTerminal, + fsGateway, + images, + jobFactory, + jobListener, + latestCommittedImage, + parsedConfig, + runningContainer, + uncommittedFile + ); + const jobTerminals = new JobTerminals(editorGateway); + const exitJob = new ExitJob(jobFactory, jobRunner, jobTerminals); + const getLicense = new GetLicense(editorGateway); + const license = new License(editorGateway, httpGateway); + const retryer = new Retryer(); + const jobProviderFactory = new JobProviderFactory( + allConfigFiles, + children, + configFile, + commandFactory, + docker, + editorGateway, + fsGateway, + license, + config, + jobFactory, + logFactory, + reporterGateway, + retryer, + warningFactory, + allJobs + ); + + const licenseInput = new LicenseInput(editorGateway, license); + const licensePresenter = new LicensePresenter(license); + const licenseProviderFactory = new LicenseProviderFactory( + license, + licenseInput, + licensePresenter, + editorGateway + ); + const complain = new Complain(editorGateway); + const help = new Help(editorGateway, reporterGateway); + const registrarFactory = new RegistrarFactory( + complain, + configFile, + createConfigFile, + debugRepo, + new EnterLicense(licenseInput), + enterToken, + exitAllJobs, + exitJob, + new FirstActivation(editorGateway, reporterGateway, email), + getLicense, + help, + licenseInput, + new LogProviderFactory(fsGateway), + new Refresh(), + new RefreshLicenseTree(editorGateway), + new ReRunJob(editorGateway, jobRunner, jobTerminals, reporterGateway), + new RunJob(editorGateway, jobRunner, reporterGateway), + new RunWalkthroughJob(config, configFile, editorGateway, reporterGateway), + new SelectRepo(allConfigFiles, images, editorGateway, reporterGateway), + new ShowLogFile(logFile), + new StartDocker(childProcessGateway, envPath, spawn), + new TryProcessAgain(configFile, fsGateway), + editorGateway + ); + + const localCi = new LocalCi( + fsGateway, + jobProviderFactory, + licenseProviderFactory, + registrarFactory, + reporterGateway + ); + + return { + allConfigFiles, + buildAgentSettings, + childProcessGateway, + commandDecorators, + complain, + configFile, + createConfigFile, + debugRepo, + docker, + editorGateway, + email, + envPath, + envVar, + finalTerminal, + fsGateway, + help, + httpGateway, + images, + jobFactory, + jobProviderFactory, + jobTerminals, + license, + licenseInput, + licensePresenter, + localCi, + osGateway, + parsedConfig, + processFile, + processGateway, + reporterGateway, + spawn, + uncommittedFile, + volume, + workspace, + }; +} diff --git a/src/test-tool/helper/AppTestHarness.ts b/src/test-tool/helper/AppTestHarness.ts deleted file mode 100644 index cf6d2bf6..00000000 --- a/src/test-tool/helper/AppTestHarness.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { Container } from 'inversify'; -import Types from 'common/Types'; -import BaseIOC from 'common/BaseIoc'; -import FakeChildProcessGateway from 'gateway/FakeChildProcessGateway'; -import FakeEditorGateway from 'gateway/FakeEditorGateway'; -import FakeEnvVar from 'process/FakeEnvVar'; -import FakeFsGateway from 'gateway/FakeFsGateway'; -import FakeHttpGateway from 'gateway/FakeHttpGateway'; -import FakeOsGateway from 'gateway/FakeOsGateway'; -import FakeProcessGateway from 'gateway/FakeProcessGateway'; -import FakeReporterGateway from 'gateway/FakeReporterGateway'; -import FakeVolume from 'containerization/FakeVolume'; - -export default class AppTestHarness { - container!: Container; - childProcessGateway!: FakeChildProcessGateway; - editorGateway!: FakeEditorGateway; - fsGateway!: FakeFsGateway; - httpGateway!: FakeHttpGateway; - osGateway!: FakeOsGateway; - processGateway!: FakeProcessGateway; - reporterGateway!: FakeReporterGateway; - - init() { - this.container = new BaseIOC().buildBaseTemplate(); - this.container - .bind(Types.IChildProcessGateway) - .to(FakeChildProcessGateway) - .inSingletonScope(); - this.container.bind(Types.IEnvVar).to(FakeEnvVar).inSingletonScope(); - this.container - .bind(Types.IEditorGateway) - .to(FakeEditorGateway) - .inSingletonScope(); - this.container.bind(Types.IFsGateway).to(FakeFsGateway).inSingletonScope(); - this.container - .bind(Types.IHttpGateway) - .to(FakeHttpGateway) - .inSingletonScope(); - this.container.bind(Types.IOsGateway).to(FakeOsGateway).inSingletonScope(); - this.container - .bind(Types.IProcessGateway) - .to(FakeProcessGateway) - .inSingletonScope(); - this.container - .bind(Types.IReporterGateway) - .to(FakeReporterGateway) - .inSingletonScope(); - this.container.bind(Types.IVolume).to(FakeVolume).inSingletonScope(); - - this.childProcessGateway = this.container.get(Types.IChildProcessGateway); - this.editorGateway = this.container.get(Types.IEditorGateway); - this.fsGateway = this.container.get(Types.IFsGateway); - this.httpGateway = this.container.get(Types.IHttpGateway); - this.osGateway = this.container.get(Types.IOsGateway); - this.processGateway = this.container.get(Types.IProcessGateway); - this.reporterGateway = this.container.get(Types.IReporterGateway); - } -} diff --git a/src/test-tool/jest.setup.ts b/src/test-tool/jest.setup.ts deleted file mode 100644 index d2c9bc6e..00000000 --- a/src/test-tool/jest.setup.ts +++ /dev/null @@ -1 +0,0 @@ -import 'reflect-metadata'; diff --git a/tsconfig.json b/tsconfig.json index 5e9668b4..5167c507 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,7 +7,7 @@ "es6" ], "sourceMap": true, - "types": ["jest", "node", "reflect-metadata"], + "types": ["jest", "node"], "rootDir": "src", "baseUrl": "src", "strict": true,