Skip to content

Commit

Permalink
Unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
bitdisaster committed May 6, 2020
1 parent 21df06a commit af60e57
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 23 deletions.
76 changes: 61 additions & 15 deletions __tests__/creator-spec.ts
Expand Up @@ -74,31 +74,47 @@ const defaultOptions = {
outputDirectory: path.join(os.tmpdir(), 'electron-wix-msi-test')
};

const testIncludes = (title: string, ...content: Array<string>) => {
const testIncludesBase = (title: string, expectation: boolean , ...content: Array<string>) => {
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(singleLineWxContent.includes(innerContent)).toBeTruthy();
expect(singleLineWxContent.includes(innerContent)).toBe(expectation);
});
}
});
};

const testIncludes = (title: string, ...content: Array<string>) => {
return testIncludesBase(title, true, ...content );
};

const regexTestIncludes = (title: string, ...content: Array<RegExp>) => {
const testIncludesNot = (title: string, ...content: Array<string>) => {
return testIncludesBase(title, false, ...content );
};


const regexTestIncludesBase = (title: string, expectation: boolean , ...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();
expect(innerContent.test(singleLineWxContent)).toBe(expectation);
});
}
});
};

const regexTestIncludes = (title: string, ...content: Array<RegExp>) => {
return regexTestIncludesBase(title, true, ...content );
};

const regexTestIncludesNot = (title: string, ...content: Array<RegExp>) => {
return regexTestIncludesBase(title, false, ...content );
};

let wxsContent = '';
let mockWixInstalled = true;

Expand Down Expand Up @@ -133,9 +149,9 @@ regexTestIncludes('versioned app folder', /<Directory\s*Id=".*"\s*Name="app-1\.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 + 2 Shortcuts + 1 StubExecutable + 1 installInfo file + 2 purge components
// Files + 2 Shortcuts + 2 special files + 7 registry + 1 purge components
const count = wxsContent.split('</Component>').length - 1;
expect(count).toEqual(numberOfFiles + 6);
expect(count).toEqual(numberOfFiles + 12);
});

test('MSICreator create() creates Wix file with UI properties', async () => {
Expand Down Expand Up @@ -424,12 +440,28 @@ testIncludes('Custom shortcut name', '<Shortcut Id="ApplicationStartMenuShortcut
testIncludes('Single Package Authoring setting', '<Property Id="ALLUSERS" Secure="yes" Value="2" />');
testIncludes('correct default perUser setting', '<Property Id="MSIINSTALLPERUSER" Secure="yes" Value="0" />');
testIncludes('Install path property', '<Property Id="INSTALLPATH">');
testIncludes('Install RegistrySearch', '<RegistrySearch Key="SOFTWARE\\Acme Technologies\\Acme"');
testIncludes('Install RegistrySearch', 'RegistrySearch Key="SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall');
testIncludes('RegistryInstallPath component', '<Component Id="RegistryInstallPath"');
testIncludes('RegistryInstallPath component-ref', '<ComponentRef Id="RegistryInstallPath" />');
testIncludes('PurgeOnUninstall component', '<Component Id="PurgeOnUninstall" ');
testIncludes('PurgeOnUninstall component-ref', '<ComponentRef Id="PurgeOnUninstall" />');

testIncludes('RegistryRunKey component-ref', '<ComponentRef Id="RegistryInstallPath" />');
testIncludes('RegistryRunKey component-ref', '<ComponentRef Id="UninstallDisplayName" />');
testIncludes('RegistryRunKey component-ref', '<ComponentRef Id="UninstallPublisher" />');
testIncludes('RegistryRunKey component-ref', '<ComponentRef Id="UninstallDisplayVersion" />');
testIncludes('RegistryRunKey component-ref', '<ComponentRef Id="UninstallModifyString" />');
testIncludes('RegistryRunKey component-ref', '<ComponentRef Id="UninstallString" />');
testIncludes('RegistryRunKey component-ref', '<ComponentRef Id="UninstallDisplayIcon" />');

testIncludesNot('RegistryRunKey component', '<Component Id="RegistryRunKey"');
testIncludesNot('RegistryRunKey component-ref', '<ComponentRef Id="RegistryRunKey" />');
regexTestIncludesNot('AutoLaunch feature', /<Feature Id="AutoLaunch" Title="Launch On Login" Level="2" .*>/);
regexTestIncludesNot('AutoUpdater feature', /<Feature Id="AutoUpdater" Title="Auto Updater" Level="3" .*>/);
regexTestIncludesNot('Squirrel executable component-ref', /<ComponentRef Id="_msq.exe_.*" \/>/ );
testIncludesNot('Permission component-ref', `<ComponentRef Id="SetFolderPermissions" />`);
testIncludesNot('RegistryRunKey component-ref', '<ComponentRef Id="SetUninstallDisplayVersionPermissions" />');

describe('auto-updater', () => {
test('MSICreator includes Auto-Updater feature', async () => {
const msiCreator = new MSICreator({ ...defaultOptions, features: {autoUpdate: true, autoLaunch: false }});
Expand All @@ -439,9 +471,9 @@ describe('auto-updater', () => {
});

test('.wxs file has as many components as we have files', () => {
// Files + 2 Shortcuts + StubExecutable + installInfo file + Update.exe + Permission Component + 2 purge components
// Files + 2 Shortcuts + 3 special files + 8 registry + 1 permission component + 1 purge components
const count = wxsContent.split('</Component>').length - 1;
expect(count).toEqual(numberOfFiles + 8);
expect(count).toEqual(numberOfFiles + 15);
});

test('.wxs file contains as many component refs as components', () => {
Expand All @@ -450,30 +482,38 @@ describe('auto-updater', () => {
expect(componentCount).toEqual(refCount);
});

regexTestIncludes('Squirrel executable component', /<Component Id="_MsiAwareSquirrel_1.9.1.exe_.*"/);
regexTestIncludes('Squirrel executable component', /<Component Id="_msq.exe_.*"/);

testIncludes('Permission component', `<Component Id="SetFolderPermissions"`);
testIncludes('PermissionEx call', '<util:PermissionEx User="[UPDATERUSERGROUP]" GenericAll="yes" />');
testIncludes('Updater user group property', '<Property Id="UPDATERUSERGROUP" Value="Users" />');

regexTestIncludes('AutoUpdater feature', /<Feature Id="AutoUpdater" Title="Auto Updater" Level="3" .*>/);
regexTestIncludes('Squirrel executable component-ref', /<ComponentRef Id="_MsiAwareSquirrel_1.9.1.exe_.*" \/>/ );
regexTestIncludes('Squirrel executable component-ref', /<ComponentRef Id="_msq.exe_.*" \/>/ );
testIncludes('Permission component-ref', `<ComponentRef Id="SetFolderPermissions" />`);

testIncludes('RegistryRunKey component-ref', '<ComponentRef Id="RegistryInstallPath" />');
testIncludes('RegistryRunKey component-ref', '<ComponentRef Id="UninstallDisplayName" />');
testIncludes('RegistryRunKey component-ref', '<ComponentRef Id="UninstallPublisher" />');
testIncludes('RegistryRunKey component-ref', '<ComponentRef Id="UninstallDisplayVersion" />');
testIncludes('RegistryRunKey component-ref', '<ComponentRef Id="UninstallModifyString" />');
testIncludes('RegistryRunKey component-ref', '<ComponentRef Id="UninstallString" />');
testIncludes('RegistryRunKey component-ref', '<ComponentRef Id="UninstallDisplayIcon" />');
testIncludes('RegistryRunKey component-ref', '<ComponentRef Id="SetUninstallDisplayVersionPermissions" />');
});

describe('auto-launch', () => {
test('MSICreator includes Auto-Updater feature', async () => {
const msiCreator = new MSICreator({ ...defaultOptions, features: {autoUpdate: false, autoLaunch: true }});
const { wxsFile } = await msiCreator.create();
wxsContent = await fs.readFile(wxsFile, 'utf-8');
console.log(wxsContent);
expect(wxsFile).toBeTruthy();
});

test('.wxs file has as many components as we have files', () => {
// Files + 2 Shortcuts + StubExecutable + installInfo file + 2 purge components + run key
// Files + 2 Shortcuts + 2 special files + 8 registry + 1 purge components
const count = wxsContent.split('</Component>').length - 1;
expect(count).toEqual(numberOfFiles + 7);
expect(count).toEqual(numberOfFiles + 13);
});

test('.wxs file contains as many component refs as components', () => {
Expand All @@ -484,6 +524,13 @@ describe('auto-launch', () => {

testIncludes('RegistryRunKey component', '<Component Id="RegistryRunKey"');
testIncludes('RegistryRunKey component-ref', '<ComponentRef Id="RegistryRunKey" />');
testIncludes('RegistryRunKey component-ref', '<ComponentRef Id="RegistryInstallPath" />');
testIncludes('RegistryRunKey component-ref', '<ComponentRef Id="UninstallDisplayName" />');
testIncludes('RegistryRunKey component-ref', '<ComponentRef Id="UninstallPublisher" />');
testIncludes('RegistryRunKey component-ref', '<ComponentRef Id="UninstallDisplayVersion" />');
testIncludes('RegistryRunKey component-ref', '<ComponentRef Id="UninstallModifyString" />');
testIncludes('RegistryRunKey component-ref', '<ComponentRef Id="UninstallString" />');
testIncludes('RegistryRunKey component-ref', '<ComponentRef Id="UninstallDisplayIcon" />');
regexTestIncludes('AutoLaunch feature', /<Feature Id="AutoLaunch" Title="Launch On Login" Level="2" .*>/);
});

Expand All @@ -492,7 +539,6 @@ describe('perUser install by default', () => {
const msiCreator = new MSICreator({ ...defaultOptions, defaultInstallMode: 'perUser' });
const { wxsFile } = await msiCreator.create();
wxsContent = await fs.readFile(wxsFile, 'utf-8');
console.log(wxsContent);
expect(wxsFile).toBeTruthy();
});

Expand Down
38 changes: 30 additions & 8 deletions __tests__/utils/array-to-tree-spec.ts
@@ -1,12 +1,13 @@
import { cloneDeep, defaultsDeep } from 'lodash';
import * as mockFs from 'mock-fs';

import { Registry } from '../../src/interfaces';
import { addFilesToTree, arrayToTree, isChild, isDirectChild } from '../../src/utils/array-to-tree';
import { separator as S } from '../../src/utils/separator';
import { getMockFileSystem } from '../mocks/mock-fs';

const installInfoRegex = process.platform === 'win32' ? /C:\\tmp\\\.installInfo.*\\\.installInfo\.json/ : /\/tmp\/\.installInfo.*\.installInfo\.json/;
const msiAwareSquirrelRegex = process.platform === 'win32' ? /.*\\vendor\\MsiAwareSquirrel_1\.9\.1\.exe/ : /.*\/vendor\/MsiAwareSquirrel_1\.9\.1\.exe/;
const msqSquirrelRegex = process.platform === 'win32' ? /.*\\vendor\\msq.exe/ : /.*\/vendor\/msq.exe/;
const originalTmp = process.env.TEMP;

const mockFolders = [
Expand All @@ -27,6 +28,27 @@ const mockFiles = [
`slack${S}locales${S}en-US.json`,
];

const mockSpecialFiles = [
{ name: `slack.exe`, path: `C:${S}temp${S}slack.exe`},
{ name: `.installInfo.json`, path: 'C:\\temp\\installInfo.json' }
];

const mockUpdaterSpecialFiles = [
...mockSpecialFiles,
{ name: `Update.exe`, path: 'C:\\temp\\Update.exe' }
];

const mockRegistry: Array<Registry> = [
{
id: 'RegistryInstallPath',
root: 'HKMU',
name: 'InstallPath',
key: 'SOFTWARE\\{{Manufacturer}}\\{{ApplicationName}}',
type: 'string',
value: '[APPLICATIONROOTDIRECTORY]',
}
];

const mockFolderTree = {
__ELECTRON_WIX_MSI_PATH__: `slack`,
__ELECTRON_WIX_MSI_DIR_NAME__: 'slack',
Expand Down Expand Up @@ -73,7 +95,7 @@ const mockFolderTree = {
const mockFolderFileTree = defaultsDeep(cloneDeep(mockFolderTree), {
__ELECTRON_WIX_MSI_FILES__: [ { name: 'slack.exe', path: `C:${S}temp${S}slack.exe` },
{ name: '.installInfo.json',
path: expect.stringMatching(installInfoRegex) } ],
path: 'C:\\temp\\installInfo.json' }],
__ELECTRON_WIX_MSI_REGISTRY__: [{
id: 'RegistryInstallPath',
key: 'SOFTWARE\\{{Manufacturer}}\\{{ApplicationName}}',
Expand Down Expand Up @@ -165,19 +187,19 @@ test(`arrayToTree() creates a tree structure`, () => {
});

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

test(`addFilesToTree() adds files to a tree structure on Mac`, () => {
test(`addFilesToTree() adds files to a tree structure`, () => {
const updaterMockFolderFileTree = cloneDeep(mockFolderFileTree);
updaterMockFolderFileTree.__ELECTRON_WIX_MSI_FILES__ = [ { name: 'slack.exe', path: `C:${S}temp${S}slack.exe` },
{ name: '.installInfo.json',
path: expect.stringMatching(installInfoRegex) },
path: 'C:\\temp\\installInfo.json' },
{ name: 'Update.exe',
path: expect.stringMatching(msiAwareSquirrelRegex)
} ];
path: 'C:\\temp\\Update.exe'
} ];
const folderFileTree =
addFilesToTree(mockFolderTree, mockFiles, `slack`, `C:${S}temp${S}slack.exe`, true, false, '1.0.0');
addFilesToTree(mockFolderTree, mockFiles, mockUpdaterSpecialFiles, mockRegistry, '1.0.0');
expect(folderFileTree).toEqual(updaterMockFolderFileTree);
});

0 comments on commit af60e57

Please sign in to comment.