mirror of https://github.com/zulip/zulip.git
283 lines
8.7 KiB
JavaScript
283 lines
8.7 KiB
JavaScript
var common = (function () {
|
|
|
|
var exports = {};
|
|
|
|
var test_credentials = require('../../var/casper/test_credentials.js').test_credentials;
|
|
|
|
function timestamp() {
|
|
return new Date().getTime();
|
|
}
|
|
|
|
// The timestamp of the last message send or get_events result.
|
|
var last_send_or_update = -1;
|
|
|
|
function log_in(credentials) {
|
|
if (credentials === undefined) {
|
|
credentials = test_credentials.default_user;
|
|
}
|
|
|
|
casper.test.info('Logging in');
|
|
casper.fill('form[action^="/accounts/login"]', {
|
|
username: credentials.username,
|
|
password: credentials.password
|
|
}, true /* submit form */);
|
|
}
|
|
|
|
exports.initialize_casper = function (viewport) {
|
|
if (casper.zulip_initialized !== undefined) {
|
|
return;
|
|
}
|
|
casper.zulip_initialized = true;
|
|
// These initialization steps will fail if they run before
|
|
// casper.start has been called.
|
|
|
|
// Set default viewport size to something reasonable
|
|
casper.page.viewportSize = viewport || {width: 1280, height: 1024};
|
|
|
|
// Fail if we get a JavaScript error in the page's context.
|
|
// Based on the example at http://phantomjs.org/release-1.5.html
|
|
//
|
|
// casper.on('error') doesn't work (it never gets called) so we
|
|
// set this at the PhantomJS level.
|
|
casper.page.onError = function (msg, trace) {
|
|
casper.test.error(msg);
|
|
casper.echo('Traceback:');
|
|
trace.forEach(function (item) {
|
|
casper.echo(' ' + item.file + ':' + item.line);
|
|
});
|
|
casper.exit(1);
|
|
};
|
|
|
|
// Capture screens from all failures
|
|
var casper_failure_count = 1;
|
|
casper.test.on('fail', function failure() {
|
|
if (casper_failure_count <= 10) {
|
|
casper.capture("/tmp/casper-failure" + casper_failure_count + ".png");
|
|
casper_failure_count++;
|
|
}
|
|
});
|
|
|
|
// Update last_send_or_update whenever get_events returns.
|
|
casper.on('resource.received', function (resource) {
|
|
if (/\/json\/get_events/.test(resource.url)) {
|
|
last_send_or_update = timestamp();
|
|
}
|
|
});
|
|
|
|
casper.on('load.finished', function () {
|
|
casper.evaluateOrDie(function () {
|
|
$(document).trigger($.Event('phantom_page_loaded'));
|
|
return true;
|
|
});
|
|
});
|
|
|
|
casper.evaluate(function () {
|
|
window.localStorage.clear();
|
|
});
|
|
};
|
|
|
|
exports.then_log_in = function (credentials) {
|
|
casper.then(function () {
|
|
log_in(credentials);
|
|
});
|
|
};
|
|
|
|
exports.start_and_log_in = function (credentials, viewport) {
|
|
casper.start('http://127.0.0.1:9981/accounts/login', function () {
|
|
exports.initialize_casper(viewport);
|
|
log_in(credentials);
|
|
});
|
|
};
|
|
|
|
exports.then_log_out = function () {
|
|
casper.then(function () {
|
|
casper.test.info('Logging out');
|
|
casper.click('li[title="Log out"] a');
|
|
});
|
|
};
|
|
|
|
// Put the specified string into the field_selector, then
|
|
// select the menu item matching item by typing str.
|
|
exports.select_item_via_typeahead = function (field_selector, str, item) {
|
|
casper.then(function () {
|
|
casper.test.info('Looking in ' + field_selector + ' to select ' + str + ', ' + item);
|
|
|
|
casper.evaluate(function (field_selector, str, item) {
|
|
// Set the value and then send a bogus keyup event to trigger
|
|
// the typeahead.
|
|
$(field_selector)
|
|
.focus()
|
|
.val(str)
|
|
.trigger($.Event('keyup', { which: 0 }));
|
|
|
|
// You might think these steps should be split by casper.then,
|
|
// but apparently that's enough to make the typeahead close (??),
|
|
// but not the first time.
|
|
|
|
// Trigger the typeahead.
|
|
// Reaching into the guts of Bootstrap Typeahead like this is not
|
|
// great, but I found it very hard to do it any other way.
|
|
|
|
var tah = $(field_selector).data().typeahead;
|
|
tah.mouseenter({
|
|
currentTarget: $('.typeahead:visible li:contains("'+item+'")')[0]
|
|
});
|
|
tah.select();
|
|
}, {field_selector:field_selector, str: str, item: item});
|
|
});
|
|
};
|
|
|
|
exports.enable_page_console = function () {
|
|
// Call this (after casper.start) to enable printing page-context
|
|
// console.log (plus some CasperJS-specific messages) to the
|
|
// terminal.
|
|
casper.on('remote.message', function (msg) {
|
|
casper.echo(msg);
|
|
});
|
|
};
|
|
|
|
exports.check_form = function (form_selector, expected, test_name) {
|
|
var values = casper.getFormValues(form_selector);
|
|
var k;
|
|
for (k in expected) {
|
|
if (expected.hasOwnProperty(k)) {
|
|
casper.test.assertEqual(values[k], expected[k],
|
|
test_name ? (test_name + ": " + k) : undefined);
|
|
}
|
|
}
|
|
};
|
|
|
|
// Wait for any previous send to finish, then send a message.
|
|
exports.then_send_message = function (type, params) {
|
|
casper.waitForSelector('#compose-send-button:enabled');
|
|
casper.waitForSelector('#new_message_content', function () {
|
|
if (type === "stream") {
|
|
casper.page.sendEvent('keypress', "c");
|
|
} else if (type === "private") {
|
|
casper.page.sendEvent('keypress', "C");
|
|
} else {
|
|
casper.test.assertTrue(false, "send_message got valid message type");
|
|
}
|
|
casper.fill('form[action^="/json/messages"]', params);
|
|
casper.click('#compose-send-button');
|
|
});
|
|
casper.waitFor(function emptyComposeBox() {
|
|
return casper.getFormValues('form[action^="/json/messages"]').content === '';
|
|
}, function () {
|
|
last_send_or_update = timestamp();
|
|
});
|
|
};
|
|
|
|
// Get message headings (recipient rows) and bodies out of the DOM.
|
|
// casper.evaluate plays weird tricks with a closure, evaluating
|
|
// it in the web page's context. Passing arguments from the test
|
|
// script's context is awkward (c.f. the various appearances of
|
|
// 'table' here).
|
|
exports.get_rendered_messages = function (table) {
|
|
return casper.evaluate(function (table) {
|
|
var tbl = $('#'+table);
|
|
return {
|
|
headings: $.map(tbl.find('.recipient_row .message-header-contents'), function (elem) {
|
|
return elem.innerText;
|
|
}),
|
|
|
|
bodies: $.map(tbl.find('.message_content'), function (elem) {
|
|
return elem.innerHTML;
|
|
})
|
|
};
|
|
}, {
|
|
table: table
|
|
});
|
|
};
|
|
|
|
exports.get_form_field_value = function (selector) {
|
|
return casper.evaluate(function (selector) {
|
|
return $(selector).val();
|
|
}, selector);
|
|
};
|
|
|
|
// Inject key presses by running some jQuery code in page context.
|
|
// PhantomJS and CasperJS don't provide a clean way to insert key
|
|
// presses by code, only strings of printable characters.
|
|
exports.keypress = function (code) {
|
|
casper.evaluate(function (code) {
|
|
$('body').trigger($.Event('keydown', { which: code }));
|
|
}, {
|
|
code: code
|
|
});
|
|
};
|
|
|
|
// Send a whole list of messages using then_send_message.
|
|
exports.then_send_many = function (msgs) {
|
|
msgs.forEach(function (msg) {
|
|
exports.then_send_message(
|
|
(msg.stream !== undefined) ? 'stream' : 'private',
|
|
msg);
|
|
});
|
|
};
|
|
|
|
// Wait to receive queued messages.
|
|
exports.wait_for_receive = function (step) {
|
|
// Wait until the last send or get_events result was more than 1000 ms ago.
|
|
casper.waitFor(function () {
|
|
return (timestamp() - last_send_or_update) > 1000;
|
|
}, step);
|
|
};
|
|
|
|
// Wait until the loading spinner goes away (helpful just after logging in).
|
|
exports.wait_for_load = function (step) {
|
|
casper.waitWhileVisible('#page_loading_indicator', step);
|
|
};
|
|
|
|
// innerText sometimes gives us non-breaking space characters, and occasionally
|
|
// a different number of spaces than we expect.
|
|
exports.normalize_spaces = function (str) {
|
|
return str.replace(/\s+/g, ' ');
|
|
};
|
|
|
|
exports.ltrim = function (str) {
|
|
return str.replace(/^\s+/g, '');
|
|
};
|
|
|
|
exports.rtrim = function (str) {
|
|
return str.replace(/\s+$/g, '');
|
|
};
|
|
|
|
exports.trim = function (str) {
|
|
return exports.rtrim(exports.ltrim(str));
|
|
};
|
|
|
|
// Call get_rendered_messages and then check that the last few headings and
|
|
// bodies match the specified arrays.
|
|
exports.expected_messages = function (table, headings, bodies) {
|
|
casper.test.assertVisible('#'+table,
|
|
table + ' is visible');
|
|
|
|
var msg = exports.get_rendered_messages(table);
|
|
|
|
casper.test.assertEquals(
|
|
msg.headings.slice(-headings.length).map(exports.normalize_spaces).map(exports.trim),
|
|
headings.map(exports.trim),
|
|
'Got expected message headings');
|
|
|
|
casper.test.assertEquals(
|
|
msg.bodies.slice(-bodies.length),
|
|
bodies,
|
|
'Got expected message bodies');
|
|
};
|
|
|
|
exports.un_narrow = function () {
|
|
casper.test.info('Un-narrowing');
|
|
common.keypress(27); // Esc
|
|
};
|
|
|
|
return exports;
|
|
|
|
}());
|
|
|
|
// For inclusion with CasperJS
|
|
try {
|
|
exports.common = common;
|
|
} catch (e) {
|
|
}
|