Skip to content

Commit

Permalink
Merge pull request #61 from felixrieseberg/version-side-by-side-insta…
Browse files Browse the repository at this point in the history
…llation

feat: Version side by side installation
  • Loading branch information
bitdisaster committed Feb 20, 2020
2 parents 3a1bcc6 + 19ec865 commit 7b4fabb
Show file tree
Hide file tree
Showing 25 changed files with 6,336 additions and 2,451 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
node_modules
lib
coverage
harness/app/*
harness/out/*
.DS_Store
19 changes: 19 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug",
"type": "node",
"request": "launch",
"cwd": "${workspaceFolder}",
"program": "${workspaceFolder}/harness/harness.js",
"preLaunchTask": "Build",
"outFiles": ["${workspaceFolder}/lib/**/*.js"],
"sourceMaps": true,
"runtimeArgs": ["--inspect-brk=9229"],
"console": "integratedTerminal",
"port": 9229
}
]
}

13 changes: 13 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"type": "npm",
"label": "Build",
"script": "build",
"problemMatcher": []
}
]
}
1 change: 1 addition & 0 deletions __mocks__/exe-icon-extractor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const extractIcon = jest.fn();
31 changes: 29 additions & 2 deletions __tests__/creator-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ import * as mockFs from 'mock-fs';
import * as os from 'os';
import * as path from 'path';

jest.mock('../src/utils/rc-edit', () => ({
createStubExe: jest.fn()
}));

import { MSICreator, UIOptions } from '../src/creator';
import { createStubExe } from '../src/utils/rc-edit';
import { getMockFileSystem, numberOfFiles, root } from './mocks/mock-fs';
import { MockSpawn } from './mocks/mock-spawn';

Expand All @@ -15,10 +20,15 @@ const mockSpawnArgs = {
options: {}
};


beforeAll(() => {
// console.log call needed as workaround to make jest work with mock-fs
console.log('');
// Load into cache
require('callsites');

(createStubExe as jest.Mock).mockReturnValue('C:\\Stub.exe');

jest.mock('child_process', () => ({
execSync(name: string) {
if (name === 'node -v') {
Expand Down Expand Up @@ -76,6 +86,19 @@ const testIncludes = (title: string, ...content: Array<string>) => {
});
};


const regexTestIncludes = (title: string, ...content: Array<RegExp>) => {
return test(`.wxs file includes ${title}`, () => {
if (Array.isArray(content)) {
// We want to be able to search across line breaks and multiple spaces.
const singleLineWxContent = wxsContent.replace(/\s\s+/g, ' ');
content.forEach((innerContent) => {
expect(innerContent.test(singleLineWxContent)).toBeTruthy();
});
}
});
};

let wxsContent = '';
let mockWixInstalled = true;

Expand Down Expand Up @@ -105,10 +128,14 @@ testIncludes('an ApplicationProgramsFolder', '<Directory Id="ApplicationPrograms

testIncludes('a default appUserModelId', 'Key="System.AppUserModel.ID" Value="com.squirrel.Acme.acme"');

regexTestIncludes('versioned app folder', /<Directory\s*Id=".*"\s*Name="app-1\.0\.0"/);

regexTestIncludes('stubbed exe', /<File\s*Name="acme\.exe"\s*Id=".*"\s*Source="C:\\Stub\.exe"/);

test('.wxs file has as many components as we have files', () => {
// Files + Shortcut
// Files + Shortcut + StubExecutable
const count = wxsContent.split('</Component>').length - 1;
expect(count).toEqual(numberOfFiles + 1);
expect(count).toEqual(numberOfFiles + 2);
});

test('MSICreator create() creates Wix file with UI properties', async () => {
Expand Down
16 changes: 13 additions & 3 deletions __tests__/mocks/mock-fs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,28 @@ import * as path from 'path';

export const drive = process.platform === 'win32' ? 'C:' : '/';
export const root = path.join(drive, 'Users', 'tester', 'Code', 'app');
export const tmp = path.join(drive, 'tmp');
export const numberOfFiles = 15;

const staticDir = path.join(__dirname, '../../static');
const staticContent: Record<string, Record<string, any>> = {};
staticContent[staticDir] = {};

const vendorDir = path.join(__dirname, '../../vendor');
const vendorContent: Record<string, Record<string, any>> = {};
vendorContent[vendorDir] = {};

fs.readdirSync(staticDir)
.forEach((file) => {
staticContent[staticDir][file] = fs.readFileSync(path.join(staticDir, file), 'utf-8');
});

fs.readdirSync(vendorDir)
.forEach((file) => {
vendorContent[vendorDir][file] = '';
});


export function getMockFileSystem() {
const mockFiles = {
'locales': {
Expand Down Expand Up @@ -60,8 +71,7 @@ export function getMockFileSystem() {

const system: Record<string, any> = {};
system[root] = mockFiles;

system[tmp] = {};
// Add files needed by this module:
return { ...system, ...staticContent };
return { ...vendorContent, ...system, ...staticContent };
}

100 changes: 57 additions & 43 deletions __tests__/utils/array-to-tree-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,56 +21,70 @@ const mockFiles = [
];

const mockFolderTree = {
__ELECTRON_WIX_MSI_PATH__: `slack`,
__ELECTRON_WIX_MSI_FILES__: [],
resources: {
'__ELECTRON_WIX_MSI_PATH__': `slack${S}resources`,
'__ELECTRON_WIX_MSI_FILES__': [],
'app.asar.unpacked': {
__ELECTRON_WIX_MSI_PATH__: `slack${S}resources${S}app.asar.unpacked`,
__ELECTRON_WIX_MSI_FILES__: [],
node_modules: {
__ELECTRON_WIX_MSI_PATH__: `slack${S}resources${S}app.asar.unpacked${S}node_modules`,
__ELECTRON_WIX_MSI_FILES__: []
},
src: {
__ELECTRON_WIX_MSI_PATH__: `slack${S}resources${S}app.asar.unpacked${S}src`,
__ELECTRON_WIX_MSI_FILES__: []
'__ELECTRON_WIX_MSI_PATH__': `slack`,
'__ELECTRON_WIX_MSI_DIR_NAME__': 'slack',
'__ELECTRON_WIX_MSI_FILES__': [],
'app-1.0.0' : {
__ELECTRON_WIX_MSI_PATH__: `slack`,
__ELECTRON_WIX_MSI_DIR_NAME__: 'app-1.0.0',
__ELECTRON_WIX_MSI_FILES__: [],
resources: {
'__ELECTRON_WIX_MSI_PATH__': `slack${S}resources`,
'__ELECTRON_WIX_MSI_DIR_NAME__': 'resources',
'__ELECTRON_WIX_MSI_FILES__': [],
'app.asar.unpacked': {
__ELECTRON_WIX_MSI_PATH__: `slack${S}resources${S}app.asar.unpacked`,
__ELECTRON_WIX_MSI_DIR_NAME__: 'app.asar.unpacked',
__ELECTRON_WIX_MSI_FILES__: [],
node_modules: {
__ELECTRON_WIX_MSI_PATH__: `slack${S}resources${S}app.asar.unpacked${S}node_modules`,
__ELECTRON_WIX_MSI_DIR_NAME__: 'node_modules',
__ELECTRON_WIX_MSI_FILES__: []
},
src: {
__ELECTRON_WIX_MSI_PATH__: `slack${S}resources${S}app.asar.unpacked${S}src`,
__ELECTRON_WIX_MSI_DIR_NAME__: 'src',
__ELECTRON_WIX_MSI_FILES__: []
}
}
},
locales: {
__ELECTRON_WIX_MSI_PATH__: `slack${S}locales`,
__ELECTRON_WIX_MSI_DIR_NAME__: 'locales',
__ELECTRON_WIX_MSI_FILES__: []
}
},
locales: {
__ELECTRON_WIX_MSI_PATH__: `slack${S}locales`,
__ELECTRON_WIX_MSI_FILES__: []
}
};

const mockFolderFileTree = defaultsDeep(cloneDeep(mockFolderTree), {
__ELECTRON_WIX_MSI_FILES__: [{ name: `slack.exe`, path: `slack${S}slack.exe` }],
resources: {
'__ELECTRON_WIX_MSI_FILES__': [{ name: `text.txt`, path: `slack${S}resources${S}text.txt` }],
'app.asar.unpacked': {
__ELECTRON_WIX_MSI_FILES__: [
{ name: `image.png`, path: `slack${S}resources${S}app.asar.unpacked${S}image.png` },
],
node_modules: {
__ELECTRON_WIX_MSI_FILES__: [
{ name: `package.json`, path: `slack${S}resources${S}app.asar.unpacked${S}node_modules${S}package.json` }
]
},
src: {
__ELECTRON_WIX_MSI_FILES__: [{ name: `slack.exe`, path: `C:${S}temp${S}slack.exe` }],
'app-1.0.0' : {
__ELECTRON_WIX_MSI_FILES__: [{ name: `slack.exe`, path: `slack${S}slack.exe` }],
resources: {
'__ELECTRON_WIX_MSI_FILES__': [{ name: `text.txt`, path: `slack${S}resources${S}text.txt` }],
'app.asar.unpacked': {
__ELECTRON_WIX_MSI_FILES__: [
{ name: `package.json`, path: `slack${S}resources${S}app.asar.unpacked${S}src${S}package.json` }
]
{ name: `image.png`, path: `slack${S}resources${S}app.asar.unpacked${S}image.png` },
],
node_modules: {
__ELECTRON_WIX_MSI_FILES__: [
{ name: `package.json`, path: `slack${S}resources${S}app.asar.unpacked${S}node_modules${S}package.json` }
]
},
src: {
__ELECTRON_WIX_MSI_FILES__: [
{ name: `package.json`, path: `slack${S}resources${S}app.asar.unpacked${S}src${S}package.json` }
]
}
}
},
locales: {
__ELECTRON_WIX_MSI_FILES__: [
{ name: `de-DE.json`, path: `slack${S}locales${S}de-DE.json` },
{ name: `en-US.json`, path: `slack${S}locales${S}en-US.json` }
]
}
},
locales: {
__ELECTRON_WIX_MSI_FILES__: [
{ name: `de-DE.json`, path: `slack${S}locales${S}de-DE.json` },
{ name: `en-US.json`, path: `slack${S}locales${S}en-US.json` }
]
}
}
});

test(`isChild() returns true for a child and parent`, () => {
Expand Down Expand Up @@ -109,9 +123,9 @@ test(`isDirectChild() returns false for a child and non-parent`, () => {
});

test(`arrayToTree() creates a tree structure`, () => {
expect(arrayToTree(mockFolders, `slack`)).toEqual(mockFolderTree);
expect(arrayToTree(mockFolders, `slack`, '1.0.0')).toEqual(mockFolderTree);
});

test(`addFilesToTree() adds files to a tree structure`, () => {
expect(addFilesToTree(mockFolderTree, mockFiles, `slack`)).toEqual(mockFolderFileTree);
expect(addFilesToTree(mockFolderTree, mockFiles, `slack`, `C:${S}temp${S}slack.exe`, '1.0.0')).toEqual(mockFolderFileTree);
});

0 comments on commit 7b4fabb

Please sign in to comment.