blob: 2974d9609f50424921b11d970ce00c2c44e04dbd [file] [log] [blame]
import './index';
import { $, $$ } from 'common-sk/modules/dom';
import fetchMock from 'fetch-mock';
import {
canvaskit, gm, svg, trstatus,
} from './demo_data';
import {
setUpElementUnderTest,
eventPromise,
setQueryString,
expectQueryStringToEqual,
} from '../../../infra-sk/modules/test_util';
import { testOnlySetSettings } from '../settings';
import { ByBlamePageSk } from './byblame-page-sk';
import { expect } from 'chai';
describe('byblame-page-sk', () => {
const newInstance = setUpElementUnderTest<ByBlamePageSk>('byblame-page-sk');
const loadedByblamePageSk =
(opts: {defaultCorpus?: string, baseRepoUrl?: string} = {}): Promise<ByBlamePageSk> => {
testOnlySetSettings({
defaultCorpus: opts.defaultCorpus || 'gm',
baseRepoURL: opts.baseRepoUrl || 'https://skia.googlesource.com/skia.git',
});
return new Promise((resolve) => {
let endTaskCalls = 0;
const byBlamePageSk = newInstance((ele) => {
ele.addEventListener('end-task', () => {
endTaskCalls++;
if (endTaskCalls === 2) { // Wait for 2 RPCs to finish.
resolve(byBlamePageSk);
}
});
});
});
};
beforeEach(async () => {
// Clear query string before each test case. This is needed for test cases
// that exercise the stateReflector and the browser's back/forward buttons.
setQueryString('');
});
afterEach(() => {
expect(fetchMock.done()).to.be.true; // All mock RPCs called at least once.
// Remove fetch mocking to prevent test cases interfering with each other.
fetchMock.reset();
});
it('shows loading indicator', async () => {
fetchMock.get('/json/v1/trstatus', trstatus);
// We'll resolve this RPC later to give the "loading" text a chance to show.
let resolveByBlameRpc = (_: {}) => {};
fetchMock.get(
'/json/v1/byblame?query=source_type%3Dgm',
new Promise((resolve) => resolveByBlameRpc = resolve),
);
// Instantiate page, but don't wait for it to load as we want to see the
// "loading" text.
const event = eventPromise('end-task');
testOnlySetSettings({ defaultCorpus: 'gm' });
const byblamePageSk = newInstance();
// Make these assertions immediately, i.e. do not wait for the page to load.
expect($$<HTMLElement>('.entries', byblamePageSk)!.innerText)
.to.equal('Loading untriaged digests...');
expectHasEmptyBlames(byblamePageSk);
// Resolve RPC. This allows the page to finish loading.
resolveByBlameRpc(gm);
// Assert that page finished loading.
await event;
});
it('correctly renders a page with empty results', async () => {
fetchMock.get('/json/v1/trstatus', trstatus);
fetchMock.get('/json/v1/byblame?query=source_type%3Dcanvaskit', canvaskit);
const byblamePageSk = await loadedByblamePageSk({ defaultCorpus: 'canvaskit' });
expectQueryStringToEqual('');
expectCorporaToBe(byblamePageSk, ['canvaskit', 'gm (114)', 'svg (18)']);
expectSelectedCorpusToBe(byblamePageSk, 'canvaskit');
expect($$<HTMLElement>('.entries', byblamePageSk)!.innerText)
.to.equal('No untriaged digests for corpus canvaskit.');
expectHasEmptyBlames(byblamePageSk);
});
it('renders blames for default corpus if URL does not include a corpus',
async () => {
fetchMock.get('/json/v1/trstatus', trstatus);
fetchMock.get('/json/v1/byblame?query=source_type%3Dgm', gm);
const byblamePageSk = await loadedByblamePageSk({ defaultCorpus: 'gm' });
expectQueryStringToEqual(''); // No state reflected to the URL.
expectSelectedCorpusToBe(byblamePageSk, 'gm (114)');
expectHasGmBlames(byblamePageSk);
});
it('renders blames for corpus specified in URL', async () => {
fetchMock.get('/json/v1/trstatus', trstatus);
fetchMock.get('/json/v1/byblame?query=source_type%3Dsvg', svg);
setQueryString('?corpus=svg');
const byblamePageSk = await loadedByblamePageSk({ defaultCorpus: 'gm' });
expectSelectedCorpusToBe(byblamePageSk, 'svg (18)');
expectHasSvgBlames(byblamePageSk);
});
it('switches corpora when corpus-selector-sk is clicked', async () => {
fetchMock.get('/json/v1/trstatus', trstatus);
fetchMock.get('/json/v1/byblame?query=source_type%3Dgm', gm);
fetchMock.get('/json/v1/byblame?query=source_type%3Dsvg', svg);
const byblamePageSk = await loadedByblamePageSk({ defaultCorpus: 'gm' });
expectQueryStringToEqual('');
expectSelectedCorpusToBe(byblamePageSk, 'gm (114)');
expectHasGmBlames(byblamePageSk);
await selectCorpus(byblamePageSk, 'svg (18)');
expectQueryStringToEqual('?corpus=svg');
expectSelectedCorpusToBe(byblamePageSk, 'svg (18)');
expectHasSvgBlames(byblamePageSk);
});
describe('Base repository URL', () => {
beforeEach(() => {
fetchMock.get('/json/v1/trstatus', trstatus);
fetchMock.get('/json/v1/byblame?query=source_type%3Dgm', gm);
});
it('renders commit links correctly with repo hosted on googlesource',
async () => {
const byblamePageSk = await loadedByblamePageSk({
defaultCorpus: 'gm',
baseRepoUrl: 'https://skia.googlesource.com/skia.git',
});
expectSelectedCorpusToBe(byblamePageSk, 'gm (114)');
expectHasGmBlames(byblamePageSk);
expectFirstCommitLinkHrefToBe(
byblamePageSk,
'https://skia.googlesource.com/skia.git/+show/05f6a01bf9fd25be9e5fff4af5505c3945058b1d',
);
});
it('renders commit links correctly with repo hosted on GitHub',
async () => {
const byblamePageSk = await loadedByblamePageSk({
defaultCorpus: 'gm',
baseRepoUrl: 'https://github.com/google/skia',
});
expectSelectedCorpusToBe(byblamePageSk, 'gm (114)');
expectHasGmBlames(byblamePageSk);
expectFirstCommitLinkHrefToBe(
byblamePageSk,
'https://github.com/google/skia/commit/05f6a01bf9fd25be9e5fff4af5505c3945058b1d',
);
});
});
});
function selectCorpus(byblamePageSk: ByBlamePageSk, corpus: string) {
const event = eventPromise('end-task');
$$<HTMLElement>(`corpus-selector-sk li[title="${corpus}"]`, byblamePageSk)!.click();
return event;
}
function expectCorporaToBe(byblamePageSk: ByBlamePageSk, corpora: string[]) {
expect($<HTMLLIElement>('corpus-selector-sk li').map((li) => li.innerText))
.to.deep.equal(corpora);
}
function expectSelectedCorpusToBe(byblamePageSk: ByBlamePageSk, corpus: string) {
expect($$<HTMLLIElement>('corpus-selector-sk li.selected', byblamePageSk)!.innerText)
.to.equal(corpus);
}
function expectHasEmptyBlames(byblamePageSk: ByBlamePageSk) {
expectBlames(byblamePageSk, 0);
}
function expectHasGmBlames(byblamePageSk: ByBlamePageSk) {
// Triage links for first and last entries obtained from the demo page.
expectBlames(
byblamePageSk,
6,
'/search?blame=' +
'4edb719f1bc49bae585ff270df17f08039a96b6c:252cdb782418949651cc5eb7d467c57ddff3d1c7:' +
'a1050ed2b1120613d9ae9587e3c0f4116e17337f:3f7c865936cc808af26d88bc1f5740a29cfce200:' +
'05f6a01bf9fd25be9e5fff4af5505c3945058b1d&corpus=gm&query=source_type%3Dgm',
'/search?blame=342fbc54844d0d3fc9d20e20b45115db1e33395b&corpus=gm&query=source_type%3Dgm',
);
}
function expectHasSvgBlames(byblamePageSk: ByBlamePageSk) {
// Triage links for first and last entries obtained from the demo page.
expectBlames(
byblamePageSk,
5,
'/search?blame=d2c67f44f8c2351e60e6ee224a060e916cd44f34&corpus=svg&query=source_type%3Dsvg',
'/search?blame=e1e197186238d8d304a39db9f94258d9584a8973&corpus=svg&query=source_type%3Dsvg',
);
}
function expectBlames(
byblamePageSk: ByBlamePageSk,
numBlames: number,
firstTriageLinkHref?: string,
lastTriageLinkHref?: string,
) {
const entries = $('byblameentry-sk', byblamePageSk);
expect(entries).to.have.length(numBlames);
// Spot check first and last entries.
if (firstTriageLinkHref) {
expect($$<HTMLAnchorElement>('a.triage', entries[0])!.href)
.to.have.string(firstTriageLinkHref);
}
if (lastTriageLinkHref) {
expect($$<HTMLAnchorElement>('a.triage', entries[entries.length - 1])!.href)
.to.have.string(lastTriageLinkHref);
}
}
function expectFirstCommitLinkHrefToBe(byblamePageSk: ByBlamePageSk, expectedHref: string) {
const firstCommitLinkSelector = 'byblameentry-sk:first-child ul.blames a:first-child';
const actualHref = $$<HTMLAnchorElement>(firstCommitLinkSelector, byblamePageSk)!.href;
expect(actualHref).to.equal(expectedHref);
}