diff --git a/.travis.yml b/.travis.yml index a9e62db..4cb431e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: node_js -node_js: '6' +node_js: '8' os: - linux - osx diff --git a/README.md b/README.md index 1e8b09b..79f6e13 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ ## Requirements -Requires Node 6 or greater. +Requires Node 8 or greater. ## Legal diff --git a/package.json b/package.json index 3e10707..b85a6a8 100644 --- a/package.json +++ b/package.json @@ -23,31 +23,30 @@ ], "devDependencies": { "ava": "^1.0.1", - "codecov": "^3.1.0", + "codecov": "^3.5.0", "eslint": "^5.10.0", "eslint-config-standard": "^12.0.0", "eslint-plugin-ava": "^6.0.0", "eslint-plugin-import": "^2.14.0", - "eslint-plugin-node": "^8.0.0", + "eslint-plugin-node": "^9.0.1", "eslint-plugin-promise": "^4.0.1", "eslint-plugin-standard": "^4.0.0", - "nyc": "^14.0.0", + "nyc": "^14.1.1", "sinon": "^7.2.2" }, "dependencies": { - "asar": "^1.0.0", + "asar": "^2.0.1", "cross-spawn-promise": "^0.10.1", "debug": "^4.1.1", "fs-extra": "^8.0.1", - "glob": "^7.1.3", - "glob-promise": "^3.4.0", + "glob": "^7.1.4", "lodash": "^4.17.11", "parse-author": "^2.0.0", "semver": "^6.0.0", - "tmp-promise": "^1.0.5" + "tmp-promise": "^2.0.1" }, "engines": { - "node": ">= 6.0" + "node": ">= 8.0" }, "ava": { "babel": false, @@ -67,7 +66,6 @@ "ava" ], "rules": { - "ava/prefer-async-await": 0, "node/no-unpublished-require": [ "error", { diff --git a/src/desktop.js b/src/desktop.js index f6f876d..85fa9cc 100644 --- a/src/desktop.js +++ b/src/desktop.js @@ -6,11 +6,10 @@ const path = require('path') const { wrapError } = require('./error') module.exports = { - createDesktopFile: function createDesktopFile (templatePath, dir, baseName, options) { + createDesktopFile: async function createDesktopFile (templatePath, dir, baseName, options) { const dest = path.join(dir, `${baseName}.desktop`) debug(`Creating desktop file at ${dest}`) - return createTemplatedFile(templatePath, dest, options, 0o644) - .catch(wrapError('creating desktop file')) + return wrapError('creating desktop file', () => createTemplatedFile(templatePath, dest, options, 0o644)) } } diff --git a/src/error.js b/src/error.js index 841a34e..403bed1 100644 --- a/src/error.js +++ b/src/error.js @@ -14,11 +14,28 @@ module.exports = { * ```javascript * Promise.reject(new Error('My error')).catch(wrapError('with the code')) * ``` + * + * The `wrappedFunction` parameter is used for async/await use cases. For example: + * + * ```javascript + * wrapError('with the code', async () => { + * await foo(); + * await bar(); + * }) + * ``` */ - wrapError: function wrapError (message) { - return err => { - err.message = errorMessage(message, err) - throw err + wrapError: function wrapError (message, wrappedFunction) { + if (wrappedFunction) { + try { + return wrappedFunction() + } catch (error) { + module.exports.wrapError(message)(error) + } + } else { + return err => { + err.message = errorMessage(message, err) + throw err + } } } } diff --git a/src/installer.js b/src/installer.js index b8c228e..b89757d 100644 --- a/src/installer.js +++ b/src/installer.js @@ -1,16 +1,20 @@ 'use strict' +const { promisify } = require('util') + const _ = require('lodash') const debug = require('debug')('electron-installer-common:installer') const desktop = require('./desktop') const error = require('./error') const fs = require('fs-extra') -const glob = require('glob-promise') +const glob = promisify(require('glob')) const path = require('path') const template = require('./template') const tmp = require('tmp-promise') const updateSandboxHelperPermissions = require('./sandboxhelper') +tmp.setGracefulCleanup() + class ElectronInstaller { constructor (userSupplied) { this.userSupplied = userSupplied @@ -61,48 +65,45 @@ class ElectronInstaller { /** * Copies the bundled application into the staging directory. */ - copyApplication (ignoreFunc) { + async copyApplication (ignoreFunc) { debug(`Copying application to ${this.stagingAppDir}`) - return fs.ensureDir(this.stagingAppDir, '0755') - .then(() => fs.copy(this.sourceDir, this.stagingAppDir, { filter: ignoreFunc })) - .catch(error.wrapError('copying application directory')) + return error.wrapError('copying application directory', async () => { + await fs.ensureDir(this.stagingAppDir, '0755') + return fs.copy(this.sourceDir, this.stagingAppDir, { filter: ignoreFunc }) + }) } /** * Create hicolor icon for the package. */ - copyHicolorIcons () { + async copyHicolorIcons () { return Promise.all(_.map(this.options.icon, (iconSrc, resolution) => { const iconExt = resolution === 'scalable' ? 'svg' : 'png' const iconFile = path.join(this.stagingDir, this.baseAppDir, 'share', 'icons', 'hicolor', resolution, 'apps', `${this.appIdentifier}.${iconExt}`) - return this.copyIcon(iconSrc, iconFile) - .catch(error.wrapError('creating hicolor icon file')) + return error.wrapError('creating hicolor icon file', async () => this.copyIcon(iconSrc, iconFile)) })) } /** * Generically copy an icon. */ - copyIcon (src, dest) { + async copyIcon (src, dest) { debug(`Copying icon file at from "${src}" to "${dest}"`) - return fs.pathExists(src) - .then(exists => { - if (!exists) { - throw new Error(`The icon "${src}" does not exist`) - } - return true - }).then(() => fs.ensureDir(path.dirname(dest), '0755')) - .then(() => fs.copy(src, dest)) - .then(() => fs.chmod(dest, '0644')) + if (!await fs.pathExists(src)) { + throw new Error(`The icon "${src}" does not exist`) + } + await fs.ensureDir(path.dirname(dest), '0755') + await fs.copy(src, dest) + return fs.chmod(dest, '0644') } /** * Copy `LICENSE` from the root of the app to a different location. */ - copyLicense (copyrightFile) { + async copyLicense (copyrightFile) { const licenseSrc = path.join(this.sourceDir, 'LICENSE') debug(`Copying license file from ${licenseSrc}`) @@ -112,7 +113,7 @@ class ElectronInstaller { /** * Copy icons into the appropriate locations on Linux. */ - copyLinuxIcons () { + async copyLinuxIcons () { if (_.isObject(this.options.icon)) { return this.copyHicolorIcons() } else if (this.options.icon) { @@ -123,55 +124,53 @@ class ElectronInstaller { /** * Create pixmap icon for the package. */ - copyPixmapIcon () { + async copyPixmapIcon () { const iconFile = path.join(this.stagingDir, this.baseAppDir, this.pixmapIconPath) - return this.copyIcon(this.options.icon, iconFile) - .catch(error.wrapError('creating pixmap icon file')) + return error.wrapError('creating pixmap icon file', async () => this.copyIcon(this.options.icon, iconFile)) } /** * Create the symlink to the binary for the package. */ - createBinarySymlink () { + async createBinarySymlink () { const binSrc = path.join('../lib', this.appIdentifier, this.options.bin) const binDest = path.join(this.stagingDir, this.baseAppDir, 'bin', this.appIdentifier) debug(`Symlinking binary from ${binSrc} to ${binDest}`) const bundledBin = path.join(this.sourceDir, this.options.bin) - return fs.pathExists(bundledBin) - .then(exists => { - if (!exists) { - throw new Error(`could not find the Electron app binary at "${bundledBin}". You may need to re-bundle the app using Electron Packager's "executableName" option.`) - } - return fs.ensureDir(path.dirname(binDest), '0755') - }).then(() => fs.symlink(binSrc, binDest, 'file')) - .catch(error.wrapError('creating binary symlink')) + return error.wrapError('creating binary symlink', async () => { + if (!await fs.pathExists(bundledBin)) { + throw new Error(`could not find the Electron app binary at "${bundledBin}". You may need to re-bundle the app using Electron Packager's "executableName" option.`) + } + await fs.ensureDir(path.dirname(binDest), '0755') + return fs.symlink(binSrc, binDest, 'file') + }) } /** * Generate the contents of the package in "parallel" by calling the methods specified in * `contentFunctions` getter through `Promise.all`. */ - createContents () { + async createContents () { debug('Creating contents of package') - return Promise.all(this.contentFunctions.map(func => this[func]())) - .catch(error.wrapError('creating contents of package')) + return error.wrapError('creating contents of package', async () => Promise.all(this.contentFunctions.map(func => this[func]()))) } /** * Create copyright for the package. */ - createCopyright () { + async createCopyright () { const copyrightFile = path.join(this.stagingDir, this.baseAppDir, 'share', 'doc', this.appIdentifier, 'copyright') debug(`Creating copyright file at ${copyrightFile}`) - return fs.ensureDir(path.dirname(copyrightFile), '0755') - .then(() => this.copyLicense(copyrightFile)) - .then(() => fs.chmod(copyrightFile, '0644')) - .catch(error.wrapError('creating copyright file')) + return error.wrapError('creating copyright file', async () => { + await fs.ensureDir(path.dirname(copyrightFile), '0755') + await this.copyLicense(copyrightFile) + await fs.chmod(copyrightFile, '0644') + }) } /** @@ -179,7 +178,7 @@ class ElectronInstaller { * * See: http://standards.freedesktop.org/desktop-entry-spec/latest/ */ - createDesktopFile () { + async createDesktopFile () { const templatePath = this.options.desktopTemplate || this.defaultDesktopTemplatePath const baseDir = path.join(this.stagingDir, this.baseAppDir, 'share', 'applications') return desktop.createDesktopFile(templatePath, baseDir, this.appIdentifier, this.options) @@ -188,17 +187,17 @@ class ElectronInstaller { /** * Create temporary directory where the contents of the package will live. */ - createStagingDir () { + async createStagingDir () { debug('Creating staging directory') - return tmp.dir({ prefix: 'electron-', unsafeCleanup: true }) - .then(dir => { - this.stagingDir = path.join(dir.path, `${this.appIdentifier}_${this.options.version}_${this.options.arch}`) - return fs.ensureDir(this.stagingDir, '0755') - }).catch(error.wrapError('creating staging directory')) + return error.wrapError('creating staging directory', async () => { + const dir = await tmp.dir({ prefix: 'electron-installer-', unsafeCleanup: true }) + this.stagingDir = path.join(dir.path, `${this.appIdentifier}_${this.options.version}_${this.options.arch}`) + return fs.ensureDir(this.stagingDir, '0755') + }) } - createTemplatedFile (templatePath, dest, filePermissions) { + async createTemplatedFile (templatePath, dest, filePermissions) { return template.createTemplatedFile(templatePath, dest, this.options, filePermissions) } @@ -212,23 +211,25 @@ class ElectronInstaller { /** * Move the package to the specified destination. */ - movePackage () { + async movePackage () { debug('Moving package to destination') - return glob(this.packagePattern) - .then(files => Promise.all(files.map(file => { + return error.wrapError('moving package files', async () => { + const files = await glob(this.packagePattern) + return Promise.all(files.map(async file => { const renameTemplate = this.options.rename(this.options.dest, path.basename(file)) const dest = _.template(renameTemplate)(this.options) debug(`Moving file ${file} to ${dest}`) return fs.move(file, dest, { clobber: true }) - }))).catch(error.wrapError('moving package files')) + })) + }) } /** * For Electron versions that support the setuid sandbox on Linux, changes the permissions of * the `chrome-sandbox` executable as appropriate. */ - updateSandboxHelperPermissions () { + async updateSandboxHelperPermissions () { return updateSandboxHelperPermissions(this.stagingAppDir) } } diff --git a/src/readelectronversion.js b/src/readelectronversion.js index c6ea45c..00722f9 100644 --- a/src/readelectronversion.js +++ b/src/readelectronversion.js @@ -10,7 +10,7 @@ const path = require('path') * The content of the version file post-4.0 is just the version. * Both of these are acceptable to the `semver` module. */ -module.exports = function readElectronVersion (appDir) { - return fs.readFile(path.resolve(appDir, 'version')) - .then(tag => tag.toString().trim()) +module.exports = async function readElectronVersion (appDir) { + const tag = await fs.readFile(path.resolve(appDir, 'version')) + return tag.toString().trim() } diff --git a/src/readmetadata.js b/src/readmetadata.js index 551f615..8d1a8a0 100644 --- a/src/readmetadata.js +++ b/src/readmetadata.js @@ -5,7 +5,7 @@ const fs = require('fs-extra') const path = require('path') const { wrapError } = require('./error') -function readPackageJSONFromUnpackedApp (options) { +async function readPackageJSONFromUnpackedApp (options) { const appPackageJSONPath = path.join(options.src, 'resources', 'app', 'package.json') options.logger(`Reading package metadata from ${appPackageJSONPath}`) @@ -25,16 +25,15 @@ function readPackageJSONFromUnpackedApp (options) { * * `logger`: function that handles debug messages, e.g., * `debug('electron-installer-something:some-module')` */ -module.exports = function readMetadata (options) { +module.exports = async function readMetadata (options) { const appAsarPath = path.join(options.src, 'resources/app.asar') - return fs.pathExists(appAsarPath) - .then(asarExists => { - if (asarExists) { - options.logger(`Reading package metadata from ${appAsarPath}`) - return JSON.parse(asar.extractFile(appAsarPath, 'package.json')) - } else { - return readPackageJSONFromUnpackedApp(options) - } - }).catch(wrapError('reading package metadata')) + return wrapError('reading package metadata', async () => { + if (await fs.pathExists(appAsarPath)) { + options.logger(`Reading package metadata from ${appAsarPath}`) + return JSON.parse(asar.extractFile(appAsarPath, 'package.json')) + } else { + return readPackageJSONFromUnpackedApp(options) + } + }) } diff --git a/src/sandboxhelper.js b/src/sandboxhelper.js index 39b87d0..6e41b85 100644 --- a/src/sandboxhelper.js +++ b/src/sandboxhelper.js @@ -13,14 +13,9 @@ const path = require('path') * * See: https://github.com/electron/electron/pull/17269#issuecomment-470671914 */ -module.exports = function updateSandboxHelperPermissions (appDir) { +module.exports = async function updateSandboxHelperPermissions (appDir) { const sandboxHelperPath = path.join(appDir, 'chrome-sandbox') - return fs.pathExists(sandboxHelperPath) - .then(exists => { - if (exists) { - return fs.chmod(sandboxHelperPath, 0o4755) - } else { - return Promise.resolve() - } - }) + if (await fs.pathExists(sandboxHelperPath)) { + return fs.chmod(sandboxHelperPath, 0o4755) + } } diff --git a/src/spawn.js b/src/spawn.js index a139a11..bfe87ee 100644 --- a/src/spawn.js +++ b/src/spawn.js @@ -7,17 +7,18 @@ const spawn = require('cross-spawn-promise') * * Specify updateErrorCallback (a callback) to adjust the error object before it is rethrown. */ -module.exports = function (cmd, args, logger, updateErrorCallback) { +module.exports = async function (cmd, args, logger, updateErrorCallback) { if (logger) logger(`Executing command ${cmd} ${args.join(' ')}`) - return spawn(cmd, args) - .then(stdout => stdout.toString()) - .catch(err => { - const stderr = err.stderr ? err.stderr.toString() : '' - if (updateErrorCallback) { - updateErrorCallback(err, !!logger) - } + try { + const stdout = await spawn(cmd, args) + return stdout.toString() + } catch (err) { + const stderr = err.stderr ? err.stderr.toString() : '' + if (updateErrorCallback) { + updateErrorCallback(err, !!logger) + } - throw new Error(`Error executing command (${err.message || err}):\n${cmd} ${args.join(' ')}\n${stderr}`) - }) + throw new Error(`Error executing command (${err.message || err}):\n${cmd} ${args.join(' ')}\n${stderr}`) + } } diff --git a/src/template.js b/src/template.js index 88df27a..8ae87bb 100644 --- a/src/template.js +++ b/src/template.js @@ -8,29 +8,26 @@ const path = require('path') /** * Fill in a template with the hash of data. */ -function generateTemplate (file, data) { +async function generateTemplate (file, data) { debug(`Generating template from ${file}`) - return fs.readFile(file) - .then(template => { - const result = _.template(template)(data) - debug(`Generated template from ${file}\n${result}`) - return result - }) + const result = _.template(await fs.readFile(file))(data) + debug(`Generated template from ${file}\n${result}`) + return result } module.exports = { /** * Create a file from a template. Any necessary directories are automatically created. */ - createTemplatedFile: function createTemplatedFile (templatePath, dest, options, filePermissions) { + createTemplatedFile: async function createTemplatedFile (templatePath, dest, options, filePermissions) { const fileOptions = {} if (filePermissions) { fileOptions.mode = filePermissions } - return fs.ensureDir(path.dirname(dest), '0755') - .then(() => generateTemplate(templatePath, options)) - .then(data => fs.outputFile(dest, data, fileOptions)) + await fs.ensureDir(path.dirname(dest), '0755') + const data = await generateTemplate(templatePath, options) + return fs.outputFile(dest, data, fileOptions) }, generateTemplate } diff --git a/test/_util.js b/test/_util.js index b63afb8..33fa3b6 100644 --- a/test/_util.js +++ b/test/_util.js @@ -5,29 +5,25 @@ const path = require('path') const tmp = require('tmp-promise') module.exports = { - assertPathExists: function assertPathExists (t, pathToCheck) { - return fs.pathExists(pathToCheck) - .then(exists => t.true(exists, `File "${pathToCheck}" should exist`)) + assertPathExists: async function assertPathExists (t, pathToCheck) { + t.true(await fs.pathExists(pathToCheck), `File "${pathToCheck}" should exist`) }, - assertPathNotExists: function assertPathExists (t, pathToCheck) { - return fs.pathExists(pathToCheck) - .then(exists => t.false(exists, `File "${pathToCheck}" should not exist`)) + assertPathNotExists: async function assertPathExists (t, pathToCheck) { + t.false(await fs.pathExists(pathToCheck), `File "${pathToCheck}" should not exist`) }, - assertPathPermissions: function assertPathPermissions (t, pathToCheck, expectedPermissions) { - return fs.stat(pathToCheck) - .then(stats => { - const actual = stats.mode & 0o7777 - const msg = `Expected mode=${expectedPermissions.toString(8)}, got ${actual.toString(8)}` - if (process.platform === 'win32') { - return t.true((actual & expectedPermissions) === expectedPermissions, msg) - } else { - return t.is(actual, expectedPermissions, msg) - } - }) + assertPathPermissions: async function assertPathPermissions (t, pathToCheck, expectedPermissions) { + const stats = await fs.stat(pathToCheck) + const actual = stats.mode & 0o7777 + const msg = `Expected mode=${expectedPermissions.toString(8)}, got ${actual.toString(8)}` + if (process.platform === 'win32') { + t.true((actual & expectedPermissions) === expectedPermissions, msg) + } else { + t.is(actual, expectedPermissions, msg) + } }, - assertTrimmedFileContents: function assertTrimmedFileContents (t, filePath, expectedContents) { - return fs.readFile(filePath) - .then(data => t.is(data.toString().trim(), expectedContents)) + assertTrimmedFileContents: async function assertTrimmedFileContents (t, filePath, expectedContents) { + const data = await fs.readFile(filePath) + t.is(data.toString().trim(), expectedContents) }, SIMPLE_TEMPLATE_PATH: path.resolve(__dirname, 'fixtures', 'template', 'simple.ejs'), unsafeTempDir: function unsafeTempDir (promise) { diff --git a/test/desktop.js b/test/desktop.js index 7352316..3fe6e82 100644 --- a/test/desktop.js +++ b/test/desktop.js @@ -6,9 +6,9 @@ const test = require('ava') const util = require('./_util') test('createDesktopFile', t => { - return util.unsafeTempDir(dir => { + return util.unsafeTempDir(async dir => { const renderedPath = path.join(dir.path, 'rendered.desktop') - return createDesktopFile(util.SIMPLE_TEMPLATE_PATH, dir.path, 'rendered', { name: 'World' }) - .then(() => util.assertPathPermissions(t, renderedPath, 0o644)) + await createDesktopFile(util.SIMPLE_TEMPLATE_PATH, dir.path, 'rendered', { name: 'World' }) + await util.assertPathPermissions(t, renderedPath, 0o644) }) }) diff --git a/test/error.js b/test/error.js index 8fda1af..05bcc55 100644 --- a/test/error.js +++ b/test/error.js @@ -16,3 +16,9 @@ test('wrapError', t => { .catch(error.wrapError('in a test')) return t.throwsAsync(promise, /Error in a test: My error/) }) + +test('wrapError with wrappedFunction specified', t => { + t.throws(() => error.wrapError('in a test', () => { + throw new Error('My error') + }), 'Error in a test: My error') +}) diff --git a/test/installer.js b/test/installer.js index e8330ef..7b5c0fe 100644 --- a/test/installer.js +++ b/test/installer.js @@ -7,25 +7,25 @@ const sinon = require('sinon') const test = require('ava') const util = require('./_util') -test('copyApplication', t => { +test('copyApplication', async t => { const installer = new ElectronInstaller({ name: 'copyapp', src: path.join(__dirname, 'fixtures', 'app-with-asar') }) installer.generateOptions() - return installer.createStagingDir() - .then(() => installer.copyApplication()) - .then(() => util.assertPathExists(t, installer.stagingAppDir)) - .then(() => util.assertPathExists(t, path.join(installer.stagingAppDir, 'footest'))) + await installer.createStagingDir() + await installer.copyApplication() + await util.assertPathExists(t, installer.stagingAppDir) + await util.assertPathExists(t, path.join(installer.stagingAppDir, 'footest')) }) -test('copyApplication with ignore func', t => { +test('copyApplication with ignore func', async t => { const installer = new ElectronInstaller({ name: 'copyapp', src: path.join(__dirname, 'fixtures', 'app-with-asar') }) installer.generateOptions() - return installer.createStagingDir() - .then(() => installer.copyApplication(src => src !== path.join(installer.sourceDir, 'LICENSE'))) - .then(() => util.assertPathExists(t, path.join(installer.stagingAppDir, 'footest'))) - .then(() => util.assertPathNotExists(t, path.join(installer.stagingAppDir, 'LICENSE'))) + await installer.createStagingDir() + await installer.copyApplication(src => src !== path.join(installer.sourceDir, 'LICENSE')) + await util.assertPathExists(t, path.join(installer.stagingAppDir, 'footest')) + await util.assertPathNotExists(t, path.join(installer.stagingAppDir, 'LICENSE')) }) -test('copyLinuxIcons for hicolor icons', t => { +test('copyLinuxIcons for hicolor icons', async t => { const hicolorDir = path.join('usr', 'share', 'icons', 'hicolor') const img = path.join(__dirname, 'fixtures', 'icon.fake') const installer = new ElectronInstaller({ @@ -36,43 +36,43 @@ test('copyLinuxIcons for hicolor icons', t => { } }) installer.generateOptions() - return installer.createStagingDir() - .then(() => installer.copyLinuxIcons()) - .then(() => util.assertPathExists(t, path.join(installer.stagingDir, hicolorDir, '48x48', 'apps', 'icontest.png'))) - .then(() => util.assertPathExists(t, path.join(installer.stagingDir, hicolorDir, 'scalable', 'apps', 'icontest.svg'))) + await installer.createStagingDir() + await installer.copyLinuxIcons() + await util.assertPathExists(t, path.join(installer.stagingDir, hicolorDir, '48x48', 'apps', 'icontest.png')) + await util.assertPathExists(t, path.join(installer.stagingDir, hicolorDir, 'scalable', 'apps', 'icontest.svg')) }) -test('copyLinuxIcons for pixmap', t => { +test('copyLinuxIcons for pixmap', async t => { const installer = new ElectronInstaller({ name: 'icontest', icon: path.join(__dirname, 'fixtures', 'icon.fake') }) installer.generateOptions() - return installer.createStagingDir() - .then(() => installer.copyLinuxIcons()) - .then(() => util.assertPathExists(t, path.join(installer.stagingDir, 'usr', 'share', 'pixmaps', 'icontest.png'))) + await installer.createStagingDir() + await installer.copyLinuxIcons() + await util.assertPathExists(t, path.join(installer.stagingDir, 'usr', 'share', 'pixmaps', 'icontest.png')) }) -test('copyLinuxIcon with a nonexistent source icon', t => { +test('copyLinuxIcon with a nonexistent source icon', async t => { const installer = new ElectronInstaller({ name: 'icontest', icon: path.join(__dirname, 'fixtures', 'icons', 'nonexistent.png') }) installer.generateOptions() - return installer.createStagingDir() - .then(() => t.throwsAsync(installer.copyLinuxIcons(), /The icon ".*" does not exist$/)) + await installer.createStagingDir() + await t.throwsAsync(installer.copyLinuxIcons(), /The icon ".*" does not exist$/) }) -test('copyLinuxIcons does nothing if icon option not specified', t => { +test('copyLinuxIcons does nothing if icon option not specified', async t => { const installer = new ElectronInstaller({ name: 'icontest' }) installer.generateOptions() - return installer.createStagingDir() - .then(() => installer.copyLinuxIcons()) - .then(() => util.assertPathNotExists(t, path.join(installer.stagingDir, 'usr', 'share', 'pixmaps'))) - .then(() => util.assertPathNotExists(t, path.join(installer.stagingDir, 'usr', 'share', 'icons'))) + await installer.createStagingDir() + await installer.copyLinuxIcons() + await util.assertPathNotExists(t, path.join(installer.stagingDir, 'usr', 'share', 'pixmaps')) + await util.assertPathNotExists(t, path.join(installer.stagingDir, 'usr', 'share', 'icons')) }) -test('createBinarySymlink creates symlink when bin exists', t => { +test('createBinarySymlink creates symlink when bin exists', async t => { const options = { bin: 'app-name', logger: log => log, @@ -81,13 +81,13 @@ test('createBinarySymlink creates symlink when bin exists', t => { } const installer = new ElectronInstaller(options) installer.generateOptions() - return installer.createStagingDir() - .then(() => installer.createBinarySymlink()) - .then(() => fs.lstat(path.join(installer.stagingDir, installer.baseAppDir, 'bin', 'bundled_app'))) - .then(stats => t.true(stats.isSymbolicLink())) + await installer.createStagingDir() + await installer.createBinarySymlink() + const stats = await fs.lstat(path.join(installer.stagingDir, installer.baseAppDir, 'bin', 'bundled_app')) + t.true(stats.isSymbolicLink()) }) -test('createBinarySymlink does not create symlink when bin does not exist', t => { +test('createBinarySymlink does not create symlink when bin does not exist', async t => { const options = { bin: 'nonexistent', logger: log => log, @@ -96,53 +96,53 @@ test('createBinarySymlink does not create symlink when bin does not exist', t => } const installer = new ElectronInstaller(options) installer.generateOptions() - return installer.createStagingDir() - .then(() => t.throwsAsync(installer.createBinarySymlink(), /could not find the Electron app binary/)) + await installer.createStagingDir() + await t.throwsAsync(installer.createBinarySymlink(), /could not find the Electron app binary/) }) -test('createContents', t => { +test('createContents', async t => { const installer = new ElectronInstaller({ name: 'World' }) installer.createFakeContent = sinon.spy() sinon.stub(installer, 'contentFunctions').get(() => ['createFakeContent']) - return installer.createContents() - .then(() => t.true(installer.createFakeContent.called)) + await installer.createContents() + await t.true(installer.createFakeContent.called) }) test('createCopyright', t => { - return util.unsafeTempDir(dir => { + return util.unsafeTempDir(async dir => { const installer = new ElectronInstaller({ name: 'copyright-test', src: dir.path }) installer.generateOptions() - return installer.createStagingDir() - .then(() => fs.outputFile(path.join(dir.path, 'LICENSE'), 'License')) - .then(() => installer.createCopyright()) - .then(() => util.assertTrimmedFileContents(t, path.join(installer.stagingDir, 'usr', 'share', 'doc', 'copyright-test', 'copyright'), 'License')) + await installer.createStagingDir() + await fs.outputFile(path.join(dir.path, 'LICENSE'), 'License') + await installer.createCopyright() + await util.assertTrimmedFileContents(t, path.join(installer.stagingDir, 'usr', 'share', 'doc', 'copyright-test', 'copyright'), 'License') }) }) -test('createDesktopFile with default template', t => { +test('createDesktopFile with default template', async t => { const installer = new ElectronInstaller({ name: 'World' }) sinon.stub(installer, 'defaultDesktopTemplatePath').get(() => util.SIMPLE_TEMPLATE_PATH) installer.generateOptions() - return installer.createStagingDir() - .then(() => installer.createDesktopFile()) - .then(() => util.assertPathExists(t, path.join(installer.stagingDir, 'usr', 'share', 'applications', 'World.desktop'))) + await installer.createStagingDir() + await installer.createDesktopFile() + await util.assertPathExists(t, path.join(installer.stagingDir, 'usr', 'share', 'applications', 'World.desktop')) }) -test('createDesktopFile with custom desktopTemplate', t => { +test('createDesktopFile with custom desktopTemplate', async t => { const installer = new ElectronInstaller({ name: 'World', desktopTemplate: util.SIMPLE_TEMPLATE_PATH }) installer.generateOptions() - return installer.createStagingDir() - .then(() => installer.createDesktopFile()) - .then(() => util.assertPathExists(t, path.join(installer.stagingDir, 'usr', 'share', 'applications', 'World.desktop'))) + await installer.createStagingDir() + await installer.createDesktopFile() + await util.assertPathExists(t, path.join(installer.stagingDir, 'usr', 'share', 'applications', 'World.desktop')) }) test('createTemplatedFile', t => { - return util.unsafeTempDir(dir => { + return util.unsafeTempDir(async dir => { const renderedPath = path.join(dir.path, 'rendered') const installer = new ElectronInstaller({ name: 'World' }) installer.generateOptions() - return installer.createTemplatedFile(util.SIMPLE_TEMPLATE_PATH, renderedPath) - .then(() => util.assertTrimmedFileContents(t, renderedPath, 'Hello, World!')) + await installer.createTemplatedFile(util.SIMPLE_TEMPLATE_PATH, renderedPath) + await util.assertTrimmedFileContents(t, renderedPath, 'Hello, World!') }) }) @@ -162,7 +162,7 @@ test('generateOptions merges API values & CLI options', t => { }) test('movePackage', t => { - return util.unsafeTempDir(dir => { + return util.unsafeTempDir(async dir => { const destDir = path.join(dir.path, 'moveTo') const rename = (dest, src) => { return path.join(dest, 'test_<%= name %>.pkg') @@ -170,36 +170,36 @@ test('movePackage', t => { const installer = new ElectronInstaller({ name: 'foo', dest: destDir, rename: rename }) installer.generateOptions() installer.packagePattern = path.join(dir.path, '*.pkg') - return fs.ensureDir(destDir) - .then(() => fs.outputFile(path.join(dir.path, 'test.pkg'), 'hello')) - .then(() => installer.movePackage()) - .then(() => util.assertPathExists(t, path.join(destDir, 'test_foo.pkg'))) + await fs.ensureDir(destDir) + await fs.outputFile(path.join(dir.path, 'test.pkg'), 'hello') + await installer.movePackage() + await util.assertPathExists(t, path.join(destDir, 'test_foo.pkg')) }) }) if (process.platform !== 'win32') { - test('updateSandboxHelperPermissions with no sandbox does nothing', t => { + test('updateSandboxHelperPermissions with no sandbox does nothing', async t => { const installer = new ElectronInstaller({ name: 'copyapp', src: path.join(__dirname, 'fixtures', 'app-with-asar') }) installer.generateOptions() - return installer.createStagingDir() - .then(() => installer.copyApplication()) - .then(() => installer.updateSandboxHelperPermissions()) - .then(() => util.assertPathNotExists(t, path.join(installer.stagingAppDir, 'chrome-sandbox'))) + await installer.createStagingDir() + await installer.copyApplication() + await installer.updateSandboxHelperPermissions() + await util.assertPathNotExists(t, path.join(installer.stagingAppDir, 'chrome-sandbox')) }) test('updateSandboxHelperPermissions with sandbox chmods the sandbox file correctly', t => { - return util.unsafeTempDir(dir => { + return util.unsafeTempDir(async dir => { const originalFixturesDir = path.join(__dirname, 'fixtures', 'app-with-asar') const copiedFixturesDir = path.join(dir.path, 'bundled_app') const chromeSandbox = 'chrome-sandbox' const installer = new ElectronInstaller({ name: 'copyapp', src: copiedFixturesDir }) installer.generateOptions() - return fs.copy(originalFixturesDir, copiedFixturesDir) - .then(() => fs.outputFile(path.join(copiedFixturesDir, chromeSandbox), '')) - .then(() => installer.createStagingDir()) - .then(() => installer.copyApplication()) - .then(() => installer.updateSandboxHelperPermissions()) - .then(() => util.assertPathPermissions(t, path.join(installer.stagingAppDir, chromeSandbox), 0o4755)) + await fs.copy(originalFixturesDir, copiedFixturesDir) + await fs.outputFile(path.join(copiedFixturesDir, chromeSandbox), '') + await installer.createStagingDir() + await installer.copyApplication() + await installer.updateSandboxHelperPermissions() + await util.assertPathPermissions(t, path.join(installer.stagingAppDir, chromeSandbox), 0o4755) }) }) } diff --git a/test/readelectronversion.js b/test/readelectronversion.js index 64ab73a..d64f660 100644 --- a/test/readelectronversion.js +++ b/test/readelectronversion.js @@ -4,7 +4,7 @@ const path = require('path') const readElectronVersion = require('../src/readelectronversion') const test = require('ava') -test('readElectronVersion', t => { - return readElectronVersion(path.resolve(__dirname, 'fixtures')) - .then(version => t.is(version, 'v3.0.11')) +test('readElectronVersion', async t => { + const version = await readElectronVersion(path.resolve(__dirname, 'fixtures')) + t.is(version, 'v3.0.11') }) diff --git a/test/readmetadata.js b/test/readmetadata.js index 8130cf3..169495d 100644 --- a/test/readmetadata.js +++ b/test/readmetadata.js @@ -4,14 +4,14 @@ const readMetadata = require('../src/readmetadata') const path = require('path') const test = require('ava') -test('readMetadata for app with asar', t => { - return readMetadata({ src: path.join(__dirname, 'fixtures', 'app-with-asar'), logger: log => log }) - .then(packageJSON => t.regex(packageJSON.description, /with asar/)) +test('readMetadata for app with asar', async t => { + const packageJSON = await readMetadata({ src: path.join(__dirname, 'fixtures', 'app-with-asar'), logger: log => log }) + t.regex(packageJSON.description, /with asar/) }) -test('readMetadata for app without asar', t => { - return readMetadata({ src: path.join(__dirname, 'fixtures', 'app-without-asar'), logger: log => log }) - .then(packageJSON => t.regex(packageJSON.description, /without asar/)) +test('readMetadata for app without asar', async t => { + const packageJSON = await readMetadata({ src: path.join(__dirname, 'fixtures', 'app-without-asar'), logger: log => log }) + t.regex(packageJSON.description, /without asar/) }) test('readMetadata for invalid app', t => { diff --git a/test/spawn.js b/test/spawn.js index f5ae58a..2fe3362 100644 --- a/test/spawn.js +++ b/test/spawn.js @@ -3,10 +3,10 @@ const spawn = require('../src/spawn') const test = require('ava') -test('returns stdout', t => { +test('returns stdout', async t => { const dir = process.platform === 'darwin' ? 'ls' : 'dir' - return spawn(dir, [__dirname], log => null) - .then(output => t.regex(output, /spawn/)) + const output = await spawn(dir, [__dirname], log => null) + t.regex(output, /spawn/) }) test('throws an error when it cannot find an executable', t => { diff --git a/test/template.js b/test/template.js index 6053509..6f017f3 100644 --- a/test/template.js +++ b/test/template.js @@ -5,24 +5,24 @@ const template = require('../src/template') const test = require('ava') const util = require('./_util') -test('generateTemplate', t => { - return template.generateTemplate(util.SIMPLE_TEMPLATE_PATH, { name: 'World' }) - .then(data => t.is(data.trim(), 'Hello, World!')) +test('generateTemplate', async t => { + const data = await template.generateTemplate(util.SIMPLE_TEMPLATE_PATH, { name: 'World' }) + t.is(data.trim(), 'Hello, World!') }) test('createTemplatedFile', t => { - return util.unsafeTempDir(dir => { + return util.unsafeTempDir(async dir => { const renderedPath = path.join(dir.path, 'rendered') - return template.createTemplatedFile(util.SIMPLE_TEMPLATE_PATH, renderedPath, { name: 'World' }) - .then(() => util.assertTrimmedFileContents(t, renderedPath, 'Hello, World!')) + await template.createTemplatedFile(util.SIMPLE_TEMPLATE_PATH, renderedPath, { name: 'World' }) + await util.assertTrimmedFileContents(t, renderedPath, 'Hello, World!') }) }) test('createTemplatedFile with permissions', t => { - return util.unsafeTempDir(dir => { + return util.unsafeTempDir(async dir => { const renderedPath = path.join(dir.path, 'rendered') - return template.createTemplatedFile(util.SIMPLE_TEMPLATE_PATH, renderedPath, { name: 'World' }, 0o644) - .then(() => util.assertTrimmedFileContents(t, renderedPath, 'Hello, World!')) - .then(() => util.assertPathPermissions(t, renderedPath, 0o644)) + await template.createTemplatedFile(util.SIMPLE_TEMPLATE_PATH, renderedPath, { name: 'World' }, 0o644) + await util.assertTrimmedFileContents(t, renderedPath, 'Hello, World!') + await util.assertPathPermissions(t, renderedPath, 0o644) }) })