From 3cdf25a59853bfd22ce57d85783903a5e367bf1c Mon Sep 17 00:00:00 2001 From: develar Date: Fri, 4 Mar 2016 18:12:47 +0100 Subject: [PATCH] refactor: rewrite test in typescript MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Typescript is much more easy to maintain in all aspects. (as result, one error was discovered in tests — temp dir prefix). --- .eslintignore | 2 - .gitignore | 2 +- .idea/electron-builder.iml | 2 + .idea/jsLibraryMappings.xml | 4 +- .../libraries/electron_builder_for_tests.xml | 14 ++ .idea/runConfigurations/BuildTest.xml | 3 +- .idea/scopes/src.xml | 2 +- .idea/typescript-compiler.xml | 1 - package.json | 66 ++---- src/awaiter.ts | 8 +- src/build-cli.ts | 5 +- src/builder.ts | 9 +- src/codeSign.ts | 6 +- src/gitHubPublisher.ts | 7 +- src/gitHubRequest.ts | 3 +- src/index.ts | 7 +- src/linuxPackager.ts | 15 +- src/macPackager.ts | 18 +- src/packager.ts | 9 +- src/platformPackager.ts | 26 ++- src/promise.ts | 3 +- src/promisifed-fs.ts | 28 +-- src/repositoryInfo.ts | 9 +- src/util.ts | 6 - src/winPackager.ts | 21 +- test/helpers/codeSignData.js | 3 - test/helpers/packTester.js | 109 --------- index.spec.js => test/index.spec.js | 34 +-- test/old-cli-test.js | 53 ----- .../ArtifactPublisherTest.ts} | 19 +- test/{BuildTest.js => src/BuildTest.ts} | 28 ++- test/{CodeSignTest.js => src/CodeSignTest.ts} | 13 +- test/{RepoSlugTest.js => src/RepoSlugTest.ts} | 13 +- .../avaEx.js => src/helpers/avaEx.ts} | 13 ++ test/src/helpers/codeSignData.ts | 3 + .../helpers/expectedContents.ts} | 0 test/src/helpers/packTester.ts | 139 ++++++++++++ .../runTests.js => src/helpers/runTests.ts} | 74 ++++--- .../linuxPackagerTest.ts} | 7 +- test/src/old-cli-test.ts | 54 +++++ .../winPackagerTest.ts} | 7 +- test/tsconfig.json | 65 ++++++ test/typings/ava.d.ts | 168 ++++++++++++++ test/typings/json-parse-helpfulerror.d.ts | 3 + test/typings/path-sort.d.ts | 5 + test/typings/plist.d.ts | 4 + .../should => test/typings}/should.d.ts | 6 +- tsconfig.json | 13 +- tslint.json | 6 +- typings/bluebird.d.ts | 63 ------ typings/main/ambient/fs-extra/fs-extra.d.ts | 207 ------------------ typings/main/ambient/tmp/tmp.d.ts | 62 +++--- 52 files changed, 733 insertions(+), 714 deletions(-) delete mode 100644 .eslintignore create mode 100644 .idea/libraries/electron_builder_for_tests.xml delete mode 100644 test/helpers/codeSignData.js delete mode 100644 test/helpers/packTester.js rename index.spec.js => test/index.spec.js (79%) delete mode 100644 test/old-cli-test.js rename test/{ArtifactPublisherTest.js => src/ArtifactPublisherTest.ts} (69%) rename test/{BuildTest.js => src/BuildTest.ts} (55%) rename test/{CodeSignTest.js => src/CodeSignTest.ts} (51%) rename test/{RepoSlugTest.js => src/RepoSlugTest.ts} (75%) rename test/{helpers/avaEx.js => src/helpers/avaEx.ts} (59%) create mode 100644 test/src/helpers/codeSignData.ts rename test/{helpers/expectedContents.js => src/helpers/expectedContents.ts} (100%) create mode 100644 test/src/helpers/packTester.ts rename test/{helpers/runTests.js => src/helpers/runTests.ts} (62%) rename test/{linuxPackagerTest.js => src/linuxPackagerTest.ts} (57%) create mode 100644 test/src/old-cli-test.ts rename test/{winPackagerTest.js => src/winPackagerTest.ts} (66%) create mode 100644 test/tsconfig.json create mode 100644 test/typings/ava.d.ts create mode 100644 test/typings/json-parse-helpfulerror.d.ts create mode 100644 test/typings/path-sort.d.ts create mode 100644 test/typings/plist.d.ts rename {typings/main/ambient/should => test/typings}/should.d.ts (98%) delete mode 100644 typings/bluebird.d.ts delete mode 100644 typings/main/ambient/fs-extra/fs-extra.d.ts diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 6bc991c9bf8..00000000000 --- a/.eslintignore +++ /dev/null @@ -1,2 +0,0 @@ -test/fixtures/ -test/old-cli-test.js \ No newline at end of file diff --git a/.gitignore b/.gitignore index e83a6a117eb..6906145b6ee 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ node_modules/ *.log -/out/ +out/ npm-debug.log dist/ /.idea/compiler.xml diff --git a/.idea/electron-builder.iml b/.idea/electron-builder.iml index b289b290bbd..feb9628e9bb 100644 --- a/.idea/electron-builder.iml +++ b/.idea/electron-builder.iml @@ -10,9 +10,11 @@ + + \ No newline at end of file diff --git a/.idea/jsLibraryMappings.xml b/.idea/jsLibraryMappings.xml index 38929e35e1f..f8471c1083a 100644 --- a/.idea/jsLibraryMappings.xml +++ b/.idea/jsLibraryMappings.xml @@ -1,8 +1,8 @@ - + + - \ No newline at end of file diff --git a/.idea/libraries/electron_builder_for_tests.xml b/.idea/libraries/electron_builder_for_tests.xml new file mode 100644 index 00000000000..ccbf7c28a4b --- /dev/null +++ b/.idea/libraries/electron_builder_for_tests.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations/BuildTest.xml b/.idea/runConfigurations/BuildTest.xml index 5911c5394d6..4fc2604c6a4 100644 --- a/.idea/runConfigurations/BuildTest.xml +++ b/.idea/runConfigurations/BuildTest.xml @@ -1,7 +1,6 @@ - + - diff --git a/.idea/scopes/src.xml b/.idea/scopes/src.xml index a8b2d7fa999..67c76fc93ff 100644 --- a/.idea/scopes/src.xml +++ b/.idea/scopes/src.xml @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/.idea/typescript-compiler.xml b/.idea/typescript-compiler.xml index d10f84f5465..88b88fe9a19 100644 --- a/.idea/typescript-compiler.xml +++ b/.idea/typescript-compiler.xml @@ -3,7 +3,6 @@ diff --git a/package.json b/package.json index 9ba50462699..59ef6c93e7f 100644 --- a/package.json +++ b/package.json @@ -4,13 +4,14 @@ "version": "0.0.0-semantic-release", "main": "out/index.js", "scripts": { - "compile": "tsconfig -i 2 && ts-babel", - "lint": "eslint ./lib test cli.js index.js && tslint src/*", - "pretest": "npm run compile && npm run lint && npm run declaration", - "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", + "compile": "npm run compile-production && npm run compile-test", + "compile-production": "tsconfig -i 2 && ts-babel", + "compile-test": "tsconfig -i 2 test && ts-babel test", + "lint": "eslint ./lib cli.js index.js && tslint src/*", + "pretest": "npm run compile && npm run lint", + "test": "node ./test/out/helpers/runTests.js", + "test-nix": "tape ./lib/*.spec.js ./lib/**/*.spec.js && ava", "test-win": "ava", - "declaration": "dts-generator --name electron-builder --out out/electron-builder.d.ts", "semantic-release": "semantic-release pre && npm publish && semantic-release post" }, "repository": { @@ -49,11 +50,12 @@ "bugs": "https://github.com/loopline-systems/electron-builder/issues", "homepage": "https://github.com/loopline-systems/electron-builder", "dependencies": { - "bluebird": "^3.3.3", + "bluebird": "^3.3.4", "command-line-args": "^2.1.6", "electron-packager-tf": "^5.2.3", "electron-winstaller-temp-fork": "^2.0.5-beta.3", "fs-extra": "^0.26.5", + "fs-extra-p": "^0.1.0", "gm": "^1.21.1", "hosted-git-info": "^2.1.4", "lodash.template": "^4.2.2", @@ -69,61 +71,39 @@ "appdmg": "^0.3.6" }, "devDependencies": { - "ava-tf": "^0.12.3", - "babel-eslint": "^6.0.0-beta.1", + "ava-tf": "^0.12.4-beta.6", "babel-plugin-array-includes": "^2.0.3", - "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", + "babel-plugin-transform-es2015-parameters": "^6.6.5", "electron-download": "^2.0.0", - "eslint": "^2.2.0", + "eslint": "^2.3.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", "semantic-release": "^4.3.5", "should": "^8.2.2", - "tap-nyan": "0.0.2", - "tap-spec": "^4.1.1", - "tape": "^4.5.0", - "ts-babel": "^0.4.5", + "tape": "^4.5.1", + "ts-babel": "^0.6.1", "tsconfig-glob": "^0.4.1", - "tsd-generator": "^2.0.2", - "tslint": "^3.5.0", - "typescript": "^1.8.7", - "validate-commit-msg": "^2.2.0" + "tslint": "next", + "typescript": "1.9.0-dev.20160307", + "validate-commit-msg": "^2.3.1" }, "babel": { "plugins": [ "transform-es2015-parameters", "array-includes" - ], - "env": { - "test": { - "ignore": ["**/out/*.js"], - "plugins": [ - [ - "transform-async-to-module-method", - { - "module": "bluebird", - "method": "coroutine" - } - ], - "transform-es2015-modules-commonjs", - "transform-strict-mode" - ] - } - } + ] }, "ava": { "verbose": true, - "require": [ - "babel-register" + "cache": false, + "files": [ + "test/out/*", + "test/old-cli-test.js", + "test/index.spec.js" ] }, "typings": "./out/electron-builder.d.ts", diff --git a/src/awaiter.ts b/src/awaiter.ts index 070561e4a1f..c7d71a4abe6 100644 --- a/src/awaiter.ts +++ b/src/awaiter.ts @@ -1,5 +1,11 @@ import { Promise as BluebirdPromise } from "bluebird" +import "source-map-support/register" -export function tsAwaiter(thisArg: any, _arguments: any, ignored: any, generator: Function) { +BluebirdPromise.config({ + longStackTraces: true, + cancellation: true +}) + +export = function tsAwaiter(thisArg: any, _arguments: any, ignored: any, generator: Function) { return BluebirdPromise.coroutine(generator).call(thisArg, _arguments) } diff --git a/src/build-cli.ts b/src/build-cli.ts index 4b3a855594b..6b488e0c05e 100644 --- a/src/build-cli.ts +++ b/src/build-cli.ts @@ -5,13 +5,12 @@ import { build } from "./builder" import { PublishOptions } from "./gitHubPublisher" import { commonArgs } from "./util" import { printErrorAndExit } from "./promise" -import { tsAwaiter } from "./awaiter" import cla = require("command-line-args") import { readFileSync } from "fs" import * as path from "path" -const __awaiter = tsAwaiter -Array.isArray(__awaiter) +//noinspection JSUnusedLocalSymbols +const __awaiter = require("./awaiter") interface CliOptions extends PackagerOptions, PublishOptions { help: boolean diff --git a/src/builder.ts b/src/builder.ts index b4961c25e22..39799f0023b 100644 --- a/src/builder.ts +++ b/src/builder.ts @@ -3,12 +3,11 @@ import { PackagerOptions } from "./platformPackager" import { PublishOptions, Publisher, GitHubPublisher } from "./gitHubPublisher" import { executeFinally } from "./promise" import { Promise as BluebirdPromise } from "bluebird" -import { tsAwaiter } from "./awaiter" import { InfoRetriever } from "./repositoryInfo" import { log } from "./util" -const __awaiter = tsAwaiter -Array.isArray(__awaiter) +//noinspection JSUnusedLocalSymbols +const __awaiter = require("./awaiter") export async function createPublisher(packager: Packager, options: BuildOptions, repoSlug: InfoRetriever, isPublishOptionGuessed: boolean = false): Promise { const info = await repoSlug.getInfo(packager) @@ -74,13 +73,13 @@ export function build(options: BuildOptions = {}): Promise { const packager = new Packager(options, repositoryInfo) if (options.publish != null && options.publish !== "never") { let publisher: BluebirdPromise = null - packager.artifactCreated(path => { + packager.artifactCreated((file, platform) => { if (publisher == null) { publisher = >createPublisher(packager, options, repositoryInfo, isPublishOptionGuessed) } if (publisher != null) { - publisher.then(it => publishTasks.push(>it.upload(path))) + publisher.then(it => publishTasks.push(>it.upload(file))) } }) } diff --git a/src/codeSign.ts b/src/codeSign.ts index bbb8d2c84be..233aaa7ecc7 100644 --- a/src/codeSign.ts +++ b/src/codeSign.ts @@ -1,15 +1,13 @@ import { exec } from "./util" -import { deleteFile } from "./promisifed-fs" +import { deleteFile } from "fs-extra-p" import { download } from "./httpRequest" import { tmpdir } from "os" import * as path from "path" import { executeFinally, all } from "./promise" import { Promise as BluebirdPromise } from "bluebird" import { randomBytes } from "crypto" -import { tsAwaiter } from "./awaiter" -const __awaiter = tsAwaiter -Array.isArray(__awaiter) +const __awaiter = require("./awaiter") export interface CodeSigningInfo { cscName: string diff --git a/src/gitHubPublisher.ts b/src/gitHubPublisher.ts index e41fc0a47ea..42813f0d881 100644 --- a/src/gitHubPublisher.ts +++ b/src/gitHubPublisher.ts @@ -3,17 +3,16 @@ import { log } from "./util" import { basename } from "path" import { parse as parseUrl } from "url" import * as mime from "mime" -import { stat } from "./promisifed-fs" +import { stat } from "fs-extra-p" import { createReadStream } from "fs" import { gitHubRequest, HttpError, doGitHubRequest } from "./gitHubRequest" import { Promise as BluebirdPromise } from "bluebird" -import { tsAwaiter } from "./awaiter" import { ReadStream } from "tty" import progressStream = require("progress-stream") import ProgressBar = require("progress") -const __awaiter = tsAwaiter -Array.isArray(__awaiter) +//noinspection JSUnusedLocalSymbols +const __awaiter = require("./awaiter") export interface Publisher { upload(path: string): Promise diff --git a/src/gitHubRequest.ts b/src/gitHubRequest.ts index 8658169364e..9922af03287 100644 --- a/src/gitHubRequest.ts +++ b/src/gitHubRequest.ts @@ -3,9 +3,8 @@ import { RequestOptions } from "https" import { IncomingMessage, ClientRequest } from "http" import { addTimeOutHandler } from "./httpRequest" import { Promise as BluebirdPromise } from "bluebird" -import { tsAwaiter } from "./awaiter" -const __awaiter = tsAwaiter +const __awaiter = require("./awaiter") Array.isArray(__awaiter) export function gitHubRequest(path: string, token: string, data: { [name: string]: any; } = null, method: string = "GET"): BluebirdPromise { diff --git a/src/index.ts b/src/index.ts index 7eea6bc064c..5e438ca26b5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,8 +1,9 @@ import platforms = require("./platforms") import * as path from "path" -import * as fse from "fs-extra" +import * as fs from "fs-extra-p" export { Packager } from "./packager" +export { PackagerOptions, Platform } from "./platformPackager" /** * Prototype for electron-builder @@ -34,9 +35,9 @@ const Builder = { // make sure the output // directory exists - if (!fse.existsSync(options.out)) { + if (!fs.existsSync(options.out)) { options.log("- Output directory ´" + options.out + "´ does not exist ") - fse.mkdirsSync(options.out) + fs.mkdirsSync(options.out) options.log(`- Created '${options.out}`) } diff --git a/src/linuxPackager.ts b/src/linuxPackager.ts index fbf746189a5..47279d97716 100644 --- a/src/linuxPackager.ts +++ b/src/linuxPackager.ts @@ -1,13 +1,12 @@ import * as path from "path" import { Promise as BluebirdPromise } from "bluebird" -import { tsAwaiter } from "./awaiter" import { init } from "../lib/linux" -import { PlatformPackager, BuildInfo } from "./platformPackager" -import { dir as _tpmDir, Options as TmpOptions } from "tmp" +import { PlatformPackager, BuildInfo, Platform } from "./platformPackager" +import { dir as _tpmDir, TmpOptions } from "tmp" import { exec, log } from "./util" import { State as Gm } from "gm" -const __awaiter = tsAwaiter +const __awaiter = require("./awaiter") Array.isArray(__awaiter) const buildDeb = BluebirdPromise.promisify(init().build) @@ -27,6 +26,10 @@ export class LinuxPackager extends PlatformPackager { } } + protected get platform() { + return Platform.LINUX + } + private async computeDesktopIconPath(): Promise> { const tempDir = await tmpDir({ unsafeCleanup: true, @@ -59,10 +62,6 @@ export class LinuxPackager extends PlatformPackager { ] } - getBuildConfigurationKey() { - return "linux" - } - async packageInDistributableFormat(outDir: string, appOutDir: string, arch: string): Promise { const specification: DebOptions = { version: this.metadata.version, diff --git a/src/macPackager.ts b/src/macPackager.ts index d832a1ee106..a63a8280841 100644 --- a/src/macPackager.ts +++ b/src/macPackager.ts @@ -1,11 +1,10 @@ -import { PlatformPackager, BuildInfo } from "./platformPackager" +import { PlatformPackager, BuildInfo, Platform } from "./platformPackager" import * as path from "path" import { Promise as BluebirdPromise } from "bluebird" -import { tsAwaiter } from "./awaiter" import { log, spawn } from "./util" import { createKeychain, deleteKeychain, CodeSigningInfo, generateKeychainName, sign } from "./codeSign" -const __awaiter = tsAwaiter +const __awaiter = require("./awaiter") Array.isArray(__awaiter) export default class MacPackager extends PlatformPackager { @@ -24,8 +23,8 @@ export default class MacPackager extends PlatformPackager } } - getBuildConfigurationKey() { - return "osx" + protected get platform() { + return Platform.OSX } async pack(platform: string, outDir: string, appOutDir: string, arch: string): Promise { @@ -100,7 +99,14 @@ export default class MacPackager extends PlatformPackager const appName = this.metadata.name // -y param is important - "store symbolic links as the link instead of the referenced file" const resultPath = `${appName}-${this.metadata.version}-mac.zip` - return spawn("zip", ["-ryXq", resultPath, appName + ".app"], { + const args = ["-ryXq", resultPath, appName + ".app"] + + // todo move to options + if (process.env.TEST_MODE === "true") { + args.unshift("-0") + } + + return spawn("zip", args, { cwd: outDir, stdio: "inherit", }) diff --git a/src/packager.ts b/src/packager.ts index f4cb83fafd4..93567d350a2 100644 --- a/src/packager.ts +++ b/src/packager.ts @@ -4,15 +4,14 @@ import { DEFAULT_APP_DIR_NAME, installDependencies, log, getElectronVersion, rea import { all, executeFinally } from "./promise" import { EventEmitter } from "events" import { Promise as BluebirdPromise } from "bluebird" -import { tsAwaiter } from "./awaiter" import { AppMetadata, InfoRetriever } from "./repositoryInfo" -import { PackagerOptions, PlatformPackager, BuildInfo, DevMetadata } from "./platformPackager" +import { PackagerOptions, PlatformPackager, BuildInfo, DevMetadata, Platform } from "./platformPackager" import MacPackager from "./macPackager" import WinPackager from "./winPackager" import * as errorMessages from "./errorMessages" import * as util from "util" -const __awaiter = tsAwaiter +const __awaiter = require("./awaiter") Array.isArray(__awaiter) function addHandler(emitter: EventEmitter, event: string, handler: Function) { @@ -39,7 +38,7 @@ export class Packager implements BuildInfo { this.appDir = this.computeAppDirectory() } - artifactCreated(handler: (path: string) => void): Packager { + artifactCreated(handler: (file: string, platform: Platform) => void): Packager { addHandler(this.eventEmitter, "artifactCreated", handler) return this } @@ -52,7 +51,7 @@ export class Packager implements BuildInfo { const buildPackageFile = this.devPackageFile const appPackageFile = this.projectDir === this.appDir ? buildPackageFile : path.join(this.appDir, "package.json") const platforms = normalizePlatforms(this.options.platform) - await BluebirdPromise.all(Array.from(new Set([buildPackageFile, appPackageFile]), readPackageJson)) + await BluebirdPromise.map(Array.from(new Set([buildPackageFile, appPackageFile])), readPackageJson) .then(result => { this.metadata = result[result.length - 1] this.devMetadata = result[0] diff --git a/src/platformPackager.ts b/src/platformPackager.ts index d5027e41fe5..8935693864b 100644 --- a/src/platformPackager.ts +++ b/src/platformPackager.ts @@ -1,15 +1,27 @@ import { AppMetadata, InfoRetriever, ProjectMetadataProvider, Metadata } from "./repositoryInfo" import EventEmitter = NodeJS.EventEmitter -import { tsAwaiter } from "./awaiter" import { Promise as BluebirdPromise } from "bluebird" import * as path from "path" import packager = require("electron-packager-tf") -const __awaiter = tsAwaiter -Array.isArray(__awaiter) +//noinspection JSUnusedLocalSymbols +const __awaiter = require("./awaiter") const pack = BluebirdPromise.promisify(packager) +export class Platform { + public static OSX = new Platform("osx", "osx") + public static LINUX = new Platform("linux", "linux") + public static WINDOWS = new Platform("windows", "win") + + constructor(public name: string, public buildConfigurationKey: string) { + } + + toString() { + return this.name + } +} + export interface DevMetadata extends Metadata { build: DevBuildMetadata @@ -70,7 +82,7 @@ export abstract class PlatformPackager implements ProjectMetadataProvider { customDistOptions: DC - protected abstract getBuildConfigurationKey(): string + protected abstract get platform(): Platform constructor(protected info: BuildInfo) { this.options = info.options @@ -82,7 +94,7 @@ export abstract class PlatformPackager implements ProjectMetadataProvider { if (this.options.dist) { const buildMetadata: any = info.devMetadata.build - this.customDistOptions = buildMetadata == null ? buildMetadata : buildMetadata[this.getBuildConfigurationKey()] + this.customDistOptions = buildMetadata == null ? buildMetadata : buildMetadata[this.platform.buildConfigurationKey] } } @@ -91,8 +103,8 @@ export abstract class PlatformPackager implements ProjectMetadataProvider { return (directories == null ? null : directories.buildResources) || "build" } - protected dispatchArtifactCreated(path: string) { - this.info.eventEmitter.emit("artifactCreated", path) + protected dispatchArtifactCreated(file: string) { + this.info.eventEmitter.emit("artifactCreated", file, this.platform) } pack(platform: string, outDir: string, appOutDir: string, arch: string): Promise { diff --git a/src/promise.ts b/src/promise.ts index 7677d68e236..ee811fdb2ea 100644 --- a/src/promise.ts +++ b/src/promise.ts @@ -1,7 +1,6 @@ import { Promise as BluebirdPromise } from "bluebird" -import { tsAwaiter } from "./awaiter" -const __awaiter = tsAwaiter +const __awaiter = require("./awaiter") Array.isArray(__awaiter) export function printErrorAndExit(error: Error) { diff --git a/src/promisifed-fs.ts b/src/promisifed-fs.ts index 399e0131ee5..c4f8e695bd8 100644 --- a/src/promisifed-fs.ts +++ b/src/promisifed-fs.ts @@ -1,34 +1,8 @@ -import * as fs from "fs-extra" +import * as fs from "fs-extra-p" import { Promise as BluebirdPromise } from "bluebird" const readFileAsync: ((filename: string, encoding?: string) => Promise) = BluebirdPromise.promisify(fs.readFile) export function readText(file: string): BluebirdPromise { return >readFileAsync(file, "utf8") -} - -export function deleteFile(path: string, ignoreIfNotExists: boolean = false): BluebirdPromise { - return new BluebirdPromise((resolve, reject) => { - fs.unlink(path, it => it == null || (ignoreIfNotExists && it.code === "ENOENT") ? resolve(null) : reject(it)) - }) -} - -// returns new name -export function renameFile(oldPath: string, newPath: string): BluebirdPromise { - return new BluebirdPromise((resolve, reject) => { - fs.rename(oldPath, newPath, error => error == null ? resolve(newPath) : reject(error)) - }) -} - -// returns copied name -export function copyFile(src: string, dest: string): BluebirdPromise { - return new BluebirdPromise((resolve, reject) => { - fs.copy(src, dest, error => error == null ? resolve(dest) : reject(error)) - }) -} - -const statFileAsync = BluebirdPromise.promisify(fs.stat) - -export function stat(path: string): BluebirdPromise { - return statFileAsync(path) } \ No newline at end of file diff --git a/src/repositoryInfo.ts b/src/repositoryInfo.ts index dac2535f32d..e0055e6dcdf 100644 --- a/src/repositoryInfo.ts +++ b/src/repositoryInfo.ts @@ -1,9 +1,8 @@ -import { tsAwaiter } from "./awaiter" import { fromUrl as parseRepositoryUrl, Info } from "hosted-git-info" import { readText } from "./promisifed-fs" import * as path from "path" -const __awaiter = tsAwaiter +const __awaiter = require("./awaiter") Array.isArray(__awaiter) export interface RepositoryInfo { @@ -47,7 +46,7 @@ export interface RepositorySlug { export class InfoRetriever { _info: Promise - getInfo(provider: ProjectMetadataProvider): Promise { + getInfo(provider?: ProjectMetadataProvider): Promise { if (this._info == null) { this._info = getInfo(provider) } @@ -83,8 +82,8 @@ async function getGitUrlFromGitConfig(): Promise { return null } -async function getInfo(provider: ProjectMetadataProvider): Promise { - const repo = provider.devMetadata.repository || provider.metadata.repository +async function getInfo(provider?: ProjectMetadataProvider): Promise { + const repo = provider == null ? null : (provider.devMetadata.repository || provider.metadata.repository) if (repo == null) { let url = process.env.TRAVIS_REPO_SLUG if (url == null) { diff --git a/src/util.ts b/src/util.ts index 546300b68bb..ce76f633131 100644 --- a/src/util.ts +++ b/src/util.ts @@ -1,15 +1,9 @@ import { execFile, spawn as _spawn } from "child_process" import { Promise as BluebirdPromise } from "bluebird" -import "source-map-support/register" import readPackageJsonAsync = require("read-package-json") export const log = console.log -BluebirdPromise.config({ - longStackTraces: true, - cancellation: true -}) - export const DEFAULT_APP_DIR_NAME = "app" export const commonArgs: any[] = [{ diff --git a/src/winPackager.ts b/src/winPackager.ts index 5f1c29f9061..a989c375102 100644 --- a/src/winPackager.ts +++ b/src/winPackager.ts @@ -1,18 +1,13 @@ import { downloadCertificate } from "./codeSign" import { Promise as BluebirdPromise } from "bluebird" -import { tsAwaiter } from "./awaiter" -import { PlatformPackager, BuildInfo } from "./platformPackager" +import { PlatformPackager, BuildInfo, Platform } from "./platformPackager" import * as path from "path" -import { Stats } from "fs" import { log } from "./util" -import { deleteFile, stat, renameFile, copyFile } from "./promisifed-fs" -import * as fse from "fs-extra" +import { deleteFile, stat, rename, copy, emptyDir, Stats } from "fs-extra-p" -const __awaiter = tsAwaiter +const __awaiter = require("./awaiter") Array.isArray(__awaiter) -const emptyDir = BluebirdPromise.promisify(fse.emptyDir) - export default class WinPackager extends PlatformPackager { certFilePromise: Promise isNsis: boolean @@ -45,8 +40,8 @@ export default class WinPackager extends PlatformPackager { } } - getBuildConfigurationKey() { - return "win" + protected get platform() { + return Platform.WINDOWS } pack(platform: string, outDir: string, appOutDir: string, arch: string): Promise { @@ -135,9 +130,9 @@ export default class WinPackager extends PlatformPackager { } const promises = [ - renameFile(path.join(installerOutDir, "Setup.exe"), installerExePath) + rename(path.join(installerOutDir, "Setup.exe"), installerExePath) .then(it => this.dispatchArtifactCreated(it)), - renameFile(path.join(installerOutDir, appName + "-" + version + "-full.nupkg"), path.join(installerOutDir, appName + "-" + version + archSuffix + "-full.nupkg")) + rename(path.join(installerOutDir, appName + "-" + version + "-full.nupkg"), path.join(installerOutDir, appName + "-" + version + archSuffix + "-full.nupkg")) .then(it => this.dispatchArtifactCreated(it)) ] @@ -145,7 +140,7 @@ export default class WinPackager extends PlatformPackager { this.dispatchArtifactCreated(path.join(installerOutDir, "RELEASES")) } else { - promises.push(copyFile(path.join(installerOutDir, "RELEASES"), path.join(installerOutDir, "RELEASES-ia32")) + promises.push(copy(path.join(installerOutDir, "RELEASES"), path.join(installerOutDir, "RELEASES-ia32")) .then(it => this.dispatchArtifactCreated(it))) } diff --git a/test/helpers/codeSignData.js b/test/helpers/codeSignData.js deleted file mode 100644 index a4a9121a44a..00000000000 --- a/test/helpers/codeSignData.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports.CSC_LINK = "https://www.dropbox.com/s/86zaffzbao198xe/test.p12?dl=1" -module.exports.CSC_KEY_PASSWORD = "password" -module.exports.CSC_NAME = "Test Test" \ No newline at end of file diff --git a/test/helpers/packTester.js b/test/helpers/packTester.js deleted file mode 100644 index 1b9c8cb14e8..00000000000 --- a/test/helpers/packTester.js +++ /dev/null @@ -1,109 +0,0 @@ -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 { normalizePlatforms } from "out/packager" -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, packagerOptions, 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 platforms = Array.isArray(platform) ? platform : [platform] - const packager = new Packager(Object.assign({ - projectDir: projectDir, - cscLink: CSC_LINK, - cscKeyPassword: CSC_KEY_PASSWORD, - dist: true, - platform: platforms, - }, packagerOptions)) - - let artifacts = [] - packager.artifactCreated(it => { - artifacts.push(path.basename(it)) - }) - - await packager.build() - - artifacts = pathSorter(artifacts) - const expandedPlatforms = normalizePlatforms(platforms) - - if (expandedPlatforms.includes("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 (expandedPlatforms.includes("linux")) { - assertThat(await getContents(projectDir + "/dist/TestApp-1.0.0-amd64.deb")).deepEqual(expectedLinuxContents) - if (packagerOptions == null || packagerOptions.arch === null || packagerOptions.arch === "ia32") { - 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)) - } - else if (expandedPlatforms.includes("win32") && (packagerOptions == null || packagerOptions.target == null)) { - const expected32 = [ - "RELEASES-ia32", - "TestApp-1.0.0-full.nupkg", - "TestAppSetup-1.0.0.exe" - ] - const expected64 = [ - "RELEASES", - "TestAppSetup-1.0.0-x64.exe", - "TestApp-1.0.0-x64-full.nupkg" - ] - let expected - if (packagerOptions != null && packagerOptions.arch === "x64") { - expected = expected64 - } - else { - expected = expected32.concat(expected64) - } - assertThat(artifacts).deepEqual(pathSorter(expected)) - } -} - -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/index.spec.js b/test/index.spec.js similarity index 79% rename from index.spec.js rename to test/index.spec.js index a153710695c..1e1373cf493 100644 --- a/index.spec.js +++ b/test/index.spec.js @@ -7,7 +7,7 @@ * Licensed under the MIT license. */ -var test = require( 'tape' ); +var test = require( 'ava-tf' ); var tmp = require( 'tmp' ); var fs = require( 'fs' ); var proxyquire = require( 'proxyquire' ); @@ -17,21 +17,21 @@ test( 'Builder.init', function( t ) { t.plan( 2 ); var Builder = proxyquireStrict( - './out/index.js', + 'out', { './platforms' : {} } ); - t.equal( typeof Builder.init, 'function' ); - t.equal( typeof Builder.init().build, 'function' ); + t.is( typeof Builder.init, 'function' ); + t.is( typeof Builder.init().build, 'function' ); } ); -test( 'Builder.init().build - call the correct platform', function( t ) { +test.cb( 'Builder.init().build - call the correct platform', function( t ) { t.plan( 2 ); var Builder = proxyquireStrict( - './out/index.js', + 'out', { './platforms' : function( platform ) { if ( platform === 'bar' ) { @@ -58,19 +58,19 @@ test( 'Builder.init().build - call the correct platform', function( t ) { log : function() {} }, function( error, result ) { - t.equal( error, null ); - t.equal( result, 'foo' ); + t.is( error, null ); + t.is( result, 'foo' ); t.end(); } ); } ); -test( 'Builder.init().build - create output directory if not present', function( t ) { +test.cb( 'Builder.init().build - create output directory if not present', function( t ) { t.plan( 1 ); var tmpDir = tmp.dirSync( { unsafeCleanup : true } ); var Builder = proxyquireStrict( - './out/index.js', + 'out', { './platforms' : function( platform ) { if ( platform === 'bar' ) { @@ -98,7 +98,7 @@ test( 'Builder.init().build - create output directory if not present', function( log : function() {} }, function( error, result ) { - t.equal( fs.existsSync( tmpDir.name + '/foo' ), true ); + t.is( fs.existsSync( tmpDir.name + '/foo' ), true ); tmpDir.removeCallback(); @@ -111,7 +111,7 @@ test( 'Builder.init().build - check for required options', function( t ) { t.plan( 5 ); var Builder = proxyquireStrict( - './out/index.js', + 'out', { './platforms' : {} } @@ -125,7 +125,7 @@ test( 'Builder.init().build - check for required options', function( t ) { log : function() {} }, function( error ) { - t.equal( error.message, 'Required option not set' ); + t.is( error.message, 'Required option not set' ); } ); @@ -137,7 +137,7 @@ test( 'Builder.init().build - check for required options', function( t ) { log : function() {} }, function( error ) { - t.equal( error.message, 'Required option not set' ); + t.is( error.message, 'Required option not set' ); } ); @@ -149,7 +149,7 @@ test( 'Builder.init().build - check for required options', function( t ) { log : function() {} }, function( error ) { - t.equal( error.message, 'Required option not set' ); + t.is( error.message, 'Required option not set' ); } ); @@ -161,7 +161,7 @@ test( 'Builder.init().build - check for required options', function( t ) { log : function() {} }, function( error ) { - t.equal( error.message, 'Required option not set' ); + t.is( error.message, 'Required option not set' ); } ); @@ -174,7 +174,7 @@ test( 'Builder.init().build - check for required options', function( t ) { log : function() {} }, function( error ) { - t.equal( + t.is( error.message, 'No config property found for `baz`.\nPlease check your configuration file and the documentation.' ); diff --git a/test/old-cli-test.js b/test/old-cli-test.js deleted file mode 100644 index 5eca2f649ab..00000000000 --- a/test/old-cli-test.js +++ /dev/null @@ -1,53 +0,0 @@ -'use strict'; - -const Promise = require("bluebird") -const test = require('ava-tf') -const fs = Promise.promisifyAll(require('fs-extra')) -const execFileAsync = Promise.promisify(require('child_process').execFile) -const path = require('path') - -const exampleAppPath = path.join(__dirname, '..', 'example-app') -const cliPath = path.join(process.env.NODE_PATH, '..', '.bin', 'electron-builder') + (process.platform === "win32" ? ".cmd" : "") - -function exec(args) { - return execFileAsync(cliPath, args, { - cwd: exampleAppPath, - shell: process.platform === "win32" - }) -} - -test('Cli - no input', t => { - t.throws(exec([]), /Path to electron app not provided/) -}) - -test('Cli - config file provided but not found', t => { - t.throws(exec(['Example.app', '--platform=osx', '--config=no-builder.json']), /Could not load config file/) -}) - -if (process.platform === "darwin") { - test('Cli - osx - config file provided', async t => { - await exec(['Example.app', '--platform=osx', '--config=builder.json']) - t.ok(await fs.statAsync(exampleAppPath + '/Builder\ Config\ osx\ Example.dmg'), 'dmg created') - await fs.removeAsync(exampleAppPath + '/Builder\ Config\ osx\ Example.dmg') - }) - - test('Cli - osx - no config file provided', async t => { - await exec(['Example.app', '--platform=osx']) - t.ok(await fs.statAsync(exampleAppPath + '/Electron\ Builder\ Example.dmg'), 'dmg created') - await fs.removeAsync(exampleAppPath + '/Electron\ Builder\ Example.dmg') - }) -} - -if (!process.env.CI || process.platform === "win32") { - 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.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')) - }) -} \ No newline at end of file diff --git a/test/ArtifactPublisherTest.js b/test/src/ArtifactPublisherTest.ts similarity index 69% rename from test/ArtifactPublisherTest.js rename to test/src/ArtifactPublisherTest.ts index dbe922404a7..adccee0b508 100644 --- a/test/ArtifactPublisherTest.js +++ b/test/src/ArtifactPublisherTest.ts @@ -1,8 +1,12 @@ import test from "ava-tf" import { GitHubPublisher } from "out/gitHubPublisher" +import { HttpError } from "out/gitHubRequest" import { join } from "path" -function getRandomInt(min, max) { +//noinspection JSUnusedLocalSymbols +const __awaiter = require("out/awaiter") + +function getRandomInt(min: number, max: number) { return Math.floor(Math.random() * (max - min + 1)) + min } @@ -11,18 +15,23 @@ function versionNumber() { } const token = new Buffer("Y2Y5NDdhZDJhYzJlMzg1OGNiNzQzYzcwOWZhNGI0OTk2NWQ4ZDg3Yg==", "base64").toString() -const iconPath = join(__dirname, "fixtures", "test-app", "build", "icon.icns") +const iconPath = join(__dirname, "..", "fixtures", "test-app", "build", "icon.icns") //test("GitHub unauthorized", async (t) => { // t.throws(await new GitHubPublisher("github-releases-test", "test-repo", versionNumber(), "incorrect token") // .releasePromise, /(Bad credentials|Unauthorized|API rate limit exceeded)/) //}) -function isApiRateError(e) { - return e.description != null && e.description.message != null && e.description.message.includes("API rate limit exceeded") +function isApiRateError(e: Error): boolean { + if (e instanceof HttpError) { + return e.description != null && e instanceof HttpError && e.description.message != null && e.description.message.includes("API rate limit exceeded") + } + else { + return false + } } -function testAndIgnoreApiRate(name, testFunction) { +function testAndIgnoreApiRate(name: string, testFunction: () => Promise) { test(name, async () => { try { await testFunction() diff --git a/test/BuildTest.js b/test/src/BuildTest.ts similarity index 55% rename from test/BuildTest.js rename to test/src/BuildTest.ts index 761e1ef20d6..159ba7e4e38 100644 --- a/test/BuildTest.js +++ b/test/src/BuildTest.ts @@ -1,29 +1,27 @@ import test from "./helpers/avaEx" import { assertPack } from "./helpers/packTester" -import fse from "fs-extra" -import Promise from "bluebird" +import { move, writeJson, readJson } from "fs-extra-p" +import { Promise as BluebirdPromise } from "bluebird" import * as path from "path" -import { readText } from "out/promisifed-fs" -import { parse as parseJson } from "json-parse-helpfulerror" -const writeFile = Promise.promisify(fse.writeFile) -const moveFile = Promise.promisify(fse.move) +//noinspection JSUnusedLocalSymbols +const __awaiter = require("out/awaiter") if (process.env.TRAVIS !== "true") { // we don't use CircleCI, so, we can safely set this env process.env.CIRCLE_BUILD_NUM = 42 } -test.ifOsx("mac: two-package.json", async function () { +test.ifOsx("mac: two-package.json", async () => { await assertPack("test-app", "darwin") }) -test.ifOsx("mac: one-package.json", async function () { +test.ifOsx("mac: one-package.json", async () => { await assertPack("test-app-one", "darwin") }) -test("custom app dir", async function () { - let platforms +test("custom app dir", async () => { + let platforms: Array if (process.platform === "darwin") { platforms = ["darwin", "linux"] } @@ -38,16 +36,16 @@ test("custom app dir", async function () { await assertPack("test-app-one", platforms, { // speed up tests, we don't need check every arch arch: process.arch - }, true, async projectDir => { + }, true, async (projectDir) => { const file = path.join(projectDir, "package.json") - const data = parseJson(await readText(file)) + const data = await readJson(file) data.directories = { buildResources: "custom" } - return Promise.all([ - writeFile(file, JSON.stringify(data, null, 2)), - moveFile(path.join(projectDir, "build"), path.join(projectDir, "custom")) + return await BluebirdPromise.all([ + writeJson(file, data, {spaces: 2}), + move(path.join(projectDir, "build"), path.join(projectDir, "custom")) ]) }) }) diff --git a/test/CodeSignTest.js b/test/src/CodeSignTest.ts similarity index 51% rename from test/CodeSignTest.js rename to test/src/CodeSignTest.ts index 7038f70adba..619fe64c18c 100644 --- a/test/CodeSignTest.js +++ b/test/src/CodeSignTest.ts @@ -1,14 +1,17 @@ import { createKeychain, deleteKeychain, generateKeychainName } from "out/codeSign" -import assertThat from "should/as-function" +import * as assertThat from "should/as-function" import test from "./helpers/avaEx" import { CSC_NAME, CSC_LINK, CSC_KEY_PASSWORD } from "./helpers/codeSignData" -import promises from "out/promise" +import { executeFinally, all } from "out/promise" -test.ifOsx("create keychain", async () => { +//noinspection JSUnusedLocalSymbols +const __awaiter = require("out/awaiter") + +test.ifOsx("create keychain", async (t) => { const keychainName = generateKeychainName() - await promises.executeFinally(createKeychain(keychainName, CSC_LINK, CSC_KEY_PASSWORD) + await executeFinally(createKeychain(keychainName, CSC_LINK, CSC_KEY_PASSWORD) .then(result => { assertThat(result.cscKeychainName).not.empty() assertThat(result.cscName).equal(CSC_NAME) - }), () => promises.all([deleteKeychain(keychainName)])) + }), () => all([deleteKeychain(keychainName)])) }) \ No newline at end of file diff --git a/test/RepoSlugTest.js b/test/src/RepoSlugTest.ts similarity index 75% rename from test/RepoSlugTest.js rename to test/src/RepoSlugTest.ts index 95acf057827..56824d2fe06 100644 --- a/test/RepoSlugTest.js +++ b/test/src/RepoSlugTest.ts @@ -1,12 +1,17 @@ import { InfoRetriever } from "out/repositoryInfo" -import assertThat from "should/as-function" +import { Info } from "hosted-git-info" +import * as assertThat from "should/as-function" import test from "ava-tf" +import { Promise as BluebirdPromise } from "bluebird" + +//noinspection JSUnusedLocalSymbols +const __awaiter = require("out/awaiter") test("repo slug from TRAVIS_REPO_SLUG", () => { const oldValue = process.env.TRAVIS_REPO_SLUG try { process.env.TRAVIS_REPO_SLUG = "travis-ci/travis-build" - const info = (new InfoRetriever()).getInfo({devMetadata: {}, metadata: {}}).value() + const info = (>(new InfoRetriever()).getInfo()).value() assertThat(info).has.properties({ user: "travis-ci", project: "travis-build", @@ -19,7 +24,7 @@ test("repo slug from TRAVIS_REPO_SLUG", () => { } }) -function restoreEnv(name, value) { +function restoreEnv(name: string, value: string) { if (value != null) { // otherwise will be set to string value "undefined" process.env[name] = value @@ -37,7 +42,7 @@ test("repo slug from APPVEYOR", () => { process.env.APPVEYOR_ACCOUNT_NAME = "travis-ci" process.env.APPVEYOR_PROJECT_NAME = "travis-build" - const info = (new InfoRetriever()).getInfo({devMetadata: {}, metadata: {}}).value() + const info = (>(new InfoRetriever()).getInfo()).value() assertThat(info).has.properties({ user: "travis-ci", project: "travis-build", diff --git a/test/helpers/avaEx.js b/test/src/helpers/avaEx.ts similarity index 59% rename from test/helpers/avaEx.js rename to test/src/helpers/avaEx.ts index f5a03efb35c..b3623d54e62 100644 --- a/test/helpers/avaEx.js +++ b/test/src/helpers/avaEx.ts @@ -1,5 +1,18 @@ import test from "ava-tf" +declare module "ava-tf" { + namespace test { + export const ifNotWindows: typeof test; + export const ifOsx: typeof test; + export const ifNotCi: typeof test; + export const ifNotTravis: typeof test; + } + + interface AssertContext { + throws(value: (() => void) | Promise, error?: ErrorValidator, message?: string): void + } +} + Object.defineProperties(test, { "ifNotWindows": { get: function () { diff --git a/test/src/helpers/codeSignData.ts b/test/src/helpers/codeSignData.ts new file mode 100644 index 00000000000..f41aed0c1bd --- /dev/null +++ b/test/src/helpers/codeSignData.ts @@ -0,0 +1,3 @@ +export const CSC_LINK = "https://www.dropbox.com/s/86zaffzbao198xe/test.p12?dl=1" +export const CSC_KEY_PASSWORD = "password" +export const CSC_NAME = "Test Test" \ No newline at end of file diff --git a/test/helpers/expectedContents.js b/test/src/helpers/expectedContents.ts similarity index 100% rename from test/helpers/expectedContents.js rename to test/src/helpers/expectedContents.ts diff --git a/test/src/helpers/packTester.ts b/test/src/helpers/packTester.ts new file mode 100644 index 00000000000..4782f477839 --- /dev/null +++ b/test/src/helpers/packTester.ts @@ -0,0 +1,139 @@ +import { copy, emptyDir, remove } from "fs-extra-p" +import * as 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, PackagerOptions, Platform } from "out" +import { normalizePlatforms } from "out/packager" +import { exec } from "out/util" +import pathSorter = require("path-sort") +import { tmpdir } from "os" + +//noinspection JSUnusedLocalSymbols +const __awaiter = require("out/awaiter") + +const tmpDirPrefix = "electron-builder-test-" + process.pid + "-" +let tmpDirCounter = 0 + +export async function assertPack(fixtureName: string, platform: string | Array, packagerOptions?: PackagerOptions, useTempDir?: boolean, tempDirCreated?: (projectDir: string) => Promise) { + let projectDir = path.join(__dirname, "..", "..", "fixtures", fixtureName) + // 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 = path.join(tmpdir(), tmpDirPrefix + fixtureName + tmpDirCounter++) + await emptyDir(dir) + await copy(projectDir, dir, { + filter: it => { + const basename = path.basename(it) + return basename !== "dist" && basename !== "node_modules" && basename[0] !== "." + } + }) + projectDir = dir + } + + try { + if (tempDirCreated != null) { + await tempDirCreated(projectDir) + } + + const platforms = Array.isArray(platform) ? platform : [platform] + await packAndCheck(projectDir, platforms, packagerOptions) + } + finally { + if (useTempDir) { + try { + await remove(projectDir) + } + catch (e) { + console.warn("Cannot delete temporary directory " + projectDir + ": " + (e.stack || e)) + } + } + } +} + +async function packAndCheck(projectDir: string, platforms: string[], packagerOptions?: PackagerOptions) { + const packager = new Packager(Object.assign({ + projectDir: projectDir, + cscLink: CSC_LINK, + cscKeyPassword: CSC_KEY_PASSWORD, + dist: true, + platform: platforms, + }, packagerOptions)) + + const artifacts: Map> = new Map() + packager.artifactCreated((file, platform) => { + let list = artifacts.get(platform) + if (list == null) { + list = [] + artifacts.set(platform, list) + } + list.push(path.basename(file)) + }) + + await packager.build() + + for (let key of artifacts.keys()) { + artifacts.set(key, pathSorter(artifacts.get(key))) + } + + const expandedPlatforms = normalizePlatforms(platforms) + if (expandedPlatforms.includes("darwin")) { + await checkOsXResult(projectDir, artifacts.get(Platform.OSX)) + } + else if (expandedPlatforms.includes("linux")) { + assertThat(await getContents(projectDir + "/dist/TestApp-1.0.0-amd64.deb")).deepEqual(expectedLinuxContents) + if (packagerOptions == null || packagerOptions.arch === null || packagerOptions.arch === "ia32") { + 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)) + } + else if (expandedPlatforms.includes("win32") && (packagerOptions == null || packagerOptions.target == null)) { + checkWindowsResult(packagerOptions, artifacts.get(Platform.WINDOWS)) + } +} + +async function checkOsXResult(projectDir: string, artifacts: Array) { + 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/) + + assertThat(artifacts).deepEqual(pathSorter([ + "TestApp-1.0.0-mac.zip", + "TestApp-1.0.0.dmg" + ])) +} + +function checkWindowsResult(packagerOptions: PackagerOptions, artifacts: Array) { + const expected32 = [ + "RELEASES-ia32", + "TestApp-1.0.0-full.nupkg", + "TestAppSetup-1.0.0.exe" + ] + const expected64 = [ + "RELEASES", + "TestAppSetup-1.0.0-x64.exe", + "TestApp-1.0.0-x64-full.nupkg" + ] + const expected = packagerOptions != null && packagerOptions.arch === "x64" ? expected64 : expected32.concat(expected64) + assertThat(artifacts).deepEqual(pathSorter(expected)) +} + +async function getContents(path: string) { + const result = await exec("dpkg", ["--contents", path]) + return pathSorter(result[0].toString() + .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/src/helpers/runTests.ts similarity index 62% rename from test/helpers/runTests.js rename to test/src/helpers/runTests.ts index 0cef97f36da..23d4f48b4f2 100644 --- a/test/helpers/runTests.js +++ b/test/src/helpers/runTests.ts @@ -1,23 +1,25 @@ -"use strict" +import { spawn } from "child_process" +import * as path from "path" +import { Promise as BluebirdPromise } from "bluebird" +import * as fs from "fs-extra-p" -const childProcess = require("child_process") -const path = require("path") -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") +// we set NODE_PATH in this file, so, we cannot use 'out/awaiter' path here +//noinspection JSUnusedLocalSymbols +const __awaiter = require("../../../out/awaiter") -const rootDir = path.join(__dirname, "..", "..") +const downloadElectron: (options: any) => Promise = BluebirdPromise.promisify(require("electron-download")) +const packager = require("../../../out/packager") + +const rootDir = path.join(__dirname, "..", "..", "..") const testPackageDir = path.join(require("os").tmpdir(), "electron_builder_published") const testNodeModules = path.join(testPackageDir, "node_modules") const electronVersion = "0.36.9" -Promise.all([ +BluebirdPromise.all([ deleteOldElectronVersion(), downloadAllRequiredElectronVersions(), - fs.outputFileAsync(path.join(testPackageDir, "package.json"), `{ + fs.outputFile(path.join(testPackageDir, "package.json"), `{ "private": true, "version": "1.0.0", "name": "test", @@ -29,14 +31,14 @@ Promise.all([ ]) .then(() => install()) .catch(error => { - console.error(error) + console.error(error.stack || error) process.exit(1) }) -function deleteOldElectronVersion() { +function deleteOldElectronVersion(): Promise { if (process.env.CI) { const cacheDir = path.join(require("os").homedir(), ".electron") - return fs.readdirAsync(cacheDir) + return fs.readdir(cacheDir) .catch(error => { if (error.code === "ENOENT") { return [] @@ -46,23 +48,23 @@ function deleteOldElectronVersion() { } }) .then(it => { - const deletePromises = [] + const deletePromises: Array> = [] 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))) + deletePromises.push(fs.unlink(path.join(cacheDir, file))) } } - return Promise.all(deletePromises) + return BluebirdPromise.all(deletePromises) }) } else { - return Promise.resolve() + return BluebirdPromise.resolve() } } -function downloadAllRequiredElectronVersions() { - const downloadPromises = [] +function downloadAllRequiredElectronVersions(): Promise { + const downloadPromises: Array> = [] for (let platform of packager.normalizePlatforms(["all"])) { for (let arch of packager.normalizeArchs(platform)) { downloadPromises.push(downloadElectron({ @@ -72,15 +74,15 @@ function downloadAllRequiredElectronVersions() { })) } } - return Promise.all(downloadPromises) + return BluebirdPromise.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) + return fs.emptyDir(testNodeModules) + .then(() => fs.readJson(path.join(rootDir, "package.json"), "utf-8")) + .then((it: any) => { + const devDeps = Object.keys(it.devDependencies) const filtered = new Set() /*eslint prefer-const: 0*/ for (let name of devDeps) { @@ -89,7 +91,7 @@ function copyDependencies() { filtered.add(path.join(rootDir, "node_modules", ".bin")) - return fs.copyAsync(path.join(rootDir, "node_modules"), testNodeModules, { + return fs.copy(path.join(rootDir, "node_modules"), testNodeModules, { filter: it => { if (it.includes("node_modules" + path.sep + "babel-")) { return false @@ -100,29 +102,29 @@ function copyDependencies() { }) } -function install() { +function install(): void { // 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", rootDir], () => { + exec("npm", ["install", "--cache-min", "999999999", "--production", rootDir], () => { // prune stale packages - spawn("npm", ["prune", "--production"], () => { + exec("npm", ["prune", "--production"], () => { runTests() }) }) } -function runTests() { - spawn("npm", ["run", "test-" + (process.platform === "win32" ? "win" : "nix")], () => { +function runTests(): void { + exec("npm", ["run", "test-" + (process.platform === "win32" ? "win" : "nix")], () => { }, { cwd: path.join(__dirname, "..", ".."), env: Object.assign({}, process.env, { NODE_PATH: path.join(testNodeModules, "electron-builder"), - BABEL_ENV: "test", + TEST_MODE: "true", }) }) } -function spawn(command, args, callback, options) { +function exec(command: string, args: Array, callback: () => void, options?: any) { if (command === "npm") { const npmExecPath = process.env.npm_execpath || process.env.NPM_CLI_JS if (npmExecPath != null) { @@ -136,8 +138,8 @@ function spawn(command, args, callback, options) { cwd: testPackageDir, }, options) console.log("Execute " + command + " " + args.join(" ") + " (cwd: " + effectiveOptions.cwd + ")") - const child = childProcess.spawn(command, args, effectiveOptions) - child.on("close", code => { + const child = spawn(command, args, effectiveOptions) + child.on("close", (code: number) => { if (code === 0) { callback() } @@ -156,7 +158,7 @@ function spawn(command, args, callback, options) { process.exit(1) } }) - child.on("error", error => { + child.on("error", (error: Error) => { console.error(`Failed to start child process: ${command} ${args.join(" ")}` + (error.stack || error)) process.exit(1) }) diff --git a/test/linuxPackagerTest.js b/test/src/linuxPackagerTest.ts similarity index 57% rename from test/linuxPackagerTest.js rename to test/src/linuxPackagerTest.ts index 90ff853be73..ededfa22d90 100644 --- a/test/linuxPackagerTest.js +++ b/test/src/linuxPackagerTest.ts @@ -1,10 +1,13 @@ import test from "./helpers/avaEx" import { assertPack } from "./helpers/packTester" -test.ifNotWindows("linux", async function () { +//noinspection JSUnusedLocalSymbols +const __awaiter = require("out/awaiter") + +test.ifNotWindows("linux", async () => { await assertPack("test-app-one", "linux") }) -test.ifNotWindows("no-author-email", async(t) => { +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/src/old-cli-test.ts b/test/src/old-cli-test.ts new file mode 100644 index 00000000000..2f46164be56 --- /dev/null +++ b/test/src/old-cli-test.ts @@ -0,0 +1,54 @@ +import { Promise as BluebirdPromise } from "bluebird" +import test from "./helpers/avaEx" +import { stat, remove } from "fs-extra-p" +const execFileAsync: (path: string, args: Array, options?: any) => Promise = BluebirdPromise.promisify(require("child_process").execFile) +import * as path from "path" + +//noinspection JSUnusedLocalSymbols +const __awaiter = require("out/awaiter") + +const exampleAppPath = path.join(__dirname, "..", "..", "example-app") +const cliPath = path.join(process.env.NODE_PATH, "..", ".bin", "electron-builder") + (process.platform === "win32" ? ".cmd" : "") + +function exec(args: Array): Promise { + return execFileAsync(cliPath, args, { + cwd: exampleAppPath, + shell: process.platform === "win32" + }) +} + +test('Cli - no input', t => { + t.throws(exec([]), /Path to electron app not provided/) +}) + +test('Cli - config file provided but not found', t => { + t.throws(exec(['Example.app', '--platform=osx', '--config=no-builder.json']), /Could not load config file/) +}) + +if (process.platform === "darwin") { + test('Cli - osx - config file provided', async (t) => { + await exec(['Example.app', '--platform=osx', '--config=builder.json']) + t.ok(await stat(exampleAppPath + '/Builder\ Config\ osx\ Example.dmg'), 'dmg created') + await remove(exampleAppPath + '/Builder\ Config\ osx\ Example.dmg') + }) + + test('Cli - osx - no config file provided', async (t) => { + await exec(['Example.app', '--platform=osx']) + t.ok(await stat(exampleAppPath + '/Electron\ Builder\ Example.dmg'), 'dmg created') + await remove(exampleAppPath + '/Electron\ Builder\ Example.dmg') + }) +} + +if (!process.env.CI || process.platform === "win32") { + test.serial('Cli - windows - config file provided', async (t) => { + await exec(['Example-win32-ia32', '--platform=win', '--config=builder.json']) + t.ok(await stat(path.join(exampleAppPath, 'Builder\ Config\ Windows\ example\ Setup.exe')), 'exe created') + await remove(path.join(exampleAppPath, 'Builder\ Config\ Windows\ example\ Setup.exe')) + }) + + test.serial('Cli - windows - no config file provided', async (t) => { + await exec(['Example-win32-ia32', '--platform=win']) + t.ok(await stat(path.join(exampleAppPath, 'Electron\ Builder\ Example\ Setup.exe')), 'exe created') + await remove(path.join(exampleAppPath, 'Electron\ Builder\ Example\ Setup.exe')) + }) +} \ No newline at end of file diff --git a/test/winPackagerTest.js b/test/src/winPackagerTest.ts similarity index 66% rename from test/winPackagerTest.js rename to test/src/winPackagerTest.ts index c01fd3dcbca..b172f0afa52 100644 --- a/test/winPackagerTest.js +++ b/test/src/winPackagerTest.ts @@ -1,12 +1,15 @@ import test from "./helpers/avaEx" import { assertPack } from "./helpers/packTester" -test.ifNotTravis("win", async function () { +//noinspection JSUnusedLocalSymbols +const __awaiter = require("out/awaiter") + +test.ifNotTravis("win", async () => { 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 () { +test.ifNotCi.serial("win: nsis", async () => { await assertPack("test-app-one", "win32", { target: ["nsis"], arch: process.arch diff --git a/test/tsconfig.json b/test/tsconfig.json new file mode 100644 index 00000000000..98ccb4aeeb8 --- /dev/null +++ b/test/tsconfig.json @@ -0,0 +1,65 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es6", + "noImplicitAny": true, + "removeComments": true, + "outDir": "out", + "newLine": "LF", + "noResolve": true, + "noEmitOnError": true, + "inlineSources": true, + "sourceMap": true, + "noImplicitReturns": true, + "noEmitHelpers": true, + "noFallthroughCasesInSwitch": true + }, + "filesGlob": [ + "../typings/**/*.d.ts", + "typings/**/*.d.ts", + "!../typings/browser/**/*.d.ts", + "!../typings/browser.d.ts", + "!../typings/main.d.ts", + "../node_modules/typescript/lib/lib.es7.d.ts", + "src/**/*.ts", + "../node_modules/fs-extra-p/index.d.ts", + "../node_modules/fs-extra-p/bluebird.d.ts", + "out/electron-builder.d.ts" + ], + "files": [ + "../typings/appdmg.d.ts", + "../typings/command-line-args.d.ts", + "../typings/electron-packager.d.ts", + "../typings/gh-api.d.ts", + "../typings/hosted-git-info.d.ts", + "../typings/main/ambient/gm/gm.d.ts", + "../typings/main/ambient/mime/mime.d.ts", + "../typings/main/ambient/progress/progress.d.ts", + "../typings/main/ambient/tmp/tmp.d.ts", + "../typings/main/definitions/source-map-support/source-map-support.d.ts", + "../typings/node.d.ts", + "../typings/progress-stream.d.ts", + "../typings/read-package-json.d.ts", + "typings/ava.d.ts", + "typings/json-parse-helpfulerror.d.ts", + "typings/path-sort.d.ts", + "typings/plist.d.ts", + "typings/should.d.ts", + "../node_modules/typescript/lib/lib.es7.d.ts", + "../node_modules/fs-extra-p/index.d.ts", + "../node_modules/fs-extra-p/bluebird.d.ts", + "out/electron-builder.d.ts", + "src/ArtifactPublisherTest.ts", + "src/BuildTest.ts", + "src/CodeSignTest.ts", + "src/helpers/avaEx.ts", + "src/helpers/codeSignData.ts", + "src/helpers/expectedContents.ts", + "src/helpers/packTester.ts", + "src/helpers/runTests.ts", + "src/linuxPackagerTest.ts", + "src/old-cli-test.ts", + "src/RepoSlugTest.ts", + "src/winPackagerTest.ts" + ] +} diff --git a/test/typings/ava.d.ts b/test/typings/ava.d.ts new file mode 100644 index 00000000000..6974f255076 --- /dev/null +++ b/test/typings/ava.d.ts @@ -0,0 +1,168 @@ +declare module "ava-tf" { + export interface Observable { + subscribe(observer: (value: {}) => void): void; + } + + export type Test = (t: TestContext) => Promise | Iterator | Observable | void; + export type ContextualTest = (t: ContextualTestContext) => Promise | Iterator | Observable | void; + export type SerialTest = (t: TestContext) => void; + export type ContextualSerialTest = (t: ContextualTestContext) => void; + export type CallbackTest = (t: CallbackTestContext) => void; + export type ContextualCallbackTest = (t: ContextualCallbackTestContext) => void; + + export interface Runner { + (name: string, run: Test): void; + (run: Test): void; + skip: Runner; + cb: CallbackRunner; + } + export interface ContextualRunner { + (name: string, run: ContextualTest): void; + (run: ContextualTest): void; + skip: ContextualRunner; + cb: ContextualCallbackRunner; + } + export interface SerialRunner { + (name: string, run: SerialTest): void; + (run: SerialTest): void; + skip: SerialRunner; + } + export interface ContextualSerialRunner { + (name: string, run: ContextualSerialTest): void; + (run: ContextualSerialTest): void; + skip: ContextualSerialRunner; + } + export interface CallbackRunner { + (name: string, run: CallbackTest): void; + (run: CallbackTest): void; + skip: CallbackRunner; + } + export interface ContextualCallbackRunner { + (name: string, run: ContextualCallbackTest): void; + (run: ContextualCallbackTest): void; + skip: ContextualCallbackRunner; + } + + export function test(name: string, run: ContextualTest): void; + export function test(run: ContextualTest): void; + export namespace test { + export const before: Runner; + export const after: Runner; + export const beforeEach: ContextualRunner; + export const afterEach: ContextualRunner; + + export const skip: typeof test; + export const only: typeof test; + + export function serial(name: string, run: ContextualSerialTest): void; + export function serial(run: ContextualSerialTest): void; + export function cb(name: string, run: ContextualCallbackTest): void; + export function cb(run: ContextualCallbackTest): void; + } + export namespace test.serial { + export const before: SerialRunner; + export const after: SerialRunner; + export const beforeEach: ContextualSerialRunner; + export const afterEach: ContextualSerialRunner; + + export const skip: typeof test.serial; + export const only: typeof test.serial; + } + export namespace test.cb { + export const before: CallbackRunner; + export const after: CallbackRunner; + export const beforeEach: ContextualCallbackRunner; + export const afterEach: ContextualCallbackRunner; + + export const skip: typeof test.cb; + export const only: typeof test.cb; + } + export default test; + + export type ErrorValidator + = (new (...args: any[]) => any) + | RegExp + | string + | ((error: any) => boolean); + + export interface AssertContext { + /** + * Passing assertion. + */ + pass(message?: string): void; + /** + * Failing assertion. + */ + fail(message?: string): void; + /** + * Assert that value is truthy. + */ + ok(value: any, message?: string): void; + /** + * Assert that value is falsy. + */ + notOk(value: any, message?: string): void; + /** + * Assert that value is true. + */ + true(value: boolean, message?: string): void; + /** + * Assert that value is false. + */ + false(value: boolean, message?: string): void; + /** + * Assert that value is equal to expected. + */ + is(value: U, expected: U, message?: string): void; + /** + * Assert that value is not equal to expected. + */ + not(value: U, expected: U, message?: string): void; + /** + * Assert that value is deep equal to expected. + */ + same(value: U, expected: U, message?: string): void; + /** + * Assert that value is not deep equal to expected. + */ + notSame(value: U, expected: U, message?: string): void; + /** + * Assert that function throws an error or promise rejects. + * @param error Can be a constructor, regex, error message or validation function. + */ + throws(value: (() => void) | Promise<{}>, error?: ErrorValidator, message?: string): void; + /** + * Assert that function doesn't throw an error or promise resolves. + */ + notThrows(value: (() => void) | Promise<{}>, message?: string): void; + /** + * Assert that contents matches regex. + */ + regex(contents: string, regex: RegExp, message?: string): void; + /** + * Assert that error is falsy. + */ + ifError(error: any, message?: string): void; + } + export interface TestContext extends AssertContext { + /** + * Plan how many assertion there are in the test. + * The test will fail if the actual assertion count doesn't match planned assertions. + */ + plan(count: number): void; + + skip: AssertContext; + } + export interface CallbackTestContext extends TestContext { + /** + * End the test. + */ + end(): void; + } + export interface ContextualTestContext extends TestContext { + context: any; + } + export interface ContextualCallbackTestContext extends CallbackTestContext { + context: any; + } +} \ No newline at end of file diff --git a/test/typings/json-parse-helpfulerror.d.ts b/test/typings/json-parse-helpfulerror.d.ts new file mode 100644 index 00000000000..773f1cf7152 --- /dev/null +++ b/test/typings/json-parse-helpfulerror.d.ts @@ -0,0 +1,3 @@ +declare module "json-parse-helpfulerror" { + export function parse(data: string): any +} \ No newline at end of file diff --git a/test/typings/path-sort.d.ts b/test/typings/path-sort.d.ts new file mode 100644 index 00000000000..a091e4f5d24 --- /dev/null +++ b/test/typings/path-sort.d.ts @@ -0,0 +1,5 @@ +declare module "path-sort" { + function sort(files: Array): Array + + export = sort +} \ No newline at end of file diff --git a/test/typings/plist.d.ts b/test/typings/plist.d.ts new file mode 100644 index 00000000000..3803dc20955 --- /dev/null +++ b/test/typings/plist.d.ts @@ -0,0 +1,4 @@ +declare module "plist" { + export function parse(data: string): any +} + \ No newline at end of file diff --git a/typings/main/ambient/should/should.d.ts b/test/typings/should.d.ts similarity index 98% rename from typings/main/ambient/should/should.d.ts rename to test/typings/should.d.ts index 24795a8b3e8..0d556ff44f6 100644 --- a/typings/main/ambient/should/should.d.ts +++ b/test/typings/should.d.ts @@ -1,4 +1,4 @@ -// Compiled using typings@0.6.8 +// Compiled using typings@0.6.9 // Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/5aa6dff6990465c7fb41504538ad7aa133ab01d3/should/should.d.ts // Type definitions for should.js v8.1.1 // Project: https://github.com/shouldjs/should.js @@ -169,4 +169,8 @@ interface Window { declare module "should" { export = should; +} + +declare module "should/as-function" { + export = should; } \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index e3c48ce9475..73c1e935851 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,6 +14,10 @@ "noEmitHelpers": true, "noFallthroughCasesInSwitch": true }, + "declaration": { + "electron-builder": "out/electron-builder.d.ts", + "": "test/out/electron-builder.d.ts" + }, "filesGlob": [ "src/*.ts", "lib/*.d.ts", @@ -21,27 +25,28 @@ "!typings/browser/**/*.d.ts", "!typings/browser.d.ts", "!typings/main.d.ts", - "node_modules/typescript/lib/lib.es7.d.ts" + "node_modules/typescript/lib/lib.es7.d.ts", + "node_modules/fs-extra-p/index.d.ts", + "node_modules/fs-extra-p/bluebird.d.ts" ], "files": [ "lib/linux.d.ts", "typings/appdmg.d.ts", - "typings/bluebird.d.ts", "typings/command-line-args.d.ts", "typings/electron-packager.d.ts", "typings/gh-api.d.ts", "typings/hosted-git-info.d.ts", - "typings/main/ambient/fs-extra/fs-extra.d.ts", "typings/main/ambient/gm/gm.d.ts", "typings/main/ambient/mime/mime.d.ts", "typings/main/ambient/progress/progress.d.ts", - "typings/main/ambient/should/should.d.ts", "typings/main/ambient/tmp/tmp.d.ts", "typings/main/definitions/source-map-support/source-map-support.d.ts", "typings/node.d.ts", "typings/progress-stream.d.ts", "typings/read-package-json.d.ts", "node_modules/typescript/lib/lib.es7.d.ts", + "node_modules/fs-extra-p/index.d.ts", + "node_modules/fs-extra-p/bluebird.d.ts", "src/awaiter.ts", "src/build-cli.ts", "src/builder.ts", diff --git a/tslint.json b/tslint.json index 21b4619e04f..414c4a828a4 100644 --- a/tslint.json +++ b/tslint.json @@ -19,13 +19,15 @@ "no-unreachable": true, "no-unused-expression": true, "no-unused-variable": [ - true + true, + { + "ignore-pattern": "^_+awaiter$" + } ], "no-use-before-declare": true, "no-internal-module": true, "no-trailing-whitespace": true, "no-var-keyword": true, - "no-var-requires": true, "one-line": [ true, "check-open-brace", diff --git a/typings/bluebird.d.ts b/typings/bluebird.d.ts deleted file mode 100644 index 66f7676eb8a..00000000000 --- a/typings/bluebird.d.ts +++ /dev/null @@ -1,63 +0,0 @@ -// Type definitions for bluebird 2.0.0 -// Project: https://github.com/petkaantonov/bluebird -// Definitions by: Bart van der Schoor , falsandtru -// Definitions: https://github.com/borisyankov/DefinitelyTyped - -declare module 'bluebird' { - interface Disposer { - } - - class BluebirdPromise implements Promise { - constructor(callback: (resolve: (value?: T | PromiseLike) => void, reject: (reason?: Error) => void, onCancel?: (handler: () => void) => void) => void) - - static config(options: any): void - - static all(values: Iterable>): BluebirdPromise - - static mapSeries(items: Iterable, mapper: (item: T) => BluebirdPromise): BluebirdPromise - - static reject(error: Error): BluebirdPromise - - static coroutine(generator: Function): Function - - /** - * Returns a function that will wrap the given `nodeFunction`. Instead of taking a callback, the returned function will return a promise whose fate is decided by the callback behavior of the given node function. The node function should conform to node.js convention of accepting a callback as last argument and calling that callback with error as the first argument and success value on the second argument. - * - * If the `nodeFunction` calls its callback with multiple success values, the fulfillment value will be an array of them. - * - * If you pass a `receiver`, the `nodeFunction` will be called as a method on the `receiver`. - */ - static promisify(func: (callback: (err: any, result: T) => void) => void, receiver?: any): () => BluebirdPromise; - static promisify(func: (arg1: A1, callback: (err: any, result: T) => void) => void, receiver?: any): (arg1: A1) => BluebirdPromise; - static promisify(func: (arg1: A1, arg2: A2, callback: (err: any, result: T) => void) => void, receiver?: any): (arg1: A1, arg2: A2) => BluebirdPromise; - static promisify(func: (arg1: A1, arg2: A2, callback: (error: Error) => void) => void, receiver?: any): (arg1: A1, arg2: A2) => BluebirdPromise; - static promisify(func: (arg1: A1, arg2: A2, arg3: A3, callback: (err: any, result: T) => void) => void, receiver?: any): (arg1: A1, arg2: A2, arg3: A3) => BluebirdPromise; - static promisify(func: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, callback: (err: any, result: T) => void) => void, receiver?: any): (arg1: A1, arg2: A2, arg3: A3, arg4: A4) => BluebirdPromise; - static promisify(func: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5, callback: (err: any, result: T) => void) => void, receiver?: any): (arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5) => BluebirdPromise; - static promisify(nodeFunction: Function, receiver?: any): Function; - - static resolve(value: T | PromiseLike): BluebirdPromise - static resolve(): BluebirdPromise - - then(fulfilled: (value: T) => R | PromiseLike, rejected?: (reason: any) => R | PromiseLike): BluebirdPromise - - //noinspection ReservedWordAsName - catch(onrejected?: (reason: any) => T | PromiseLike): BluebirdPromise - //noinspection ReservedWordAsName - catch(onrejected?: (reason: any) => void): BluebirdPromise; - - [Symbol.toStringTag]: any - - disposer(disposer: (result: T, promise: Promise) => Promise | void): Disposer - - thenReturn(result: T): BluebirdPromise - - cancel(): void - - isFulfilled(): boolean - - value(): T - } - - export { BluebirdPromise as Promise } -} \ No newline at end of file diff --git a/typings/main/ambient/fs-extra/fs-extra.d.ts b/typings/main/ambient/fs-extra/fs-extra.d.ts deleted file mode 100644 index 5e472978438..00000000000 --- a/typings/main/ambient/fs-extra/fs-extra.d.ts +++ /dev/null @@ -1,207 +0,0 @@ -// Compiled using typings@0.6.8 -// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/72d95b38f008fed506c6cbf3af8a693bd7c3363a/fs-extra/fs-extra.d.ts -// Type definitions for fs-extra -// Project: https://github.com/jprichardson/node-fs-extra -// Definitions by: midknight41 -// Definitions: https://github.com/borisyankov/DefinitelyTyped - -// Imported from: https://github.com/soywiz/typescript-node-definitions/fs-extra.d.ts - - -declare module "fs-extra" { - import stream = require("stream"); - - interface Stats { - isFile(): boolean; - isDirectory(): boolean; - isBlockDevice(): boolean; - isCharacterDevice(): boolean; - isSymbolicLink(): boolean; - isFIFO(): boolean; - isSocket(): boolean; - dev: number; - ino: number; - mode: number; - nlink: number; - uid: number; - gid: number; - rdev: number; - size: number; - blksize: number; - blocks: number; - atime: Date; - mtime: Date; - ctime: Date; - birthtime: Date; - } - - export interface FSWatcher { - close(): void; - } - - export class ReadStream extends stream.Readable { } - export class WriteStream extends stream.Writable { } - - //extended methods - export function copy(src: string, dest: string, callback?: (err: Error) => void): void; - export function copy(src: string, dest: string, filter: (src: string) => boolean, callback?: (err: Error) => void): void; - - export function copySync(src: string, dest: string): void; - export function copySync(src: string, dest: string, filter: (src: string) => boolean): void; - - export function createFile(file: string, callback?: (err: Error) => void): void; - export function createFileSync(file: string): void; - - export function mkdirs(dir: string, callback?: (err: Error) => void): void; - export function mkdirp(dir: string, callback?: (err: Error) => void): void; - export function mkdirs(dir: string, options?: MkdirOptions, callback?: (err: Error) => void): void; - export function mkdirp(dir: string, options?: MkdirOptions, callback?: (err: Error) => void): void; - export function mkdirsSync(dir: string, options?: MkdirOptions): void; - export function mkdirpSync(dir: string, options?: MkdirOptions): void; - - export function outputFile(file: string, data: any, callback?: (err: Error) => void): void; - export function outputFileSync(file: string, data: any): void; - - export function outputJson(file: string, data: any, callback?: (err: Error) => void): void; - export function outputJSON(file: string, data: any, callback?: (err: Error) => void): void; - export function outputJsonSync(file: string, data: any): void; - export function outputJSONSync(file: string, data: any): void; - - export function readJson(file: string, callback: (err: Error, jsonObject: any) => void): void; - export function readJson(file: string, options: OpenOptions, callback: (err: Error, jsonObject: any) => void): void; - export function readJSON(file: string, callback: (err: Error, jsonObject: any) => void): void; - export function readJSON(file: string, options: OpenOptions, callback: (err: Error, jsonObject: any) => void): void; - - export function readJsonSync(file: string, options?: OpenOptions): any; - export function readJSONSync(file: string, options?: OpenOptions): any; - - export function remove(dir: string, callback?: (err: Error) => void): void; - export function removeSync(dir: string): void; - // export function delete(dir: string, callback?: (err: Error) => void): void; - // export function deleteSync(dir: string): void; - - export function writeJson(file: string, object: any, callback?: (err: Error) => void): void; - export function writeJson(file: string, object: any, options?: OpenOptions, callback?: (err: Error) => void): void; - export function writeJSON(file: string, object: any, callback?: (err: Error) => void): void; - export function writeJSON(file: string, object: any, options?: OpenOptions, callback?: (err: Error) => void): void; - - export function writeJsonSync(file: string, object: any, options?: OpenOptions): void; - export function writeJSONSync(file: string, object: any, options?: OpenOptions): void; - - export function rename(oldPath: string, newPath: string, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function renameSync(oldPath: string, newPath: string): void; - export function truncate(fd: number, len: number, callback?: (err: Error) => void): void; - export function truncateSync(fd: number, len: number): void; - export function chown(path: string, uid: number, gid: number, callback?: (err: Error) => void): void; - export function chownSync(path: string, uid: number, gid: number): void; - export function fchown(fd: number, uid: number, gid: number, callback?: (err: Error) => void): void; - export function fchownSync(fd: number, uid: number, gid: number): void; - export function lchown(path: string, uid: number, gid: number, callback?: (err: Error) => void): void; - export function lchownSync(path: string, uid: number, gid: number): void; - export function chmod(path: string, mode: number, callback?: (err: Error) => void): void; - export function chmod(path: string, mode: string, callback?: (err: Error) => void): void; - export function chmodSync(path: string, mode: number): void; - export function chmodSync(path: string, mode: string): void; - export function fchmod(fd: number, mode: number, callback?: (err: Error) => void): void; - export function fchmod(fd: number, mode: string, callback?: (err: Error) => void): void; - export function fchmodSync(fd: number, mode: number): void; - export function fchmodSync(fd: number, mode: string): void; - export function lchmod(path: string, mode: string, callback?: (err: Error) => void): void; - export function lchmod(path: string, mode: number, callback?: (err: Error) => void): void; - export function lchmodSync(path: string, mode: number): void; - export function lchmodSync(path: string, mode: string): void; - export function stat(path: string, callback?: (err: Error, stats: Stats) => void): void; - export function lstat(path: string, callback?: (err: Error, stats: Stats) => void): void; - export function fstat(fd: number, callback?: (err: Error, stats: Stats) => void): void; - export function statSync(path: string): Stats; - export function lstatSync(path: string): Stats; - export function fstatSync(fd: number): Stats; - export function link(srcpath: string, dstpath: string, callback?: (err: Error) => void): void; - export function linkSync(srcpath: string, dstpath: string): void; - export function symlink(srcpath: string, dstpath: string, type?: string, callback?: (err: Error) => void): void; - export function symlinkSync(srcpath: string, dstpath: string, type?: string): void; - export function readlink(path: string, callback?: (err: Error, linkString: string) => void): void; - export function realpath(path: string, callback?: (err: Error, resolvedPath: string) => void): void; - export function realpath(path: string, cache: string, callback: (err: Error, resolvedPath: string) => void): void; - export function realpathSync(path: string, cache?: boolean): string; - export function unlink(path: string, callback?: (err?: NodeJS.ErrnoException) => void): void; - export function unlinkSync(path: string): void; - export function rmdir(path: string, callback?: (err: Error) => void): void; - export function rmdirSync(path: string): void; - export function mkdir(path: string, mode?: number, callback?: (err: Error) => void): void; - export function mkdir(path: string, mode?: string, callback?: (err: Error) => void): void; - export function mkdirSync(path: string, mode?: number): void; - export function mkdirSync(path: string, mode?: string): void; - export function readdir(path: string, callback?: (err: Error, files: string[]) => void ): void; - export function readdirSync(path: string): string[]; - export function close(fd: number, callback?: (err: Error) => void): void; - export function closeSync(fd: number): void; - export function open(path: string, flags: string, mode?: string, callback?: (err: Error, fs: number) => void): void; - export function openSync(path: string, flags: string, mode?: string): number; - export function utimes(path: string, atime: number, mtime: number, callback?: (err: Error) => void): void; - export function utimesSync(path: string, atime: number, mtime: number): void; - export function futimes(fd: number, atime: number, mtime: number, callback?: (err: Error) => void): void; - export function futimesSync(fd: number, atime: number, mtime: number): void; - export function fsync(fd: number, callback?: (err: Error) => void): void; - export function fsyncSync(fd: number): void; - export function write(fd: number, buffer: NodeBuffer, offset: number, length: number, position: number, callback?: (err: Error, written: number, buffer: NodeBuffer) => void): void; - export function writeSync(fd: number, buffer: NodeBuffer, offset: number, length: number, position: number): number; - export function read(fd: number, buffer: NodeBuffer, offset: number, length: number, position: number, callback?: (err: Error, bytesRead: number, buffer: NodeBuffer) => void ): void; - export function readSync(fd: number, buffer: NodeBuffer, offset: number, length: number, position: number): number; - export function readFile(filename: string, encoding: string, callback: (err: Error, data: string) => void ): void; - export function readFile(filename: string, options: OpenOptions, callback: (err: Error, data: string) => void ): void; - export function readFile(filename: string, callback: (err: Error, data: NodeBuffer) => void ): void; - export function readFileSync(filename: string): NodeBuffer; - export function readFileSync(filename: string, encoding: string): string; - export function readFileSync(filename: string, options: OpenOptions): string; - export function writeFile(filename: string, data: any, encoding?: string, callback?: (err: Error) => void): void; - export function writeFile(filename: string, data: any, options?: OpenOptions, callback?: (err: Error) => void): void; - export function writeFileSync(filename: string, data: any, encoding?: string): void; - export function writeFileSync(filename: string, data: any, option?: OpenOptions): void; - export function appendFile(filename: string, data: any, encoding?: string, callback?: (err: Error) => void): void; - export function appendFile(filename: string, data: any,option?: OpenOptions, callback?: (err: Error) => void): void; - export function appendFileSync(filename: string, data: any, encoding?: string): void; - export function appendFileSync(filename: string, data: any, option?: OpenOptions): void; - export function watchFile(filename: string, listener: { curr: Stats; prev: Stats; }): void; - export function watchFile(filename: string, options: { persistent?: boolean; interval?: number; }, listener: { curr: Stats; prev: Stats; }): void; - export function unwatchFile(filename: string, listener?: Stats): void; - export function watch(filename: string, options?: { persistent?: boolean; }, listener?: (event: string, filename: string) => any): FSWatcher; - export function exists(path: string, callback?: (exists: boolean) => void ): void; - export function existsSync(path: string): boolean; - export function ensureDir(path: string, cb: (err: Error) => void): void; - export function ensureDirSync(path: string): void; - export function ensureFile(path: string, cb: (err: Error) => void): void; - export function ensureFileSync(path: string): void; - export function ensureLink(path: string, cb: (err: Error) => void): void; - export function ensureLinkSync(path: string): void; - export function ensureSymlink(path: string, cb: (err: Error) => void): void; - export function ensureSymlinkSync(path: string): void; - export function emptyDir(path: string, callback?: (err: Error) => void): void; - export function emptyDirSync(path: string): boolean; - - export interface OpenOptions { - encoding?: string; - flag?: string; - } - - export interface MkdirOptions { - fs?: any; - mode?: number; - } - - export interface ReadStreamOptions { - flags?: string; - encoding?: string; - fd?: number; - mode?: number; - bufferSize?: number; - } - export interface WriteStreamOptions { - flags?: string; - encoding?: string; - string?: string; - } - export function createReadStream(path: string, options?: ReadStreamOptions): ReadStream; - export function createWriteStream(path: string, options?: WriteStreamOptions): WriteStream; - export function createOutputStream(path: string, options?: WriteStreamOptions): WriteStream; -} \ No newline at end of file diff --git a/typings/main/ambient/tmp/tmp.d.ts b/typings/main/ambient/tmp/tmp.d.ts index 72fcfb066cb..c957a40a585 100644 --- a/typings/main/ambient/tmp/tmp.d.ts +++ b/typings/main/ambient/tmp/tmp.d.ts @@ -1,50 +1,46 @@ -// Compiled using typings@0.6.8 -// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/48f20e97bfaf70fc1a9537b38aed98e9749be0ae/tmp/tmp.d.ts +// Compiled using typings@0.6.8 +// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/48f20e97bfaf70fc1a9537b38aed98e9749be0ae/tmp/tmp.d.ts // Type definitions for tmp v0.0.28 // Project: https://www.npmjs.com/package/tmp // Definitions by: Jared Klopper // Definitions: https://github.com/borisyankov/DefinitelyTyped declare module "tmp" { + export interface TmpFileOptions extends TmpOptions { + mode?: number; + } - module tmp { - interface Options extends SimpleOptions { - mode?: number; - } + export interface TmpOptions { + prefix?: string; + postfix?: string; - interface SimpleOptions { - prefix?: string; - postfix?: string; - template?: string; - dir?: string; - tries?: number; - keep?: boolean; - unsafeCleanup?: boolean; - } + template?: string; + dir?: string; + tries?: number; + keep?: boolean; + unsafeCleanup?: boolean; + } - interface SynchrounousResult { - name: string; - fd: number; - removeCallback: () => void; - } + interface SynchrounousResult { + name: string; + fd: number; + removeCallback: () => void; + } - function file(callback: (err: any, path: string, fd: number, cleanupCallback: () => void) => void): void; - function file(config: Options, callback?: (err: any, path: string, fd: number, cleanupCallback: () => void) => void): void; + function file(callback: (err: any, path: string, fd: number, cleanupCallback: () => void) => void): void; + function file(config: TmpFileOptions, callback?: (err: any, path: string, fd: number, cleanupCallback: () => void) => void): void; - function fileSync(config?: Options): SynchrounousResult; + function fileSync(config?: TmpFileOptions): SynchrounousResult; - function dir(callback: (err: any, path: string, cleanupCallback: () => void) => void): void; - function dir(config: Options, callback?: (err: any, path: string, cleanupCallback: () => void) => void): void; + export function dir(callback: (err: any, path: string, cleanupCallback: () => void) => void): void; + export function dir(config: TmpFileOptions, callback?: (err: any, path: string, cleanupCallback: () => void) => void): void; - function dirSync(config?: Options): SynchrounousResult; + function dirSync(config?: TmpFileOptions): SynchrounousResult; - function tmpName(callback: (err: any, path: string) => void): void; - function tmpName(config: SimpleOptions, callback?: (err: any, path: string) => void): void; + function tmpName(callback: (err: any, path: string) => void): void; + function tmpName(config: TmpOptions, callback?: (err: any, path: string) => void): void; - function tmpNameSync(config?: SimpleOptions): string; + function tmpNameSync(config?: TmpOptions): string; - function setGracefulCleanup(): void; - } - - export = tmp; + function setGracefulCleanup(): void; } \ No newline at end of file