diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 00000000000..6bc991c9bf8
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,2 @@
+test/fixtures/
+test/old-cli-test.js
\ No newline at end of file
diff --git a/.idea/electron-builder.iml b/.idea/electron-builder.iml
index ebf2654843f..b289b290bbd 100644
--- a/.idea/electron-builder.iml
+++ b/.idea/electron-builder.iml
@@ -10,7 +10,6 @@
-
diff --git a/.idea/runConfigurations/BuildTest.xml b/.idea/runConfigurations/BuildTest.xml
index a9da6082eba..5911c5394d6 100644
--- a/.idea/runConfigurations/BuildTest.xml
+++ b/.idea/runConfigurations/BuildTest.xml
@@ -1,5 +1,9 @@
-
+
+
+
+
+
\ No newline at end of file
diff --git a/cli.js b/cli.js
index 7f1c527dcfa..bbb7301b0e2 100755
--- a/cli.js
+++ b/cli.js
@@ -79,7 +79,7 @@ builder.build( Object.assign( cli.flags, {
* @return {Object} configuration
*/
function getConfigFromFile( configPath, property ) {
- var config = JSON.parse( fs.readFileSync( configPath ) );
+ var config = JSON.parse( fs.readFileSync( configPath, 'utf8' ) );
if ( property ) {
if ( config[ property ] ) {
diff --git a/.eslintrc b/lib/.eslintrc
similarity index 100%
rename from .eslintrc
rename to lib/.eslintrc
diff --git a/lib/osx.js b/lib/osx.js
index aa7f292b0d5..73ed84e303d 100644
--- a/lib/osx.js
+++ b/lib/osx.js
@@ -11,6 +11,7 @@ var fs = require( 'fs' );
var path = require( 'path' );
var os = require( 'os' );
var appdmg = require( 'appdmg' );
+var tmp = require( 'tmp' );
/**
* Prototype for the osx installer builder
@@ -39,7 +40,7 @@ var OSXBuilder = {
osx.icon = path.resolve( options.basePath, osx.icon );
osx.contents[ 1 ].path = options.appPath;
- var configFilePath = path.join( os.tmpDir(), 'appdmg.json' );
+ var configFilePath = tmp.fileSync().name;
fs.writeFileSync( configFilePath, JSON.stringify( options.config.osx ) );
diff --git a/lib/osx.spec.js b/lib/osx.spec.js
index 5d9e4e9c97c..5433953a884 100644
--- a/lib/osx.spec.js
+++ b/lib/osx.spec.js
@@ -40,7 +40,7 @@ if ( process.platform === 'darwin' ) {
t.equal( options.target, '/somewhere/out/there/Example App.dmg' );
var configFilePath = options.source;
- var config = require( configFilePath, 'utf8' );
+ var config = JSON.parse( fs.readFileSync( configFilePath, 'utf8' ) );
t.equal( config.background, '/foo/boooom.png' );
t.equal( config.icon, '/foo/icon.icns' );
diff --git a/lib/win.js b/lib/win.js
index 562320cfce1..c170b49c368 100644
--- a/lib/win.js
+++ b/lib/win.js
@@ -93,7 +93,6 @@ var WinBuilder = {
options.log( ' $ apt-get install wine nsis -y' );
break;
}
- options.log( process.env );
return callback( new Error( 'makensis failed' ) );
} );
diff --git a/package.json b/package.json
index 4a90bc1958e..b60b471aca1 100644
--- a/package.json
+++ b/package.json
@@ -5,7 +5,7 @@
"main": "out/index.js",
"scripts": {
"compile": "tsconfig -i 2 && ts-babel",
- "lint": "eslint ./lib cli.js index.js && tslint src/*",
+ "lint": "eslint ./lib test cli.js index.js && tslint src/*",
"pretest": "npm run compile && npm run lint",
"test": "node ./test/helpers/runTests.js",
"test-nix": "result=\"$(tape index.spec.js ./lib/*.spec.js ./lib/**/*.spec.js)\"; echo \"$result\" | tap-spec; echo \"$result\" | tnyan; ava",
@@ -51,12 +51,12 @@
"dependencies": {
"bluebird": "^3.3.3",
"command-line-args": "^2.1.6",
- "electron-packager-tf": "^5.2.2",
- "electron-winstaller-temp-fork": "^0.1.0",
+ "electron-packager-tf": "^5.2.3",
+ "electron-winstaller-temp-fork": "^2.0.5-beta.0",
"fs-extra": "^0.26.5",
"gm": "^1.21.1",
"hosted-git-info": "^2.1.4",
- "lodash.template": "^4.2.1",
+ "lodash.template": "^4.2.2",
"meow": "^3.7.0",
"mime": "^1.3.4",
"progress": "^1.1.8",
@@ -70,10 +70,19 @@
},
"devDependencies": {
"ava-tf": "^0.12.3",
+ "babel-eslint": "^6.0.0-beta.1",
"babel-plugin-array-includes": "^2.0.3",
- "babel-plugin-transform-es2015-parameters": "^6.6.0",
+ "babel-plugin-transform-async-to-module-method": "^6.5.2",
+ "babel-plugin-transform-es2015-modules-commonjs": "^6.6.4",
+ "babel-plugin-transform-es2015-parameters": "^6.6.4",
+ "babel-plugin-transform-strict-mode": "^6.6.4",
+ "babel-register": "^6.6.0",
+ "electron-download": "^1.4.1",
"eslint": "^2.2.0",
+ "eslint-plugin-ava": "sindresorhus/eslint-plugin-ava",
"ghooks": "^1.0.3",
+ "json-parse-helpfulerror": "^1.0.3",
+ "option-chain": "^0.1.1",
"path-sort": "^0.1.0",
"plist": "^1.2.0",
"proxyquire": "^1.7.4",
@@ -81,22 +90,41 @@
"should": "^8.2.2",
"tap-nyan": "0.0.2",
"tap-spec": "^4.1.1",
- "tape": "^4.4.0",
- "ts-babel": "^0.4.3",
+ "tape": "^4.5.0",
+ "ts-babel": "^0.4.5",
"tsconfig-glob": "^0.4.1",
"tsd-generator": "^2.0.2",
"tslint": "^3.5.0",
- "typescript": "^1.8.2",
+ "typescript": "^1.8.7",
"validate-commit-msg": "^2.1.0"
},
"babel": {
"plugins": [
"transform-es2015-parameters",
"array-includes"
- ]
+ ],
+ "env": {
+ "test": {
+ "ignore": "**/out/*.js",
+ "plugins": [
+ [
+ "babel-plugin-transform-async-to-module-method",
+ {
+ "module": "bluebird",
+ "method": "coroutine"
+ }
+ ],
+ "babel-plugin-transform-es2015-modules-commonjs",
+ "transform-strict-mode"
+ ]
+ }
+ }
},
"ava": {
- "verbose": true
+ "verbose": true,
+ "require": [
+ "babel-register"
+ ]
},
"typings": "./out/electron-builder.d.ts",
"config": {
diff --git a/src/linuxPackager.ts b/src/linuxPackager.ts
index cfcd15c76b7..89d1fcc0198 100644
--- a/src/linuxPackager.ts
+++ b/src/linuxPackager.ts
@@ -33,7 +33,7 @@ export class LinuxPackager extends PlatformPackager {
prefix: "png-icons"
})
- const outputs = await exec("icns2png", ["-x", "-o", tempDir, path.join(this.projectDir, "build", "icon.icns")])
+ const outputs = await exec("icns2png", ["-x", "-o", tempDir, path.join(this.buildResourcesDir, "icon.icns")])
if (!outputs[0].toString().includes("ih32")) {
log("48x48 is not found in the icns, 128x128 will be resized")
// icns doesn't contain required 48x48, use gm to resize
diff --git a/src/macPackager.ts b/src/macPackager.ts
index 2231939538d..68b2436cbac 100644
--- a/src/macPackager.ts
+++ b/src/macPackager.ts
@@ -57,9 +57,9 @@ export default class MacPackager extends PlatformPackager
const specification: appdmg.Specification = {
title: this.metadata.name,
- icon: "build/icon.icns",
+ icon: path.join(this.buildResourcesDir, "icon.icns"),
"icon-size": 80,
- background: "build/background.png",
+ background: path.join(this.buildResourcesDir, "background.png"),
contents: [
{
"x": 410, "y": 220, "type": "link", "path": "/Applications"
diff --git a/src/packager.ts b/src/packager.ts
index ec6caafedcd..b0ead44770b 100644
--- a/src/packager.ts
+++ b/src/packager.ts
@@ -69,8 +69,7 @@ export class Packager implements BuildInfo {
const distTasks: Array> = []
for (let platform of platforms) {
const helper = this.createHelper(platform, cleanupTasks)
- const archs = platform === "darwin" ? ["x64"] : (this.options.arch == null || this.options.arch === "all" ? ["ia32", "x64"] : [this.options.arch])
- for (let arch of archs) {
+ for (let arch of normalizeArchs(platform, this.options.arch)) {
await this.installAppDependencies(arch)
helper.currentArch = arch
@@ -176,7 +175,11 @@ export class Packager implements BuildInfo {
}
}
-function normalizePlatforms(platforms: Array): Array {
+export function normalizeArchs(platform: string, arch?: string) {
+ return platform === "darwin" ? ["x64"] : (arch == null || arch === "all" ? ["ia32", "x64"] : [arch])
+}
+
+export function normalizePlatforms(platforms: Array): Array {
if (platforms == null || platforms.length === 0) {
return [process.platform]
}
diff --git a/src/platformPackager.ts b/src/platformPackager.ts
index 5186c71d1a7..59494e5d629 100644
--- a/src/platformPackager.ts
+++ b/src/platformPackager.ts
@@ -12,6 +12,12 @@ const pack = BluebirdPromise.promisify(packager)
export interface DevMetadata extends Metadata {
build: DevBuildMetadata
+
+ directories?: MetadataDirectories
+}
+
+interface MetadataDirectories {
+ buildResources?: string
}
export interface DevBuildMetadata {
@@ -57,9 +63,10 @@ export abstract class PlatformPackager implements ProjectMetadataProvider {
protected options: PackagerOptions
protected projectDir: string
+ protected buildResourcesDir: string
metadata: AppMetadata
- devMetadata: Metadata
+ devMetadata: DevMetadata
customDistOptions: DC
@@ -73,12 +80,19 @@ export abstract class PlatformPackager implements ProjectMetadataProvider {
this.metadata = info.metadata
this.devMetadata = info.devMetadata
+ this.buildResourcesDir = path.resolve(this.projectDir, this.relativeBuildResourcesDirname)
+
if (this.options.dist) {
const buildMetadata: any = info.devMetadata.build
this.customDistOptions = buildMetadata == null ? buildMetadata : buildMetadata[this.getBuildConfigurationKey()]
}
}
+ protected get relativeBuildResourcesDirname() {
+ const directories = this.devMetadata.directories
+ return (directories == null ? null : directories.buildResources) || "build"
+ }
+
protected dispatchArtifactCreated(path: string) {
this.info.eventEmitter.emit("artifactCreated", path)
}
@@ -98,7 +112,7 @@ export abstract class PlatformPackager implements ProjectMetadataProvider {
platform: platform,
arch: this.currentArch,
version: this.info.electronVersion,
- icon: path.join(this.projectDir, "build", "icon"),
+ icon: path.join(this.buildResourcesDir, "icon"),
asar: true,
overwrite: true,
"app-version": version,
diff --git a/src/winPackager.ts b/src/winPackager.ts
index b1116d211ca..7c6d2e54379 100644
--- a/src/winPackager.ts
+++ b/src/winPackager.ts
@@ -28,7 +28,7 @@ export default class WinPackager extends PlatformPackager {
// on appveyor (well, yes, it is a Windows bug)
// Because NSIS support will be dropped some day, correct solution is not implemented
const iconPath = this.customDistOptions == null ? null : this.customDistOptions.icon
- require("../lib/win").copyAssetsToTmpFolder(iconPath || path.join(this.projectDir, "build", "icon.ico"))
+ require("../lib/win").copyAssetsToTmpFolder(iconPath || path.join(this.buildResourcesDir, "icon.ico"))
}
// https://developer.mozilla.org/en-US/docs/Signing_an_executable_with_Authenticode
@@ -77,12 +77,12 @@ export default class WinPackager extends PlatformPackager {
if (this.info.repositoryInfo != null) {
const info = await this.info.repositoryInfo.getInfo(this)
if (info != null) {
- iconUrl = `https://raw.githubusercontent.com/${info.user}/${info.project}/master/build/icon.ico`
+ iconUrl = `https://raw.githubusercontent.com/${info.user}/${info.project}/master/${this.relativeBuildResourcesDirname}/icon.ico`
}
}
if (!iconUrl) {
- throw new Error("iconUrl is not specified, please see https://github.com/develar/electron-complete-builder#in-short")
+ throw new Error("iconUrl is not specified, please see https://github.com/loopline-systems/electron-builder#in-short")
}
}
}
@@ -100,9 +100,9 @@ export default class WinPackager extends PlatformPackager {
productName: appName,
version: version,
description: this.metadata.description,
- authors: this.metadata.author,
+ authors: this.metadata.author.name,
iconUrl: iconUrl,
- setupIcon: path.join(this.projectDir, "build", "icon.ico"),
+ setupIcon: path.join(this.buildResourcesDir, "icon.ico"),
certificateFile: certificateFile,
certificatePassword: this.options.cscKeyPassword,
}, this.customDistOptions)
@@ -112,8 +112,7 @@ export default class WinPackager extends PlatformPackager {
}
try {
- const build = <(options: any, callback: (error: Error) => void) => void>require("electron-winstaller-temp-fork").build
- await BluebirdPromise.promisify(build)(options)
+ await require("electron-winstaller-temp-fork").createWindowsInstaller(options)
}
catch (e) {
if (!e.message.includes("Unable to set icon")) {
diff --git a/test/.eslintrc.yml b/test/.eslintrc.yml
new file mode 100644
index 00000000000..b049345ac28
--- /dev/null
+++ b/test/.eslintrc.yml
@@ -0,0 +1,43 @@
+env:
+ es6: true
+ node: true
+
+parserOptions:
+ ecmaVersion: 6
+ sourceType: module
+ ecmaFeatures:
+ impliedStrict: true
+
+parser: babel-eslint
+
+plugins:
+ - ava
+
+extends: "eslint:recommended"
+
+rules:
+ ava/max-asserts: [0, 5]
+ ava/no-cb-test: 0
+ ava/no-identical-title: 2
+ ava/no-invalid-end: 2
+ ava/no-only-test: 2
+ ava/no-skip-assert: 2
+ ava/no-skip-test: 2
+ ava/prefer-power-assert: 0
+ ava/test-ended: 2
+ ava/test-title: [2, 'always']
+
+ "quotes": [ 2, "double" ]
+ semi: [2, "never"]
+ "linebreak-style": [ 2, "unix" ]
+ no-trailing-spaces: 2
+ no-var: 2
+ comma-dangle: 0
+ no-console: 0
+ curly: 2
+ eqeqeq: [2, "allow-null"]
+ no-throw-literal: 2
+ no-unused-expressions: 2
+ no-path-concat: 2
+ prefer-arrow-callback: 2
+ prefer-const: 2
\ No newline at end of file
diff --git a/test/ArtifactPublisherTest.js b/test/ArtifactPublisherTest.js
index 2fb20b7a91e..dbe922404a7 100644
--- a/test/ArtifactPublisherTest.js
+++ b/test/ArtifactPublisherTest.js
@@ -1,13 +1,13 @@
import test from "ava-tf"
-import { GitHubPublisher } from "electron-builder/out/gitHubPublisher"
+import { GitHubPublisher } from "out/gitHubPublisher"
import { join } from "path"
function getRandomInt(min, max) {
- return Math.floor(Math.random() * (max - min + 1)) + min;
+ return Math.floor(Math.random() * (max - min + 1)) + min
}
function versionNumber() {
- return getRandomInt(0, 99) + "." + Date.now() + "." + getRandomInt(0, 9);
+ return getRandomInt(0, 99) + "." + Date.now() + "." + getRandomInt(0, 9)
}
const token = new Buffer("Y2Y5NDdhZDJhYzJlMzg1OGNiNzQzYzcwOWZhNGI0OTk2NWQ4ZDg3Yg==", "base64").toString()
diff --git a/test/BuildTest.js b/test/BuildTest.js
index 2527208f171..bb8de6f04d4 100644
--- a/test/BuildTest.js
+++ b/test/BuildTest.js
@@ -1,152 +1,51 @@
-import test from "ava-tf"
+import test from "./helpers/avaEx"
+import { assertPack } from "./helpers/packTester"
import fse from "fs-extra"
-import tmp from "tmp"
import Promise from "bluebird"
-import assertThat from "should/as-function"
import * as path from "path"
-import { parse as parsePlist } from "plist"
-import { Packager } from "electron-builder"
-import { exec } from "electron-builder/out/util"
-import { readText } from "electron-builder/out/promisifed-fs"
-import { CSC_LINK, CSC_KEY_PASSWORD } from "./helpers/codeSignData"
-import pathSorter from "path-sort"
+import { readText } from "out/promisifed-fs"
+import { parse as parseJson } from "json-parse-helpfulerror"
-const copyDir = Promise.promisify(fse.copy)
-const tmpDir = Promise.promisify(tmp.dir)
-
-const expectedLinuxContents = ['/',
- '/opt/',
- '/usr/',
- '/opt/TestApp/',
- '/opt/TestApp/content_shell.pak',
- '/opt/TestApp/icudtl.dat',
- '/opt/TestApp/libnode.so',
- '/opt/TestApp/LICENSE',
- '/opt/TestApp/LICENSES.chromium.html',
- '/opt/TestApp/natives_blob.bin',
- '/opt/TestApp/pkgtarget',
- '/opt/TestApp/snapshot_blob.bin',
- '/opt/TestApp/TestApp',
- '/opt/TestApp/version',
- '/usr/share/',
- '/opt/TestApp/resources/',
- '/opt/TestApp/resources/app.asar',
- '/opt/TestApp/resources/atom.asar',
- '/usr/share/applications/',
- '/usr/share/applications/TestApp.desktop',
- '/usr/share/doc/',
- '/usr/share/icons/',
- '/usr/share/doc/testapp/',
- '/usr/share/doc/testapp/changelog.Debian.gz',
- '/usr/share/icons/hicolor/',
- '/usr/share/icons/hicolor/128x128/',
- '/usr/share/icons/hicolor/16x16/',
- '/usr/share/icons/hicolor/256x256/',
- '/usr/share/icons/hicolor/32x32/',
- '/usr/share/icons/hicolor/48x48/',
- '/usr/share/icons/hicolor/512x512/',
- '/usr/share/icons/hicolor/128x128/apps/',
- '/usr/share/icons/hicolor/128x128/apps/TestApp.png',
- '/usr/share/icons/hicolor/16x16/apps/',
- '/usr/share/icons/hicolor/16x16/apps/TestApp.png',
- '/usr/share/icons/hicolor/256x256/apps/',
- '/usr/share/icons/hicolor/256x256/apps/TestApp.png',
- '/usr/share/icons/hicolor/32x32/apps/',
- '/usr/share/icons/hicolor/32x32/apps/TestApp.png',
- '/usr/share/icons/hicolor/48x48/apps/',
- '/usr/share/icons/hicolor/48x48/apps/TestApp.png',
- '/usr/share/icons/hicolor/512x512/apps/',
- '/usr/share/icons/hicolor/512x512/apps/TestApp.png'
-]
-
-async function assertPack(projectDir, platform, target, useTempDir) {
- projectDir = path.join(__dirname, "fixtures", projectDir)
- // const isDoNotUseTempDir = platform === "darwin"
- if (useTempDir) {
- // non-osx test uses the same dir as osx test, but we cannot share node_modules (because tests executed in parallel)
- const dir = await tmpDir({
- unsafeCleanup: true,
- prefix: platform
- })
- await copyDir(projectDir, dir, {
- filter: function (p) {
- const basename = path.basename(p)
- return basename !== "dist" && basename !== "node_modules" && basename[0] !== "."
- }
- })
- projectDir = dir
- }
-
- const packager = new Packager({
- projectDir: projectDir,
- cscLink: CSC_LINK,
- cscKeyPassword: CSC_KEY_PASSWORD,
- dist: true,
- platform: [platform],
- target: target
- })
-
- await packager.build()
- if (platform === "darwin") {
- const packedAppDir = projectDir + "/dist/TestApp-darwin-x64/TestApp.app"
- const info = parsePlist(await readText(packedAppDir + "/Contents/Info.plist"))
- assertThat(info).has.properties({
- CFBundleDisplayName: "TestApp",
- CFBundleIdentifier: "your.id",
- LSApplicationCategoryType: "your.app.category.type",
- CFBundleVersion: "1.0.0" + "." + (process.env.TRAVIS_BUILD_NUMBER || process.env.CIRCLE_BUILD_NUM)
- })
-
- const result = await exec("codesign", ["--verify", packedAppDir])
- assertThat(result[0].toString()).not.match(/is not signed at all/)
- }
- else if (platform === "linux") {
- assertThat(await getContents(projectDir + "/dist/TestApp-1.0.0-amd64.deb")).deepEqual(expectedLinuxContents)
- assertThat(await getContents(projectDir + "/dist/TestApp-1.0.0-i386.deb")).deepEqual(expectedLinuxContents)
- // console.log(await getContents(projectDir + "/dist/TestApp-1.0.0-amd64.deb"))
- // console.log(await getContents(projectDir + "/dist/TestApp-1.0.0-i386.deb"))
- }
-}
-
-async function getContents(path) {
- const result = await exec("dpkg", ["--contents", path])
- return pathSorter(result[0]
- .split("\n")
- .map(it => it.length === 0 ? null : it.substring(it.indexOf('.') + 1))
- .filter(it => it != null && !(it.startsWith("/opt/TestApp/locales/") || it.startsWith("/opt/TestApp/libgcrypt")))
- )
-}
+const writeFile = Promise.promisify(fse.writeFile)
+const moveFile = Promise.promisify(fse.move)
if (process.env.TRAVIS !== "true") {
// we don't use CircleCI, so, we can safely set this env
process.env.CIRCLE_BUILD_NUM = 42
}
-if (process.platform === "darwin") {
- test("mac: two-package.json", async function () {
- await assertPack("test-app", "darwin")
- })
+test.ifOsx("mac: two-package.json", async function () {
+ await assertPack("test-app", "darwin")
+})
- test("mac: one-package.json", async function () {
- await assertPack("test-app-one", "darwin")
- })
-}
+test.ifOsx("mac: one-package.json", async function () {
+ await assertPack("test-app-one", "darwin")
+})
-if (process.platform !== "win32") {
- test("linux", async function () {
- await assertPack("test-app-one", "linux")
- })
+test("custom app dir", async function () {
+ let platforms
+ if (process.platform === "darwin") {
+ platforms = ["darwin", "linux"]
+ }
+ else if (process.platform === "linux") {
+ // todo install wine on Linux agent
+ platforms = ["linux"]
+ }
+ else {
+ platforms = ["win32"]
+ }
- test("no-author-email", async (t) => {
- t.throws(assertPack("test-app-no-author-email", "linux"), /Please specify author 'email' in .*/)
+ await assertPack("test-app-one", platforms, [], true, async projectDir => {
+ const file = path.join(projectDir, "package.json")
+ const data = parseJson(await readText(file))
+ data.directories = {
+ buildResources: "custom"
+ }
+
+ return Promise.all([
+ writeFile(file, JSON.stringify(data, null, 2)),
+ moveFile(path.join(projectDir, "build"), path.join(projectDir, "custom"))
+ ])
})
-}
+})
-if (!process.env.TRAVIS) {
- test("win", async function () {
- await assertPack("test-app-one", "win32")
- })
- test("win: nsis", async function () {
- await assertPack("test-app-one", "win32", ["nsis"], true)
- })
-}
\ No newline at end of file
diff --git a/test/CodeSignTest.js b/test/CodeSignTest.js
index 5e885ae3578..7038f70adba 100644
--- a/test/CodeSignTest.js
+++ b/test/CodeSignTest.js
@@ -1,23 +1,14 @@
-import { createKeychain, deleteKeychain, generateKeychainName } from "electron-builder/out/codeSign"
+import { createKeychain, deleteKeychain, generateKeychainName } from "out/codeSign"
import assertThat from "should/as-function"
-import avaTest from "ava-tf"
+import test from "./helpers/avaEx"
import { CSC_NAME, CSC_LINK, CSC_KEY_PASSWORD } from "./helpers/codeSignData"
-import promises from "electron-builder/out/promise"
+import promises from "out/promise"
-function test(doNotSkip, name, testFunction) {
- if (doNotSkip) {
- avaTest(name, testFunction)
- }
- else {
- avaTest.skip(name, testFunction)
- }
-}
-
-test(process.platform === "darwin", "create keychain", async () => {
+test.ifOsx("create keychain", async () => {
const keychainName = generateKeychainName()
await promises.executeFinally(createKeychain(keychainName, CSC_LINK, CSC_KEY_PASSWORD)
.then(result => {
assertThat(result.cscKeychainName).not.empty()
assertThat(result.cscName).equal(CSC_NAME)
- }), error => promises.all([deleteKeychain(keychainName)]))
+ }), () => promises.all([deleteKeychain(keychainName)]))
})
\ No newline at end of file
diff --git a/test/RepoSlugTest.js b/test/RepoSlugTest.js
index 6af28cc491f..95acf057827 100644
--- a/test/RepoSlugTest.js
+++ b/test/RepoSlugTest.js
@@ -1,8 +1,8 @@
-import { InfoRetriever } from "electron-builder/out/repositoryInfo"
+import { InfoRetriever } from "out/repositoryInfo"
import assertThat from "should/as-function"
import test from "ava-tf"
-test("repo slug from TRAVIS_REPO_SLUG", function () {
+test("repo slug from TRAVIS_REPO_SLUG", () => {
const oldValue = process.env.TRAVIS_REPO_SLUG
try {
process.env.TRAVIS_REPO_SLUG = "travis-ci/travis-build"
@@ -26,7 +26,7 @@ function restoreEnv(name, value) {
}
}
-test("repo slug from APPVEYOR", function () {
+test("repo slug from APPVEYOR", () => {
const oldAppveyorAccountName = process.env.APPVEYOR_ACCOUNT_NAME
const oldAppveyorProjectName = process.env.APPVEYOR_PROJECT_NAME
const travisSlug = process.env.TRAVIS_REPO_SLUG
diff --git a/test/fixtures/test-app-no-author-email/package.json b/test/fixtures/test-app-no-author-email/package.json
index cb88b903213..62d74748411 100644
--- a/test/fixtures/test-app-no-author-email/package.json
+++ b/test/fixtures/test-app-no-author-email/package.json
@@ -5,7 +5,7 @@
"description": "Test Application",
"author": "Foo Bar",
"devDependencies": {
- "electron-prebuilt": "^0.36.7"
+ "electron-prebuilt": "^0.36.9"
},
"build": {
"app-bundle-id": "your.id",
diff --git a/test/fixtures/test-app-one/package.json b/test/fixtures/test-app-one/package.json
index 6a0bd32e999..355709e9e71 100644
--- a/test/fixtures/test-app-one/package.json
+++ b/test/fixtures/test-app-one/package.json
@@ -8,7 +8,7 @@
},
"author": "Foo Bar ",
"devDependencies": {
- "electron-prebuilt": "^0.36.7"
+ "electron-prebuilt": "^0.36.9"
},
"build": {
"app-bundle-id": "your.id",
diff --git a/test/fixtures/test-app/package.json b/test/fixtures/test-app/package.json
index 2c969fe45d2..2079c28dd2e 100644
--- a/test/fixtures/test-app/package.json
+++ b/test/fixtures/test-app/package.json
@@ -4,6 +4,6 @@
"start": "electron ."
},
"devDependencies": {
- "electron-prebuilt": "^0.36.7"
+ "electron-prebuilt": "^0.36.9"
}
}
diff --git a/test/helpers/avaEx.js b/test/helpers/avaEx.js
new file mode 100644
index 00000000000..f5a03efb35c
--- /dev/null
+++ b/test/helpers/avaEx.js
@@ -0,0 +1,26 @@
+import test from "ava-tf"
+
+Object.defineProperties(test, {
+ "ifNotWindows": {
+ get: function () {
+ return process.platform === "win32" ? this.skip : this
+ }
+ },
+ "ifNotCi": {
+ get: function () {
+ return process.env.CI ? this.skip : this
+ }
+ },
+ "ifNotTravis": {
+ get: function () {
+ return process.env.TRAVIS ? this.skip : this
+ }
+ },
+ "ifOsx": {
+ get: function () {
+ return process.platform === "darwin" ? this : this.skip
+ }
+ }
+})
+
+export default test
\ No newline at end of file
diff --git a/test/helpers/expectedContents.js b/test/helpers/expectedContents.js
new file mode 100644
index 00000000000..d5db75e3132
--- /dev/null
+++ b/test/helpers/expectedContents.js
@@ -0,0 +1,46 @@
+export const expectedLinuxContents = [
+ "/",
+ "/opt/",
+ "/usr/",
+ "/opt/TestApp/",
+ "/opt/TestApp/content_shell.pak",
+ "/opt/TestApp/icudtl.dat",
+ "/opt/TestApp/libffmpeg.so",
+ "/opt/TestApp/libnode.so",
+ "/opt/TestApp/LICENSE",
+ "/opt/TestApp/LICENSES.chromium.html",
+ "/opt/TestApp/natives_blob.bin",
+ "/opt/TestApp/pkgtarget",
+ "/opt/TestApp/snapshot_blob.bin",
+ "/opt/TestApp/TestApp",
+ "/opt/TestApp/version",
+ "/usr/share/",
+ "/opt/TestApp/resources/",
+ "/opt/TestApp/resources/app.asar",
+ "/opt/TestApp/resources/atom.asar",
+ "/usr/share/applications/",
+ "/usr/share/applications/TestApp.desktop",
+ "/usr/share/doc/",
+ "/usr/share/icons/",
+ "/usr/share/doc/testapp/",
+ "/usr/share/doc/testapp/changelog.Debian.gz",
+ "/usr/share/icons/hicolor/",
+ "/usr/share/icons/hicolor/128x128/",
+ "/usr/share/icons/hicolor/16x16/",
+ "/usr/share/icons/hicolor/256x256/",
+ "/usr/share/icons/hicolor/32x32/",
+ "/usr/share/icons/hicolor/48x48/",
+ "/usr/share/icons/hicolor/512x512/",
+ "/usr/share/icons/hicolor/128x128/apps/",
+ "/usr/share/icons/hicolor/128x128/apps/TestApp.png",
+ "/usr/share/icons/hicolor/16x16/apps/",
+ "/usr/share/icons/hicolor/16x16/apps/TestApp.png",
+ "/usr/share/icons/hicolor/256x256/apps/",
+ "/usr/share/icons/hicolor/256x256/apps/TestApp.png",
+ "/usr/share/icons/hicolor/32x32/apps/",
+ "/usr/share/icons/hicolor/32x32/apps/TestApp.png",
+ "/usr/share/icons/hicolor/48x48/apps/",
+ "/usr/share/icons/hicolor/48x48/apps/TestApp.png",
+ "/usr/share/icons/hicolor/512x512/apps/",
+ "/usr/share/icons/hicolor/512x512/apps/TestApp.png"
+]
\ No newline at end of file
diff --git a/test/helpers/packTester.js b/test/helpers/packTester.js
new file mode 100644
index 00000000000..8fb875c1050
--- /dev/null
+++ b/test/helpers/packTester.js
@@ -0,0 +1,77 @@
+import fse from "fs-extra"
+import tmp from "tmp"
+import Promise from "bluebird"
+import assertThat from "should/as-function"
+import * as path from "path"
+import { parse as parsePlist } from "plist"
+import { CSC_LINK, CSC_KEY_PASSWORD } from "./codeSignData"
+import { expectedLinuxContents } from "./expectedContents"
+import { readText } from "out/promisifed-fs"
+import { Packager } from "out/index"
+import { exec } from "out/util"
+import pathSorter from "path-sort"
+
+const copyDir = Promise.promisify(fse.copy)
+const tmpDir = Promise.promisify(tmp.dir)
+
+export async function assertPack(projectDir, platform, target, useTempDir, tempDirCreated) {
+ projectDir = path.join(__dirname, "..", "fixtures", projectDir)
+ // const isDoNotUseTempDir = platform === "darwin"
+ if (useTempDir) {
+ // non-osx test uses the same dir as osx test, but we cannot share node_modules (because tests executed in parallel)
+ const dir = await tmpDir({
+ unsafeCleanup: true,
+ prefix: platform
+ })
+ await copyDir(projectDir, dir, {
+ filter: function (p) {
+ const basename = path.basename(p)
+ return basename !== "dist" && basename !== "node_modules" && basename[0] !== "."
+ }
+ })
+ projectDir = dir
+
+ if (tempDirCreated != null) {
+ await tempDirCreated(projectDir)
+ }
+ }
+
+ const packager = new Packager({
+ projectDir: projectDir,
+ cscLink: CSC_LINK,
+ cscKeyPassword: CSC_KEY_PASSWORD,
+ dist: true,
+ platform: Array.isArray(platform) ? platform : [platform],
+ target: target
+ })
+
+ await packager.build()
+ if (platform === "darwin" || (platform === "all" && process.platform === "darwin")) {
+ const packedAppDir = projectDir + "/dist/TestApp-darwin-x64/TestApp.app"
+ const info = parsePlist(await readText(packedAppDir + "/Contents/Info.plist"))
+ assertThat(info).has.properties({
+ CFBundleDisplayName: "TestApp",
+ CFBundleIdentifier: "your.id",
+ LSApplicationCategoryType: "your.app.category.type",
+ CFBundleVersion: "1.0.0" + "." + (process.env.TRAVIS_BUILD_NUMBER || process.env.CIRCLE_BUILD_NUM)
+ })
+
+ const result = await exec("codesign", ["--verify", packedAppDir])
+ assertThat(result[0].toString()).not.match(/is not signed at all/)
+ }
+ else if (platform === "linux" || (platform === "all" && process.platform !== "win32")) {
+ assertThat(await getContents(projectDir + "/dist/TestApp-1.0.0-amd64.deb")).deepEqual(expectedLinuxContents)
+ assertThat(await getContents(projectDir + "/dist/TestApp-1.0.0-i386.deb")).deepEqual(expectedLinuxContents)
+ // console.log(JSON.stringify(await getContents(projectDir + "/dist/TestApp-1.0.0-amd64.deb"), null, 2))
+ // console.log(JSON.stringify(await getContents(projectDir + "/dist/TestApp-1.0.0-i386.deb"), null, 2))
+ }
+}
+
+async function getContents(path) {
+ const result = await exec("dpkg", ["--contents", path])
+ return pathSorter(result[0]
+ .split("\n")
+ .map(it => it.length === 0 ? null : it.substring(it.indexOf(".") + 1))
+ .filter(it => it != null && !(it.startsWith("/opt/TestApp/locales/") || it.startsWith("/opt/TestApp/libgcrypt")))
+ )
+}
\ No newline at end of file
diff --git a/test/helpers/runTests.js b/test/helpers/runTests.js
index f90aa683527..0cef97f36da 100644
--- a/test/helpers/runTests.js
+++ b/test/helpers/runTests.js
@@ -1,23 +1,109 @@
+"use strict"
+
const childProcess = require("child_process")
const path = require("path")
-const fs = require("bluebird").promisifyAll(require("fs-extra"))
+const Promise = require("bluebird")
+const fs = Promise.promisifyAll(require("fs-extra"))
+const readText = require("../../out/promisifed-fs").readText
+const downloadElectron = Promise.promisify(require("electron-download"))
+const packager = require("../../out/packager")
-const testPackageDir = path.join(__dirname, "..")
+const rootDir = path.join(__dirname, "..", "..")
+const testPackageDir = path.join(require("os").tmpdir(), "electron_builder_published")
+const testNodeModules = path.join(testPackageDir, "node_modules")
-// npm is very slow and not reliable - so, just copy and then prune dev dependencies
-const dest = path.join(testPackageDir, "node_modules")
-fs.emptyDirAsync(dest)
- .then(() => fs.copyAsync(path.join(testPackageDir, "..", "node_modules"), dest))
+const electronVersion = "0.36.9"
+
+Promise.all([
+ deleteOldElectronVersion(),
+ downloadAllRequiredElectronVersions(),
+ fs.outputFileAsync(path.join(testPackageDir, "package.json"), `{
+ "private": true,
+ "version": "1.0.0",
+ "name": "test",
+ "dependencies": {
+ "electron-builder": "file:${path.posix.join(__dirname.replace(/\\/g, "/"), "..", "..")}"
+ }
+ }`)
+ .then(() => copyDependencies())
+ ])
.then(() => install())
.catch(error => {
console.error(error)
process.exit(1)
})
+function deleteOldElectronVersion() {
+ if (process.env.CI) {
+ const cacheDir = path.join(require("os").homedir(), ".electron")
+ return fs.readdirAsync(cacheDir)
+ .catch(error => {
+ if (error.code === "ENOENT") {
+ return []
+ }
+ else {
+ throw error
+ }
+ })
+ .then(it => {
+ const deletePromises = []
+ for (let file of it) {
+ if (file.endsWith(".zip") && !file.includes(electronVersion)) {
+ console.log("Remove old electron " + file)
+ deletePromises.push(fs.unlinkAsync(path.join(cacheDir, file)))
+ }
+ }
+ return Promise.all(deletePromises)
+ })
+ }
+ else {
+ return Promise.resolve()
+ }
+}
+
+function downloadAllRequiredElectronVersions() {
+ const downloadPromises = []
+ for (let platform of packager.normalizePlatforms(["all"])) {
+ for (let arch of packager.normalizeArchs(platform)) {
+ downloadPromises.push(downloadElectron({
+ version: electronVersion,
+ arch: arch,
+ platform: platform,
+ }))
+ }
+ }
+ return Promise.all(downloadPromises)
+}
+
+function copyDependencies() {
+// npm is very slow and not reliable - so, just copy and then prune dev dependencies
+ return fs.emptyDirAsync(testNodeModules)
+ .then(() => readText(path.join(rootDir, "package.json")))
+ .then(it => {
+ const devDeps = Object.keys(JSON.parse(it).devDependencies)
+ const filtered = new Set()
+ /*eslint prefer-const: 0*/
+ for (let name of devDeps) {
+ filtered.add(path.join(rootDir, "node_modules", name))
+ }
+
+ filtered.add(path.join(rootDir, "node_modules", ".bin"))
+
+ return fs.copyAsync(path.join(rootDir, "node_modules"), testNodeModules, {
+ filter: it => {
+ if (it.includes("node_modules" + path.sep + "babel-")) {
+ return false
+ }
+ return !filtered.has(it)
+ }
+ })
+ })
+}
+
function install() {
// install from cache - all dependencies are already installed before run test
// https://github.com/npm/npm/issues/2568
- spawn("npm", ["install", "--cache-min", "999999999", "--production", path.join(testPackageDir, "..")], () => {
+ spawn("npm", ["install", "--cache-min", "999999999", "--production", rootDir], () => {
// prune stale packages
spawn("npm", ["prune", "--production"], () => {
runTests()
@@ -30,13 +116,14 @@ function runTests() {
}, {
cwd: path.join(__dirname, "..", ".."),
env: Object.assign({}, process.env, {
- NODE_PATH: path.join(testPackageDir, "node_modules")
+ NODE_PATH: path.join(testNodeModules, "electron-builder"),
+ BABEL_ENV: "test",
})
})
}
function spawn(command, args, callback, options) {
- if (command == "npm") {
+ if (command === "npm") {
const npmExecPath = process.env.npm_execpath || process.env.NPM_CLI_JS
if (npmExecPath != null) {
args.unshift(npmExecPath)
@@ -62,6 +149,7 @@ function spawn(command, args, callback, options) {
console.error(fs.readFileSync(path.join(testPackageDir, "npm-debug.log"), "utf8"))
}
catch (e) {
+ // ignore
}
}
diff --git a/test/linuxPackagerTest.js b/test/linuxPackagerTest.js
new file mode 100644
index 00000000000..90ff853be73
--- /dev/null
+++ b/test/linuxPackagerTest.js
@@ -0,0 +1,10 @@
+import test from "./helpers/avaEx"
+import { assertPack } from "./helpers/packTester"
+
+test.ifNotWindows("linux", async function () {
+ await assertPack("test-app-one", "linux")
+})
+
+test.ifNotWindows("no-author-email", async(t) => {
+ t.throws(assertPack("test-app-no-author-email", "linux"), /Please specify author 'email' in .*/)
+})
diff --git a/test/old-cli-test.js b/test/old-cli-test.js
index 635333cc855..5eca2f649ab 100644
--- a/test/old-cli-test.js
+++ b/test/old-cli-test.js
@@ -7,7 +7,7 @@ const execFileAsync = Promise.promisify(require('child_process').execFile)
const path = require('path')
const exampleAppPath = path.join(__dirname, '..', 'example-app')
-const cliPath = path.join(__dirname, 'node_modules', '.bin', 'electron-builder') + (process.platform === "win32" ? ".cmd" : "")
+const cliPath = path.join(process.env.NODE_PATH, '..', '.bin', 'electron-builder') + (process.platform === "win32" ? ".cmd" : "")
function exec(args) {
return execFileAsync(cliPath, args, {
@@ -39,13 +39,13 @@ if (process.platform === "darwin") {
}
if (!process.env.CI || process.platform === "win32") {
- test('Cli - windows - config file provided', async (t) => {
+ test.serial('Cli - windows - config file provided', async (t) => {
await exec(['Example-win32-ia32', '--platform=win', '--config=builder.json'])
t.ok(await fs.statAsync(path.join(exampleAppPath, 'Builder\ Config\ Windows\ example\ Setup.exe')), 'exe created')
await fs.removeAsync(path.join(exampleAppPath, 'Builder\ Config\ Windows\ example\ Setup.exe'))
})
- test('Cli - windows - no config file provided', async t => {
+ test.serial('Cli - windows - no config file provided', async t => {
await exec(['Example-win32-ia32', '--platform=win'])
t.ok(await fs.statAsync(path.join(exampleAppPath, 'Electron\ Builder\ Example\ Setup.exe')), 'exe created')
await fs.removeAsync(path.join(exampleAppPath, 'Electron\ Builder\ Example\ Setup.exe'))
diff --git a/test/package.json b/test/package.json
deleted file mode 100644
index 1d2c6914fad..00000000000
--- a/test/package.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "private": true,
- "version": "1.0.0",
- "name": "test",
- "dependencies": {
- "electron-builder": "file:.."
- }
-}
diff --git a/test/winPackagerTest.js b/test/winPackagerTest.js
new file mode 100644
index 00000000000..7766b717489
--- /dev/null
+++ b/test/winPackagerTest.js
@@ -0,0 +1,11 @@
+import test from "./helpers/avaEx"
+import { assertPack } from "./helpers/packTester"
+
+test.ifNotTravis("win", async function () {
+ await assertPack("test-app-one", "win32")
+})
+
+// nsis is deprecated and not thread-safe - just do not run on CI to avoid failures
+test.ifNotCi.serial("win: nsis", async function () {
+ await assertPack("test-app-one", "win32", ["nsis"], true)
+})
\ No newline at end of file