Skip to content

Commit 4049e31

Browse files
MarshallOfSoundmalept
authored andcommitted
test(installer): add test coverage for the installer
1 parent 6c63aaf commit 4049e31

File tree

4 files changed

+200
-2
lines changed

4 files changed

+200
-2
lines changed

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
"babel-plugin-transform-runtime": "^6.15.0",
4040
"babel-preset-es2015": "^6.16.0",
4141
"chai": "^3.5.0",
42+
"chai-as-promised": "^6.0.0",
43+
"chai-fetch-mock": "^1.0.0",
4244
"commitizen": "^2.8.6",
4345
"coveralls": "^2.11.15",
4446
"cross-env": "^3.1.3",
@@ -48,6 +50,7 @@
4850
"eslint": "^3.7.1",
4951
"eslint-config-airbnb-base": "^8.0.0",
5052
"eslint-plugin-import": "^1.16.0",
53+
"fetch-mock": "^5.8.1",
5154
"generate-changelog": "^1.0.2",
5255
"gulp": "^3.9.1",
5356
"gulp-babel": "^6.1.2",

src/api/install.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import fetch from 'node-fetch';
44
import fs from 'fs-promise';
55
import inquirer from 'inquirer';
66
import nugget from 'nugget';
7-
import opn from 'opn';
87
import os from 'os';
98
import path from 'path';
109
import pify from 'pify';
@@ -16,6 +15,7 @@ import darwinDMGInstaller from '../installers/darwin/dmg';
1615
import darwinZipInstaller from '../installers/darwin/zip';
1716
import linuxDebInstaller from '../installers/linux/deb';
1817
import linuxRPMInstaller from '../installers/linux/rpm';
18+
import win32ExeInstaller from '../installers/win32/exe';
1919

2020
const d = debug('electron-forge:install');
2121

@@ -144,7 +144,7 @@ export default async (providedOptions = {}) => {
144144
await asyncOra('Installing Application', async (installSpinner) => {
145145
const installActions = {
146146
win32: {
147-
'.exe': async filePath => await opn(filePath, { wait: false }),
147+
'.exe': win32ExeInstaller,
148148
},
149149
darwin: {
150150
'.zip': darwinZipInstaller,

src/installers/win32/exe.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import opn from 'opn';
2+
3+
export default async filePath => await opn(filePath, { wait: false });

test/slow/install_spec_slow.js

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
import chai, { expect } from 'chai';
2+
import fetchMock from 'fetch-mock';
3+
import chaiFetchMock from 'chai-fetch-mock';
4+
import chaiAsPromised from 'chai-as-promised';
5+
import proxyquire from 'proxyquire';
6+
import sinon from 'sinon';
7+
8+
chai.use(chaiFetchMock);
9+
chai.use(chaiAsPromised);
10+
11+
describe('install', () => {
12+
let install;
13+
let nuggetSpy;
14+
let mockInquirer;
15+
const mockInstaller = () => Promise.resolve();
16+
17+
beforeEach(() => {
18+
nuggetSpy = sinon.stub();
19+
mockInquirer = {
20+
createPromptModule: sinon.spy(() => sinon.spy(() => Promise.resolve({ assetID: 1 }))),
21+
};
22+
23+
install = proxyquire.noCallThru().load('../../src/api/install', {
24+
'node-fetch': fetchMock.fetchMock,
25+
nugget: (...args) => {
26+
nuggetSpy(...args);
27+
args[args.length - 1]();
28+
},
29+
'../installers/darwin/dmg': mockInstaller,
30+
'../installers/darwin/zip': mockInstaller,
31+
'../installers/linux/deb': mockInstaller,
32+
'../installers/linux/rpm': mockInstaller,
33+
'../installers/win32/exe': mockInstaller,
34+
inquirer: mockInquirer,
35+
}).default;
36+
});
37+
38+
afterEach(() => {
39+
fetchMock.restore();
40+
});
41+
42+
it('should throw an error when a repo name is not given', async () => {
43+
await expect(install()).to.eventually.be.rejected;
44+
});
45+
46+
it('should throw an error when given an invalid repository name', async () => {
47+
await expect(install({ repo: 'foobar', interactive: false })).to.eventually.be.rejected;
48+
});
49+
50+
it('should throw an error if the fetch fails', async () => {
51+
fetchMock.get('*', {
52+
throws: new Error('it broke'),
53+
});
54+
await expect(install({ repo: 'a/b', interactive: false })).to.eventually.be.rejectedWith(
55+
'Failed to find releases for repository "a/b". Please check the name and try again.'
56+
);
57+
});
58+
59+
it('should throw an error if we can\'t find the repo', async () => {
60+
fetchMock.get('*', {
61+
message: 'Not Found',
62+
});
63+
await expect(install({ repo: 'b/c', interactive: false })).to.eventually.be.rejectedWith(
64+
'Failed to find releases for repository "b/c". Please check the name and try again.'
65+
);
66+
});
67+
68+
it('should throw an error if the API does not return a release array', async () => {
69+
fetchMock.get('*', {
70+
lolz: 'this aint no array',
71+
});
72+
await expect(install({ repo: 'c/d', interactive: false })).to.eventually.be.rejectedWith(
73+
'Failed to find releases for repository "c/d". Please check the name and try again.'
74+
);
75+
});
76+
77+
it('should throw an error if the latest release has no assets', async () => {
78+
fetchMock.get('*', [
79+
{ tag_name: 'v1.0.0' },
80+
{ tag_name: '0.3.0' },
81+
{ tag_name: 'v1.2.0' },
82+
{ tag_name: '0.1.0' },
83+
]);
84+
await expect(install({ repo: 'e/f', interactive: false })).to.eventually.be.rejectedWith(
85+
'Could not find any assets for the latest release'
86+
);
87+
});
88+
89+
it('should throw an error if there are no release compatable with the current platform', async () => {
90+
fetchMock.get('*', [
91+
{
92+
tag_name: '1.0.0',
93+
assets: [
94+
{
95+
name: 'installer.unicorn',
96+
},
97+
],
98+
},
99+
]);
100+
await expect(install({ repo: 'f/g', interactive: false })).to.eventually.be.rejectedWith(
101+
`Failed to find any installable assets for target platform: ${`${process.platform}`.cyan}`
102+
);
103+
});
104+
105+
// eslint-disable-next-line no-nested-ternary
106+
const compatSuffix = process.platform === 'darwin' ? 'dmg' : (process.platform === 'win32' ? 'exe' : 'deb');
107+
108+
it('should download a release if there is a single compatable asset', async () => {
109+
fetchMock.get('*', [
110+
{
111+
tag_name: '1.0.0',
112+
assets: [
113+
{
114+
name: `installer.${compatSuffix}`,
115+
browser_download_url: 'fetch.it',
116+
},
117+
],
118+
},
119+
]);
120+
expect(nuggetSpy.callCount).to.equal(0);
121+
await install({ repo: 'g/h', interactive: false });
122+
expect(nuggetSpy.callCount).to.equal(1);
123+
expect(nuggetSpy.firstCall.args[0]).to.equal('fetch.it');
124+
});
125+
126+
it('should throw an error if there is more than compatable asset with no chooseAsset method', async () => {
127+
fetchMock.get('*', [
128+
{
129+
tag_name: '1.0.0',
130+
assets: [
131+
{
132+
name: `installer.${compatSuffix}`,
133+
browser_download_url: 'fetch.it',
134+
},
135+
{
136+
name: `installer2.${compatSuffix}`,
137+
browser_download_url: 'fetch.it.2',
138+
},
139+
],
140+
},
141+
]);
142+
await expect(install({ repo: 'h/i', interactive: false })).to.eventually.be.rejectedWith(
143+
'expected a chooseAsset function to be provided but it was not'
144+
);
145+
});
146+
147+
it('should provide compatable assets to chooseAsset if more than one exists', async () => {
148+
const chooseAsset = sinon.spy(async assets => assets[0]);
149+
fetchMock.get('*', [
150+
{
151+
tag_name: '1.0.0',
152+
assets: [
153+
{
154+
name: `installer.${compatSuffix}`,
155+
browser_download_url: 'fetch.it',
156+
},
157+
{
158+
name: `installer2.${compatSuffix}`,
159+
browser_download_url: 'fetch.it.2',
160+
},
161+
],
162+
},
163+
]);
164+
expect(chooseAsset.callCount).to.equal(0);
165+
await install({ repo: 'i/j', interactive: false, chooseAsset });
166+
expect(chooseAsset.callCount).to.equal(1);
167+
expect(chooseAsset.firstCall.args[0].length).to.equal(2);
168+
});
169+
170+
it('should prompt the user to choose an asset if in interactive mode and more than one exists', async () => {
171+
// mockInquirer
172+
fetchMock.get('*', [
173+
{
174+
tag_name: '1.0.0',
175+
assets: [
176+
{
177+
id: 1,
178+
name: `installer.${compatSuffix}`,
179+
browser_download_url: 'fetch.it',
180+
},
181+
{
182+
name: `installer2.${compatSuffix}`,
183+
browser_download_url: 'fetch.it.2',
184+
},
185+
],
186+
},
187+
]);
188+
expect(mockInquirer.createPromptModule.callCount).to.equal(0);
189+
await install({ repo: 'j/k', interactive: true });
190+
expect(mockInquirer.createPromptModule.callCount).to.equal(1);
191+
});
192+
});

0 commit comments

Comments
 (0)