/*
Copyright 2016 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
const React = require('react');
const ReactDOM = require("react-dom");
const TestUtils = require('react-addons-test-utils');
const expect = require('expect');
import sinon from 'sinon';
const sdk = require('matrix-react-sdk');
const MessagePanel = sdk.getComponent('structures.MessagePanel');
import UserSettingsStore from '../../../src/UserSettingsStore';
import MatrixClientPeg from '../../../src/MatrixClientPeg';
const test_utils = require('test-utils');
const mockclock = require('mock-clock');
let client;
// wrap MessagePanel with a component which provides the MatrixClient in the context.
const WrappedMessagePanel = React.createClass({
childContextTypes: {
matrixClient: React.PropTypes.object,
},
getChildContext: function() {
return {
matrixClient: client,
};
},
render: function() {
return ;
},
});
describe('MessagePanel', function() {
const clock = mockclock.clock();
const realSetTimeout = window.setTimeout;
const events = mkEvents();
let sandbox = null;
beforeEach(function() {
test_utils.beforeEach(this);
sandbox = test_utils.stubClient();
client = MatrixClientPeg.get();
client.credentials = {userId: '@me:here'};
UserSettingsStore.getSyncedSettings = sinon.stub().returns({});
});
afterEach(function() {
clock.uninstall();
sandbox.restore();
});
function mkEvents() {
const events = [];
const ts0 = Date.now();
for (let i = 0; i < 10; i++) {
events.push(test_utils.mkMessage(
{
event: true, room: "!room:id", user: "@user:id",
ts: ts0 + i*1000,
}));
}
return events;
}
it('should show the events', function() {
const res = TestUtils.renderIntoDocument(
,
);
// just check we have the right number of tiles for now
const tiles = TestUtils.scryRenderedComponentsWithType(
res, sdk.getComponent('rooms.EventTile'));
expect(tiles.length).toEqual(10);
});
it('should show the read-marker in the right place', function() {
const res = TestUtils.renderIntoDocument(
,
);
const tiles = TestUtils.scryRenderedComponentsWithType(
res, sdk.getComponent('rooms.EventTile'));
// find the
which wraps the read marker
const rm = TestUtils.findRenderedDOMComponentWithClass(res, 'mx_RoomView_myReadMarker_container');
// it should follow the which wraps the event tile for event 4
const eventContainer = ReactDOM.findDOMNode(tiles[4]).parentNode;
expect(rm.previousSibling).toEqual(eventContainer);
});
it('shows a ghost read-marker when the read-marker moves', function(done) {
// fake the clock so that we can test the velocity animation.
clock.install();
clock.mockDate();
const parentDiv = document.createElement('div');
// first render with the RM in one place
let mp = ReactDOM.render(
, parentDiv);
const tiles = TestUtils.scryRenderedComponentsWithType(
mp, sdk.getComponent('rooms.EventTile'));
const tileContainers = tiles.map(function(t) {
return ReactDOM.findDOMNode(t).parentNode;
});
// find the which wraps the read marker
const rm = TestUtils.findRenderedDOMComponentWithClass(mp, 'mx_RoomView_myReadMarker_container');
expect(rm.previousSibling).toEqual(tileContainers[4]);
// now move the RM
mp = ReactDOM.render(
, parentDiv);
// now there should be two RM containers
const found = TestUtils.scryRenderedDOMComponentsWithClass(mp, 'mx_RoomView_myReadMarker_container');
expect(found.length).toEqual(2);
// the first should be the ghost
expect(found[0].previousSibling).toEqual(tileContainers[4]);
const hr = found[0].children[0];
// the second should be the real thing
expect(found[1].previousSibling).toEqual(tileContainers[6]);
// advance the clock, and then let the browser run an animation frame,
// to let the animation start
clock.tick(1500);
realSetTimeout(() => {
// then advance it again to let it complete
clock.tick(1000);
realSetTimeout(() => {
// the ghost should now have finished
expect(hr.style.opacity).toEqual('0');
done();
}, 100);
}, 100);
});
it('shows only one ghost when the RM moves twice', function() {
const parentDiv = document.createElement('div');
// first render with the RM in one place
let mp = ReactDOM.render(
, parentDiv);
const tiles = TestUtils.scryRenderedComponentsWithType(
mp, sdk.getComponent('rooms.EventTile'));
const tileContainers = tiles.map(function(t) {
return ReactDOM.findDOMNode(t).parentNode;
});
// now move the RM
mp = ReactDOM.render(
, parentDiv);
// now there should be two RM containers
let found = TestUtils.scryRenderedDOMComponentsWithClass(mp, 'mx_RoomView_myReadMarker_container');
expect(found.length).toEqual(2);
// the first should be the ghost
expect(tileContainers.indexOf(found[0].previousSibling)).toEqual(4);
// the second should be the real RM
expect(tileContainers.indexOf(found[1].previousSibling)).toEqual(6);
// and move the RM again
mp = ReactDOM.render(
, parentDiv);
// still two RM containers
found = TestUtils.scryRenderedDOMComponentsWithClass(mp, 'mx_RoomView_myReadMarker_container');
expect(found.length).toEqual(2);
// they should have moved
expect(tileContainers.indexOf(found[0].previousSibling)).toEqual(6);
expect(tileContainers.indexOf(found[1].previousSibling)).toEqual(8);
});
});