Merge pull request #264 from matrix-org/rav/react_testing_tweaks

Improvements to the react-sdk test framework
This commit is contained in:
Richard van der Hoff 2016-04-08 15:55:59 +01:00
commit 5f96e9980b
6 changed files with 75 additions and 27 deletions

View file

@ -11,11 +11,18 @@ var fs = require('fs');
* If you run karma in multi-run mode (with `npm run test-multi`), it will watch * If you run karma in multi-run mode (with `npm run test-multi`), it will watch
* the tests for changes, and webpack will rebuild using a cache. This is much quicker * the tests for changes, and webpack will rebuild using a cache. This is much quicker
* than a clean rebuild. * than a clean rebuild.
*
* TODO:
* - can we run one test at a time?
*/ */
// the name of the test file. By default, a special file which runs all tests.
//
// TODO: this could be a pattern, and karma would run each file, with a
// separate webpack bundle for each file. But then we get a separate instance
// of the sdk, and each of the dependencies, for each test file, and everything
// gets very confused. Can we persuade webpack to put all of the dependencies
// in a 'common' bundle?
//
var testFile = process.env.KARMA_TEST_FILE || 'test/all-tests.js';
process.env.PHANTOMJS_BIN = 'node_modules/.bin/phantomjs'; process.env.PHANTOMJS_BIN = 'node_modules/.bin/phantomjs';
function fileExists(name) { function fileExists(name) {
@ -33,6 +40,7 @@ if (!fileExists(gsCss)) {
gsCss = 'node_modules/react-gemini-scrollbar/'+gsCss; gsCss = 'node_modules/react-gemini-scrollbar/'+gsCss;
} }
module.exports = function (config) { module.exports = function (config) {
config.set({ config.set({
// frameworks to use // frameworks to use
@ -41,15 +49,15 @@ module.exports = function (config) {
// list of files / patterns to load in the browser // list of files / patterns to load in the browser
files: [ files: [
'test/tests.js', testFile,
gsCss, gsCss,
], ],
// list of files to exclude // list of files to exclude
// //
// This doesn't work. It turns out that it's webpack which does the // This doesn't work. It turns out that it's webpack which does the
// watching of the /test directory (possibly karma only watches // watching of the /test directory (karma only watches `testFile`
// tests.js itself). Webpack watches the directory so that it can spot // itself). Webpack watches the directory so that it can spot
// new tests, which is fair enough; unfortunately it triggers a rebuild // new tests, which is fair enough; unfortunately it triggers a rebuild
// every time a lockfile is created in that directory, and there // every time a lockfile is created in that directory, and there
// doesn't seem to be any way to tell webpack to ignore particular // doesn't seem to be any way to tell webpack to ignore particular
@ -63,7 +71,7 @@ module.exports = function (config) {
// available preprocessors: // available preprocessors:
// https://npmjs.org/browse/keyword/karma-preprocessor // https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: { preprocessors: {
'test/tests.js': ['webpack', 'sourcemap'] 'test/**/*.js': ['webpack', 'sourcemap']
}, },
// test results reporter to use // test results reporter to use
@ -139,7 +147,7 @@ module.exports = function (config) {
}, },
resolve: { resolve: {
alias: { alias: {
'matrix-react-sdk': path.resolve('src/index.js'), 'matrix-react-sdk': path.resolve('test/skinned-sdk.js'),
'sinon': 'sinon/pkg/sinon.js', 'sinon': 'sinon/pkg/sinon.js',
}, },
root: [ root: [

View file

@ -1,11 +1,7 @@
// tests.js // all-tests.js
// //
// Our master test file: uses the webpack require API to find our test files // Our master test file: uses the webpack require API to find our test files
// and run them // and run them
// this is a handly place to make sure the sdk has been skinned
var sdk = require("matrix-react-sdk");
sdk.loadSkin(require('./test-component-index'));
var context = require.context('.', true, /-test\.jsx?$/); var context = require.context('.', true, /-test\.jsx?$/);
context.keys().forEach(context); context.keys().forEach(context);

View file

@ -3,16 +3,21 @@ var TestUtils = require('react-addons-test-utils');
var expect = require('expect'); var expect = require('expect');
var sdk = require('matrix-react-sdk'); var sdk = require('matrix-react-sdk');
var MatrixChat = sdk.getComponent('structures.MatrixChat');
var peg = require('../../../src/MatrixClientPeg');
var test_utils = require('../../test-utils'); var test_utils = require('../../test-utils');
var peg = require('../../../src/MatrixClientPeg.js');
var q = require('q'); var q = require('q');
describe('MatrixChat', function () { describe('MatrixChat', function () {
var MatrixChat; var sandbox;
before(function() {
test_utils.stubClient(); beforeEach(function() {
MatrixChat = sdk.getComponent('structures.MatrixChat'); sandbox = test_utils.stubClient();
});
afterEach(function() {
sandbox.restore();
}); });
it('gives a login panel by default', function () { it('gives a login panel by default', function () {

View file

@ -27,12 +27,19 @@ var test_utils = require('test-utils');
var mockclock = require('mock-clock'); var mockclock = require('mock-clock');
describe('MessagePanel', function () { describe('MessagePanel', function () {
var sandbox;
var clock = mockclock.clock(); var clock = mockclock.clock();
var realSetTimeout = window.setTimeout; var realSetTimeout = window.setTimeout;
var events = mkEvents(); var events = mkEvents();
beforeEach(function() {
test_utils.beforeEach(this);
sandbox = test_utils.stubClient(sandbox);
});
afterEach(function () { afterEach(function () {
clock.uninstall(); clock.uninstall();
sandbox.restore();
}); });
function mkEvents() { function mkEvents() {

View file

@ -1,12 +1,16 @@
/* /*
* test-component-index.js * skinned-sdk.js
* *
* Stub out a bunch of the components which we expect the application to * Skins the react-sdk with a few stub components which we expect the
* provide * application to provide
*/ */
var components = require('../src/component-index.js').components;
var sdk = require("../src/index");
var skin = require('../src/component-index.js');
var stubComponent = require('./components/stub-component.js'); var stubComponent = require('./components/stub-component.js');
var components = skin.components;
components['structures.LeftPanel'] = stubComponent(); components['structures.LeftPanel'] = stubComponent();
components['structures.RightPanel'] = stubComponent(); components['structures.RightPanel'] = stubComponent();
components['structures.RoomDirectory'] = stubComponent(); components['structures.RoomDirectory'] = stubComponent();
@ -18,4 +22,6 @@ components['views.messages.DateSeparator'] = stubComponent({displayName: 'DateSe
components['views.messages.MessageTimestamp'] = stubComponent({displayName: 'MessageTimestamp'}); components['views.messages.MessageTimestamp'] = stubComponent({displayName: 'MessageTimestamp'});
components['views.messages.SenderProfile'] = stubComponent({displayName: 'SenderProfile'}); components['views.messages.SenderProfile'] = stubComponent({displayName: 'SenderProfile'});
module.exports.components = components; sdk.loadSkin(skin);
module.exports = sdk;

View file

@ -1,9 +1,11 @@
"use strict"; "use strict";
var sinon = require('sinon');
var q = require('q');
var peg = require('../src/MatrixClientPeg.js'); var peg = require('../src/MatrixClientPeg.js');
var jssdk = require('matrix-js-sdk'); var jssdk = require('matrix-js-sdk');
var MatrixEvent = jssdk.MatrixEvent; var MatrixEvent = jssdk.MatrixEvent;
var sinon = require('sinon');
/** /**
* Perform common actions before each test case, e.g. printing the test case * Perform common actions before each test case, e.g. printing the test case
@ -21,12 +23,36 @@ module.exports.beforeEach = function(context) {
/** /**
* Stub out the MatrixClient, and configure the MatrixClientPeg object to * Stub out the MatrixClient, and configure the MatrixClientPeg object to
* return it when get() is called. * return it when get() is called.
*
* @returns {sinon.Sandbox}; remember to call sandbox.restore afterwards.
*/ */
module.exports.stubClient = function() { module.exports.stubClient = function() {
var pegstub = sinon.stub(peg); var sandbox = sinon.sandbox.create();
var matrixClientStub = sinon.createStubInstance(jssdk.MatrixClient); var client = {
pegstub.get.returns(matrixClientStub); getHomeserverUrl: sinon.stub(),
getIdentityServerUrl: sinon.stub(),
getPushActionsForEvent: sinon.stub(),
getRoom: sinon.stub(),
loginFlows: sinon.stub(),
on: sinon.stub(),
paginateEventTimeline: sinon.stub().returns(q()),
sendReadReceipt: sinon.stub().returns(q()),
};
// create the peg
// 'sandbox.restore()' doesn't work correctly on inherited methods,
// so we do this for each method
var methods = ['get', 'unset', 'replaceUsingUrls',
'replaceUsingAccessToken'];
for (var i = 0; i < methods.length; i++) {
sandbox.stub(peg, methods[i]);
}
peg.get.returns(client);
return sandbox;
} }