From 5b0d80dba48a81df3740d5b40c3ded5286e230fb Mon Sep 17 00:00:00 2001 From: Jason Ginchereau Date: Wed, 17 May 2017 09:44:46 -0700 Subject: [PATCH] Test and document upgrade command --- doc/ADD.md | 6 +- doc/ALIAS.md | 58 ++--- doc/AUTO.md | 10 +- doc/EXEC.md | 6 +- doc/LINK.md | 8 +- doc/LIST-REMOTE.md | 10 +- doc/LIST.md | 8 +- doc/MIGRATE.md | 6 +- doc/REMOTE.md | 18 +- doc/REMOVE.md | 8 +- doc/RUN.md | 16 +- doc/SETUP.md | 2 + doc/UNLINK.md | 8 +- doc/UPGRADE.md | 34 +++ doc/USE.md | 13 +- doc/WHICH.md | 6 +- lib/help.js | 2 +- lib/upgrade.js | 31 ++- test/cli/{bash.js => bashTests.js} | 0 test/cli/{cmd.js => cmdTests.js} | 0 test/cli/{git-bash.js => gitBashTests.js} | 0 test/cli/{ps.js => psTests.js} | 0 test/cli/{zsh.js => zshTests.js} | 0 test/fsUtil.js | 2 +- .../{addRemove.js => addRemoveTests.js} | 0 test/modules/{auto.js => autoTests.js} | 0 test/modules/{link.js => linkTests.js} | 0 test/modules/{list.js => listTests.js} | 0 test/modules/{migrate.js => migrateTests.js} | 0 test/modules/upgradeTests.js | 214 ++++++++++++++++++ test/modules/{use.js => useTests.js} | 0 test/modules/{version.js => versionTests.js} | 0 32 files changed, 363 insertions(+), 103 deletions(-) create mode 100644 doc/UPGRADE.md rename test/cli/{bash.js => bashTests.js} (100%) rename test/cli/{cmd.js => cmdTests.js} (100%) rename test/cli/{git-bash.js => gitBashTests.js} (100%) rename test/cli/{ps.js => psTests.js} (100%) rename test/cli/{zsh.js => zshTests.js} (100%) rename test/modules/{addRemove.js => addRemoveTests.js} (100%) rename test/modules/{auto.js => autoTests.js} (100%) rename test/modules/{link.js => linkTests.js} (100%) rename test/modules/{list.js => listTests.js} (100%) rename test/modules/{migrate.js => migrateTests.js} (100%) create mode 100644 test/modules/upgradeTests.js rename test/modules/{use.js => useTests.js} (100%) rename test/modules/{version.js => versionTests.js} (100%) diff --git a/doc/ADD.md b/doc/ADD.md index a4e2a35..acb42ee 100644 --- a/doc/ADD.md +++ b/doc/ADD.md @@ -1,7 +1,7 @@ # ADD Command - Node Version Switcher -``` -nvs add -``` + + nvs add + Downloads and extracts a requested node version. An added node version is then ready to activate with a USE command. A version string consists of a complete or partial semantic version number or version label ("lts", "latest", "Argon", etc.), optionally preceded by a remote name, optionally followed by a processor architecture or bitness ("x86", "x64", "32", "64"), separated by slashes. When a partial version matches multiple available versions, the latest version is automatically selected. Examples: "node/lts", "4.6.0", "6/x86", "node/6.7/x64". An alias may also be used in place of a version string. diff --git a/doc/ALIAS.md b/doc/ALIAS.md index 4958436..4a69128 100644 --- a/doc/ALIAS.md +++ b/doc/ALIAS.md @@ -1,39 +1,39 @@ # ALIAS Command - Node Version Switcher -``` -nvs alias -nvs alias -nvs alias -nvs alias -nvs alias -d -``` + + nvs alias + nvs alias + nvs alias + nvs alias + nvs alias -d + Queries, sets, or removes version aliases. When no arguments are specified, all alias names and values are listed. When just a name is specified, the value for that alias is shown, if it exists. When a name and value are specified, the alias is added or updated to the persisted list. The `-d` switch removes an item. The alias settings are persisted in `$NVS_HOME/settings.json`. An alias may refer to a combination of a remote name and a semantic version. (Processor architectures are not aliased.) When setting an alias, the remote name may be omitted, in which case the alias refers to the default remote. For example `nvs alias 6.7.0` is exactly equivalent to `nvs alias default/6.7.0`. When using an alias with other commands, a processor architecture may be optionally appended to override the system default, the same as with semantic versions. For example: -``` -$ nvs alias myalias 6.7.0 -$ nvs alias -myalias default/6.7.0 -$ nvs run myalias --version -v6.7.0 -$ nvs which myalias -~/.nvs/node/6.7.0/x64/bin/node -$ nvs which myalias/32 -~/.nvs/node/6.7.0/x86/bin/node -``` + + $ nvs alias myalias 6.7.0 + $ nvs alias + myalias default/6.7.0 + $ nvs run myalias --version + v6.7.0 + $ nvs which myalias + ~/.nvs/node/6.7.0/x64/bin/node + $ nvs which myalias/32 + ~/.nvs/node/6.7.0/x86/bin/node + ## Aliasing directories An alias may also refer to a local directory containing any node executable. Create an alias like this to enable NVS to switch to/from a version of node that was built locally from source: -``` -$ nvs alias dev ~/src/node/out/Release -$ nvs use dev -PATH += ~/src/node/out/Release -$ nvs ls - #node/6.9.1/x64 - >/home/username/src/node/out/Release (dev) -$ nvs use lts -PATH -= ~/src/node/out/Release -PATH += ~/.nvs/node/6.9.1/x64/bin -``` + + $ nvs alias dev ~/src/node/out/Release + $ nvs use dev + PATH += ~/src/node/out/Release + $ nvs ls + #node/6.9.1/x64 + >/home/username/src/node/out/Release (dev) + $ nvs use lts + PATH -= ~/src/node/out/Release + PATH += ~/.nvs/node/6.9.1/x64/bin + Note it is not possible to `nvs use` a directory without using an alias. diff --git a/doc/AUTO.md b/doc/AUTO.md index b99b943..1bd856b 100644 --- a/doc/AUTO.md +++ b/doc/AUTO.md @@ -1,9 +1,9 @@ # AUTO Command - Node Version Switcher -``` -nvs auto -nvs auto on -nvs auto off -``` + + nvs auto + nvs auto on + nvs auto off + When invoked with no parameters, `nvs auto` searches for the nearest `.node-version` file in the current directory or parent directories. If found, the version specified in the file is then downloaded (if necessary) and used. If no `.node-version` file is found, then the default (linked) version, if any, is used. The `nvs auto on` command enables automatic switching as needed whenever the current shell's working directory changes; `nvs auto off` disables automatic switching in the current shell. (This feature is not supported in Windows Command Prompt.) diff --git a/doc/EXEC.md b/doc/EXEC.md index eb9e629..759cf7c 100644 --- a/doc/EXEC.md +++ b/doc/EXEC.md @@ -1,5 +1,5 @@ # EXEC Command - Node Version Switcher -``` -nvs exec [args...] -``` + + nvs exec [args...] + Runs any executable using a `PATH` environment that includes the specified node version, without changing the caller's `PATH`. diff --git a/doc/LINK.md b/doc/LINK.md index 34a668e..c08958f 100644 --- a/doc/LINK.md +++ b/doc/LINK.md @@ -1,8 +1,8 @@ # LINK Command - Node Version Switcher -``` -nvs link [version] -nvs ln [version] -``` + + nvs link [version] + nvs ln [version] + Creates a symbolic directory link at `$NVS_HOME/default` that points to the specified version (or the current version from `PATH` at the time of the command). This sets a "default" node version, which is restored whenever the current version is removed, or when running `nvs use` with no version. It can also be useful when there is a need to configure a fixed path elsewhere (such as in an IDE), allowing the version to be switched without changing the path. On Windows, this command also updates the profile `PATH` environment variable to include the default (linked) version, so that any newly opened shells will use that default version. diff --git a/doc/LIST-REMOTE.md b/doc/LIST-REMOTE.md index b534907..6cbcb2c 100644 --- a/doc/LIST-REMOTE.md +++ b/doc/LIST-REMOTE.md @@ -1,9 +1,9 @@ # LIST-REMOTE Command - Node Version Switcher -``` -nvs lsr [filter] -nvs ls-remote [filter] -nvs list-remote [filter] -``` + + nvs lsr [filter] + nvs ls-remote [filter] + nvs list-remote [filter] + Lists node versions available to download. The optional filter parameter may be a configured remote name, or a partial semantic version such as `6.5`, or a remote name and partial version such as `node/6`. If the filter is or includes a remote name, then available versions from that remote are listed; otherwise versions from the default remote are listed. A remote name is one of the keys from the `remotes` mapping in `$NVS_HOME/settings.json`. diff --git a/doc/LIST.md b/doc/LIST.md index ab3b909..e37b990 100644 --- a/doc/LIST.md +++ b/doc/LIST.md @@ -1,8 +1,8 @@ # LIST Command - Node Version Switcher -``` -nvs ls [filter] -nvs list [filter] -``` + + nvs ls [filter] + nvs list [filter] + Lists local node versions that are immediately available to use. The optional filter parameter may be a configured remote name, or a partial semantic version such as `6.5`, or a remote name and partial version such as `node/6`. If the filter is omitted then all available versions are listed. diff --git a/doc/MIGRATE.md b/doc/MIGRATE.md index 135ef9a..a768952 100644 --- a/doc/MIGRATE.md +++ b/doc/MIGRATE.md @@ -1,7 +1,7 @@ # MIGRATE Command - Node Version Switcher -``` -nvs migrate [targetversion] -``` + + nvs migrate [targetversion] + Migrates globally-installed and globally-linked modules from a source node version to a target node version. Note this ignores any configuration (NPM_CONFIG_PREFIX environment variable or prefix setting in the user's npmrc) that might override the global modules directory location, because that configuration would apply apply to both versions and therefore no migration would be necessary or possible. The source and target versions must refer to previously-added node versions. The target version optional; if unspecified then the currently used version is the target. diff --git a/doc/REMOTE.md b/doc/REMOTE.md index bbf9509..a0c0ae8 100644 --- a/doc/REMOTE.md +++ b/doc/REMOTE.md @@ -1,16 +1,16 @@ # REMOTE Command - Node Version Switcher -``` -nvs remote -nvs remote ls -nvs remote + nvs remote + nvs remote ls -nvs remote -nvs remote add + nvs remote + + nvs remote + nvs remote add + + nvs remote -d + nvs remote rm -nvs remote -d -nvs remote rm -``` Queries, sets, or removes URIs for downloading node. When no arguments are specified, all remote names and URIs are listed. When just a name is specified, the URI for that remote is shown, if it exists. When a name and value are specified (optionally with an `add` command), the remote is added or updated to the persisted list. The `-d` or `rm` command removes an item. A special `default` remote may also be set to refer to the name of another remote. A remote that is pointed to by the default may not be removed; switch the default to another remote first. diff --git a/doc/REMOVE.md b/doc/REMOVE.md index a3ee9bd..e1336c1 100644 --- a/doc/REMOVE.md +++ b/doc/REMOVE.md @@ -1,8 +1,8 @@ # REMOVE Command - Node Version Switcher -``` -nvs rm -nvs remove -``` + + nvs rm + nvs remove + Removes a node version that was previously added via an ADD command. Any symlinks or PATH entries (in the calling shell environment only) pointing to that version are also removed. A version string consists of a semantic version number, optionally preceded by a remote name, optionally followed by a processor architecture or bitness ("x86", "x64", "32", "64"), separated by slashes. Examples: "4.6.0", "6/x86", "node/6.7/x64" diff --git a/doc/RUN.md b/doc/RUN.md index c92a11d..6c1349c 100644 --- a/doc/RUN.md +++ b/doc/RUN.md @@ -1,12 +1,12 @@ # RUN Command - Node Version Switcher -``` -nvs [args...] -nvs run [args...] -nvs run auto [args...] - -nvs [args...] -nvs run [args...] -``` + + nvs [args...] + nvs run [args...] + nvs run auto [args...] + + nvs [args...] + nvs run [args...] + Runs a node module using a specified node version, without changing the caller's `PATH`. If no version (or "auto") is specified, NVS searches for the nearest `.node-version` file in the current directory or parent directories. If found, the version specified in the file is then downloaded (if necessary) and used to run the module. If no `.node-version` file is found, then the current version of node is used to run the module; if there is no current version then the default (linked) version, if any, is used to run the module. diff --git a/doc/SETUP.md b/doc/SETUP.md index 7d7ac60..0a2bb1b 100644 --- a/doc/SETUP.md +++ b/doc/SETUP.md @@ -8,6 +8,8 @@ Before installing, decide on either a single-user installation or a system insta By default, downloaded Node.js files are cached under the NVS installation directory. To override this behavior, set the `NVS_HOME` environment variable to another location. ## Windows +NVS requires PowerShell 3.0, which is included with Windows 8 and later. On Windows 7, get PowerShell 3.0 from [Windows Management Framework 3.0](https://www.microsoft.com/en-us/download/details.aspx?id=34595) (which requires Windows 7 Service Pack 1). + Download and run the Windows Installer (MSI) package from the [Releases page on GitHub](https://github.com/jasongin/nvs/releases). Note the single MSI package supports both x86 and x64 systems and both per-user and per-machine installations. As an alternative to installing the MSI, the following manual steps may be used to setup NVS on Windows, from either a Command Prompt or PowerShell. diff --git a/doc/UNLINK.md b/doc/UNLINK.md index bb9af12..dafb298 100644 --- a/doc/UNLINK.md +++ b/doc/UNLINK.md @@ -1,8 +1,8 @@ # UNLINK Command - Node Version Switcher -``` -nvs unlink [version] -nvs ul [version] -``` + + nvs unlink [version] + nvs ul [version] + Removes a symbolic directory link if it exists at `$NVS_HOME/default`. If a version is specified, then the link is only removed if it points to that version. On Windows, this command also removes the default (linked) version from the profile `PATH` environment variable. Afterward, new shell windows will not use any Node.js version. diff --git a/doc/UPGRADE.md b/doc/UPGRADE.md new file mode 100644 index 0000000..8b97ce6 --- /dev/null +++ b/doc/UPGRADE.md @@ -0,0 +1,34 @@ +# UPGRADE Command - Node Version Switcher + + nvs upgrade [fromversion] + +Upgrades the specified Node version to the latest available build with the same major version. If no version is specified, the version currently in use is implied, if any. + +## Upgrade procedure +The following steps are performed automatically by the upgrade command: + + 1. Query the remote to identify the latest available version with the same major version as the specified version. + 2. Download and install (`nvs add`) the newer version, if not already added. + 3. Migrate global packages (`nvs migrate`) from the old to the new version. + 4. If the old version was linked, link (`nvs link`) the new version instead. + 5. Use (`nvs use`) the new version if the old version was previously in use. + 6. Remove the old version. + +## Examples + + nvs add lts # Adds 6.10.1 + # Some time later 6.10.2 is published + nvs use lts # Uses 6.10.1 (nvs use does not check for a newer version) + nvs upgrade # Upgrades from 6.10.1 to 6.10.2 + + nvs add argon # Adds 4.8.1 + # Some time later 4.9.0 is published + nvs upgrade argon # Upgrades from 4.8.1 to 4.9.0 + + nvs add 7.7 # Adds 7.7.4 + nvs add 7 # Adds 7.8.0... forgot to use the upgrade command + nvs upgrade 7.7 # Upgrades from 7.7.4 to 7.8.0 + + nvs add nightly # Adds the latest build from the "nightly" remote: 8.0.0-nightly20170331... + # One day later + nvs upgrade nightly # Upgrades from 8.0.0-nightly20170331... to 8.0.0-nightly20170401... diff --git a/doc/USE.md b/doc/USE.md index d1ab1c7..da136d4 100644 --- a/doc/USE.md +++ b/doc/USE.md @@ -1,14 +1,13 @@ # USE Command - Node Version Switcher -``` -nvs -nvs use -nvs use -nvs use auto + nvs + nvs use -nvs use default + nvs use + nvs use auto + + nvs use default -``` Updates the `PATH` of the calling shell to include the specified node version (which must have been already added). If no version (or "auto") is specified, NVS searches for the nearest `.node-version` file in the current directory or parent directories. If found, the version specified in the file is then added (if necessary) and used. If no `.node-version` file is found, then the default (linked) version, if any, is used. A version string consists of a complete or partial semantic version number or version label ("lts", "latest", "Argon", etc.), optionally preceded by a remote name, optionally followed by a processor architecture or bitness ("x86", "x64", "32", "64"), separated by slashes. When a partial version matches multiple available versions, the latest version is automatically selected. Examples: "node/lts", "4.6.0", "6/x86", "node/6.7/x64". An alias may also be used in place of a version string. diff --git a/doc/WHICH.md b/doc/WHICH.md index 393f812..7b7b0f8 100644 --- a/doc/WHICH.md +++ b/doc/WHICH.md @@ -1,5 +1,5 @@ # WHICH Command - Node Version Switcher -``` -nvs which [version] -``` + + nvs which [version] + Shows the path to a specified local node version, or the current version in the PATH if a version is not specified. diff --git a/lib/help.js b/lib/help.js index bc27f53..d4192de 100644 --- a/lib/help.js +++ b/lib/help.js @@ -21,7 +21,6 @@ function help(topic) { } if (helpText) { - helpText = helpText.replace(/#+ /g, ''); helpText = helpText.replace(/```[\w+-]*/g, ''); helpText = wrapLines(helpText, process.stdout.columns); return helpText; @@ -40,6 +39,7 @@ function help(topic) { 'nvs add Download and extract a node version', 'nvs rm Remove a node version', 'nvs migrate [tover] Migrate global modules', + 'nvs upgrade [fromver] Upgrade to latest patch of major version', '', 'nvs use [version] ' + (canUpdateEnv ? 'Use a node version in the current shell' diff --git a/lib/upgrade.js b/lib/upgrade.js index 27e4bb1..fc633d2 100644 --- a/lib/upgrade.js +++ b/lib/upgrade.js @@ -1,5 +1,8 @@ /* global settings */ +'use strict'; + const NodeVersion = require('./version'); +const Error = require('./error'); let nvsUse = require('./use'); // Non-const enables test mocking let nvsList = require('./list'); // Non-const enables test mocking let nvsAddRemove = null; // Lazy load @@ -31,12 +34,14 @@ function upgradeAsync(version) { let newVersion = availableVersions[0]; if (!newVersion || NodeVersion.compare(version, newVersion) <= 0) { - throw new Error('No new version found. ' + + return ['No new version found. ' + `${version.semanticVersion} is the latest ` + - `${version.remoteName}/${majorVersion} version available.`); + `${version.remoteName}/${majorVersion} version available.`]; } - console.log(`Upgrading ${version} to ${newVersion.semanticVersion}...`); + if (!settings.quiet) { + console.log(`Upgrading ${version} to ${newVersion.semanticVersion}...`); + } newVersion.arch = version.arch; let newBinPath = nvsUse.getVersionBinary(newVersion); @@ -45,7 +50,9 @@ function upgradeAsync(version) { } else { nvsAddRemove = nvsAddRemove || require('./addRemove'); return nvsAddRemove.addAsync(newVersion).then(() => { - console.log(`Added at: ${nvsUse.homePath(nvsUse.getVersionBinary(newVersion))}`); + if (!settings.quiet) { + console.log(`Added at: ${nvsUse.homePath(nvsUse.getVersionBinary(newVersion))}`); + } return upgradeToVersion(version, newVersion); }); } @@ -60,17 +67,21 @@ function upgradeToVersion(oldVersion, newVersion) { nvsLink = nvsLink || require('./link'); let linkedVersion = nvsLink.getLinkedVersion(); - linkedVersion.os = NodeVersion.defaultOs; - if (NodeVersion.equal(oldVersion, linkedVersion)) { - result = result.concat(nvsLink.link(newVersion)); + if (linkedVersion) { + linkedVersion.os = NodeVersion.defaultOs; + if (NodeVersion.equal(oldVersion, linkedVersion)) { + result = result.concat(nvsLink.link(newVersion)); + } } // TODO: Migrate aliases from the old to new version. let currentVersion = nvsUse.getCurrentVersion(); - currentVersion.os = NodeVersion.defaultOs; - if (NodeVersion.equal(oldVersion, currentVersion)) { - result = result.concat(nvsUse.use(newVersion)); + if (currentVersion) { + currentVersion.os = NodeVersion.defaultOs; + if (NodeVersion.equal(oldVersion, currentVersion)) { + result = result.concat(nvsUse.use(newVersion)); + } } nvsAddRemove = nvsAddRemove || require('./addRemove'); diff --git a/test/cli/bash.js b/test/cli/bashTests.js similarity index 100% rename from test/cli/bash.js rename to test/cli/bashTests.js diff --git a/test/cli/cmd.js b/test/cli/cmdTests.js similarity index 100% rename from test/cli/cmd.js rename to test/cli/cmdTests.js diff --git a/test/cli/git-bash.js b/test/cli/gitBashTests.js similarity index 100% rename from test/cli/git-bash.js rename to test/cli/gitBashTests.js diff --git a/test/cli/ps.js b/test/cli/psTests.js similarity index 100% rename from test/cli/ps.js rename to test/cli/psTests.js diff --git a/test/cli/zsh.js b/test/cli/zshTests.js similarity index 100% rename from test/cli/zsh.js rename to test/cli/zshTests.js diff --git a/test/fsUtil.js b/test/fsUtil.js index d81c933..4f43cf0 100644 --- a/test/fsUtil.js +++ b/test/fsUtil.js @@ -14,7 +14,7 @@ function removeDirectoryIfEmpty(dir) { try { fs.rmdirSync(dir); } catch (e) { - if (e.code !== 'ENOTEMPTY' && e.code !== 'ENOENT') { + if (e.code !== 'ENOTEMPTY' && e.code !== 'ENOENT' && e.code !== 'EBUSY') { throw e; } } diff --git a/test/modules/addRemove.js b/test/modules/addRemoveTests.js similarity index 100% rename from test/modules/addRemove.js rename to test/modules/addRemoveTests.js diff --git a/test/modules/auto.js b/test/modules/autoTests.js similarity index 100% rename from test/modules/auto.js rename to test/modules/autoTests.js diff --git a/test/modules/link.js b/test/modules/linkTests.js similarity index 100% rename from test/modules/link.js rename to test/modules/linkTests.js diff --git a/test/modules/list.js b/test/modules/listTests.js similarity index 100% rename from test/modules/list.js rename to test/modules/listTests.js diff --git a/test/modules/migrate.js b/test/modules/migrateTests.js similarity index 100% rename from test/modules/migrate.js rename to test/modules/migrateTests.js diff --git a/test/modules/upgradeTests.js b/test/modules/upgradeTests.js new file mode 100644 index 0000000..7e5da31 --- /dev/null +++ b/test/modules/upgradeTests.js @@ -0,0 +1,214 @@ +const path = require('path'); +const test = require('ava').test; +const rewire = require('rewire'); +const Error = require('../../lib/error'); + +test.before(require('../checkNodeVersion')); + +const mockFs = require('../mocks/fs'); +const testHome = mockFs.fixSep('/home/test/nvs/'); + +global.settings = { + home: testHome, + aliases: {}, + remotes: { + 'default': 'test', + 'test': 'http://example.com/test', + }, + quiet: true, +}; + +const NodeVersion = require('../../lib/version'); +const nvsUpgrade = rewire('../../lib/upgrade'); +const nvsList = rewire('../../lib/list'); +const nvsUse = rewire('../../lib/use'); +const bin = (nvsUse.isWindows ? '' : '/bin'); +const lib = (nvsUse.isWindows ? '' : '/lib'); +const exe = (nvsUse.isWindows ? 'node.exe' : 'node'); + +let mockNvsList = { + localVersions: [], + remoteVersions: [], + getVersions() { + return this.localVersions; + }, + find(version, versions) { + return nvsList.find(version, versions || this.getVersions()); + }, + getRemoteVersionsAsync() { + return Promise.resolve(this.remoteVersions.map(v => { + v.packages = { + find() { return true; } + }; + return v; + })); + } +}; +nvsUpgrade.__set__('nvsList', mockNvsList); + +let mockNvsAddRemove = { + addCalls: [], + removeCalls: [], + addAsync(version) { + this.addCalls.push(version); + return Promise.resolve([ 'Mock added: ' + version.toString() ]); + }, + remove(version) { + this.removeCalls.push(version); + return [ 'Mock removed: ' + version.toString() ]; + } +}; +nvsUpgrade.__set__('nvsAddRemove', mockNvsAddRemove); + +let mockNvsUse = { + currentVersion: null, + useCalls: [], + getCurrentVersion() { + return this.currentVersion; + }, + getVersionBinary(version) { + return mockNvsList.localVersions.indexOf(version) >= 0 ? exe : null; + }, + use(version) { + this.useCalls.push(version); + return [ 'Mock used: ' + version.toString() ]; + }, +}; +nvsUpgrade.__set__('nvsUse', mockNvsUse); + +let mockNvsLink = { + linkedVersion: null, + linkCalls: [], + getLinkedVersion() { + return this.linkedVersion; + }, + link(version) { + this.linkedVersion = version; + this.linkCalls.push(version); + return [ 'Mock linked: ' + version.toString() ]; + } +}; +nvsUpgrade.__set__('nvsLink', mockNvsLink); + +let mockNvsMigrate = { + migrateCalls: [], + migrateGlobalModules(from, to) { + console.log('migrate(' + from + ', ' + to + ')'); + this.migrateCalls.push([from, to]); + }, +}; +nvsUpgrade.__set__('nvsMigrate', mockNvsMigrate); + +test.beforeEach(t => { + mockFs.reset(); + mockNvsList.localVersions = [], + mockNvsList.remoteVersions = [], + mockNvsUse.currentVersion = null; + mockNvsUse.useCalls = []; + mockNvsAddRemove.addCalls = []; + mockNvsAddRemove.removeCalls = []; + mockNvsLink.linkedVersion = null; + mockNvsLink.linkCalls = []; + mockNvsMigrate.migrateCalls = []; +}); + +test.serial('Upgrade to existing version', t => { + const v1 = NodeVersion.parse('3.4.5'); + const v2 = NodeVersion.parse('3.5.0'); + mockNvsList.localVersions = [ v2, v1 ]; + mockNvsList.remoteVersions = mockNvsList.localVersions; + return nvsUpgrade.upgradeAsync(v1).then(message => { + t.regex(message[0], /^Mock removed/); + t.is(mockNvsUse.useCalls.length, 0); + t.is(mockNvsLink.linkCalls.length, 0); + t.is(mockNvsAddRemove.addCalls.length, 0); + t.is(mockNvsAddRemove.removeCalls.length, 1); + t.is(mockNvsAddRemove.removeCalls[0].semanticVersion, v1.semanticVersion); + t.is(mockNvsMigrate.migrateCalls.length, 1); + t.is(mockNvsMigrate.migrateCalls[0][0].semanticVersion, v1.semanticVersion); + t.is(mockNvsMigrate.migrateCalls[0][1].semanticVersion, v2.semanticVersion); + }); +}); + +test.serial('Upgrade to added version', t => { + const v1 = NodeVersion.parse('3.4.5'); + const v2 = NodeVersion.parse('3.5.0'); + mockNvsList.localVersions = [ v1 ]; + mockNvsList.remoteVersions = [ v2, v1 ]; + return nvsUpgrade.upgradeAsync(v1).then(message => { + t.regex(message[0], /^Mock removed/); + t.is(mockNvsUse.useCalls.length, 0); + t.is(mockNvsLink.linkCalls.length, 0); + t.is(mockNvsAddRemove.addCalls.length, 1); + t.is(mockNvsAddRemove.addCalls[0], v2); + t.is(mockNvsAddRemove.removeCalls.length, 1); + t.is(mockNvsAddRemove.removeCalls[0].semanticVersion, v1.semanticVersion); + t.is(mockNvsMigrate.migrateCalls.length, 1); + t.is(mockNvsMigrate.migrateCalls[0][0].semanticVersion, v1.semanticVersion); + t.is(mockNvsMigrate.migrateCalls[0][1].semanticVersion, v2.semanticVersion); + }); +}); + +test.serial('Upgrade current version', t => { + const v1 = NodeVersion.parse('3.4.5'); + const v2 = NodeVersion.parse('3.5.0'); + mockNvsList.localVersions = [ v2, v1 ]; + mockNvsList.remoteVersions = mockNvsList.localVersions; + mockNvsUse.currentVersion = v1; + return nvsUpgrade.upgradeAsync().then(message => { + t.regex(message[0], /^Mock used/); + t.regex(message[1], /^Mock removed/); + t.is(mockNvsUse.useCalls.length, 1); + t.is(mockNvsUse.useCalls[0], v2); + t.is(mockNvsLink.linkCalls.length, 0); + t.is(mockNvsAddRemove.addCalls.length, 0); + t.is(mockNvsAddRemove.removeCalls.length, 1); + t.is(mockNvsAddRemove.removeCalls[0].semanticVersion, v1.semanticVersion); + t.is(mockNvsMigrate.migrateCalls.length, 1); + t.is(mockNvsMigrate.migrateCalls[0][0].semanticVersion, v1.semanticVersion); + t.is(mockNvsMigrate.migrateCalls[0][1].semanticVersion, v2.semanticVersion); + }); +}); + +test.serial('Upgrade linked version', t => { + const v1 = NodeVersion.parse('3.4.5'); + const v2 = NodeVersion.parse('3.5.0'); + mockNvsList.localVersions = [ v2, v1 ]; + mockNvsList.remoteVersions = mockNvsList.localVersions; + v1.arch = NodeVersion.defaultArch; + v1.os = NodeVersion.defaultOs; + mockNvsLink.linkedVersion = v1; + return nvsUpgrade.upgradeAsync(v1).then(message => { + t.regex(message[0], /^Mock linked/); + t.regex(message[1], /^Mock removed/); + t.is(mockNvsUse.useCalls.length, 0); + t.is(mockNvsLink.linkCalls.length, 1); + t.is(mockNvsLink.linkCalls[0], v2); + t.is(mockNvsAddRemove.addCalls.length, 0); + t.is(mockNvsAddRemove.removeCalls.length, 1); + t.is(mockNvsAddRemove.removeCalls[0].semanticVersion, v1.semanticVersion); + t.is(mockNvsMigrate.migrateCalls.length, 1); + t.is(mockNvsMigrate.migrateCalls[0][0].semanticVersion, v1.semanticVersion); + t.is(mockNvsMigrate.migrateCalls[0][1].semanticVersion, v2.semanticVersion); + }); +}); + +test('Upgrade not available', t => { + const v = NodeVersion.parse('3.4.5'); + mockNvsList.localVersions = [ v ]; + return nvsUpgrade.upgradeAsync(v).then(message => { + t.regex(message[0], /is the latest/); + }); +}); + +test('Upgrade target not found', t => { + t.throws(() => { + return nvsUpgrade.upgradeAsync(NodeVersion.parse('3.4.5')); + }, (e) => e.code === Error.ENOENT); +}); + +test('Upgrade no current version', t => { + t.throws(() => { + return nvsUpgrade.upgradeAsync(null); + }, /Specify a version/); +}); diff --git a/test/modules/use.js b/test/modules/useTests.js similarity index 100% rename from test/modules/use.js rename to test/modules/useTests.js diff --git a/test/modules/version.js b/test/modules/versionTests.js similarity index 100% rename from test/modules/version.js rename to test/modules/versionTests.js