@dbg-riskit/angular-testing
Version:
1,304 lines (1,279 loc) • 60.1 kB
JavaScript
import '@dbg-riskit/angular-polyfill';
import 'zone.js/testing';
import { getTestBed, tick, discardPeriodicTasks, TestBed } from '@angular/core/testing';
import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';
import * as i0 from '@angular/core';
import { EventEmitter, Injectable, Component, Directive, Input, Inject, NgModule } from '@angular/core';
import { MatMenuTrigger, MatMenuItem } from '@angular/material/menu';
import { By } from '@angular/platform-browser';
import * as i1 from '@dbg-riskit/angular-file';
import { CSVFileDownloadDirective, FileDownloadDirective, FileModule } from '@dbg-riskit/angular-file';
import * as fileSaver from 'file-saver';
import * as i1$2 from '@dbg-riskit/angular-view';
import { RISK_INITIAL_LOAD_SELECTOR, RISK_NO_DATA_SELECTOR, LayoutComponent, NoopAnimationMessageComponent, RISK_GOOD_SELECTOR, RISK_ERROR_SELECTOR, RISK_INFO_SELECTOR, RISK_MESSAGE_SELECTOR, RISK_WARN_SELECTOR, RISK_UPDATE_FAILED_SELECTOR, CommonViewModule, NoopAnimationsCommonViewModule } from '@dbg-riskit/angular-view';
export { LayoutComponent, NoopAnimationMessageComponent, NoopAnimationsCommonViewModule } from '@dbg-riskit/angular-view';
import { throwError, of, timer, EMPTY, BehaviorSubject } from 'rxjs';
import { switchMap, defaultIfEmpty, map } from 'rxjs/operators';
import { MatCard } from '@angular/material/card';
import { MatButton, MatAnchor } from '@angular/material/button';
import { MatButtonToggle } from '@angular/material/button-toggle';
import { MatIcon } from '@angular/material/icon';
import { MatTooltip } from '@angular/material/tooltip';
import { secureRandom, globalScope } from '@dbg-riskit/common';
import * as i1$1 from '@dbg-riskit/angular-datatable';
import { PagingComponent, DataTableRowDetailExpanderComponent, HIGHLIGHTER_CLASS, DataTableComponent, HighlighterDirective, DataTableModule } from '@dbg-riskit/angular-datatable';
import { MatSidenavContainer, MatSidenav } from '@angular/material/sidenav';
import { MatToolbar } from '@angular/material/toolbar';
import { Router, NavigationEnd, UrlSegmentGroup, UrlSegment, ActivatedRoute, RouterModule } from '@angular/router';
import * as i1$3 from '@dbg-riskit/angular-auth';
import { AuthRoutingFlowService, AUTH_CONFIG, AuthService } from '@dbg-riskit/angular-auth';
import { AUTH_PROVIDER } from '@dbg-riskit/angular-common';
// Has to be first in this order
const COMPILE_TIMEOUT_INTERVAL = Math.pow(2, 31) - 1;
function initTestEnvironment() {
Error.stackTraceLimit = 10;
jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000;
// TODO: Quick fix for memory leaks
window.addEventListener = () => {
return;
};
window.document.addEventListener = () => {
return;
};
// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), {
teardown: { destroyAfterEach: false }
});
}
/** Button events to pass to `DebugElement.triggerEventHandler` for RouterLink event handler */
const BUTTON_CLICK_EVENTS = {
left: { button: 0 },
right: { button: 2 }
};
/** Simulate element click. Defaults to mouse left-button click event. */
function click(el, eventObj = BUTTON_CLICK_EVENTS.left) {
if (el instanceof HTMLElement) {
el.click();
}
else {
el.triggerEventHandler('click', eventObj);
}
}
function setNgModelValue(element, value, realAsync = false) {
if (!(element.nativeElement instanceof HTMLInputElement)) {
throw new Error('Not an instance of HTMLInputElement');
}
const input = element.nativeElement;
input.value = value;
dispatchEvent(input, 'input'); // tell Angular
if (!realAsync) {
tick();
}
}
function setNgModelSelectValue(element, selectedIndex, realAsync = false) {
if (!(element.nativeElement instanceof HTMLSelectElement)) {
throw new Error('Not an instance of HTMLInputElement');
}
const input = element.nativeElement;
input.selectedIndex = selectedIndex;
dispatchEvent(input, 'change'); // tell Angular
if (!realAsync) {
tick();
}
}
function dispatchEvent(element, eventName) {
if (element instanceof HTMLElement) {
element.dispatchEvent(newEvent(eventName));
}
else if (element instanceof Window) {
element.dispatchEvent(newEvent(eventName));
}
else {
element.nativeElement.dispatchEvent(newEvent(eventName));
}
}
/**
* Create custom DOM event the old fashioned way
*
* https://developer.mozilla.org/en-US/docs/Web/API/Event/initEvent
* Although officially deprecated, some browsers (phantom) don't accept the preferred "new Event(eventName)"
*/
function newEvent(eventName, bubbles = false, cancelable = false) {
const evt = document.createEvent('CustomEvent'); // MUST be 'CustomEvent'
evt.initCustomEvent(eventName, bubbles, cancelable, null);
return evt;
}
const FAKE_HTTP_ASYNC_TIMEOUT = 1000;
class HttpServiceStub {
constructor() {
this.value = [];
this.error = [];
this.unauthorized = new EventEmitter();
}
returnValue(value) {
this.value.push(value);
}
popReturnValue() {
return this.value.pop();
}
shiftReturnValue() {
return this.value.shift();
}
throwError(value) {
this.error.push(value);
}
get(request) {
if (this.error.length) {
const error = this.error.shift();
return throwError(error);
}
const value = this.value.shift();
return of(value);
}
post(request) {
return this.get(request);
}
}
HttpServiceStub.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.6", ngImport: i0, type: HttpServiceStub, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
HttpServiceStub.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.2.6", ngImport: i0, type: HttpServiceStub });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.6", ngImport: i0, type: HttpServiceStub, decorators: [{
type: Injectable
}] });
class HttpAsyncServiceStub extends HttpServiceStub {
get(request, auth = true) {
return timer(FAKE_HTTP_ASYNC_TIMEOUT).pipe(switchMap(() => super.get(request)));
}
post(request) {
return this.get(request);
}
}
HttpAsyncServiceStub.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.6", ngImport: i0, type: HttpAsyncServiceStub, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
HttpAsyncServiceStub.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.2.6", ngImport: i0, type: HttpAsyncServiceStub });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.6", ngImport: i0, type: HttpAsyncServiceStub, decorators: [{
type: Injectable
}] });
class MessageComponentDef {
constructor(debugElement) {
this.debugElement = debugElement;
if (debugElement == null) {
throw new Error('Debug element not found!');
}
}
get text() {
return this.debugElement.query(By.directive(MatCard)).nativeElement.textContent.replace(/\n\s*/g, ' ')
.replace(/\r\s*/g, ' ').trim();
}
}
class Page {
constructor(fixture) {
this.fixture = fixture;
this._timeOffset = 0;
this.debugElement = fixture.debugElement;
this.component = this.debugElement.componentInstance;
}
detectChanges(millis = 0) {
this.fixture.detectChanges();
tick(millis);
this._timeOffset += millis;
}
advanceAndDetectChanges(millis = 0) {
tick(millis);
this._timeOffset += millis;
this.detectChanges();
}
advanceHTTP() {
this.advanceAndDetectChanges(FAKE_HTTP_ASYNC_TIMEOUT);
}
advanceAndDetectChangesUsingOffset(millis) {
this.advanceAndDetectChanges(millis - this._timeOffset);
this.resetTimeOffset();
}
resetTimeOffset() {
this._timeOffset = 0;
}
destroy() {
this.fixture.destroy();
try {
// Move a lot into fututre ;)
tick(60 * 60 * 1000);
discardPeriodicTasks();
}
catch (ignore) {
// Nothing to do...
}
}
}
class PageWithLoading extends Page {
constructor(fixture) {
super(fixture);
}
get initialLoadComponent() {
const element = this.debugElement.query(By.css(RISK_INITIAL_LOAD_SELECTOR));
if (element) {
return new MessageComponentDef(element);
}
return null;
}
get noDataComponent() {
const element = this.debugElement.query(By.css(RISK_NO_DATA_SELECTOR));
if (element) {
return new MessageComponentDef(element);
}
return null;
}
}
class CSVDownloadMenuPage extends Page {
constructor(fixture) {
super(fixture);
}
get downloadWindowsLink() {
// Open the menu first
click(this.debugElement.query(By.directive(MatMenuTrigger)));
this.detectChanges(500);
return new DownloadLink(this.debugElement.queryAll(By.directive(MatMenuItem))[0], this);
}
get downloadUnixLink() {
// Open the menu first
click(this.debugElement.query(By.directive(MatMenuTrigger)));
this.detectChanges(500);
return new DownloadLink(this.debugElement.queryAll(By.directive(MatMenuItem))[1], this);
}
}
class DownloadLink {
constructor(element, page) {
this.element = element;
this.page = page;
}
click() {
this.setupBlobConstructorSpy();
this.setupSaveBlobSpy();
click(this.element);
this.page.detectChanges();
}
get blobSpy() {
this.setupBlobConstructorSpy();
return this._blobSpy;
}
setupBlobConstructorSpy() {
if (!this._blobSpy) {
let downloadDirective;
try {
downloadDirective = this.element.injector.get(CSVFileDownloadDirective);
}
catch (_) {
downloadDirective = this.element.injector.get(FileDownloadDirective);
}
this._blobSpy = spyOn(downloadDirective, 'createBlob').and.callThrough();
}
}
get saveSpy() {
this.setupSaveBlobSpy();
return this._saveBlobSpy;
}
setupSaveBlobSpy() {
if (!this._saveBlobSpy) {
this._saveBlobSpy = spyOn(fileSaver, 'saveAs');
}
}
}
class DownloadTestComponent {
}
DownloadTestComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.6", ngImport: i0, type: DownloadTestComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
DownloadTestComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.6", type: DownloadTestComponent, selector: "ng-component", ngImport: i0, template: `
<a [risk-download]="data"
[risk-download-content-type]="contentType"
[risk-download-filename]="filename">Download</a>
`, isInline: true, directives: [{ type: i1.FileDownloadDirective, selector: "[risk-download]", inputs: ["risk-download", "risk-download-content-type", "risk-download-filename"] }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.6", ngImport: i0, type: DownloadTestComponent, decorators: [{
type: Component,
args: [{
template: `
<a [risk-download]="data"
[risk-download-content-type]="contentType"
[risk-download-filename]="filename">Download</a>
`
}]
}] });
class DownloadTestComponentPage extends Page {
constructor(fixture) {
super(fixture);
}
get downloadLink() {
return new DownloadLink(this.debugElement.query(By.directive(FileDownloadDirective)), this);
}
}
class DataTableDefinition {
constructor(debugElement, page) {
this.debugElement = debugElement;
this.page = page;
}
get component() {
return this.debugElement.componentInstance;
}
get data() {
return this.component.plainData;
}
get element() {
return this.debugElement.query(By.css('.risk-data-table-wrapper > table'));
}
get header() {
return new TableHeader(this.debugElement.query((de) => de.references.mainHeader), this.page);
}
get sorting() {
return new TableSorting(this, this.page);
}
get body() {
return new TableBody(this.debugElement.query((de) => de.references.mainBody), this.page);
}
get footer() {
return new TableFooter(this.debugElement.query((de) => de.references.mainFooter));
}
get recordsCount() {
return new RecordsCount(this.debugElement.query(By.css('.risk-data-table-page-count')));
}
get pager() {
return new Pager(this.debugElement.query(By.directive(PagingComponent)), this.page);
}
}
// <editor-fold defaultstate="collapsed" desc="Table header">
class TableHeader {
constructor(element, page) {
this.element = element;
this.page = page;
}
get rows() {
return this.element.queryAll(By.css('tr')).map((element) => {
return new TableHeaderRow(element, this.page);
});
}
get cells() {
return this.element.queryAll(By.css('th')).map((element) => {
return new TableHeaderCell(element, this.page);
});
}
}
class TableHeaderRow {
constructor(element, page) {
this.element = element;
this.page = page;
}
get cells() {
return this.element.queryAll(By.css('th')).map((element) => {
return new TableHeaderCell(element, this.page);
});
}
}
class TableHeaderCell {
constructor(element, page) {
this.element = element;
this.page = page;
}
get sortingHandle() {
const handle = this.element.query(By.directive(MatButton));
if (handle) {
return new SortingHandle(this.page, handle);
}
return null;
}
get tooltip() {
const handle = this.element.query(By.directive(MatTooltip));
if (handle) {
return handle.injector.get(MatTooltip).message;
}
return null;
}
get title() {
const textNode = this.element.childNodes.find((node) => node.nativeNode.nodeType === Node.TEXT_NODE);
if (textNode != null) {
return textNode
.nativeNode.textContent.trim();
}
return '';
}
get colspan() {
return this.element.nativeElement.colspan;
}
get rowspan() {
return this.element.nativeElement.rowspan;
}
}
// <editor-fold defaultstate="collapsed" desc="Sorting">
class TableSorting {
constructor(table, page) {
this.table = table;
this.page = page;
}
get handles() {
const handles = this.table.debugElement.query((de) => de.references.mainHeader)
.queryAll(By.directive(MatButton));
if (!handles) {
return [];
}
return handles.map((handle) => {
return new SortingHandle(this.page, handle);
});
}
get detailRowHandles() {
const handles = this.table.debugElement.query(By.css('.risk-data-table-detail')).query(By.css('thead'))
.queryAll(By.directive(MatButton));
if (!handles) {
return null;
}
return handles.map((handle) => {
return new SortingHandle(this.page, handle);
});
}
get currentOrdering() {
return this.table.component.ordering;
}
checkSorting(firstNRows = this.table.component.rows.length, criterium) {
// WARN: call data once as it calls .map on all table rows
const data = this.table.data;
let ordering;
if (criterium) {
ordering = [criterium].concat(this.table.component._defaultOrdering);
}
else {
ordering = this.currentOrdering;
}
for (let i = 1; i < Math.min(data.length, firstNRows); i++) {
ordering.some((criteria) => {
//noinspection EqualityComparisonWithCoercionJS
const valueA = criteria.get(data[i - 1]);
const valueB = criteria.get(data[i]);
if (valueA == null && valueB == null) {
return false;
}
expect(valueA).not.toBeNull();
expect(valueA).not.toBeUndefined();
if (valueB != null) {
if (criteria.descending) {
expect(valueA >= valueB)
.toBeTruthy('Expect: ' + valueA + ' >= '
+ valueB);
}
else {
expect(valueA <= valueB)
.toBeTruthy('Expect: ' + valueA + ' <= '
+ valueB);
}
}
return valueA !== valueB;
});
}
}
}
class SortingHandle {
constructor(page, handle) {
this.page = page;
this.handle = handle;
}
click() {
click(this.handle);
this.page.detectChanges();
}
}
// </editor-fold>
// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="Table body">
class TableBody {
constructor(element, page) {
this.element = element;
this.page = page;
}
get rows() {
return this.element.queryAll((de) => de.references.masterRow).map((element) => {
return new TableBodyRow(element, this.page);
});
}
get cells() {
let cells = [];
this.element.queryAll((de) => de.references.masterRow).forEach((row) => {
cells = cells.concat(row.queryAll(By.css('td')).map((cell) => {
return new TableBodyCell(cell);
}));
});
return cells;
}
}
class TableBodyRow {
constructor(element, page) {
this.element = element;
this.page = page;
}
expandRow() {
click(this.element);
this.page.detectChanges();
}
get expander() {
return new RowExpander(this.element.query(By.directive(DataTableRowDetailExpanderComponent)).query(By.directive(MatAnchor)));
}
get cells() {
return this.element.queryAll(By.css('td')).map((element) => {
return new TableBodyCell(element);
});
}
get rowDetail() {
const parent = this.element.parent;
if (parent != null) {
const next = parent.children[parent.children.indexOf(this.element) + 1];
if (next && !next.references.masterRow) {
return new TableBodyDetail(next, this.page);
}
}
return null;
}
get highlighted() {
return this.element.nativeElement.classList.contains(HIGHLIGHTER_CLASS);
}
}
class RowExpander {
constructor(element) {
this.element = element;
}
get icon() {
return this.element.query(By.directive(MatIcon)).nativeElement.textContent.trim();
}
get opened() {
return this.icon === 'expand_less';
}
get closed() {
return this.icon === 'expand_more';
}
}
class TableBodyCell {
constructor(element) {
this.element = element;
}
get colspan() {
return this.element.nativeElement.colspan;
}
get rowspan() {
return this.element.nativeElement.rowspan;
}
}
// <editor-fold defaultstate="collapsed" desc="Row detail">
class TableBodyDetail {
constructor(element, page) {
this.element = element;
this.page = page;
}
header() {
return new TableHeader(this.element.query(By.css('thead')), this.page);
}
get body() {
return new TableBodyDetailBody(this.element.query(By.css('tbody')));
}
get highlighted() {
return this.element.nativeElement.classList.contains(HIGHLIGHTER_CLASS);
}
get colspan() {
return this.element.children[0].nativeElement.colspan;
}
}
class TableBodyDetailBody {
constructor(element) {
this.element = element;
}
get rows() {
return this.element.queryAll(By.css('tr')).map((element) => {
return new TableBodyDetailRow(element);
});
}
get cells() {
let cells = [];
this.element.queryAll(By.css('tr')).forEach((row) => {
cells = cells.concat(row.queryAll(By.css('td')).map((cell) => {
return new TableBodyCell(cell);
}));
});
return cells;
}
}
class TableBodyDetailRow {
constructor(element) {
this.element = element;
}
get cells() {
return this.element.queryAll(By.css('td')).map((element) => {
return new TableBodyCell(element);
});
}
}
// </editor-fold>
// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="Table footer">
class TableFooter {
constructor(element) {
this.element = element;
}
get rows() {
return this.element.queryAll(By.css('tr')).map((element) => {
return new TableFooterRow(element);
});
}
get cells() {
let cells = [];
this.element.queryAll(By.css('tr')).forEach((row) => {
cells = cells.concat(row.queryAll(By.css('th')).map((cell) => {
return new TableBodyCell(cell);
}));
});
return cells;
}
}
class TableFooterRow {
constructor(element) {
this.element = element;
}
get cells() {
return this.element.queryAll(By.css('th')).map((element) => {
return new TableBodyCell(element);
});
}
}
// </editor-fold>
class RecordsCount {
constructor(element) {
this.element = element;
}
get message() {
return this.element.nativeElement.textContent;
}
}
class Pager {
constructor(element, page) {
this.element = element;
this.page = page;
}
get pageButtons() {
return this.element.queryAll(By.directive(MatButtonToggle));
}
expectLeadingButtonsDisabled() {
for (let i = 0; i < 2; i++) {
expect(this.pageButtons[i].classes['mat-button-toggle-disabled'])
.toBe(true, 'First two are disabled.');
}
}
expectLeadingButtonsNotDisabled() {
for (let i = 0; i < 2; i++) {
expect(this.pageButtons[i].classes['mat-button-toggle-disabled'])
.not.toBe(true, 'First two are not disabled.');
}
}
expectTrailingButtonsDisabled() {
for (let i = this.pageButtons.length - 1; i > this.pageButtons.length - 3; i--) {
expect(this.pageButtons[i].classes['mat-button-toggle-disabled'])
.toBe(true, 'Last two are disabled.');
}
}
expectTrailingButtonsNotDisabled() {
for (let i = this.pageButtons.length - 1; i > this.pageButtons.length - 3; i--) {
expect(this.pageButtons[i].classes['mat-button-toggle-disabled'])
.not.toBe(true, 'Last two are not disabled.');
}
}
expectButtonNumbers(numbers) {
for (let i = 0; i < numbers.length; i++) {
expect(this.pageButtons[i + 2].query(By.css('.mat-button-toggle-label-content'))
.nativeElement.textContent.trim())
.toEqual(numbers[i] + '', 'Button numbers are correct');
}
}
expectButtonActive(index) {
expect(this.pageButtons[index].classes['mat-button-toggle-checked'])
.toBe(true, 'Button is active.');
}
click(index) {
click(this.pageButtons[index].query(By.css('.mat-button-toggle-label-content')).nativeElement);
this.page.detectChanges();
this.page.advanceAndDetectChanges();
}
}
function chceckSorting(page, criteria) {
page.dataTable.sorting.checkSorting(150);
page.dataTable.sorting.handles.forEach((handle, index) => {
// Tigger sort based on a handle
handle.click();
page.detectChanges();
// Check the sorting
page.dataTable.sorting.checkSorting(150, {
get: criteria[index]
});
// Tigger sort based on a handle
handle.click();
page.detectChanges();
// Check the sorting
page.dataTable.sorting.checkSorting(150, {
get: criteria[index],
descending: true
});
});
}
class DataTableDefinitionHosted extends Page {
constructor(fixture) {
super(fixture);
}
get dataTable() {
return new DataTableDefinition(this.debugElement.query(By.directive(DataTableComponent)), this);
}
}
class TestDataTableHostComponent {
constructor() {
this.data = [];
for (let i = 0; i < 500; i++) {
this.data.push({
value1: Math.floor(secureRandom() * 20) + ' - value 1',
value2: Math.floor(secureRandom() * 20) + ' - value 2',
value3: Math.floor(secureRandom() * 20) + ' - value 3'
});
}
this.footer = this.data[0];
}
get defaultOrdering() {
return [
{
get: (record) => {
return record.value3;
},
descending: true
},
(record) => {
return record.value2;
}
];
}
get valueGetter() {
return (record) => {
return record.value1;
};
}
}
TestDataTableHostComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.6", ngImport: i0, type: TestDataTableHostComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
TestDataTableHostComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.6", type: TestDataTableHostComponent, selector: "ng-component", ngImport: i0, template: `
<risk-data-table [data]="data"
[footer]="footer"
[pageSize]="20"
[defaultOrdering]="defaultOrdering"
[striped]="true">
<risk-data-table-column title="Test Column 1"
[sortingKey]="valueGetter">
<ng-template let-record="row" risk-data-table-cell>
{{record.value1}}
</ng-template>
</risk-data-table-column>
<risk-data-table-column>
<ng-template risk-data-table-cell let-record="row" let-expanded="expanded">
<risk-data-table-detail-expander [expanded]="expanded"></risk-data-table-detail-expander>
</ng-template>
<ng-template risk-data-table-footer-cell let-footer="footer">
{{footer.value1}}
</ng-template>
</risk-data-table-column>
<!-- Sub detail -->
<risk-data-table-detail-row>
<risk-data-table-column-group>
<risk-data-table-column title="Test Detail Column 1"
[sortingKey]="valueGetter">
<ng-template risk-data-table-cell let-record="row">
{{record.value1}}
</ng-template>
</risk-data-table-column>
</risk-data-table-column-group>
<risk-data-table-column-group>
<risk-data-table-column title="Test Detail Column 2">
<ng-template risk-data-table-cell let-record="row">
{{record.value2}}
</ng-template>
</risk-data-table-column>
<risk-data-table-column title="Test Detail Column 3">
<ng-template risk-data-table-cell let-record="row">
{{record.value3}}
</ng-template>
</risk-data-table-column>
</risk-data-table-column-group>
<risk-data-table-column-group></risk-data-table-column-group>
</risk-data-table-detail-row>
</risk-data-table>`, isInline: true, components: [{ type: i1$1.DataTableComponent, selector: "risk-data-table", inputs: ["footer", "pageSize", "striped", "showFooter", "allowEmpty", "trackByRowKey", "highlighting", "stickyHeader", "stickyHeaderOffsetTopPx", "data", "defaultOrdering"], exportAs: ["dataTable"] }, { type: i1$1.DataTableRowDetailExpanderComponent, selector: "risk-data-table-detail-expander", inputs: ["expanded"] }], directives: [{ type: i1$1.ɵDataTableColumnDirective, selector: "risk-data-table-column", inputs: ["title", "sortingKey", "tooltip", "contentAlign", "headerAlign", "footerAlign", "class"] }, { type: i1$1.ɵDataTableColumnCellDirective, selector: "[risk-data-table-cell]" }, { type: i1$1.ɵDataTableColumnFooterDirective, selector: "[risk-data-table-footer-cell]" }, { type: i1$1.ɵDataTableRowDetailDirective, selector: "risk-data-table-detail-row" }, { type: i1$1.ɵDataTableColumnGroupDirective, selector: "risk-data-table-column-group" }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.6", ngImport: i0, type: TestDataTableHostComponent, decorators: [{
type: Component,
args: [{
template: `
<risk-data-table [data]="data"
[footer]="footer"
[pageSize]="20"
[defaultOrdering]="defaultOrdering"
[striped]="true">
<risk-data-table-column title="Test Column 1"
[sortingKey]="valueGetter">
<ng-template let-record="row" risk-data-table-cell>
{{record.value1}}
</ng-template>
</risk-data-table-column>
<risk-data-table-column>
<ng-template risk-data-table-cell let-record="row" let-expanded="expanded">
<risk-data-table-detail-expander [expanded]="expanded"></risk-data-table-detail-expander>
</ng-template>
<ng-template risk-data-table-footer-cell let-footer="footer">
{{footer.value1}}
</ng-template>
</risk-data-table-column>
<!-- Sub detail -->
<risk-data-table-detail-row>
<risk-data-table-column-group>
<risk-data-table-column title="Test Detail Column 1"
[sortingKey]="valueGetter">
<ng-template risk-data-table-cell let-record="row">
{{record.value1}}
</ng-template>
</risk-data-table-column>
</risk-data-table-column-group>
<risk-data-table-column-group>
<risk-data-table-column title="Test Detail Column 2">
<ng-template risk-data-table-cell let-record="row">
{{record.value2}}
</ng-template>
</risk-data-table-column>
<risk-data-table-column title="Test Detail Column 3">
<ng-template risk-data-table-cell let-record="row">
{{record.value3}}
</ng-template>
</risk-data-table-column>
</risk-data-table-column-group>
<risk-data-table-column-group></risk-data-table-column-group>
</risk-data-table-detail-row>
</risk-data-table>`
}]
}], ctorParameters: function () { return []; } });
class HighLighterDirectiveTestComponent {
trackBy(index, row) {
return row.rowData;
}
}
HighLighterDirectiveTestComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.6", ngImport: i0, type: HighLighterDirectiveTestComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
HighLighterDirectiveTestComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.6", type: HighLighterDirectiveTestComponent, selector: "ng-component", ngImport: i0, template: `
<div [risk-data-table-highlighter]="trackBy" [risk-data-table-highlighter-context]="context"></div>`, isInline: true, directives: [{ type: i1$1.HighlighterDirective, selector: "[risk-data-table-highlighter]", inputs: ["risk-data-table-highlighter", "risk-data-table-highlighter-context"] }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.6", ngImport: i0, type: HighLighterDirectiveTestComponent, decorators: [{
type: Component,
args: [{
template: `
<div [risk-data-table-highlighter]="trackBy" [risk-data-table-highlighter-context]="context"></div>`
}]
}] });
class HighLighterDirectivePage extends Page {
constructor(fixture) {
super(fixture);
}
get highlightedElement() {
return this.debugElement.query(By.directive(HighlighterDirective));
}
get classList() {
return this.highlightedElement.nativeElement.classList;
}
get highlighter() {
return this.highlightedElement.injector.get(HighlighterDirective);
}
}
// @dynamic
class ByUtil {
static and(...predicates) {
return (val) => {
return predicates.every((predicate) => predicate(val));
};
}
static or(...predicates) {
return (val) => {
return predicates.some((predicate) => predicate(val));
};
}
static not(predicate) {
return (val) => {
return !predicate(val);
};
}
}
class LayoutComponentDefinition {
constructor(debugElement, page) {
this.debugElement = debugElement;
this.page = page;
}
get component() {
return this.debugElement.componentInstance;
}
get headToolbar() {
return this.debugElement.query(ByUtil.and(By.directive(MatToolbar), By.css('.mat-elevation-z2')));
}
get logo() {
return this.headToolbar.query(By.css('.risk-layout-logo'));
}
get menu() {
return this.headToolbar.queryAll(ByUtil.or(By.css('[menu-horizontal]'), By.css('risk-layout-horizontal')));
}
get sideNavContainer() {
return this.debugElement.query(By.directive(MatSidenavContainer));
}
get sideNav() {
return this.sideNavContainer.query(By.directive(MatSidenav));
}
openSideNav() {
this.sideNav.componentInstance.open();
this.page.advanceAndDetectChanges();
}
closeSideNav() {
this.sideNav.componentInstance.close();
this.page.advanceAndDetectChanges(1);
}
get sideNavMenu() {
return this.sideNav.queryAll(ByUtil.or(By.css('[menu-vertical]'), By.css('risk-layout-vertical')));
}
get content() {
return this.sideNavContainer.query(By.css('.risk-layout-content'));
}
}
class TestLayoutComponentHostPage extends Page {
get layoutComponent() {
return new LayoutComponentDefinition(this.debugElement.query(By.directive(LayoutComponent)), this);
}
}
class TestLayoutHostComponent {
}
TestLayoutHostComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.6", ngImport: i0, type: TestLayoutHostComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
TestLayoutHostComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.6", type: TestLayoutHostComponent, selector: "ng-component", ngImport: i0, template: `
<risk-layout>
<!-- menu-horizontal -->
<risk-layout-horizontal>
HorizontalMenu
</risk-layout-horizontal>
<!-- menu-horizontal -->
<!-- menu-vertical -->
<risk-layout-vertical>
Vertical menu
</risk-layout-vertical>
<span>Content</span>
</risk-layout>
`, isInline: true, components: [{ type: i1$2.LayoutComponent, selector: "risk-layout", inputs: ["smallScreenMenuVisible", "smallScreenWidth", "footerVisible", "toolbarBackgroundColor", "backgroundColor"] }], directives: [{ type: i1$2.HorizontalLayoutDirective, selector: "risk-layout-horizontal" }, { type: i1$2.VerticalLayoutDirective, selector: "risk-layout-vertical" }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.6", ngImport: i0, type: TestLayoutHostComponent, decorators: [{
type: Component,
args: [{
template: `
<risk-layout>
<!-- menu-horizontal -->
<risk-layout-horizontal>
HorizontalMenu
</risk-layout-horizontal>
<!-- menu-horizontal -->
<!-- menu-vertical -->
<risk-layout-vertical>
Vertical menu
</risk-layout-vertical>
<span>Content</span>
</risk-layout>
`
}]
}] });
class RouterLinkStubDirective {
constructor(injector) {
this.navigatedTo = null;
this._urlTree = null;
this.routerStub = injector.get(Router, null);
}
ngOnChanges() {
if (this.linkParams && this.routerStub) {
this._urlTree = this.routerStub.getURLTree(this.linkParams);
}
}
onClick() {
this.navigatedTo = this.linkParams;
if (this.routerStub) {
if (Array.isArray(this.navigatedTo)) {
this.routerStub.navigate(this.navigatedTo);
}
else {
this.routerStub.navigateByUrl(this.navigatedTo);
}
}
}
get urlTree() {
return this._urlTree;
}
}
RouterLinkStubDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.6", ngImport: i0, type: RouterLinkStubDirective, deps: [{ token: i0.Injector }], target: i0.ɵɵFactoryTarget.Directive });
RouterLinkStubDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.2.6", type: RouterLinkStubDirective, selector: "[routerLink]", inputs: { linkParams: ["routerLink", "linkParams"] }, host: { listeners: { "click": "onClick()" } }, usesOnChanges: true, ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.6", ngImport: i0, type: RouterLinkStubDirective, decorators: [{
type: Directive,
args: [{
/* eslint-disable @angular-eslint/directive-selector */
selector: '[routerLink]',
/* eslint-enable */
host: {
'(click)': 'onClick()'
}
}]
}], ctorParameters: function () { return [{ type: i0.Injector }]; }, propDecorators: { linkParams: [{
type: Input,
args: ['routerLink']
}] } });
class LinkDefinition {
constructor(page, link) {
this.page = page;
this.link = link;
}
get stub() {
return this.link.injector.get(RouterLinkStubDirective);
}
get text() {
return this.link.nativeElement.textContent.trim();
}
click() {
click(this.link.nativeElement);
this.page.advanceAndDetectChanges();
}
}
class LinkOnlyPage extends Page {
constructor(fixture) {
super(fixture);
}
get link() {
return new LinkDefinition(this, this.debugElement.query(By.directive(RouterLinkStubDirective)));
}
}
class LoginMenuPage extends Page {
get menuTrigger() {
return this.debugElement.query(By.directive(MatMenuTrigger));
}
clickMenuTrigger() {
click(this.menuTrigger);
this.waitForMenu();
}
waitForMenu() {
this.detectChanges(500);
}
get loginLink() {
return new LinkDefinition(this, this.debugElement.query(ByUtil.and(By.directive(MatMenuItem), (value) => value.nativeElement.textContent.trim().endsWith('Login'))));
}
get logoutLink() {
return new LinkDefinition(this, this.debugElement.query(ByUtil.and(By.directive(MatMenuItem), (value) => value.nativeElement.textContent.trim().endsWith('Logout'))));
}
}
class LoginPage extends Page {
constructor(fixture) {
super(fixture);
}
get formElement() {
return this.debugElement.query(By.css('form'));
}
get usernameElement() {
return this.formElement.query(By.css('input[name=username]'));
}
set username(username) {
setNgModelValue(this.usernameElement, username);
}
get passwordElement() {
return this.formElement.query(By.css('input[name=password]'));
}
set password(password) {
setNgModelValue(this.passwordElement, password);
}
get loginButtonElement() {
return this.formElement.query(By.directive(MatButton));
}
get successMessage() {
const debugElement = this.debugElement.query(ByUtil.and(By.directive(NoopAnimationMessageComponent), By.css(RISK_GOOD_SELECTOR)));
if (!debugElement) {
return null;
}
return new MessageComponentDef(debugElement);
}
get errorMessage() {
const debugElement = this.debugElement.query(ByUtil.or(ByUtil.and(By.directive(NoopAnimationMessageComponent), By.css(RISK_ERROR_SELECTOR)), By.css('h3')));
if (!debugElement) {
return null;
}
return new MessageComponentDef(debugElement);
}
clickLogin() {
click(this.loginButtonElement.nativeElement);
tick();
this.detectChanges();
}
}
class TestMessageHostComponent {
constructor() {
this.message = 'custom message';
}
}
TestMessageHostComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.6", ngImport: i0, type: TestMessageHostComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
TestMessageHostComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.6", type: TestMessageHostComponent, selector: "ng-component", ngImport: i0, template: `
<risk-error [message]="message"></risk-error>
<risk-good [message]="message"></risk-good>
<risk-info [message]="message"></risk-info>
<risk-message [message]="message"></risk-message>
<risk-warn [message]="message"></risk-warn>
<risk-initial-load [message]="message"></risk-initial-load>
<risk-update-failed [message]="message"></risk-update-failed>
<risk-no-data [message]="message"></risk-no-data>
`, isInline: true, components: [{ type: i1$2.MessageComponent, selector: "risk-error, risk-good, risk-info, risk-message, risk-warn, risk-initial-load, risk-no-data, risk-update-failed", inputs: ["message"] }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.6", ngImport: i0, type: TestMessageHostComponent, decorators: [{
type: Component,
args: [{
template: `
<risk-error [message]="message"></risk-error>
<risk-good [message]="message"></risk-good>
<risk-info [message]="message"></risk-info>
<risk-message [message]="message"></risk-message>
<risk-warn [message]="message"></risk-warn>
<risk-initial-load [message]="message"></risk-initial-load>
<risk-update-failed [message]="message"></risk-update-failed>
<risk-no-data [message]="message"></risk-no-data>
`
}]
}] });
class MessageHostedPage extends Page {
constructor(fixture) {
super(fixture);
}
get error() {
return new MessageComponentDef(this.debugElement.query(By.css(RISK_ERROR_SELECTOR)));
}
get good() {
return new MessageComponentDef(this.debugElement.query(By.css(RISK_GOOD_SELECTOR)));
}
get info() {
return new MessageComponentDef(this.debugElement.query(By.css(RISK_INFO_SELECTOR)));
}
get message() {
return new MessageComponentDef(this.debugElement.query(By.css(RISK_MESSAGE_SELECTOR)));
}
get warn() {
return new MessageComponentDef(this.debugElement.query(By.css(RISK_WARN_SELECTOR)));
}
get initialLoad() {
return new MessageComponentDef(this.debugElement.query(By.css(RISK_INITIAL_LOAD_SELECTOR)));
}
get noData() {
return new MessageComponentDef(this.debugElement.query(By.css(RISK_NO_DATA_SELECTOR)));
}
get updateFailed() {
return new MessageComponentDef(this.debugElement.query(By.css(RISK_UPDATE_FAILED_SELECTOR)));
}
}
const storage = { authRequestedPath: null };
class AuthRoutingFlowServiceStub extends AuthRoutingFlowService {
constructor(authServiceStub, authConfig) {
super(null, null, { loggedIn: of(null) }, storage, authConfig, null);
this.authServiceStub = authServiceStub;
// cleanup
storage.authRequestedPath = null;
}
logout(state) {
return this.authServiceStub.logout().pipe(defaultIfEmpty(0), map(() => true));
}
login(username, password) {
return this.authServiceStub.directLogin(username, password);
}
loginViaService() {
return this.authServiceStub.loginViaAuthService();
}
}
AuthRoutingFlowServiceStub.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.6", ngImport: i0, type: AuthRoutingFlowServiceStub, deps: [{ token: AUTH_PROVIDER }, { token: AUTH_CONFIG }], target: i0.ɵɵFactoryTarget.Injectable });
AuthRoutingFlowServiceStub.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.2.6", ngImport: i0, type: AuthRoutingFlowServiceStub });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.6", ngImport: i0, type: AuthRoutingFlowServiceStub, decorators: [{
type: Injectable
}], ctorParameters: function () {
return [{ type: i1$3.AuthService, decorators: [{
type: Inject,
args: [AUTH_PROVIDER]
}] }, { type: undefined, decorators: [{
type: Inject,
args: [AUTH_CONFIG]
}] }];
} });
const WELL_KNOWN = {
endpoints: {
auth: '/auth',
token: '/token',
logout: '/logout'
},
issuer: 'risk-auth'
};
class WellKnownServiceStub {
get wellKnown() {
return of(WELL_KNOWN);
}
}
WellKnownServiceStub.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.6", ngImport: i0, type: WellKnownServiceStub, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
WellKnownServiceStub.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.2.6", ngImport: i0, type: WellKnownServiceStub });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.6", ngImport: i0, type: WellKnownServiceStub, decorators: [{
type: Injectable
}] });
class AuthServiceStub extends AuthService {
constructor() {
super({}, new WellKnownServiceStub(), null, null, null);
}
get loggedIn() {
return of(!!this.user);
}
get userProfile() {
return of({
name: this.user
});
}
loginViaAuthService() {
return of(true);
}
checkLocationForLoginData() {
return of(true);
}
directLogin(username, password) {
this.user = username;
this.emitLoginStatusChange(true);
return of(true);
}
logout() {
this.emitLoginStatusChange(false);
delete this.user;
return EMPTY;
}
}
AuthServiceStub.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.6", ngImport: i0, type: AuthServiceStub, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
AuthServiceStub.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.2.6", ngImport: i0, type: AuthServiceStub });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.6", ngImport: i0, type: AuthServiceStub, decorators: [{
type: Injectable
}], ctorParameters: function () { return []; } });
class LoginMenuStubComponent {
constructor() {
this.orientation = 'row';
}
}
LoginMenuStubComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.6", ngImport: i0, type: LoginMenuStubComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
LoginMenuStubComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.6", type: LoginMenuStubComponent, selector: "login-menu, risk-login-menu", inputs: { orientation: "orientation" }, ngImport: i0, template: '', isInline: true });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.6", ngImport: i0, type: LoginMenuStubComponent, decorators: [{
type: Component,
args: [{
selector: 'login-menu, risk-login-menu',
template: ''
}]
}], propDecorators: { orientation: [{
type: Input
}] } });
class ActivatedRouteStub {
constructor() {
// Test parameters
this._testParams = {};
// ActivatedRoute.params is Observable
this.subject = new BehaviorSubject(this.testParams);
this.params = this.subject.asObservable();
}
get testParams() {
return this._testParams;
}
set testParams(params) {
this._testParams = params;
this.subject.next(params);
}
// ActivatedRoute.snapshot.params
get snapshot() {
return { params: this.testParams };
}
}
ActivatedRouteStub.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.6", ngImport: i0, type: ActivatedRouteStub, deps: [], target: i0.ɵɵFactoryTarget.Inj