movehat 0.1.9 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +132 -279
- package/dist/__tests__/deployContract.test.d.ts +2 -0
- package/dist/__tests__/deployContract.test.d.ts.map +1 -0
- package/dist/__tests__/deployContract.test.js +368 -0
- package/dist/__tests__/deployContract.test.js.map +1 -0
- package/dist/__tests__/errors.test.d.ts +2 -0
- package/dist/__tests__/errors.test.d.ts.map +1 -0
- package/dist/__tests__/errors.test.js +46 -0
- package/dist/__tests__/errors.test.js.map +1 -0
- package/dist/__tests__/fixtures/sigint-deploy-harness.d.ts +24 -0
- package/dist/__tests__/fixtures/sigint-deploy-harness.d.ts.map +1 -0
- package/dist/__tests__/fixtures/sigint-deploy-harness.js +82 -0
- package/dist/__tests__/fixtures/sigint-deploy-harness.js.map +1 -0
- package/dist/__tests__/fork/api.test.d.ts +2 -0
- package/dist/__tests__/fork/api.test.d.ts.map +1 -0
- package/dist/__tests__/fork/api.test.js +110 -0
- package/dist/__tests__/fork/api.test.js.map +1 -0
- package/dist/__tests__/harness/Harness.createLive.test.d.ts +2 -0
- package/dist/__tests__/harness/Harness.createLive.test.d.ts.map +1 -0
- package/dist/__tests__/harness/Harness.createLive.test.js +53 -0
- package/dist/__tests__/harness/Harness.createLive.test.js.map +1 -0
- package/dist/__tests__/harness/Harness.proxy.test.d.ts +2 -0
- package/dist/__tests__/harness/Harness.proxy.test.d.ts.map +1 -0
- package/dist/__tests__/harness/Harness.proxy.test.js +89 -0
- package/dist/__tests__/harness/Harness.proxy.test.js.map +1 -0
- package/dist/__tests__/harness/_fixture.d.ts +54 -0
- package/dist/__tests__/harness/_fixture.d.ts.map +1 -0
- package/dist/__tests__/harness/_fixture.js +69 -0
- package/dist/__tests__/harness/_fixture.js.map +1 -0
- package/dist/__tests__/harness/codeObject.deploy.test.d.ts +2 -0
- package/dist/__tests__/harness/codeObject.deploy.test.d.ts.map +1 -0
- package/dist/__tests__/harness/codeObject.deploy.test.js +288 -0
- package/dist/__tests__/harness/codeObject.deploy.test.js.map +1 -0
- package/dist/__tests__/harness/codeObject.upgrade.test.d.ts +2 -0
- package/dist/__tests__/harness/codeObject.upgrade.test.d.ts.map +1 -0
- package/dist/__tests__/harness/codeObject.upgrade.test.js +138 -0
- package/dist/__tests__/harness/codeObject.upgrade.test.js.map +1 -0
- package/dist/__tests__/harness/script.test.d.ts +2 -0
- package/dist/__tests__/harness/script.test.d.ts.map +1 -0
- package/dist/__tests__/harness/script.test.js +219 -0
- package/dist/__tests__/harness/script.test.js.map +1 -0
- package/dist/__tests__/harness/view.test.d.ts +2 -0
- package/dist/__tests__/harness/view.test.d.ts.map +1 -0
- package/dist/__tests__/harness/view.test.js +92 -0
- package/dist/__tests__/harness/view.test.js.map +1 -0
- package/dist/__tests__/runtime.test.d.ts +2 -0
- package/dist/__tests__/runtime.test.d.ts.map +1 -0
- package/dist/__tests__/runtime.test.js +141 -0
- package/dist/__tests__/runtime.test.js.map +1 -0
- package/dist/cli.js +2 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/__tests__/compile.test.d.ts +2 -0
- package/dist/commands/__tests__/compile.test.d.ts.map +1 -0
- package/dist/commands/__tests__/compile.test.js +351 -0
- package/dist/commands/__tests__/compile.test.js.map +1 -0
- package/dist/commands/__tests__/init.test.d.ts +2 -0
- package/dist/commands/__tests__/init.test.d.ts.map +1 -0
- package/dist/commands/__tests__/init.test.js +101 -0
- package/dist/commands/__tests__/init.test.js.map +1 -0
- package/dist/commands/__tests__/run.test.d.ts +2 -0
- package/dist/commands/__tests__/run.test.d.ts.map +1 -0
- package/dist/commands/__tests__/run.test.js +166 -0
- package/dist/commands/__tests__/run.test.js.map +1 -0
- package/dist/commands/__tests__/test-move.test.d.ts +2 -0
- package/dist/commands/__tests__/test-move.test.d.ts.map +1 -0
- package/dist/commands/__tests__/test-move.test.js +59 -0
- package/dist/commands/__tests__/test-move.test.js.map +1 -0
- package/dist/commands/__tests__/test.test.d.ts +2 -0
- package/dist/commands/__tests__/test.test.d.ts.map +1 -0
- package/dist/commands/__tests__/test.test.js +168 -0
- package/dist/commands/__tests__/test.test.js.map +1 -0
- package/dist/commands/__tests__/update.test.d.ts +2 -0
- package/dist/commands/__tests__/update.test.d.ts.map +1 -0
- package/dist/commands/__tests__/update.test.js +176 -0
- package/dist/commands/__tests__/update.test.js.map +1 -0
- package/dist/commands/compile.d.ts +7 -1
- package/dist/commands/compile.d.ts.map +1 -1
- package/dist/commands/compile.js +150 -33
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/fork/__tests__/create.test.d.ts +2 -0
- package/dist/commands/fork/__tests__/create.test.d.ts.map +1 -0
- package/dist/commands/fork/__tests__/create.test.js +108 -0
- package/dist/commands/fork/__tests__/create.test.js.map +1 -0
- package/dist/commands/fork/__tests__/fund.test.d.ts +2 -0
- package/dist/commands/fork/__tests__/fund.test.d.ts.map +1 -0
- package/dist/commands/fork/__tests__/fund.test.js +72 -0
- package/dist/commands/fork/__tests__/fund.test.js.map +1 -0
- package/dist/commands/fork/__tests__/list.test.d.ts +2 -0
- package/dist/commands/fork/__tests__/list.test.d.ts.map +1 -0
- package/dist/commands/fork/__tests__/list.test.js +119 -0
- package/dist/commands/fork/__tests__/list.test.js.map +1 -0
- package/dist/commands/fork/__tests__/serve.test.d.ts +2 -0
- package/dist/commands/fork/__tests__/serve.test.d.ts.map +1 -0
- package/dist/commands/fork/__tests__/serve.test.js +97 -0
- package/dist/commands/fork/__tests__/serve.test.js.map +1 -0
- package/dist/commands/fork/__tests__/view-resource.test.d.ts +2 -0
- package/dist/commands/fork/__tests__/view-resource.test.d.ts.map +1 -0
- package/dist/commands/fork/__tests__/view-resource.test.js +77 -0
- package/dist/commands/fork/__tests__/view-resource.test.js.map +1 -0
- package/dist/commands/fork/create.d.ts +1 -1
- package/dist/commands/fork/create.d.ts.map +1 -1
- package/dist/commands/fork/create.js +3 -2
- package/dist/commands/fork/create.js.map +1 -1
- package/dist/commands/fork/fund.d.ts.map +1 -1
- package/dist/commands/fork/fund.js +15 -8
- package/dist/commands/fork/fund.js.map +1 -1
- package/dist/commands/fork/list.d.ts.map +1 -1
- package/dist/commands/fork/list.js +2 -1
- package/dist/commands/fork/list.js.map +1 -1
- package/dist/commands/fork/serve.d.ts +1 -0
- package/dist/commands/fork/serve.d.ts.map +1 -1
- package/dist/commands/fork/serve.js +4 -2
- package/dist/commands/fork/serve.js.map +1 -1
- package/dist/commands/fork/view-resource.d.ts.map +1 -1
- package/dist/commands/fork/view-resource.js +10 -5
- package/dist/commands/fork/view-resource.js.map +1 -1
- package/dist/commands/run.d.ts +15 -0
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +50 -27
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/test-move.d.ts.map +1 -1
- package/dist/commands/test-move.js +3 -2
- package/dist/commands/test-move.js.map +1 -1
- package/dist/commands/test.js +52 -46
- package/dist/commands/test.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +15 -13
- package/dist/commands/update.js.map +1 -1
- package/dist/core/AccountManager.d.ts +1 -4
- package/dist/core/AccountManager.d.ts.map +1 -1
- package/dist/core/AccountManager.js +20 -12
- package/dist/core/AccountManager.js.map +1 -1
- package/dist/core/Publisher.d.ts +26 -0
- package/dist/core/Publisher.d.ts.map +1 -0
- package/dist/core/Publisher.js +240 -0
- package/dist/core/Publisher.js.map +1 -0
- package/dist/core/__tests__/AccountManager.test.d.ts +2 -0
- package/dist/core/__tests__/AccountManager.test.d.ts.map +1 -0
- package/dist/core/__tests__/AccountManager.test.js +239 -0
- package/dist/core/__tests__/AccountManager.test.js.map +1 -0
- package/dist/core/__tests__/config.test.d.ts +2 -0
- package/dist/core/__tests__/config.test.d.ts.map +1 -0
- package/dist/core/__tests__/config.test.js +311 -0
- package/dist/core/__tests__/config.test.js.map +1 -0
- package/dist/core/__tests__/deployments.test.d.ts +2 -0
- package/dist/core/__tests__/deployments.test.d.ts.map +1 -0
- package/dist/core/__tests__/deployments.test.js +201 -0
- package/dist/core/__tests__/deployments.test.js.map +1 -0
- package/dist/core/__tests__/shell.test.d.ts +2 -0
- package/dist/core/__tests__/shell.test.d.ts.map +1 -0
- package/dist/core/__tests__/shell.test.js +107 -0
- package/dist/core/__tests__/shell.test.js.map +1 -0
- package/dist/core/config.d.ts +13 -1
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +80 -11
- package/dist/core/config.js.map +1 -1
- package/dist/core/contract.d.ts +1 -4
- package/dist/core/contract.d.ts.map +1 -1
- package/dist/core/contract.js +15 -7
- package/dist/core/contract.js.map +1 -1
- package/dist/core/deployments.d.ts +2 -8
- package/dist/core/deployments.d.ts.map +1 -1
- package/dist/core/deployments.js +8 -18
- package/dist/core/deployments.js.map +1 -1
- package/dist/core/movementProfile.d.ts +34 -0
- package/dist/core/movementProfile.d.ts.map +1 -0
- package/dist/core/movementProfile.js +150 -0
- package/dist/core/movementProfile.js.map +1 -0
- package/dist/core/shell.d.ts +23 -7
- package/dist/core/shell.d.ts.map +1 -1
- package/dist/core/shell.js +32 -14
- package/dist/core/shell.js.map +1 -1
- package/dist/errors.d.ts +35 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +54 -0
- package/dist/errors.js.map +1 -1
- package/dist/fork/__tests__/manager.test.d.ts +2 -0
- package/dist/fork/__tests__/manager.test.d.ts.map +1 -0
- package/dist/fork/__tests__/manager.test.js +309 -0
- package/dist/fork/__tests__/manager.test.js.map +1 -0
- package/dist/fork/__tests__/server.test.d.ts +2 -0
- package/dist/fork/__tests__/server.test.d.ts.map +1 -0
- package/dist/fork/__tests__/server.test.js +54 -0
- package/dist/fork/__tests__/server.test.js.map +1 -0
- package/dist/fork/__tests__/storage.test.d.ts +2 -0
- package/dist/fork/__tests__/storage.test.d.ts.map +1 -0
- package/dist/fork/__tests__/storage.test.js +222 -0
- package/dist/fork/__tests__/storage.test.js.map +1 -0
- package/dist/fork/__tests__/test.test.d.ts +2 -0
- package/dist/fork/__tests__/test.test.d.ts.map +1 -0
- package/dist/fork/__tests__/test.test.js +81 -0
- package/dist/fork/__tests__/test.test.js.map +1 -0
- package/dist/fork/api.d.ts +14 -3
- package/dist/fork/api.d.ts.map +1 -1
- package/dist/fork/api.js +25 -14
- package/dist/fork/api.js.map +1 -1
- package/dist/fork/manager.d.ts +23 -29
- package/dist/fork/manager.d.ts.map +1 -1
- package/dist/fork/manager.js +79 -76
- package/dist/fork/manager.js.map +1 -1
- package/dist/fork/server.d.ts +11 -3
- package/dist/fork/server.d.ts.map +1 -1
- package/dist/fork/server.js +45 -13
- package/dist/fork/server.js.map +1 -1
- package/dist/fork/storage.d.ts +4 -4
- package/dist/fork/storage.d.ts.map +1 -1
- package/dist/fork/storage.js +7 -9
- package/dist/fork/storage.js.map +1 -1
- package/dist/fork/test.d.ts +12 -4
- package/dist/fork/test.d.ts.map +1 -1
- package/dist/fork/test.js +36 -27
- package/dist/fork/test.js.map +1 -1
- package/dist/harness/Harness.d.ts +118 -0
- package/dist/harness/Harness.d.ts.map +1 -0
- package/dist/harness/Harness.js +187 -0
- package/dist/harness/Harness.js.map +1 -0
- package/dist/harness/codeObject.d.ts +31 -0
- package/dist/harness/codeObject.d.ts.map +1 -0
- package/dist/harness/codeObject.js +267 -0
- package/dist/harness/codeObject.js.map +1 -0
- package/dist/harness/errors.d.ts +14 -0
- package/dist/harness/errors.d.ts.map +1 -0
- package/dist/harness/errors.js +22 -0
- package/dist/harness/errors.js.map +1 -0
- package/dist/harness/index.d.ts +4 -0
- package/dist/harness/index.d.ts.map +1 -0
- package/dist/harness/index.js +3 -0
- package/dist/harness/index.js.map +1 -0
- package/dist/harness/proxy.d.ts +7 -0
- package/dist/harness/proxy.d.ts.map +1 -0
- package/dist/harness/proxy.js +36 -0
- package/dist/harness/proxy.js.map +1 -0
- package/dist/harness/script.d.ts +21 -0
- package/dist/harness/script.d.ts.map +1 -0
- package/dist/harness/script.js +155 -0
- package/dist/harness/script.js.map +1 -0
- package/dist/harness/view.d.ts +22 -0
- package/dist/harness/view.d.ts.map +1 -0
- package/dist/harness/view.js +28 -0
- package/dist/harness/view.js.map +1 -0
- package/dist/helpers/__tests__/semver-utils.test.d.ts +2 -0
- package/dist/helpers/__tests__/semver-utils.test.d.ts.map +1 -0
- package/dist/helpers/__tests__/semver-utils.test.js +103 -0
- package/dist/helpers/__tests__/semver-utils.test.js.map +1 -0
- package/dist/helpers/index.d.ts +3 -2
- package/dist/helpers/index.d.ts.map +1 -1
- package/dist/helpers/index.js +2 -2
- package/dist/helpers/index.js.map +1 -1
- package/dist/helpers/move-tests.d.ts +3 -3
- package/dist/helpers/move-tests.d.ts.map +1 -1
- package/dist/helpers/move-tests.js +21 -20
- package/dist/helpers/move-tests.js.map +1 -1
- package/dist/helpers/npm-registry.d.ts.map +1 -1
- package/dist/helpers/npm-registry.js +1 -3
- package/dist/helpers/npm-registry.js.map +1 -1
- package/dist/helpers/semver-utils.d.ts.map +1 -1
- package/dist/helpers/semver-utils.js +4 -3
- package/dist/helpers/semver-utils.js.map +1 -1
- package/dist/helpers/setup.d.ts.map +1 -1
- package/dist/helpers/setup.js +6 -4
- package/dist/helpers/setup.js.map +1 -1
- package/dist/helpers/setupLocalTesting.d.ts +31 -27
- package/dist/helpers/setupLocalTesting.d.ts.map +1 -1
- package/dist/helpers/setupLocalTesting.js +179 -180
- package/dist/helpers/setupLocalTesting.js.map +1 -1
- package/dist/helpers/testFixtures.d.ts +19 -53
- package/dist/helpers/testFixtures.d.ts.map +1 -1
- package/dist/helpers/testFixtures.js +89 -107
- package/dist/helpers/testFixtures.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/dist/node/LocalNodeManager.d.ts +9 -1
- package/dist/node/LocalNodeManager.d.ts.map +1 -1
- package/dist/node/LocalNodeManager.js +75 -58
- package/dist/node/LocalNodeManager.js.map +1 -1
- package/dist/node/__tests__/LocalNodeManager.test.d.ts +2 -0
- package/dist/node/__tests__/LocalNodeManager.test.d.ts.map +1 -0
- package/dist/node/__tests__/LocalNodeManager.test.js +349 -0
- package/dist/node/__tests__/LocalNodeManager.test.js.map +1 -0
- package/dist/runtime.d.ts +12 -15
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +26 -239
- package/dist/runtime.js.map +1 -1
- package/dist/templates/README.md +1 -1
- package/dist/templates/movehat.config.ts +10 -0
- package/dist/templates/package.json +2 -1
- package/dist/templates/scripts/deploy-counter.ts +46 -38
- package/dist/templates/tests/Counter.test.ts +39 -51
- package/dist/templates/types/movehat.d.ts +6 -9
- package/dist/types/config.d.ts +8 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/fork.d.ts +7 -1
- package/dist/types/fork.d.ts.map +1 -1
- package/dist/types/harness.d.ts +166 -0
- package/dist/types/harness.d.ts.map +1 -0
- package/dist/types/harness.js +2 -0
- package/dist/types/harness.js.map +1 -0
- package/dist/types/runtime.d.ts +7 -1
- package/dist/types/runtime.d.ts.map +1 -1
- package/dist/ui/__tests__/colors.test.d.ts +2 -0
- package/dist/ui/__tests__/colors.test.d.ts.map +1 -0
- package/dist/ui/__tests__/colors.test.js +127 -0
- package/dist/ui/__tests__/colors.test.js.map +1 -0
- package/dist/ui/colors.d.ts.map +1 -1
- package/dist/ui/colors.js +6 -2
- package/dist/ui/colors.js.map +1 -1
- package/dist/ui/logger.d.ts +17 -0
- package/dist/ui/logger.d.ts.map +1 -1
- package/dist/ui/logger.js +22 -0
- package/dist/ui/logger.js.map +1 -1
- package/dist/ui/symbols.d.ts +1 -0
- package/dist/ui/symbols.d.ts.map +1 -1
- package/dist/ui/symbols.js +7 -1
- package/dist/ui/symbols.js.map +1 -1
- package/dist/utils/__tests__/address.test.d.ts +2 -0
- package/dist/utils/__tests__/address.test.d.ts.map +1 -0
- package/dist/utils/__tests__/address.test.js +70 -0
- package/dist/utils/__tests__/address.test.js.map +1 -0
- package/dist/utils/__tests__/childProcessAdapter.test.d.ts +2 -0
- package/dist/utils/__tests__/childProcessAdapter.test.d.ts.map +1 -0
- package/dist/utils/__tests__/childProcessAdapter.test.js +217 -0
- package/dist/utils/__tests__/childProcessAdapter.test.js.map +1 -0
- package/dist/utils/__tests__/runCli.test.d.ts +2 -0
- package/dist/utils/__tests__/runCli.test.d.ts.map +1 -0
- package/dist/utils/__tests__/runCli.test.js +187 -0
- package/dist/utils/__tests__/runCli.test.js.map +1 -0
- package/dist/utils/address.d.ts +29 -0
- package/dist/utils/address.d.ts.map +1 -0
- package/dist/utils/address.js +48 -0
- package/dist/utils/address.js.map +1 -0
- package/dist/utils/childProcessAdapter.d.ts +93 -0
- package/dist/utils/childProcessAdapter.d.ts.map +1 -0
- package/dist/utils/childProcessAdapter.js +108 -0
- package/dist/utils/childProcessAdapter.js.map +1 -0
- package/dist/utils/parseCliOutput.d.ts +20 -0
- package/dist/utils/parseCliOutput.d.ts.map +1 -0
- package/dist/utils/parseCliOutput.js +26 -0
- package/dist/utils/parseCliOutput.js.map +1 -0
- package/dist/utils/redact.d.ts +15 -0
- package/dist/utils/redact.d.ts.map +1 -0
- package/dist/utils/redact.js +24 -0
- package/dist/utils/redact.js.map +1 -0
- package/dist/utils/runCli.d.ts +24 -0
- package/dist/utils/runCli.d.ts.map +1 -0
- package/dist/utils/runCli.js +37 -0
- package/dist/utils/runCli.js.map +1 -0
- package/package.json +15 -4
- package/src/__tests__/deployContract.test.ts +429 -0
- package/src/__tests__/errors.test.ts +84 -0
- package/src/__tests__/fixtures/sigint-deploy-harness.ts +95 -0
- package/src/__tests__/fork/api.test.ts +143 -0
- package/src/__tests__/harness/Harness.createLive.test.ts +57 -0
- package/src/__tests__/harness/Harness.proxy.test.ts +111 -0
- package/src/__tests__/harness/_fixture.ts +131 -0
- package/src/__tests__/harness/codeObject.deploy.test.ts +319 -0
- package/src/__tests__/harness/codeObject.upgrade.test.ts +156 -0
- package/src/__tests__/harness/script.test.ts +245 -0
- package/src/__tests__/harness/view.test.ts +104 -0
- package/src/__tests__/runtime.test.ts +182 -0
- package/src/cli.ts +2 -1
- package/src/commands/__tests__/compile.test.ts +407 -0
- package/src/commands/__tests__/init.test.ts +125 -0
- package/src/commands/__tests__/run.test.ts +192 -0
- package/src/commands/__tests__/test-move.test.ts +81 -0
- package/src/commands/__tests__/test.test.ts +204 -0
- package/src/commands/__tests__/update.test.ts +223 -0
- package/src/commands/compile.ts +168 -32
- package/src/commands/fork/__tests__/create.test.ts +132 -0
- package/src/commands/fork/__tests__/fund.test.ts +104 -0
- package/src/commands/fork/__tests__/list.test.ts +139 -0
- package/src/commands/fork/__tests__/serve.test.ts +121 -0
- package/src/commands/fork/__tests__/view-resource.test.ts +101 -0
- package/src/commands/fork/create.ts +4 -3
- package/src/commands/fork/fund.ts +16 -9
- package/src/commands/fork/list.ts +3 -2
- package/src/commands/fork/serve.ts +6 -3
- package/src/commands/fork/view-resource.ts +11 -6
- package/src/commands/run.ts +54 -28
- package/src/commands/test-move.ts +4 -3
- package/src/commands/test.ts +56 -44
- package/src/commands/update.ts +19 -16
- package/src/core/AccountManager.ts +23 -22
- package/src/core/Publisher.ts +314 -0
- package/src/core/__tests__/AccountManager.test.ts +290 -0
- package/src/core/__tests__/config.test.ts +377 -0
- package/src/core/__tests__/deployments.test.ts +247 -0
- package/src/core/__tests__/shell.test.ts +138 -0
- package/src/core/config.ts +96 -12
- package/src/core/contract.ts +13 -7
- package/src/core/deployments.ts +13 -23
- package/src/core/movementProfile.ts +179 -0
- package/src/core/shell.ts +34 -14
- package/src/errors.ts +60 -0
- package/src/fork/__tests__/manager.test.ts +385 -0
- package/src/fork/__tests__/server.test.ts +65 -0
- package/src/fork/__tests__/storage.test.ts +281 -0
- package/src/fork/__tests__/test.test.ts +97 -0
- package/src/fork/api.ts +28 -14
- package/src/fork/manager.ts +88 -83
- package/src/fork/server.ts +53 -19
- package/src/fork/storage.ts +12 -15
- package/src/fork/test.ts +57 -32
- package/src/harness/Harness.ts +222 -0
- package/src/harness/codeObject.ts +384 -0
- package/src/harness/errors.ts +22 -0
- package/src/harness/index.ts +3 -0
- package/src/harness/proxy.ts +40 -0
- package/src/harness/script.ts +196 -0
- package/src/harness/view.ts +34 -0
- package/src/helpers/__tests__/semver-utils.test.ts +121 -0
- package/src/helpers/index.ts +2 -8
- package/src/helpers/move-tests.ts +27 -23
- package/src/helpers/npm-registry.ts +4 -3
- package/src/helpers/semver-utils.ts +4 -3
- package/src/helpers/setup.ts +6 -4
- package/src/helpers/setupLocalTesting.ts +218 -200
- package/src/helpers/testFixtures.ts +106 -118
- package/src/index.ts +8 -3
- package/src/node/LocalNodeManager.ts +87 -62
- package/src/node/__tests__/LocalNodeManager.test.ts +452 -0
- package/src/runtime.ts +28 -288
- package/src/templates/README.md +1 -1
- package/src/templates/movehat.config.ts +10 -0
- package/src/templates/package.json +2 -1
- package/src/templates/scripts/deploy-counter.ts +46 -38
- package/src/templates/tests/Counter.test.ts +39 -51
- package/src/templates/types/movehat.d.ts +6 -9
- package/src/types/config.ts +8 -0
- package/src/types/fork.ts +7 -1
- package/src/types/harness.ts +182 -0
- package/src/types/runtime.ts +11 -3
- package/src/ui/__tests__/colors.test.ts +156 -0
- package/src/ui/colors.ts +5 -2
- package/src/ui/logger.ts +22 -0
- package/src/ui/symbols.ts +7 -1
- package/src/utils/__tests__/address.test.ts +93 -0
- package/src/utils/__tests__/childProcessAdapter.test.ts +266 -0
- package/src/utils/__tests__/runCli.test.ts +240 -0
- package/src/utils/address.ts +52 -0
- package/src/utils/childProcessAdapter.ts +214 -0
- package/src/utils/parseCliOutput.ts +27 -0
- package/src/utils/redact.ts +24 -0
- package/src/utils/runCli.ts +64 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { existsSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { propagateRunResultExit } from "../run.js";
|
|
6
|
+
import type { RunResult } from "../../utils/childProcessAdapter.js";
|
|
7
|
+
|
|
8
|
+
// Mock runCli for orchestrator tests so we never spawn a real node/tsx.
|
|
9
|
+
// Use vi.hoisted to make the mock fn visible to the hoisted vi.mock factory.
|
|
10
|
+
const { runCliMock } = vi.hoisted(() => ({ runCliMock: vi.fn() }));
|
|
11
|
+
vi.mock("../../utils/runCli.js", () => ({
|
|
12
|
+
runCli: runCliMock,
|
|
13
|
+
}));
|
|
14
|
+
|
|
15
|
+
// Static import after mock declaration — vi hoists vi.mock.
|
|
16
|
+
const { default: runCommand } = await import("../run.js");
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Direct coverage for the signal-forwarding branch added to fix the
|
|
20
|
+
* CodeRabbit finding on PR #100 — `process.kill(process.pid, signal)`
|
|
21
|
+
* cannot run inside vitest without killing the runner, so the helper is
|
|
22
|
+
* exported and `process.kill` / `process.exit` are spied.
|
|
23
|
+
*/
|
|
24
|
+
describe("propagateRunResultExit", () => {
|
|
25
|
+
let killSpy: ReturnType<typeof vi.spyOn>;
|
|
26
|
+
let exitSpy: ReturnType<typeof vi.spyOn>;
|
|
27
|
+
|
|
28
|
+
beforeEach(() => {
|
|
29
|
+
killSpy = vi.spyOn(process, "kill").mockImplementation(() => true);
|
|
30
|
+
exitSpy = vi
|
|
31
|
+
.spyOn(process, "exit")
|
|
32
|
+
.mockImplementation(((_code?: number) => undefined) as never);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
afterEach(() => {
|
|
36
|
+
killSpy.mockRestore();
|
|
37
|
+
exitSpy.mockRestore();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("re-raises the signal on the parent when result.signal is set", () => {
|
|
41
|
+
const result: RunResult = {
|
|
42
|
+
exitCode: -1,
|
|
43
|
+
stdout: "",
|
|
44
|
+
stderr: "",
|
|
45
|
+
signal: "SIGINT",
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
propagateRunResultExit(result);
|
|
49
|
+
|
|
50
|
+
expect(killSpy).toHaveBeenCalledTimes(1);
|
|
51
|
+
expect(killSpy).toHaveBeenCalledWith(process.pid, "SIGINT");
|
|
52
|
+
expect(exitSpy).not.toHaveBeenCalled();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("forwards a non-negative numeric exit code via process.exit", () => {
|
|
56
|
+
const result: RunResult = { exitCode: 42, stdout: "", stderr: "" };
|
|
57
|
+
|
|
58
|
+
propagateRunResultExit(result);
|
|
59
|
+
|
|
60
|
+
expect(exitSpy).toHaveBeenCalledTimes(1);
|
|
61
|
+
expect(exitSpy).toHaveBeenCalledWith(42);
|
|
62
|
+
expect(killSpy).not.toHaveBeenCalled();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("clamps a negative exit code with no signal to exit 1 (avoids -1 → 255 mask)", () => {
|
|
66
|
+
const result: RunResult = { exitCode: -1, stdout: "", stderr: "" };
|
|
67
|
+
|
|
68
|
+
propagateRunResultExit(result);
|
|
69
|
+
|
|
70
|
+
expect(exitSpy).toHaveBeenCalledWith(1);
|
|
71
|
+
expect(killSpy).not.toHaveBeenCalled();
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("treats exitCode 0 as a normal success exit (not a signal)", () => {
|
|
75
|
+
const result: RunResult = { exitCode: 0, stdout: "", stderr: "" };
|
|
76
|
+
|
|
77
|
+
propagateRunResultExit(result);
|
|
78
|
+
|
|
79
|
+
expect(exitSpy).toHaveBeenCalledWith(0);
|
|
80
|
+
expect(killSpy).not.toHaveBeenCalled();
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
describe("runCommand — orchestrator", () => {
|
|
85
|
+
let tmpCwd: string;
|
|
86
|
+
let origCwd: string;
|
|
87
|
+
let exitSpy: ReturnType<typeof vi.spyOn>;
|
|
88
|
+
|
|
89
|
+
beforeEach(() => {
|
|
90
|
+
runCliMock.mockReset();
|
|
91
|
+
origCwd = process.cwd();
|
|
92
|
+
tmpCwd = mkdtempSync(join(tmpdir(), "movehat-runcmd-"));
|
|
93
|
+
process.chdir(tmpCwd);
|
|
94
|
+
// Throw on exit so the orchestrator's process.exit branches actually
|
|
95
|
+
// halt the flow (otherwise execution continues past process.exit and
|
|
96
|
+
// crashes on the next stmt with confusing errors).
|
|
97
|
+
exitSpy = vi
|
|
98
|
+
.spyOn(process, "exit")
|
|
99
|
+
.mockImplementation(((code?: number) => {
|
|
100
|
+
throw new Error(`__test_exit_${code ?? 0}__`);
|
|
101
|
+
}) as never);
|
|
102
|
+
// Suppress the signal-forwarding branch from killing the test runner.
|
|
103
|
+
vi.spyOn(process, "kill").mockImplementation(() => true);
|
|
104
|
+
vi.spyOn(console, "log").mockImplementation(() => undefined);
|
|
105
|
+
vi.spyOn(console, "error").mockImplementation(() => undefined);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
afterEach(() => {
|
|
109
|
+
process.chdir(origCwd);
|
|
110
|
+
if (existsSync(tmpCwd)) rmSync(tmpCwd, { recursive: true, force: true });
|
|
111
|
+
vi.restoreAllMocks();
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it("exits 1 when scriptPath is empty", async () => {
|
|
115
|
+
await expect(runCommand("")).rejects.toThrow("__test_exit_1__");
|
|
116
|
+
expect(runCliMock).not.toHaveBeenCalled();
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it("exits 1 when the script file does not exist", async () => {
|
|
120
|
+
await expect(runCommand("nonexistent.ts")).rejects.toThrow("__test_exit_1__");
|
|
121
|
+
expect(runCliMock).not.toHaveBeenCalled();
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it("exits 1 on an unsupported file extension", async () => {
|
|
125
|
+
const path = join(tmpCwd, "script.txt");
|
|
126
|
+
writeFileSync(path, "console.log('hi');");
|
|
127
|
+
await expect(runCommand("script.txt")).rejects.toThrow("__test_exit_1__");
|
|
128
|
+
expect(runCliMock).not.toHaveBeenCalled();
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it("invokes runCli when both script and tsx are resolvable (orchestrator happy path)", async () => {
|
|
132
|
+
// Inside vitest, the __dirname fallback in run.ts resolves tsx via
|
|
133
|
+
// the workspace's own node_modules. We don't need to plant a fake
|
|
134
|
+
// tsx — the orchestrator finds it and reaches the runCli call.
|
|
135
|
+
const scriptPath = join(tmpCwd, "deploy.ts");
|
|
136
|
+
writeFileSync(scriptPath, "// noop");
|
|
137
|
+
runCliMock.mockResolvedValueOnce({ exitCode: 0, stdout: "", stderr: "" });
|
|
138
|
+
|
|
139
|
+
// propagateRunResultExit's thrown __test_exit_0__ gets caught by the
|
|
140
|
+
// outer try/catch in runCommand, which then logs and calls
|
|
141
|
+
// process.exit(1) → throws __test_exit_1__. The interesting bit is
|
|
142
|
+
// that runCli got called with the right args.
|
|
143
|
+
await expect(runCommand("deploy.ts")).rejects.toThrow();
|
|
144
|
+
|
|
145
|
+
expect(runCliMock).toHaveBeenCalledTimes(1);
|
|
146
|
+
const callArgs = runCliMock.mock.calls[0]![0];
|
|
147
|
+
expect(callArgs.command).toBe("node");
|
|
148
|
+
// macOS resolves /var → /private/var, so compare by basename.
|
|
149
|
+
expect(callArgs.args[1]).toMatch(/deploy\.ts$/);
|
|
150
|
+
expect(callArgs.inheritStdio).toBe(true);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it("accepts .js and .mjs script extensions", async () => {
|
|
154
|
+
runCliMock.mockResolvedValueOnce({ exitCode: 0, stdout: "", stderr: "" });
|
|
155
|
+
const path = join(tmpCwd, "script.mjs");
|
|
156
|
+
writeFileSync(path, "");
|
|
157
|
+
await expect(runCommand("script.mjs")).rejects.toThrow();
|
|
158
|
+
expect(runCliMock).toHaveBeenCalledTimes(1);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it("logs the active network when MH_CLI_NETWORK is set", async () => {
|
|
162
|
+
const origNetwork = process.env.MH_CLI_NETWORK;
|
|
163
|
+
process.env.MH_CLI_NETWORK = "testnet";
|
|
164
|
+
try {
|
|
165
|
+
const path = join(tmpCwd, "script.ts");
|
|
166
|
+
writeFileSync(path, "");
|
|
167
|
+
runCliMock.mockResolvedValueOnce({ exitCode: 0, stdout: "", stderr: "" });
|
|
168
|
+
await expect(runCommand("script.ts")).rejects.toThrow();
|
|
169
|
+
expect(runCliMock).toHaveBeenCalled();
|
|
170
|
+
} finally {
|
|
171
|
+
if (origNetwork === undefined) delete process.env.MH_CLI_NETWORK;
|
|
172
|
+
else process.env.MH_CLI_NETWORK = origNetwork;
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// Note: the "tsx binary not found" exit branch (lines 80-101 in run.ts)
|
|
177
|
+
// requires `require.resolve` to throw for BOTH the cwd-paths lookup and
|
|
178
|
+
// the __dirname-paths fallback. In vitest, tsx is always resolvable via
|
|
179
|
+
// the workspace's own node_modules from __dirname's perspective, so the
|
|
180
|
+
// fallback never throws. Patching `module.createRequire` to inject a
|
|
181
|
+
// failing resolver fails with "Cannot redefine property" because the
|
|
182
|
+
// ESM-imported `node:module` is read-only. The branch is exercised
|
|
183
|
+
// by the integration suite via the "tsx not found" runtime failure
|
|
184
|
+
// when tsx is missing from a published consumer.
|
|
185
|
+
|
|
186
|
+
it("catches and exits 1 when runCli throws (spawn-time failure)", async () => {
|
|
187
|
+
runCliMock.mockRejectedValueOnce(new Error("ENOENT: node not found"));
|
|
188
|
+
const path = join(tmpCwd, "script.ts");
|
|
189
|
+
writeFileSync(path, "");
|
|
190
|
+
await expect(runCommand("script.ts")).rejects.toThrow("__test_exit_1__");
|
|
191
|
+
});
|
|
192
|
+
});
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
|
|
3
|
+
// Mock the helper before importing the command — vi.mock is hoisted.
|
|
4
|
+
const runMoveTestsMock = vi.fn();
|
|
5
|
+
vi.mock("../../helpers/move-tests.js", () => ({
|
|
6
|
+
runMoveTests: runMoveTestsMock,
|
|
7
|
+
}));
|
|
8
|
+
|
|
9
|
+
const { default: testMoveCommand } = await import("../test-move.js");
|
|
10
|
+
|
|
11
|
+
describe("testMoveCommand", () => {
|
|
12
|
+
let exitSpy: ReturnType<typeof vi.spyOn>;
|
|
13
|
+
let logSpy: ReturnType<typeof vi.spyOn>;
|
|
14
|
+
let errSpy: ReturnType<typeof vi.spyOn>;
|
|
15
|
+
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
runMoveTestsMock.mockReset();
|
|
18
|
+
// Intercept process.exit so the test process keeps running.
|
|
19
|
+
exitSpy = vi
|
|
20
|
+
.spyOn(process, "exit")
|
|
21
|
+
.mockImplementation(((_code?: number) => undefined) as never);
|
|
22
|
+
logSpy = vi.spyOn(console, "log").mockImplementation(() => undefined);
|
|
23
|
+
errSpy = vi.spyOn(console, "error").mockImplementation(() => undefined);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
afterEach(() => {
|
|
27
|
+
vi.restoreAllMocks();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("exits 0 on a successful move-tests run and forwards options", async () => {
|
|
31
|
+
runMoveTestsMock.mockResolvedValueOnce(undefined);
|
|
32
|
+
|
|
33
|
+
await testMoveCommand({ filter: "counter", ignoreWarnings: true });
|
|
34
|
+
|
|
35
|
+
expect(runMoveTestsMock).toHaveBeenCalledTimes(1);
|
|
36
|
+
expect(runMoveTestsMock).toHaveBeenCalledWith({
|
|
37
|
+
filter: "counter",
|
|
38
|
+
ignoreWarnings: true,
|
|
39
|
+
skipIfMissing: false,
|
|
40
|
+
});
|
|
41
|
+
expect(exitSpy).toHaveBeenCalledWith(0);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("defaults options to undefined when none are provided", async () => {
|
|
45
|
+
runMoveTestsMock.mockResolvedValueOnce(undefined);
|
|
46
|
+
|
|
47
|
+
await testMoveCommand();
|
|
48
|
+
|
|
49
|
+
const callArg = runMoveTestsMock.mock.calls[0]![0];
|
|
50
|
+
expect(callArg).toEqual({
|
|
51
|
+
filter: undefined,
|
|
52
|
+
ignoreWarnings: undefined,
|
|
53
|
+
skipIfMissing: false,
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("exits 1 and logs the error message when the helper throws", async () => {
|
|
58
|
+
runMoveTestsMock.mockRejectedValueOnce(new Error("move compile failed"));
|
|
59
|
+
|
|
60
|
+
await testMoveCommand({});
|
|
61
|
+
|
|
62
|
+
expect(exitSpy).toHaveBeenCalledWith(1);
|
|
63
|
+
expect(errSpy).toHaveBeenCalledWith(
|
|
64
|
+
expect.stringContaining("Move tests failed")
|
|
65
|
+
);
|
|
66
|
+
expect(errSpy).toHaveBeenCalledWith(
|
|
67
|
+
expect.stringContaining("move compile failed")
|
|
68
|
+
);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("handles non-Error throws (string) without crashing", async () => {
|
|
72
|
+
runMoveTestsMock.mockRejectedValueOnce("just a string");
|
|
73
|
+
|
|
74
|
+
await testMoveCommand({});
|
|
75
|
+
|
|
76
|
+
expect(exitSpy).toHaveBeenCalledWith(1);
|
|
77
|
+
expect(errSpy).toHaveBeenCalledWith(
|
|
78
|
+
expect.stringContaining("just a string")
|
|
79
|
+
);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { existsSync, mkdtempSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
|
|
6
|
+
const runMoveTestsMock = vi.fn();
|
|
7
|
+
const runCliMock = vi.fn();
|
|
8
|
+
const promptsMock = vi.fn();
|
|
9
|
+
|
|
10
|
+
vi.mock("../../helpers/move-tests.js", () => ({
|
|
11
|
+
runMoveTests: runMoveTestsMock,
|
|
12
|
+
}));
|
|
13
|
+
|
|
14
|
+
vi.mock("../../utils/runCli.js", () => ({
|
|
15
|
+
runCli: runCliMock,
|
|
16
|
+
}));
|
|
17
|
+
|
|
18
|
+
vi.mock("prompts", () => ({
|
|
19
|
+
default: promptsMock,
|
|
20
|
+
}));
|
|
21
|
+
|
|
22
|
+
const { default: testCommand } = await import("../test.js");
|
|
23
|
+
|
|
24
|
+
describe("testCommand — flag dispatch", () => {
|
|
25
|
+
let tmpCwd: string;
|
|
26
|
+
let origCwd: string;
|
|
27
|
+
let exitSpy: ReturnType<typeof vi.spyOn>;
|
|
28
|
+
|
|
29
|
+
beforeEach(() => {
|
|
30
|
+
runMoveTestsMock.mockReset();
|
|
31
|
+
runCliMock.mockReset();
|
|
32
|
+
promptsMock.mockReset();
|
|
33
|
+
origCwd = process.cwd();
|
|
34
|
+
tmpCwd = mkdtempSync(join(tmpdir(), "movehat-testcmd-"));
|
|
35
|
+
process.chdir(tmpCwd);
|
|
36
|
+
exitSpy = vi
|
|
37
|
+
.spyOn(process, "exit")
|
|
38
|
+
.mockImplementation(((_code?: number) => undefined) as never);
|
|
39
|
+
vi.spyOn(console, "log").mockImplementation(() => undefined);
|
|
40
|
+
vi.spyOn(console, "error").mockImplementation(() => undefined);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
afterEach(() => {
|
|
44
|
+
process.chdir(origCwd);
|
|
45
|
+
if (existsSync(tmpCwd)) rmSync(tmpCwd, { recursive: true, force: true });
|
|
46
|
+
vi.restoreAllMocks();
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("--move flag runs only the Move test path", async () => {
|
|
50
|
+
runMoveTestsMock.mockResolvedValueOnce(undefined);
|
|
51
|
+
|
|
52
|
+
await testCommand({ move: true });
|
|
53
|
+
|
|
54
|
+
expect(runMoveTestsMock).toHaveBeenCalledTimes(1);
|
|
55
|
+
expect(runMoveTestsMock).toHaveBeenCalledWith({
|
|
56
|
+
filter: undefined,
|
|
57
|
+
skipIfMissing: false,
|
|
58
|
+
});
|
|
59
|
+
expect(runCliMock).not.toHaveBeenCalled();
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("legacy --moveOnly flag is translated into --move", async () => {
|
|
63
|
+
runMoveTestsMock.mockResolvedValueOnce(undefined);
|
|
64
|
+
|
|
65
|
+
await testCommand({ moveOnly: true });
|
|
66
|
+
|
|
67
|
+
expect(runMoveTestsMock).toHaveBeenCalledTimes(1);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("legacy --tsOnly flag is translated into --ts (skips Move; mocha branch missing tests/ → skip)", async () => {
|
|
71
|
+
// No tests/ directory exists in tmpCwd, so the TS-only path skips
|
|
72
|
+
// gracefully via the "No TypeScript tests found" branch and never
|
|
73
|
+
// invokes runCli. The Move path is never entered.
|
|
74
|
+
await testCommand({ tsOnly: true });
|
|
75
|
+
|
|
76
|
+
expect(runMoveTestsMock).not.toHaveBeenCalled();
|
|
77
|
+
expect(runCliMock).not.toHaveBeenCalled();
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("--all flag forces the all-tests path", async () => {
|
|
81
|
+
runMoveTestsMock.mockResolvedValueOnce(undefined);
|
|
82
|
+
await testCommand({ all: true });
|
|
83
|
+
expect(runMoveTestsMock).toHaveBeenCalledTimes(1);
|
|
84
|
+
// skipIfMissing: true in the all-tests path.
|
|
85
|
+
expect(runMoveTestsMock.mock.calls[0]![0].skipIfMissing).toBe(true);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it("--move + --ts together also resolves to 'all'", async () => {
|
|
89
|
+
runMoveTestsMock.mockResolvedValueOnce(undefined);
|
|
90
|
+
await testCommand({ move: true, ts: true });
|
|
91
|
+
// The 'all' path uses skipIfMissing: true.
|
|
92
|
+
expect(runMoveTestsMock.mock.calls[0]![0].skipIfMissing).toBe(true);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("Move-only path exits 1 when runMoveTests throws", async () => {
|
|
96
|
+
runMoveTestsMock.mockRejectedValueOnce(new Error("compile failed"));
|
|
97
|
+
await testCommand({ move: true });
|
|
98
|
+
expect(exitSpy).toHaveBeenCalledWith(1);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it("forwards --filter to runMoveTests", async () => {
|
|
102
|
+
runMoveTestsMock.mockResolvedValueOnce(undefined);
|
|
103
|
+
await testCommand({ move: true, filter: "counter" });
|
|
104
|
+
expect(runMoveTestsMock.mock.calls[0]![0].filter).toBe("counter");
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
describe("testCommand — interactive menu", () => {
|
|
109
|
+
let tmpCwd: string;
|
|
110
|
+
let origCwd: string;
|
|
111
|
+
let exitSpy: ReturnType<typeof vi.spyOn>;
|
|
112
|
+
|
|
113
|
+
beforeEach(() => {
|
|
114
|
+
runMoveTestsMock.mockReset();
|
|
115
|
+
runCliMock.mockReset();
|
|
116
|
+
promptsMock.mockReset();
|
|
117
|
+
origCwd = process.cwd();
|
|
118
|
+
tmpCwd = mkdtempSync(join(tmpdir(), "movehat-testcmd-"));
|
|
119
|
+
process.chdir(tmpCwd);
|
|
120
|
+
exitSpy = vi
|
|
121
|
+
.spyOn(process, "exit")
|
|
122
|
+
.mockImplementation(((_code?: number) => undefined) as never);
|
|
123
|
+
vi.spyOn(console, "log").mockImplementation(() => undefined);
|
|
124
|
+
vi.spyOn(console, "error").mockImplementation(() => undefined);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
afterEach(() => {
|
|
128
|
+
process.chdir(origCwd);
|
|
129
|
+
if (existsSync(tmpCwd)) rmSync(tmpCwd, { recursive: true, force: true });
|
|
130
|
+
vi.restoreAllMocks();
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it("falls back to interactive prompt when no flags are passed; cancellation exits 0", async () => {
|
|
134
|
+
// Ctrl+C — prompt returns {}.
|
|
135
|
+
promptsMock.mockResolvedValueOnce({});
|
|
136
|
+
|
|
137
|
+
await testCommand();
|
|
138
|
+
|
|
139
|
+
expect(promptsMock).toHaveBeenCalledTimes(1);
|
|
140
|
+
expect(exitSpy).toHaveBeenCalledWith(0);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it("prompt returns 'move' → runs the Move path", async () => {
|
|
144
|
+
promptsMock.mockResolvedValueOnce({ testType: "move" });
|
|
145
|
+
runMoveTestsMock.mockResolvedValueOnce(undefined);
|
|
146
|
+
|
|
147
|
+
await testCommand();
|
|
148
|
+
|
|
149
|
+
expect(runMoveTestsMock).toHaveBeenCalledTimes(1);
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
describe("testCommand — TypeScript path with tests/ + node_modules", () => {
|
|
154
|
+
let tmpCwd: string;
|
|
155
|
+
let origCwd: string;
|
|
156
|
+
let exitSpy: ReturnType<typeof vi.spyOn>;
|
|
157
|
+
|
|
158
|
+
beforeEach(() => {
|
|
159
|
+
runMoveTestsMock.mockReset();
|
|
160
|
+
runCliMock.mockReset();
|
|
161
|
+
promptsMock.mockReset();
|
|
162
|
+
origCwd = process.cwd();
|
|
163
|
+
tmpCwd = mkdtempSync(join(tmpdir(), "movehat-testcmd-"));
|
|
164
|
+
process.chdir(tmpCwd);
|
|
165
|
+
|
|
166
|
+
// Plant a tests/ directory and a fake mocha binary.
|
|
167
|
+
mkdirSync(join(tmpCwd, "tests"), { recursive: true });
|
|
168
|
+
mkdirSync(join(tmpCwd, "node_modules", ".bin"), { recursive: true });
|
|
169
|
+
writeFileSync(join(tmpCwd, "node_modules", ".bin", "mocha"), "#!/bin/sh\nexit 0\n");
|
|
170
|
+
|
|
171
|
+
exitSpy = vi
|
|
172
|
+
.spyOn(process, "exit")
|
|
173
|
+
.mockImplementation(((_code?: number) => undefined) as never);
|
|
174
|
+
vi.spyOn(console, "log").mockImplementation(() => undefined);
|
|
175
|
+
vi.spyOn(console, "error").mockImplementation(() => undefined);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
afterEach(() => {
|
|
179
|
+
process.chdir(origCwd);
|
|
180
|
+
if (existsSync(tmpCwd)) rmSync(tmpCwd, { recursive: true, force: true });
|
|
181
|
+
vi.restoreAllMocks();
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it("--ts invokes mocha via runCli when both tests/ and node_modules/.bin/mocha exist", async () => {
|
|
185
|
+
runCliMock.mockResolvedValueOnce({ exitCode: 0, stdout: "", stderr: "" });
|
|
186
|
+
|
|
187
|
+
await testCommand({ ts: true });
|
|
188
|
+
|
|
189
|
+
expect(runCliMock).toHaveBeenCalledTimes(1);
|
|
190
|
+
expect(runCliMock.mock.calls[0]![0].command).toContain("mocha");
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it("--ts exits 1 when mocha's exit code is non-zero", async () => {
|
|
194
|
+
runCliMock.mockResolvedValueOnce({
|
|
195
|
+
exitCode: 1,
|
|
196
|
+
stdout: "",
|
|
197
|
+
stderr: "1 failing",
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
await testCommand({ ts: true });
|
|
201
|
+
|
|
202
|
+
expect(exitSpy).toHaveBeenCalledWith(1);
|
|
203
|
+
});
|
|
204
|
+
});
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
|
|
6
|
+
const fetchLatestVersionMock = vi.fn();
|
|
7
|
+
const promptsMock = vi.fn();
|
|
8
|
+
const runCliMock = vi.fn();
|
|
9
|
+
|
|
10
|
+
vi.mock("../../helpers/npm-registry.js", () => ({
|
|
11
|
+
fetchLatestVersion: fetchLatestVersionMock,
|
|
12
|
+
}));
|
|
13
|
+
|
|
14
|
+
vi.mock("prompts", () => ({
|
|
15
|
+
default: promptsMock,
|
|
16
|
+
}));
|
|
17
|
+
|
|
18
|
+
vi.mock("../../utils/runCli.js", () => ({
|
|
19
|
+
runCli: runCliMock,
|
|
20
|
+
}));
|
|
21
|
+
|
|
22
|
+
const { default: updateCommand } = await import("../update.js");
|
|
23
|
+
|
|
24
|
+
describe("updateCommand", () => {
|
|
25
|
+
let exitSpy: ReturnType<typeof vi.spyOn>;
|
|
26
|
+
let logSpy: ReturnType<typeof vi.spyOn>;
|
|
27
|
+
|
|
28
|
+
beforeEach(() => {
|
|
29
|
+
fetchLatestVersionMock.mockReset();
|
|
30
|
+
promptsMock.mockReset();
|
|
31
|
+
runCliMock.mockReset();
|
|
32
|
+
exitSpy = vi
|
|
33
|
+
.spyOn(process, "exit")
|
|
34
|
+
.mockImplementation(((_code?: number) => undefined) as never);
|
|
35
|
+
logSpy = vi.spyOn(console, "log").mockImplementation(() => undefined);
|
|
36
|
+
vi.spyOn(console, "error").mockImplementation(() => undefined);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
afterEach(() => {
|
|
40
|
+
vi.restoreAllMocks();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("does nothing further when already on the latest version", async () => {
|
|
44
|
+
// Read the actual current version from package.json — same fetch the
|
|
45
|
+
// command does internally — and report it back as the "latest".
|
|
46
|
+
const currentVersion = await import("../../../package.json", {
|
|
47
|
+
with: { type: "json" },
|
|
48
|
+
}).then((m) => m.default.version);
|
|
49
|
+
fetchLatestVersionMock.mockResolvedValueOnce(currentVersion);
|
|
50
|
+
|
|
51
|
+
await updateCommand();
|
|
52
|
+
|
|
53
|
+
expect(fetchLatestVersionMock).toHaveBeenCalledTimes(1);
|
|
54
|
+
// Prompt never fires because the command short-circuits on the
|
|
55
|
+
// "already up to date" branch.
|
|
56
|
+
expect(promptsMock).not.toHaveBeenCalled();
|
|
57
|
+
expect(runCliMock).not.toHaveBeenCalled();
|
|
58
|
+
expect(exitSpy).not.toHaveBeenCalled();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("exits 1 with a clear error when fetchLatestVersion returns null", async () => {
|
|
62
|
+
fetchLatestVersionMock.mockResolvedValueOnce(null);
|
|
63
|
+
|
|
64
|
+
await updateCommand();
|
|
65
|
+
|
|
66
|
+
expect(exitSpy).toHaveBeenCalledWith(1);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("prompts for confirmation, runs the package manager, and exits 0 on success", async () => {
|
|
70
|
+
fetchLatestVersionMock.mockResolvedValueOnce("99.0.0");
|
|
71
|
+
promptsMock.mockResolvedValueOnce({ confirm: true });
|
|
72
|
+
runCliMock.mockResolvedValueOnce({ exitCode: 0, stdout: "", stderr: "" });
|
|
73
|
+
|
|
74
|
+
await updateCommand();
|
|
75
|
+
|
|
76
|
+
expect(promptsMock).toHaveBeenCalledTimes(1);
|
|
77
|
+
expect(runCliMock).toHaveBeenCalledTimes(1);
|
|
78
|
+
expect(exitSpy).toHaveBeenCalledWith(0);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("returns without running the package manager when the user declines the prompt", async () => {
|
|
82
|
+
fetchLatestVersionMock.mockResolvedValueOnce("99.0.0");
|
|
83
|
+
promptsMock.mockResolvedValueOnce({ confirm: false });
|
|
84
|
+
|
|
85
|
+
await updateCommand();
|
|
86
|
+
|
|
87
|
+
expect(runCliMock).not.toHaveBeenCalled();
|
|
88
|
+
expect(exitSpy).not.toHaveBeenCalled();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("returns without running the package manager when the user Ctrl+Cs the prompt", async () => {
|
|
92
|
+
fetchLatestVersionMock.mockResolvedValueOnce("99.0.0");
|
|
93
|
+
// Prompt with Ctrl+C returns an empty object — `confirm` is undefined.
|
|
94
|
+
promptsMock.mockResolvedValueOnce({});
|
|
95
|
+
|
|
96
|
+
await updateCommand();
|
|
97
|
+
|
|
98
|
+
expect(runCliMock).not.toHaveBeenCalled();
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it("exits 1 when the package-manager run returns a non-zero exit code", async () => {
|
|
102
|
+
fetchLatestVersionMock.mockResolvedValueOnce("99.0.0");
|
|
103
|
+
promptsMock.mockResolvedValueOnce({ confirm: true });
|
|
104
|
+
runCliMock.mockResolvedValueOnce({
|
|
105
|
+
exitCode: 1,
|
|
106
|
+
stdout: "",
|
|
107
|
+
stderr: "permission denied",
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
await updateCommand();
|
|
111
|
+
|
|
112
|
+
expect(exitSpy).toHaveBeenCalledWith(1);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it("exits 1 when the package-manager run throws", async () => {
|
|
116
|
+
fetchLatestVersionMock.mockResolvedValueOnce("99.0.0");
|
|
117
|
+
promptsMock.mockResolvedValueOnce({ confirm: true });
|
|
118
|
+
runCliMock.mockRejectedValueOnce(new Error("ENOENT: pnpm not found"));
|
|
119
|
+
|
|
120
|
+
await updateCommand();
|
|
121
|
+
|
|
122
|
+
expect(exitSpy).toHaveBeenCalledWith(1);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it("exits 1 with a clear error when fetchLatestVersion throws", async () => {
|
|
126
|
+
fetchLatestVersionMock.mockRejectedValueOnce(new Error("network down"));
|
|
127
|
+
|
|
128
|
+
await updateCommand();
|
|
129
|
+
|
|
130
|
+
expect(exitSpy).toHaveBeenCalledWith(1);
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
describe("updateCommand — package-manager detection", () => {
|
|
135
|
+
let tmpCwd: string;
|
|
136
|
+
let origCwd: string;
|
|
137
|
+
let origAgent: string | undefined;
|
|
138
|
+
|
|
139
|
+
beforeEach(() => {
|
|
140
|
+
fetchLatestVersionMock.mockReset();
|
|
141
|
+
promptsMock.mockReset();
|
|
142
|
+
runCliMock.mockReset();
|
|
143
|
+
origCwd = process.cwd();
|
|
144
|
+
tmpCwd = mkdtempSync(join(tmpdir(), "movehat-update-pkgmgr-"));
|
|
145
|
+
process.chdir(tmpCwd);
|
|
146
|
+
origAgent = process.env.npm_config_user_agent;
|
|
147
|
+
delete process.env.npm_config_user_agent;
|
|
148
|
+
// npm_execpath is also inspected by detectPackageManager — clear it
|
|
149
|
+
// so the test doesn't pick up the runner's own value.
|
|
150
|
+
delete process.env.npm_execpath;
|
|
151
|
+
vi.spyOn(process, "exit").mockImplementation(((_code?: number) => undefined) as never);
|
|
152
|
+
vi.spyOn(console, "log").mockImplementation(() => undefined);
|
|
153
|
+
vi.spyOn(console, "error").mockImplementation(() => undefined);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
afterEach(() => {
|
|
157
|
+
process.chdir(origCwd);
|
|
158
|
+
if (origAgent === undefined) delete process.env.npm_config_user_agent;
|
|
159
|
+
else process.env.npm_config_user_agent = origAgent;
|
|
160
|
+
rmSync(tmpCwd, { recursive: true, force: true });
|
|
161
|
+
vi.restoreAllMocks();
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it("detects pnpm when pnpm-lock.yaml is present and runs `pnpm add -g`", async () => {
|
|
165
|
+
writeFileSync(join(tmpCwd, "pnpm-lock.yaml"), "");
|
|
166
|
+
fetchLatestVersionMock.mockResolvedValueOnce("99.0.0");
|
|
167
|
+
promptsMock.mockResolvedValueOnce({ confirm: true });
|
|
168
|
+
runCliMock.mockResolvedValueOnce({ exitCode: 0, stdout: "", stderr: "" });
|
|
169
|
+
|
|
170
|
+
await updateCommand();
|
|
171
|
+
|
|
172
|
+
const call = runCliMock.mock.calls[0]!;
|
|
173
|
+
expect(call[0].command).toBe("pnpm");
|
|
174
|
+
expect(call[0].args.slice(0, 2)).toEqual(["add", "-g"]);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it("detects yarn when yarn.lock is present and runs `yarn global upgrade`", async () => {
|
|
178
|
+
writeFileSync(join(tmpCwd, "yarn.lock"), "");
|
|
179
|
+
fetchLatestVersionMock.mockResolvedValueOnce("99.0.0");
|
|
180
|
+
promptsMock.mockResolvedValueOnce({ confirm: true });
|
|
181
|
+
runCliMock.mockResolvedValueOnce({ exitCode: 0, stdout: "", stderr: "" });
|
|
182
|
+
|
|
183
|
+
await updateCommand();
|
|
184
|
+
|
|
185
|
+
const call = runCliMock.mock.calls[0]!;
|
|
186
|
+
expect(call[0].command).toBe("yarn");
|
|
187
|
+
expect(call[0].args.slice(0, 2)).toEqual(["global", "upgrade"]);
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it("detects npm when package-lock.json is present and runs `npm update -g`", async () => {
|
|
191
|
+
writeFileSync(join(tmpCwd, "package-lock.json"), "{}");
|
|
192
|
+
fetchLatestVersionMock.mockResolvedValueOnce("99.0.0");
|
|
193
|
+
promptsMock.mockResolvedValueOnce({ confirm: true });
|
|
194
|
+
runCliMock.mockResolvedValueOnce({ exitCode: 0, stdout: "", stderr: "" });
|
|
195
|
+
|
|
196
|
+
await updateCommand();
|
|
197
|
+
|
|
198
|
+
const call = runCliMock.mock.calls[0]!;
|
|
199
|
+
expect(call[0].command).toBe("npm");
|
|
200
|
+
expect(call[0].args.slice(0, 2)).toEqual(["update", "-g"]);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it("falls back to user-agent detection when no lockfile is present (pnpm)", async () => {
|
|
204
|
+
process.env.npm_config_user_agent = "pnpm/8.0.0 node/v20";
|
|
205
|
+
fetchLatestVersionMock.mockResolvedValueOnce("99.0.0");
|
|
206
|
+
promptsMock.mockResolvedValueOnce({ confirm: true });
|
|
207
|
+
runCliMock.mockResolvedValueOnce({ exitCode: 0, stdout: "", stderr: "" });
|
|
208
|
+
|
|
209
|
+
await updateCommand();
|
|
210
|
+
|
|
211
|
+
expect(runCliMock.mock.calls[0]![0].command).toBe("pnpm");
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it("defaults to npm when neither lockfile nor user-agent gives a hint", async () => {
|
|
215
|
+
fetchLatestVersionMock.mockResolvedValueOnce("99.0.0");
|
|
216
|
+
promptsMock.mockResolvedValueOnce({ confirm: true });
|
|
217
|
+
runCliMock.mockResolvedValueOnce({ exitCode: 0, stdout: "", stderr: "" });
|
|
218
|
+
|
|
219
|
+
await updateCommand();
|
|
220
|
+
|
|
221
|
+
expect(runCliMock.mock.calls[0]![0].command).toBe("npm");
|
|
222
|
+
});
|
|
223
|
+
});
|