Files
meteor/tools/test-utils.js
David Glasser 08a6fa99fd Don't use _.once or instanceof with uniload
_.once has the problem that if you call the once'd function while it is
still in progress (re-entrantly or in another Fiber), it returns
undefined immediately.  That's bad for uniload! uniload already has a
cache, so just use that.  (In the future, perhaps detect an attempt to
uniload something that's currently in the process of being uniloaded in
another fiber and block until the other fiber is ready.)

Using instanceof with things you've uniloaded is a little sketchy: maybe
two different uniload calls will end up with two different copies of
Package.meteor.Meteor.Error, and it seems kind of hairy to ensure you're
not mixing and matching copies.  However, Meteor.Errors are all tagged
with a string errorType, which fills me with much less fear,
uncertainty, and doubt than instanceof.
2014-08-17 23:37:38 -07:00

203 lines
6.0 KiB
JavaScript

var _ = require('underscore');
var release = require('./release.js');
var uniload = require('./uniload.js');
var config = require('./config.js');
var utils = require('./utils.js');
var randomString = function (charsCount) {
var chars = 'abcdefghijklmnopqrstuvwxyz';
var str = '';
for (var i = 0; i < charsCount; i++) {
str = str + chars.charAt(Math.floor(Math.random() * chars.length));
}
return str;
};
exports.accountsCommandTimeoutSecs = 15 * utils.timeoutScaleFactor;
exports.randomString = randomString;
var randomAppName = function () {
return 'selftest-app-' + randomString(10);
};
exports.randomAppName = randomAppName;
exports.randomUserEmail = function () {
return 'selftest-user-' + randomString(15) + '@guerrillamail.com';
};
var ensureLegacyReleaseDownloaded = function (sandbox) {
// Ensure we have 0.7.0.1 downloaded. This version didn't actually support
// --get-ready for a built release, but it's an easy way to verify we're
// actually running an old version.
var run = sandbox.run('--release', '0.7.0.1', '--get-ready');
run.waitSecs(75);
run.matchErr('only works in a checkout\n');
run.expectExit(1);
};
// Creates an app and deploys it with an old release. 'password' is
// optional. Returns the name of the deployed app.
exports.createAndDeployLegacyApp = function (sandbox, password) {
var name = randomAppName();
sandbox.createApp(name, 'empty');
sandbox.cd(name);
ensureLegacyReleaseDownloaded(sandbox);
var runArgs = ['deploy', '--release', '0.7.0.1', name];
if (password)
runArgs.push('-P');
var run = sandbox.run.apply(sandbox, runArgs);
if (password) {
run.waitSecs(10);
run.match('New Password:');
run.write(password + '\n');
run.match('New Password (again):');
run.write(password + '\n');
}
run.waitSecs(90);
run.match('Now serving at ' + name + '.meteor.com');
// XXX: We should wait for it to exit with code 0, but it times out for some reason.
run.stop();
return name;
};
exports.cleanUpLegacyApp = function (sandbox, name, password) {
ensureLegacyReleaseDownloaded(sandbox);
var run = sandbox.run('deploy', '--release', '0.7.0.1', '-D', name);
if (password) {
run.waitSecs(10);
run.matchErr('Password:');
run.write(password + '\n');
}
run.waitSecs(60);
run.match('Deleted');
// XXX same as above, we should be waiting for exit code 0, but the
// process appears to never exit.
run.stop();
};
// Creates an app and deploys it. Assumes the sandbox is already logged
// in. Returns the name of the deployed app. Options:
// - settingsFile: a path to a settings file to deploy with
// - appName: app name to use; will be generated randomly if not
// provided
// - templateApp: the name of the template app to use. defaults to 'empty'
exports.createAndDeployApp = function (sandbox, options) {
options = options || {};
var name = options.appName || randomAppName();
sandbox.createApp(name, options.templateApp || 'empty');
sandbox.cd(name);
var runArgs = ['deploy', name];
if (options.settingsFile) {
runArgs.push('--settings');
runArgs.push(options.settingsFile);
}
var run = sandbox.run.apply(sandbox, runArgs);
run.waitSecs(90);
run.match('Now serving at ' + name + '.meteor.com');
run.waitSecs(10);
run.expectExit(0);
return name;
};
exports.cleanUpApp = function (sandbox, name) {
var run = sandbox.run('deploy', '-D', name);
run.waitSecs(90);
run.match('Deleted');
run.expectExit(0);
return name;
};
exports.login = function (s, username, password) {
var run = s.run('login');
run.waitSecs(15);
run.matchErr('Username:');
run.write(username + '\n');
run.matchErr('Password:');
run.write(password + '\n');
run.waitSecs(15);
run.matchErr('Logged in as ' + username + ".");
run.expectExit(0);
};
exports.logout = function (s) {
var run = s.run('logout');
run.waitSecs(15);
run.matchErr('Logged out');
run.expectExit(0);
};
exports.getUserId = function (s) {
var data = JSON.parse(s.readSessionFile());
return data.sessions[config.getUniverse()].userId;
};
var registrationUrlRegexp =
/https:\/\/www\.meteor\.com\/setPassword\?([a-zA-Z0-9\+\/]+)/;
exports.registrationUrlRegexp = registrationUrlRegexp;
// In the sandbox `s`, create and deploy a new app with an unregistered
// email address. Returns the registration token from the printed URL in
// the deploy message.
exports.deployWithNewEmail = function (s, email, appName) {
s.createApp('deployapp', 'empty');
s.cd('deployapp');
var run = s.run('deploy', appName);
run.waitSecs(exports.accountsCommandTimeoutSecs);
run.matchErr('Email:');
run.write(email + '\n');
run.waitSecs(90);
// Check that we got a prompt to set a password on meteor.com.
run.matchErr('set a password');
var urlMatch = run.matchErr(registrationUrlRegexp);
if (! urlMatch || ! urlMatch.length || ! urlMatch[1]) {
throw new Error("Missing registration token");
}
var token = urlMatch[1];
run.expectExit(0);
return token;
};
var getLoadedPackages = function () {
return uniload.load({
packages: ['livedata']
});
};
var ddpConnect = function (url) {
var DDP = getLoadedPackages().livedata.DDP;
return DDP.connect(url);
};
exports.ddpConnect = ddpConnect;
// Given a registration token created by doing a deferred registration
// with `email`, makes a DDP connection to the accounts server and
// finishes the registration process.
exports.registerWithToken = function (token, username, password, email) {
// XXX It might make more sense to hard-code the DDP url to
// https://www.meteor.com, since that's who the sandboxes are talking
// to.
var accountsConn = ddpConnect(config.getAuthDDPUrl());
var registrationTokenInfo = accountsConn.call('registrationTokenInfo',
token);
var registrationCode = registrationTokenInfo.code;
accountsConn.call('register', {
username: username,
password: password,
emails: [email],
token: token,
code: registrationCode
});
accountsConn.close();
};