blob: efa9455d5dcbe0e030562d072a4deabe8e031d13 [file] [log] [blame]
import './index.js';
import { $, $$ } from 'common-sk/modules/dom';
import {
changelistSummaries_5,
changelistSummaries_5_offset5,
changelistSummaries_5_offset10,
empty
} from './test_data';
import { eventPromise, expectQueryStringToEqual } from '../test_util';
import { fetchMock } from 'fetch-mock';
describe('changelists-page-sk', () => {
// A reusable HTML element in which we create our element under test.
const container = document.createElement('div');
document.body.appendChild(container);
beforeEach(function() {
// Clear out any query params we might have to not mess with our current state.
setQueryString('');
});
beforeEach(function() {
// These are the default offset/page_size params
fetchMock.get('/json/changelists?offset=0&size=50&active=true', JSON.stringify(changelistSummaries_5));
fetchMock.catch(404);
});
afterEach(function() {
// Completely remove the mocking which allows each test
// to be able to mess with the mocked routes w/o impacting other tests.
fetchMock.reset();
});
afterEach(function() {
container.innerHTML = '';
});
// calls the test callback with an element under test 'ele'.
// We can't put the describes inside the whenDefined callback because
// that doesn't work on Firefox (and possibly other places).
function createElement(test) {
return window.customElements.whenDefined('changelists-page-sk').then(() => {
container.innerHTML = `<changelists-page-sk></changelists-page-sk>`;
expect(container.firstElementChild).to.not.be.null;
test(container.firstElementChild);
});
}
function whenPageLoads(test) {
// The changelists-page-sk emits an 'end-task' event when each fetch finishes.
// For now, there is only one, but this logic may have to be tweaked if we
// do multiple.
let ran = false;
let ele = null;
const fn = (e) => {
e.stopPropagation(); // Prevent interference with eventPromise('end-task').
// reset for next time
container.removeEventListener('end-task', fn);
if (!ran) {
ran = true; // prevent multiple runs if the test makes the
// app go busy (e.g. if it calls fetch).
test(ele);
}
};
// add the listener and then create the element to make sure we don't miss
// the busy-end event. The busy-end event should trigger when all fetches
// are done and the page is rendered.
container.addEventListener('end-task', fn);
createElement((e) => {
ele = e;
});
}
//===============TESTS START====================================
describe('html layout', () => {
it('should make a table with 5 rows in the body', (done) => {
whenPageLoads((ele) => {
const tbl = $$('table', ele);
expect(tbl).to.not.be.null;
const rows = $('tbody tr', ele);
expect(rows.length).to.equal(5); // one row per item in changelistSummaries_5
done();
});
});
it('has icons that indicate the status', (done) => {
whenPageLoads((ele) => {
const rows = $('tbody tr', ele);
// First row has an open CL.
let icon = $$('cached-icon-sk', rows[0]);
expect(icon).to.not.be.null;
// Fourth row has an abandoned CL.
icon = $$('block-icon-sk', rows[3]);
expect(icon).to.not.be.null;
// Fifth row has an closed CL.
icon = $$('done-icon-sk', rows[4]);
expect(icon).to.not.be.null;
done();
});
});
}); // end describe('html layout')
describe('api calls', () => {
it('includes pagination params in request to changelists', (done) => {
whenPageLoads((ele) => {
fetchMock.resetHistory();
fetchMock.get('/json/changelists?offset=100&size=10', JSON.stringify(empty));
// pretend these were loaded in via stateReflector
ele._offset = 100;
ele._page_size = 10;
ele._showAll = true;
ele._fetch().then(done);
});
});
it('includes the active params unless show_all is set', (done) => {
whenPageLoads((ele) => {
fetchMock.resetHistory();
fetchMock.get('/json/changelists?offset=100&size=10&active=true', JSON.stringify(empty));
// pretend these were loaded in via stateReflector
ele._offset = 100;
ele._page_size = 10;
ele._showAll = false;
ele._fetch().then(done);
});
});
}); // end describe('api calls')
describe('navigation', () => {
it('responds to the browser back/forward buttons', (done) => {
// First page of results.
fetchMock.get(
'/json/changelists?offset=0&size=5&active=true',
JSON.stringify(changelistSummaries_5));
// Second page of results.
fetchMock.get(
'/json/changelists?offset=5&size=5&active=true',
JSON.stringify(changelistSummaries_5_offset5));
// Third page of results.
fetchMock.get(
'/json/changelists?offset=10&size=5&active=true',
JSON.stringify(changelistSummaries_5_offset10));
// Random query string value before instantiating the component under
// test. We'll test that we can navigate back to this URL using the
// browser's back button.
setQueryString('?hello=world');
// Query string at component instantiation. This specifies the page size
// required for the mock RPCs above to work.
setQueryString('?page_size=5');
whenPageLoads(async (el) => {
expectQueryStringToEqual('?page_size=5');
expectFirstPage();
await goToNextPage(el);
expectQueryStringToEqual('?offset=5&page_size=5');
expectSecondPage();
await goToNextPage(el);
expectQueryStringToEqual('?offset=10&page_size=5');
expectThirdPage();
await goBack();
expectQueryStringToEqual('?offset=5&page_size=5');
expectSecondPage();
// State at component instantiation.
await goBack();
expectQueryStringToEqual('?page_size=5');
expectFirstPage();
// State before the component was instantiated.
await goBack();
expectQueryStringToEqual('?hello=world');
await goForward();
expectQueryStringToEqual('?page_size=5');
expectFirstPage();
await goForward();
expectQueryStringToEqual('?offset=5&page_size=5');
expectSecondPage();
await goForward();
expectQueryStringToEqual('?offset=10&page_size=5');
expectThirdPage();
done();
});
});
}); // end describe('navigation')
describe('dynamic content', () => {
it('responds to clicking the show all checkbox', (done) => {
whenPageLoads((ele) => {
fetchMock.get('/json/changelists?offset=0&size=50', JSON.stringify(empty));
// click on the input inside the checkbox, otherwise, we see double
// events, since checkbox-sk "re-throws" the click event.
const showAllBox = $$('.controls checkbox-sk input', ele);
expect(showAllBox).to.not.be.null;
expect(ele._showAll).to.equal(false);
expectQueryStringToEqual('');
showAllBox.click();
expect(ele._showAll).to.equal(true);
expectQueryStringToEqual('?page_size=50&show_all=true');
showAllBox.click();
expect(ele._showAll).to.equal(false);
expectQueryStringToEqual('?page_size=50');
showAllBox.click();
expect(ele._showAll).to.equal(true);
expectQueryStringToEqual('?page_size=50&show_all=true');
done();
});
});
}); // end describe('dynamic content')
function setQueryString(q) {
history.pushState(
null, '', window.location.origin + window.location.pathname + q);
}
function goToNextPage(el) {
const event = eventPromise('end-task');
$$('pagination-sk button.next', el).click();
return event;
}
function goBack() {
const event = eventPromise('end-task');
history.back();
return event;
}
function goForward() {
const event = eventPromise('end-task');
history.forward();
return event;
}
function expectFirstPage(changelistsPageSk) {
expect($('td.owner', changelistsPageSk)[0].innerText).to.contain('alpha');
}
function expectSecondPage(changelistsPageSk) {
expect($('td.owner', changelistsPageSk)[0].innerText).to.contain('zeta');
}
function expectThirdPage(changelistsPageSk) {
expect($('td.owner', changelistsPageSk)[0].innerText).to.contain('lambda');
}
});