import { checkBuildRequestOptions } from "app-builder-lib"
import { doMergeConfigs } from "app-builder-lib/out/util/config/config"
import { Arch, createTargets, DIR_TARGET, Platform } from "electron-builder"
import { createYargs } from "electron-builder/out/builder"
import { promises as fs } from "fs"
import { outputFile, outputJson } from "fs-extra"
import * as path from "path"
import { app, appTwo, appTwoThrows, assertPack, getFixtureDir, linuxDirTarget, modifyPackageJson, packageJson, toSystemIndependentPath } from "./helpers/packTester"
import { ELECTRON_VERSION } from "./helpers/testConfig"
import { verifySmartUnpack } from "./helpers/verifySmartUnpack"
import { spawn } from "builder-util/out/util"
test("cli", ({ expect }) => {
const { configureBuildCommand, normalizeOptions } = require("electron-builder/out/builder")
const yargs = createYargs()
configureBuildCommand(yargs)
function parse(input: string): any {
const options = normalizeOptions(yargs.parse(input))
checkBuildRequestOptions(options)
return options
}
expect(parse("-owl --x64 --ia32"))
expect(parse("-mwl --x64 --ia32"))
expect(parse("--dir")).toMatchObject({ targets: Platform.current().createTarget(DIR_TARGET) })
expect(parse("--mac --dir")).toMatchSnapshot()
expect(parse("--x64 --dir")).toMatchObject({ targets: Platform.current().createTarget(DIR_TARGET, Arch.x64) })
expect(parse("--ia32 --x64")).toMatchObject({ targets: Platform.current().createTarget(null, Arch.x64, Arch.ia32) })
expect(parse("--linux")).toMatchSnapshot()
expect(parse("--win")).toMatchSnapshot()
expect(parse("-owl")).toMatchSnapshot()
expect(parse("-l tar.gz:ia32")).toMatchSnapshot()
expect(parse("-l tar.gz:x64")).toMatchSnapshot()
expect(parse("-l tar.gz")).toMatchSnapshot()
expect(parse("-w tar.gz:x64")).toMatchSnapshot()
expect(parse("-p always -w --x64")).toMatchSnapshot()
expect(parse("--prepackaged someDir -w --x64")).toMatchSnapshot()
expect(parse("--project someDir -w --x64")).toMatchSnapshot()
expect(parse("-c.compress=store -c.asar -c ./config.json")).toMatchObject({
config: {
asar: true,
compress: "store",
extends: "./config.json",
},
})
})
test("merge configurations", ({ expect }) => {
const result = doMergeConfigs([
{
files: [
{
from: "dist/renderer",
},
{
from: "dist/renderer-dll",
},
],
},
{
files: [
{
from: ".",
filter: ["package.json"],
},
{
from: "dist/main",
},
],
},
{
files: ["**/*", "!webpack", "!.*", "!config/jsdoc.json", "!package.*"],
},
{
files: [
{
from: ".",
filter: ["!docs"],
},
],
},
{
files: ["!private"],
},
])
expect(result).toMatchObject({
directories: {
output: "dist",
buildResources: "build",
},
files: [
{
filter: ["package.json", "**/*", "!webpack", "!.*", "!config/jsdoc.json", "!package.*", "!docs", "!private"],
},
{
from: "dist/main",
},
{
from: "dist/renderer",
},
{
from: "dist/renderer-dll",
},
],
})
})
test("build in the app package.json", ({ expect }) =>
appTwoThrows(
expect,
{ targets: linuxDirTarget },
{
projectDirCreated: it =>
modifyPackageJson(
it,
data => {
data.build = {
productName: "bar",
}
},
true
),
}
))
test("relative index", ({ expect }) =>
appTwo(
expect,
{
targets: linuxDirTarget,
},
{
projectDirCreated: projectDir =>
modifyPackageJson(
projectDir,
data => {
data.main = "./index.js"
},
true
),
}
))
it.ifDevOrLinuxCi("electron version from electron-prebuilt dependency", ({ expect }) =>
app(
expect,
{
targets: linuxDirTarget,
},
{
projectDirCreated: projectDir =>
Promise.all([
outputJson(path.join(projectDir, "node_modules", "electron-prebuilt", "package.json"), {
version: ELECTRON_VERSION,
}),
modifyPackageJson(projectDir, data => {
delete data.build.electronVersion
data.devDependencies = {}
}),
]),
}
)
)
test.ifDevOrLinuxCi("electron version from electron dependency", ({ expect }) =>
app(
expect,
{
targets: linuxDirTarget,
},
{
projectDirCreated: projectDir =>
Promise.all([
outputJson(path.join(projectDir, "node_modules", "electron", "package.json"), {
version: ELECTRON_VERSION,
}),
modifyPackageJson(projectDir, data => {
delete data.build.electronVersion
data.devDependencies = {}
}),
]),
}
)
)
test.ifDevOrLinuxCi("electron version from build", ({ expect }) =>
app(
expect,
{
targets: linuxDirTarget,
},
{
projectDirCreated: projectDir =>
modifyPackageJson(projectDir, data => {
data.devDependencies = {}
data.build.electronVersion = ELECTRON_VERSION
}),
}
)
)
test("www as default dir", ({ expect }) =>
appTwo(
expect,
{
targets: Platform.LINUX.createTarget(DIR_TARGET),
},
{
projectDirCreated: projectDir => fs.rename(path.join(projectDir, "app"), path.join(projectDir, "www")),
}
))
test.ifLinuxOrDevMac("hooks as functions", ({ expect }) => {
let artifactBuildStartedCalled = 0
let artifactBuildCompletedCalled = 0
let beforePackCalled = 0
let afterPackCalled = 0
let afterExtractCalled = 0
return assertPack(
expect,
"test-app-one",
{
targets: createTargets([Platform.LINUX, Platform.MAC], "zip", "x64"),
config: {
artifactBuildStarted: () => {
artifactBuildStartedCalled++
},
artifactBuildCompleted: () => {
artifactBuildCompletedCalled++
},
beforePack: () => {
beforePackCalled++
return Promise.resolve()
},
afterExtract: () => {
afterExtractCalled++
return Promise.resolve()
},
afterPack: () => {
afterPackCalled++
return Promise.resolve()
},
},
},
{
packed: async () => {
expect(artifactBuildStartedCalled).toEqual(2)
expect(artifactBuildCompletedCalled).toEqual(3)
expect(beforePackCalled).toEqual(2)
expect(afterExtractCalled).toEqual(2)
expect(afterPackCalled).toEqual(2)
expect(afterPackCalled).toEqual(2)
return Promise.resolve()
},
}
)
})
test.ifLinuxOrDevMac("hooks as file - cjs", async ({ expect }) => {
const hookScript = path.join(getFixtureDir(), "build-hook.cjs")
return assertPack(expect, "test-app-one", {
targets: createTargets([Platform.LINUX, Platform.MAC], "zip", "x64"),
config: {
artifactBuildStarted: hookScript,
artifactBuildCompleted: hookScript,
beforePack: hookScript,
afterExtract: hookScript,
afterPack: hookScript,
},
})
})
test.ifWindows("afterSign", ({ expect }) => {
let called = 0
return assertPack(
expect,
"test-app-one",
{
targets: createTargets([Platform.LINUX, Platform.WINDOWS], DIR_TARGET),
config: {
afterSign: () => {
called++
return Promise.resolve()
},
},
},
{
packed: async () => {
expect(called).toEqual(1)
return Promise.resolve()
},
}
)
})
test.ifLinuxOrDevMac("beforeBuild", ({ expect }) => {
let called = 0
return assertPack(
expect,
"test-app-one",
{
targets: createTargets([Platform.LINUX, Platform.MAC], DIR_TARGET),
config: {
npmRebuild: true,
beforeBuild: async () => {
called++
return Promise.resolve()
},
},
},
{
packed: async () => {
expect(called).toEqual(2)
return Promise.resolve()
},
}
)
})
test.ifDevOrLinuxCi("win smart unpack", ({ expect }) => {
const nodeModuleFiles: Array<string> = []
let p = ""
return app(
expect,
{
targets: Platform.WINDOWS.createTarget(DIR_TARGET, Arch.x64),
config: {
npmRebuild: true,
onNodeModuleFile: file => {
const name = toSystemIndependentPath(path.relative(p, file))
if (!name.startsWith(".") && !name.endsWith(".dll") && name.includes(".")) {
nodeModuleFiles.push(name)
}
},
win: {
signAndEditExecutable: false,
},
},
},
{
isInstallDepsBefore: true,
projectDirCreated: projectDir => {
p = projectDir
return packageJson(it => {
it.dependencies = {
debug: "3.1.0",
"edge-cs": "1.2.1",
"@electron-builder/test-smart-unpack": "1.0.0",
"@electron-builder/test-smart-unpack-empty": "1.0.0",
}
})(projectDir)
},
packed: async context => {
await verifySmartUnpack(expect, context.getResources(Platform.WINDOWS))
expect(nodeModuleFiles).toMatchSnapshot()
},
}
)
})
test.ifDevOrWinCi("smart unpack local module with dll file", ({ expect }) => {
return app(
expect,
{
targets: Platform.WINDOWS.createTarget(DIR_TARGET, Arch.x64),
},
{
isInstallDepsBefore: true,
projectDirCreated: async (projectDir, tmpDir) => {
const tempDir = await tmpDir.getTempDir()
const localPath = path.join(tempDir, "foo")
await outputFile(path.join(localPath, "package.json"), `{"name":"foo","version":"9.0.0","main":"index.js","license":"MIT"}`)
await outputFile(path.join(localPath, "test.dll"), `test`)
await modifyPackageJson(projectDir, data => {
data.dependencies = {
debug: "3.1.0",
"edge-cs": "1.2.1",
foo: `file:${localPath}`,
}
})
await spawn("npm", ["install"], {
cwd: projectDir,
})
},
packed: async context => {
await verifySmartUnpack(expect, context.getResources(Platform.WINDOWS))
},
}
)
})
test.ifDevOrLinuxCi("posix smart unpack", ({ expect }) =>
app(
expect,
{
targets: linuxDirTarget,
config: {
copyright: "Copyright © 2018 ${author}",
npmRebuild: true,
onNodeModuleFile: filePath => {
return filePath.includes("node_modules/three/examples")
},
files: [
{
filter: ["!node_modules/napi-build-utils/napi-build-utils-1.0.0.tgz", "!node_modules/node-abi/*", "!node_modules/**/eslint-format.js"],
},
],
},
},
{
isInstallDepsBefore: true,
projectDirCreated: packageJson(it => {
it.dependencies = {
debug: "4.1.1",
"edge-cs": "1.2.1",
keytar: "7.9.0",
three: "0.160.0",
}
}),
packed: async context => {
expect(context.packager.appInfo.copyright).toBe("Copyright © 2018 Foo Bar")
await verifySmartUnpack(expect, context.getResources(Platform.LINUX), async asarFs => {
return expect(await asarFs.readFile(`node_modules${path.sep}three${path.sep}examples${path.sep}fonts${path.sep}README.md`)).toMatchSnapshot()
})
},
}
)
)