meteor-desktop
Version:
Build a Meteor's desktop client with hot code push.
284 lines (237 loc) • 9.88 kB
JavaScript
;var regeneratorRuntime;module.link('regenerator-runtime/runtime',{default(v){regeneratorRuntime=v}},0);var chai;module.link('chai',{default(v){chai=v}},1);var dirty;module.link('dirty-chai',{default(v){dirty=v}},2);var sinonChai;module.link('sinon-chai',{default(v){sinonChai=v}},3);var sinon;module.link('sinon',{default(v){sinon=v}},4);var fs;module.link('fs',{default(v){fs=v}},5);var path;module.link('path',{default(v){path=v}},6);var shell;module.link('shelljs',{default(v){shell=v}},7);var Application;module.link('spectron',{Application(v){Application=v}},8);var mockery;module.link('mockery',{default(v){mockery=v}},9);var mockerySettings;module.link('../helpers/mockerySettings',{default(v){mockerySettings=v}},10);var paths;module.link('../helpers/paths',{default(v){paths=v}},11);var meteorDesktop;module.link('../../lib/index',{default(v){meteorDesktop=v}},12);/* eslint-disable no-console */
// eslint-disable-next-line no-unused-vars
shell.config.fatal = true;
chai.use(sinonChai);
chai.use(dirty);
const { describe, it } = global;
const { expect } = chai;
/**
* This is first experimental integration test.
*/
let appDir = '';
/**
* Waits until a promise from a function finally returns true.
* @param {Function} functionReturningPromise - function to test
* @param {number} ms - expiration timeout in milliseconds
* @returns {Promise}
*/
function waitFor(functionReturningPromise, ms = 10000) {
return new Promise((resolve, reject) => {
let invokerTimeout;
let timeout;
const invokeFunction = () =>
functionReturningPromise()
.then((result) => {
console.log(result);
if (result) {
clearTimeout(invokerTimeout);
clearTimeout(timeout);
resolve();
} else {
invokerTimeout = setTimeout(invokeFunction, 500);
}
})
.catch(() => {
invokerTimeout = setTimeout(invokeFunction, 500);
});
invokeFunction();
timeout = setTimeout(() => {
clearTimeout(invokerTimeout);
reject('timeout expired on waitFor');
}, ms);
});
}
/**
* Waits for the app to load and appear.
* @param {Object} app - test app
* @returns {{app: (Application|*), window: *}}
*/
async function waitForApp(app) {
await app.client.waitUntilWindowLoaded();
const window = app.browserWindow;
// Wait for the main window for max 30seconds. Adjust to your app.
await waitFor(window.isVisible, 30000);
expect(await app.client.getWindowCount()).to.equal(1);
await app.client.waitUntil(
async () => app.client.execute(
() => document.readyState === 'complete'
)
);
return { app, window };
}
process.env.PLUGIN_VERSION = '1.7.0';
describe('desktop', () => {
let MeteorDesktop;
before(() => {
appDir = path.join(paths.testsIntegrationTmpPath, 'test-desktop');
});
beforeEach(() => {
try {
fs.unlinkSync('meteor.log');
} catch (e) {
// No worries...
}
});
describe('add to scripts', () => {
let exitStub;
before(() => {
mockery.registerMock('path', {
resolve: dir => dir,
join: () => `${appDir}${path.sep}package.json`
});
mockery.enable(mockerySettings);
});
after(() => {
mockery.deregisterMock('path');
mockery.disable();
exitStub.restore();
});
it('should add a `desktop` entry in package.json', () => {
exitStub = sinon.stub(process, 'exit');
require('../../lib/scripts/addToScripts'); // eslint-disable-line
const packageJson = JSON.parse(fs.readFileSync(path.join(appDir, 'package.json'), 'utf8'));
expect(exitStub).to.have.callCount(0);
expect(packageJson.scripts.desktop).to.be.equal('meteor-desktop');
});
});
describe('build involved tests', () => {
let exitStub;
let app;
before(() => {
process.env.MONGO_URL = 'none';
// Load plugins directly from the package instead of those published to atmosphere.
process.env.METEOR_PACKAGE_DIRS = path.resolve(path.join(__dirname, '..', '..', 'plugins'));
});
async function runIt() {
// Run it.
app = new Application({
path: require(path.join(appDir, 'node_modules', 'electron')),
args: [path.join(appDir, '.meteor', 'desktop-build')],
requireName: 'electronRequire',
startTimeout: 60000,
env: {
NODE_ENV: 'test',
ELECTRON_ENV: 'test',
METEOR_DESKTOP_NO_SPLASH_SCREEN: 1
},
chromeDriverLogPath: path.join(__dirname, 'chrome.log')
});
try {
await app.start();
await waitForApp(app);
const title = await app.client.getTitle();
expect(title).to.equal('test-desktop');
const text = await app.client.getText('h1');
expect(text).to.equal('Welcome to Meteor!');
} catch (e) {
console.log(e);
console.log(e.trace);
console.log(fs.readFileSync(path.join(__dirname, 'chrome.log'), 'utf-8'));
}
}
afterEach(async () => {
exitStub.restore();
if (app && app.isRunning()) {
await app.stop();
}
});
beforeEach(() => {
exitStub = sinon.stub(process, 'exit').callsFake(() => {
try {
console.log(fs.readFileSync('meteor.log', 'utf8'));
} catch (e) {
// Nothing to do.
}
exitStub.restore();
process.exit(1);
});
});
it('expose electron modules', async () => {
const platformsPath = path.join(appDir, '.meteor', 'platforms');
let platforms = fs.readFileSync(platformsPath);
if (!platforms.includes('android')) {
platforms += '\nandroid\n';
fs.writeFileSync(platformsPath, platforms);
}
if (!fs.existsSync(path.join(appDir, '.meteor', 'local', 'cordova-build', 'www', 'application'))) {
try {
shell.exec('meteor build ../build --server=127.0.0.1:3080 --verbose', { cwd: appDir });
} catch (e) {
//
}
}
MeteorDesktop = meteorDesktop(
appDir,
appDir,
{
ddpUrl: 'http://127.0.0.1:3080',
build: true,
output: appDir,
skipMobileBuild: true,
forceCordovaBuild: true
}
);
await MeteorDesktop.init();
const settingsJsonPath = path.join(appDir, '.desktop', 'settings.json');
const settingJson = JSON.parse(fs.readFileSync(settingsJsonPath));
settingJson.exposedModules = ['webFrame'];
fs.writeFileSync(settingsJsonPath, JSON.stringify(settingJson, null, 2));
await MeteorDesktop.build();
await runIt();
// Test the exposedModules functionality.
const result = await app.client.execute(
() => Desktop.electron.webFrame.getZoomFactor()
);
expect(result.value).to.equal(1);
}).timeout(10 * 60000);
it('should build installer', async () => {
MeteorDesktop = meteorDesktop(
appDir,
appDir,
{
ddpUrl: 'http://127.0.0.1:3080',
build: true,
output: appDir,
scaffold: true,
skipMobileBuild: true,
forceCordovaBuild: true,
skipRemoveMobilePlatform: true
}
);
if (fs.existsSync(path.join(appDir, MeteorDesktop.env.paths.installerDir))) {
shell.rm('-rf', MeteorDesktop.env.paths.installerDir);
}
// Build the installer.
try {
await MeteorDesktop.buildInstaller(true);
} catch (e) {
throw new Error(e);
}
// For now we are just making an assumption that it went ok
// if it did not throw an error.
expect(fs.existsSync(
path.join(appDir, MeteorDesktop.env.paths.installerDir)
)).to.be.true();
}).timeout(10 * 60000);
if (process.env.TRAVIS || process.env.APPVEYOR) {
it('should build with -b', async () => {
MeteorDesktop = meteorDesktop(
appDir,
appDir,
{
ddpUrl: 'http://127.0.0.1:3080',
build: true,
output: appDir,
scaffold: true,
skipMobileBuild: !!process.env.TRAVIS,
forceCordovaBuild: !!process.env.TRAVIS,
skipRemoveMobilePlatform: true
}
);
// Build the app.
await MeteorDesktop.build();
await runIt();
}).timeout(10 * 60000);
}
});
});