Files
meteor/tools/tool-testing/test-utils.js
ekatek ef13ed9926 use selftest to run tests against galaxy
UX Changes:
  - Added a `--galaxy` option to selftest to run tests against galaxy.
    Self-test will NOT run those tests without this option. Self-test will not run any
    other tests WITH this option.

    The motivation here is two-fold:
     - We want to make it easy to use self-test to test Galaxy without running a bunch
       of extra tests. At least, we want this right now, while Galaxy is still in development.

     - Galaxy is currently pretty unstable&slow; we don't want to run our regular test suite against
       Galaxy all the time and slow down the tool development process. Additionally, the environment
       variables required by Galaxy are a pain to set.

    This is a TEMPORARY situation. Eventually, we will want to either merge the two tests together
    (especially once we rotate out Mother...) or we will have a separate unrelated Galaxy test suite
    and move a lot of this stuff here. With time, it will also become more obvious what a better default
    (run Galaxy tests always/run Galaxy tests never/run non-Galaxy-specific tests against Galaxy) is.

    The changes should be pretty self-contained.

 - Added some number of environment variables to use with --galaxy tests. This is a bit complicated
   and will be documented in
     https://mdg.hackpad.com/GalaxyECS-Admin-tasks-RTXJ5YW8pDv#:h=Testing-Galaxy-with-selftest.

Walkthrough:
    - galaxy-utls.js contains basic utils for running Galaxy tests. Use environment variables, etc.

    - galaxy.js contains the acutal test

    - simple-app is an app that responds to HTTP requests and serves some html that we can test to be running

    - minor changes to config.js to allow overriding of the domain name

    - minor changes to auth.js to allow us to automatically login as the (new) test user and use that
      login to start a DDP collection.

    - move a function out of deploy-settings.js into test-utils.js

    - some minor additions to test-utils.js

Reviewed in https://github.com/meteor/meteor/pull/4997.
2015-08-26 19:06:13 -07:00

226 lines
6.7 KiB
JavaScript

var isopackets = require('../tool-env/isopackets.js');
var config = require('../meteor-services/config.js');
var utils = require('../utils/utils.js');
var auth = require('../meteor-services/auth.js');
var selftest = require('./selftest.js');
var httpHelpers = require('../utils/http-helpers.js');
var _ = require('underscore');
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';
};
// 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);
name = config.getFullAppName(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 http://' + name);
run.waitSecs(10);
run.expectExit(0);
return name;
};
exports.cleanUpApp = function (sandbox, name) {
if (name.indexOf(".") === -1) {
name = name + "." + config.getDeployHostname();
}
var run = sandbox.run('deploy', '-D', name);
run.waitSecs(180);
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');
if (appName.indexOf(".") === -1) {
appName = appName + "." + config.getDeployHostname();
}
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 isopackets.load('ddp');
};
var ddpConnect = function (url) {
var DDP = getLoadedPackages()['ddp-client'].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();
};
exports.randomOrgName = function () {
return "selftestorg" + exports.randomString(10);
};
// Logs in as the specified user and creates a randomly named
// organization. Returns the organization name. Calls selftest.fail if
// the organization can't be created.
exports.createOrganization = function (username, password) {
var orgName = exports.randomOrgName();
auth.withAccountsConnection(function (conn) {
try {
conn.call("login", {
meteorAccountsLoginInfo: { username: username, password: password },
clientInfo: {}
});
} catch (err) {
selftest.fail("Failed to log in to Meteor developer accounts\n" +
"with test user: " + err);
}
try {
conn.call("createOrganization", orgName);
} catch (err) {
selftest.fail("Failed to create organization: " + err);
}
})();
return orgName;
};
exports.getMeteorRuntimeConfigFromHTML = function (html) {
var m = html.match(/__meteor_runtime_config__ = JSON.parse\(decodeURIComponent\("([^"]+?)"\)\)/);
if (! m) {
selftest.fail("Can't find __meteor_runtime_config__");
}
return JSON.parse(decodeURIComponent(m[1]));
};
// Poll the given app looking for the correct settings. Throws an error
// if the settings aren't found after a timeout.
exports.checkForSettings = selftest.markStack(function (appName, settings, timeoutSecs) {
var timeoutDate = new Date(new Date().valueOf() + timeoutSecs * 1000);
while (true) {
if (new Date() >= timeoutDate) {
selftest.fail('Expected settings not found on app ' + appName);
}
var result = httpHelpers.request('http://' + appName);
// XXX This is brittle; the test will break if we start formatting the
// __meteor_runtime_config__ JS differently. Ideally we'd do something
// like point a phantom at the deployed app and actually evaluate
// Meteor.settings.
try {
var mrc = exports.getMeteorRuntimeConfigFromHTML(result.body);
} catch (e) {
// ignore
continue;
}
if (_.isEqual(mrc.PUBLIC_SETTINGS, settings['public'])) {
return;
}
}
});