refactor(docs-infra): enable tslint rules for the angular.io app (#39307)
Signed-off-by: Tasos Alexiou <tasos@arrikto.com> PR Close #39307
This commit is contained in:
parent
c53bae839d
commit
356a256909
|
@ -635,61 +635,53 @@ describe('AppComponent', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('aio-toc', () => {
|
describe('aio-toc', () => {
|
||||||
let tocContainer: HTMLElement|null;
|
function setHasFloatingTocAndGetToc(hasFloatingToc: false): [null, null];
|
||||||
let toc: HTMLElement|null;
|
function setHasFloatingTocAndGetToc(hasFloatingToc: true): [HTMLElement, HTMLElement];
|
||||||
|
function setHasFloatingTocAndGetToc(hasFloatingToc: boolean) {
|
||||||
const setHasFloatingToc = (hasFloatingToc: boolean) => {
|
|
||||||
component.hasFloatingToc = hasFloatingToc;
|
component.hasFloatingToc = hasFloatingToc;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
tocContainer = fixture.debugElement.nativeElement.querySelector('.toc-container');
|
const tocContainer = fixture.debugElement.nativeElement.querySelector('.toc-container');
|
||||||
toc = tocContainer && tocContainer.querySelector('aio-toc');
|
const toc = tocContainer && tocContainer.querySelector('aio-toc');
|
||||||
};
|
|
||||||
|
|
||||||
|
return [toc, tocContainer];
|
||||||
beforeEach(() => {
|
}
|
||||||
tocContainer = null;
|
|
||||||
toc = null;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should show/hide `<aio-toc>` based on `hasFloatingToc`', () => {
|
it('should show/hide `<aio-toc>` based on `hasFloatingToc`', () => {
|
||||||
expect(tocContainer).toBeFalsy();
|
const [toc1, tocContainer1] = setHasFloatingTocAndGetToc(true);
|
||||||
expect(toc).toBeFalsy();
|
expect(tocContainer1).toBeTruthy();
|
||||||
|
expect(toc1).toBeTruthy();
|
||||||
|
|
||||||
setHasFloatingToc(true);
|
const [toc2, tocContainer2] = setHasFloatingTocAndGetToc(false);
|
||||||
expect(tocContainer).toBeTruthy();
|
expect(tocContainer2).toBeFalsy();
|
||||||
expect(toc).toBeTruthy();
|
expect(toc2).toBeFalsy();
|
||||||
|
|
||||||
setHasFloatingToc(false);
|
|
||||||
expect(tocContainer).toBeFalsy();
|
|
||||||
expect(toc).toBeFalsy();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have a non-embedded `<aio-toc>` element', () => {
|
it('should have a non-embedded `<aio-toc>` element', () => {
|
||||||
setHasFloatingToc(true);
|
const [toc] = setHasFloatingTocAndGetToc(true);
|
||||||
expect(toc!.classList.contains('embedded')).toBe(false);
|
expect(toc.classList.contains('embedded')).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should update the TOC container\'s `maxHeight` based on `tocMaxHeight`', () => {
|
it('should update the TOC container\'s `maxHeight` based on `tocMaxHeight`', () => {
|
||||||
setHasFloatingToc(true);
|
const [, tocContainer] = setHasFloatingTocAndGetToc(true);
|
||||||
|
|
||||||
component.tocMaxHeight = '100';
|
component.tocMaxHeight = '100';
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(tocContainer!.style.maxHeight).toBe('100px');
|
expect(tocContainer.style.maxHeight).toBe('100px');
|
||||||
|
|
||||||
component.tocMaxHeight = '200';
|
component.tocMaxHeight = '200';
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(tocContainer!.style.maxHeight).toBe('200px');
|
expect(tocContainer.style.maxHeight).toBe('200px');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should restrain scrolling inside the ToC container', () => {
|
it('should restrain scrolling inside the ToC container', () => {
|
||||||
const restrainScrolling = spyOn(component, 'restrainScrolling');
|
const restrainScrolling = spyOn(component, 'restrainScrolling');
|
||||||
const evt = new WheelEvent('wheel');
|
const evt = new WheelEvent('wheel');
|
||||||
|
const [, tocContainer] = setHasFloatingTocAndGetToc(true);
|
||||||
|
|
||||||
setHasFloatingToc(true);
|
|
||||||
expect(restrainScrolling).not.toHaveBeenCalled();
|
expect(restrainScrolling).not.toHaveBeenCalled();
|
||||||
|
|
||||||
tocContainer!.dispatchEvent(evt);
|
tocContainer.dispatchEvent(evt);
|
||||||
expect(restrainScrolling).toHaveBeenCalledWith(evt);
|
expect(restrainScrolling).toHaveBeenCalledWith(evt);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -697,7 +689,7 @@ describe('AppComponent', () => {
|
||||||
const loader = fixture.debugElement.injector.get(ElementsLoader) as unknown as TestElementsLoader;
|
const loader = fixture.debugElement.injector.get(ElementsLoader) as unknown as TestElementsLoader;
|
||||||
expect(loader.loadCustomElement).not.toHaveBeenCalled();
|
expect(loader.loadCustomElement).not.toHaveBeenCalled();
|
||||||
|
|
||||||
setHasFloatingToc(true);
|
setHasFloatingTocAndGetToc(true);
|
||||||
expect(loader.loadCustomElement).toHaveBeenCalledWith('aio-toc');
|
expect(loader.loadCustomElement).toHaveBeenCalledWith('aio-toc');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -721,7 +713,7 @@ describe('AppComponent', () => {
|
||||||
createTestingModule('a/b', 'stable');
|
createTestingModule('a/b', 'stable');
|
||||||
await initializeTest();
|
await initializeTest();
|
||||||
const banner: HTMLElement = fixture.debugElement.query(By.css('aio-mode-banner')).nativeElement;
|
const banner: HTMLElement = fixture.debugElement.query(By.css('aio-mode-banner')).nativeElement;
|
||||||
expect(banner.textContent!.trim()).toEqual('');
|
expect(banner.textContent?.trim()).toEqual('');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1355,10 +1347,10 @@ class TestHttpClient {
|
||||||
if (/navigation\.json/.test(url)) {
|
if (/navigation\.json/.test(url)) {
|
||||||
data = this.navJson;
|
data = this.navJson;
|
||||||
} else {
|
} else {
|
||||||
const match = /generated\/docs\/(.+)\.json/.exec(url)!;
|
const match = /generated\/docs\/(.+)\.json/.exec(url);
|
||||||
const id = match[1]!;
|
const id = match?.[1];
|
||||||
// Make up a title for test purposes
|
// Make up a title for test purposes
|
||||||
const title = id.split('/').pop()!.replace(/^([a-z])/, (_, letter) => letter.toUpperCase());
|
const title = id?.split('/')?.pop()?.replace(/^([a-z])/, (_, letter) => letter.toUpperCase());
|
||||||
const h1 = (id === 'no-title') ? '' : `<h1 class="no-toc">${title}</h1>`;
|
const h1 = (id === 'no-title') ? '' : `<h1 class="no-toc">${title}</h1>`;
|
||||||
const contents = `${h1}<h2 id="#somewhere">Some heading</h2>`;
|
const contents = `${h1}<h2 id="#somewhere">Some heading</h2>`;
|
||||||
data = { id, contents };
|
data = { id, contents };
|
||||||
|
|
|
@ -163,7 +163,7 @@ export class AppComponent implements OnInit {
|
||||||
// Find the current version - eithers title matches the current deployment mode
|
// Find the current version - eithers title matches the current deployment mode
|
||||||
// or its title matches the major version of the current version info
|
// or its title matches the major version of the current version info
|
||||||
this.currentDocVersion = this.docVersions.find(version =>
|
this.currentDocVersion = this.docVersions.find(version =>
|
||||||
version.title === this.deployment.mode || version.title === `v${versionInfo.major}`)!;
|
version.title === this.deployment.mode || version.title === `v${versionInfo.major}`) as NavigationNode;
|
||||||
this.currentDocVersion.title += ` (v${versionInfo.raw})`;
|
this.currentDocVersion.title += ` (v${versionInfo.raw})`;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -102,11 +102,11 @@ describe('AnnouncementBarComponent', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display an image', () => {
|
it('should display an image', () => {
|
||||||
expect(element.querySelector('img')!.src).toContain('dummy/image');
|
expect(element.querySelector('img')?.src).toContain('dummy/image');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display a link', () => {
|
it('should display a link', () => {
|
||||||
expect(element.querySelector('a')!.href).toContain('link/to/website');
|
expect(element.querySelector('a')?.href).toContain('link/to/website');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -38,7 +38,7 @@ describe('ApiListComponent', () => {
|
||||||
component.filteredSections.subscribe(filtered => {
|
component.filteredSections.subscribe(filtered => {
|
||||||
filtered = filtered.filter(section => section.items);
|
filtered = filtered.filter(section => section.items);
|
||||||
expect(filtered.length).toBeGreaterThan(0, 'expected something');
|
expect(filtered.length).toBeGreaterThan(0, 'expected something');
|
||||||
expect(filtered.every(section => section.items!.every(itemTest))).toBe(true, label);
|
expect(filtered.every(section => section.items?.every(itemTest))).toBe(true, label);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ describe('ApiListComponent', () => {
|
||||||
filtered = filtered.filter(section => Array.isArray(section.items));
|
filtered = filtered.filter(section => Array.isArray(section.items));
|
||||||
expect(filtered.length).toBe(1, 'only one section');
|
expect(filtered.length).toBe(1, 'only one section');
|
||||||
expect(filtered[0].name).toBe('core');
|
expect(filtered[0].name).toBe('core');
|
||||||
expect(filtered[0].items).toEqual(sections.find(section => section.name === 'core')!.items);
|
expect(filtered[0].items).toEqual(sections.find(section => section.name === 'core')?.items as ApiItem[]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -74,8 +74,8 @@ describe('ApiListComponent', () => {
|
||||||
it('should null if there are no matching items and the section itself does not match', () => {
|
it('should null if there are no matching items and the section itself does not match', () => {
|
||||||
component.setQuery('core');
|
component.setQuery('core');
|
||||||
component.filteredSections.subscribe(filtered => {
|
component.filteredSections.subscribe(filtered => {
|
||||||
const commonSection = filtered.find(section => section.name === 'common')!;
|
const commonSection = filtered.find(section => section.name === 'common');
|
||||||
expect(commonSection.items).toBe(null);
|
expect(commonSection?.items).toBe(null);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ describe('ApiListComponent', () => {
|
||||||
filtered = filtered.filter(s => s.items);
|
filtered = filtered.filter(s => s.items);
|
||||||
expect(filtered.length).toBe(1, 'sections');
|
expect(filtered.length).toBe(1, 'sections');
|
||||||
expect(filtered[0].name).toBe(section, 'section name');
|
expect(filtered[0].name).toBe(section, 'section name');
|
||||||
const items = filtered[0].items!;
|
const items = filtered[0].items as ApiItem[];
|
||||||
expect(items.length).toBe(1, 'items');
|
expect(items.length).toBe(1, 'items');
|
||||||
|
|
||||||
const item = items[0];
|
const item = items[0];
|
||||||
|
|
|
@ -17,9 +17,9 @@ import { Option } from 'app/shared/select/select.component';
|
||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
|
|
||||||
class SearchCriteria {
|
class SearchCriteria {
|
||||||
query ? = '';
|
query = '';
|
||||||
status ? = 'all';
|
status = 'all';
|
||||||
type ? = 'all';
|
type = 'all';
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -116,13 +116,13 @@ export class ApiListComponent implements OnInit {
|
||||||
const sectionNameMatches = !query || section.name.indexOf(query) !== -1;
|
const sectionNameMatches = !query || section.name.indexOf(query) !== -1;
|
||||||
|
|
||||||
const matchesQuery = (item: ApiItem) =>
|
const matchesQuery = (item: ApiItem) =>
|
||||||
sectionNameMatches || item.name.indexOf(query!) !== -1;
|
sectionNameMatches || item.name.indexOf(query) !== -1;
|
||||||
const matchesStatus = (item: ApiItem) =>
|
const matchesStatus = (item: ApiItem) =>
|
||||||
status === 'all' || status === item.stability || (status === 'security-risk' && item.securityRisk);
|
status === 'all' || status === item.stability || (status === 'security-risk' && item.securityRisk);
|
||||||
const matchesType = (item: ApiItem) =>
|
const matchesType = (item: ApiItem) =>
|
||||||
type === 'all' || type === item.docType;
|
type === 'all' || type === item.docType;
|
||||||
|
|
||||||
const items = section.items!.filter(item =>
|
const items: ApiItem[] = (section.items || []).filter(item =>
|
||||||
matchesType(item) && matchesStatus(item) && matchesQuery(item));
|
matchesType(item) && matchesStatus(item) && matchesQuery(item));
|
||||||
|
|
||||||
// If there are no items we still return an empty array if the section name matches and the type is 'package'
|
// If there are no items we still return an empty array if the section name matches and the type is 'package'
|
||||||
|
@ -160,7 +160,7 @@ export class ApiListComponent implements OnInit {
|
||||||
this.locationService.setSearch('API Search', params);
|
this.locationService.setSearch('API Search', params);
|
||||||
}
|
}
|
||||||
|
|
||||||
private setSearchCriteria(criteria: SearchCriteria) {
|
private setSearchCriteria(criteria: Partial<SearchCriteria>) {
|
||||||
this.criteriaSubject.next(Object.assign(this.searchCriteria, criteria));
|
this.criteriaSubject.next(Object.assign(this.searchCriteria, criteria));
|
||||||
this.setLocationSearch();
|
this.setLocationSearch();
|
||||||
}
|
}
|
||||||
|
|
|
@ -251,7 +251,7 @@ describe('CodeComponent', () => {
|
||||||
actualCode = spy.calls.mostRecent().args[0];
|
actualCode = spy.calls.mostRecent().args[0];
|
||||||
|
|
||||||
expect(actualCode).toBe(expectedCode, `when linenums=${linenums}`);
|
expect(actualCode).toBe(expectedCode, `when linenums=${linenums}`);
|
||||||
expect(actualCode.match(/\r?\n/g)!.length).toBe(5);
|
expect(actualCode.match(/\r?\n/g)?.length).toBe(5);
|
||||||
|
|
||||||
spy.calls.reset();
|
spy.calls.reset();
|
||||||
});
|
});
|
||||||
|
|
|
@ -45,12 +45,12 @@ export class ElementsLoader {
|
||||||
loadCustomElement(selector: string): Promise<void> {
|
loadCustomElement(selector: string): Promise<void> {
|
||||||
if (this.elementsLoading.has(selector)) {
|
if (this.elementsLoading.has(selector)) {
|
||||||
// The custom element is in the process of being loaded and registered.
|
// The custom element is in the process of being loaded and registered.
|
||||||
return this.elementsLoading.get(selector)!;
|
return this.elementsLoading.get(selector) as Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.elementsToLoad.has(selector)) {
|
if (this.elementsToLoad.has(selector)) {
|
||||||
// Load and register the custom element (for the first time).
|
// Load and register the custom element (for the first time).
|
||||||
const modulePathLoader = this.elementsToLoad.get(selector)!;
|
const modulePathLoader = this.elementsToLoad.get(selector) as LoadChildrenCallback;
|
||||||
const loadedAndRegistered =
|
const loadedAndRegistered =
|
||||||
(modulePathLoader() as Promise<NgModuleFactory<WithCustomElementComponent> | Type<WithCustomElementComponent>>)
|
(modulePathLoader() as Promise<NgModuleFactory<WithCustomElementComponent> | Type<WithCustomElementComponent>>)
|
||||||
.then(elementModuleOrFactory => {
|
.then(elementModuleOrFactory => {
|
||||||
|
@ -73,7 +73,7 @@ export class ElementsLoader {
|
||||||
const CustomElementComponent = elementModuleRef.instance.customElementComponent;
|
const CustomElementComponent = elementModuleRef.instance.customElementComponent;
|
||||||
const CustomElement = createCustomElement(CustomElementComponent, {injector});
|
const CustomElement = createCustomElement(CustomElementComponent, {injector});
|
||||||
|
|
||||||
customElements!.define(selector, CustomElement);
|
customElements.define(selector, CustomElement);
|
||||||
return customElements.whenDefined(selector);
|
return customElements.whenDefined(selector);
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
|
|
@ -337,7 +337,7 @@ describe('TocComponent', () => {
|
||||||
|
|
||||||
it('should re-apply the `active` class when the list elements change', () => {
|
it('should re-apply the `active` class when the list elements change', () => {
|
||||||
const getActiveTextContent = () =>
|
const getActiveTextContent = () =>
|
||||||
page.listItems.find(By.css('.active'))!.nativeElement.textContent.trim();
|
page.listItems.find(By.css('.active'))?.nativeElement.textContent.trim();
|
||||||
|
|
||||||
tocComponent.activeIndex = 1;
|
tocComponent.activeIndex = 1;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
|
@ -49,7 +49,7 @@ export class DocumentService {
|
||||||
if (!this.cache.has(id)) {
|
if (!this.cache.has(id)) {
|
||||||
this.cache.set(id, this.fetchDocument(id));
|
this.cache.set(id, this.fetchDocument(id));
|
||||||
}
|
}
|
||||||
return this.cache.get(id)!;
|
return this.cache.get(id) as Observable<DocumentContents>;
|
||||||
}
|
}
|
||||||
|
|
||||||
private fetchDocument(id: string): Observable<DocumentContents> {
|
private fetchDocument(id: string): Observable<DocumentContents> {
|
||||||
|
|
|
@ -213,10 +213,10 @@ describe('DocViewerComponent', () => {
|
||||||
describe('needed', () => {
|
describe('needed', () => {
|
||||||
it('should add an embedded ToC element if there is an `<h1>` heading', () => {
|
it('should add an embedded ToC element if there is an `<h1>` heading', () => {
|
||||||
doPrepareTitleAndToc(DOC_WITH_H1);
|
doPrepareTitleAndToc(DOC_WITH_H1);
|
||||||
const tocEl = getTocEl()!;
|
const tocEl = getTocEl();
|
||||||
|
|
||||||
expect(tocEl).toBeTruthy();
|
expect(tocEl).toBeTruthy();
|
||||||
expect(tocEl.classList.contains('embedded')).toBe(true);
|
expect(tocEl?.classList.contains('embedded')).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not add a second ToC element if there a hard coded one in place', () => {
|
it('should not add a second ToC element if there a hard coded one in place', () => {
|
||||||
|
|
|
@ -98,9 +98,9 @@ export class DocViewerComponent implements OnDestroy {
|
||||||
const needsToc = !!titleEl && !/no-?toc/i.test(titleEl.className);
|
const needsToc = !!titleEl && !/no-?toc/i.test(titleEl.className);
|
||||||
const embeddedToc = targetElem.querySelector('aio-toc.embedded');
|
const embeddedToc = targetElem.querySelector('aio-toc.embedded');
|
||||||
|
|
||||||
if (needsToc && !embeddedToc) {
|
if (titleEl && needsToc && !embeddedToc) {
|
||||||
// Add an embedded ToC if it's needed and there isn't one in the content already.
|
// Add an embedded ToC if it's needed and there isn't one in the content already.
|
||||||
titleEl!.insertAdjacentHTML('afterend', '<aio-toc class="embedded"></aio-toc>');
|
titleEl.insertAdjacentHTML('afterend', '<aio-toc class="embedded"></aio-toc>');
|
||||||
} else if (!needsToc && embeddedToc && embeddedToc.parentNode !== null) {
|
} else if (!needsToc && embeddedToc && embeddedToc.parentNode !== null) {
|
||||||
// Remove the embedded Toc if it's there and not needed.
|
// Remove the embedded Toc if it's there and not needed.
|
||||||
// We cannot use ChildNode.remove() because of IE11
|
// We cannot use ChildNode.remove() because of IE11
|
||||||
|
@ -223,7 +223,7 @@ export class DocViewerComponent implements OnDestroy {
|
||||||
done$ = done$.pipe(
|
done$ = done$.pipe(
|
||||||
// Remove the current view from the viewer.
|
// Remove the current view from the viewer.
|
||||||
switchMap(() => animateLeave(this.currViewContainer)),
|
switchMap(() => animateLeave(this.currViewContainer)),
|
||||||
tap(() => this.currViewContainer.parentElement!.removeChild(this.currViewContainer)),
|
tap(() => (this.currViewContainer.parentElement as HTMLElement).removeChild(this.currViewContainer)),
|
||||||
tap(() => this.docRemoved.emit()),
|
tap(() => this.docRemoved.emit()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,7 +144,7 @@ describe('NavigationService', () => {
|
||||||
url: 'b',
|
url: 'b',
|
||||||
view: 'SideNav',
|
view: 'SideNav',
|
||||||
nodes: [
|
nodes: [
|
||||||
sideNavNodes[0].children![0],
|
sideNavNodes[0].children?.[0] as NavigationNode,
|
||||||
sideNavNodes[0]
|
sideNavNodes[0]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -156,8 +156,8 @@ describe('NavigationService', () => {
|
||||||
url: 'd',
|
url: 'd',
|
||||||
view: 'SideNav',
|
view: 'SideNav',
|
||||||
nodes: [
|
nodes: [
|
||||||
sideNavNodes[0].children![0].children![1],
|
sideNavNodes[0].children?.[0].children?.[1] as NavigationNode,
|
||||||
sideNavNodes[0].children![0],
|
sideNavNodes[0].children?.[0] as NavigationNode,
|
||||||
sideNavNodes[0]
|
sideNavNodes[0]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -201,8 +201,8 @@ describe('NavigationService', () => {
|
||||||
url: 'c',
|
url: 'c',
|
||||||
view: 'SideNav',
|
view: 'SideNav',
|
||||||
nodes: [
|
nodes: [
|
||||||
sideNavNodes[0].children![0].children![0],
|
sideNavNodes[0].children?.[0].children?.[0] as NavigationNode,
|
||||||
sideNavNodes[0].children![0],
|
sideNavNodes[0].children?.[0] as NavigationNode,
|
||||||
sideNavNodes[0]
|
sideNavNodes[0]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -153,7 +153,7 @@ export class NavigationService {
|
||||||
if (!navMap.has(cleanedUrl)) {
|
if (!navMap.has(cleanedUrl)) {
|
||||||
navMap.set(cleanedUrl, {});
|
navMap.set(cleanedUrl, {});
|
||||||
}
|
}
|
||||||
const navMapItem = navMap.get(cleanedUrl)!;
|
const navMapItem = navMap.get(cleanedUrl) as CurrentNodes;
|
||||||
navMapItem[view] = { url, view, nodes };
|
navMapItem[view] = { url, view, nodes };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ describe('Attribute Utilities', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const div = document.createElement('div');
|
const div = document.createElement('div');
|
||||||
div.innerHTML = `<div a b="true" c="false" D="foo" d-E></div>`;
|
div.innerHTML = `<div a b="true" c="false" D="foo" d-E></div>`;
|
||||||
testEl = div.querySelector('div')!;
|
testEl = div.querySelector('div') as HTMLElement;
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getAttrs', () => {
|
describe('getAttrs', () => {
|
||||||
|
|
|
@ -44,7 +44,7 @@ export class CopierService {
|
||||||
* @return The temporary `<textarea>` element containing the specified text.
|
* @return The temporary `<textarea>` element containing the specified text.
|
||||||
*/
|
*/
|
||||||
private createTextArea(text: string): HTMLTextAreaElement {
|
private createTextArea(text: string): HTMLTextAreaElement {
|
||||||
const docElem = document.documentElement!;
|
const docElem = document.documentElement;
|
||||||
const isRTL = docElem.getAttribute('dir') === 'rtl';
|
const isRTL = docElem.getAttribute('dir') === 'rtl';
|
||||||
|
|
||||||
// Create a temporary element to hold the contents to copy.
|
// Create a temporary element to hold the contents to copy.
|
||||||
|
|
|
@ -65,5 +65,5 @@ describe('CustomIconRegistry', () => {
|
||||||
function createSvg(svgSrc: string): SVGElement {
|
function createSvg(svgSrc: string): SVGElement {
|
||||||
const div = document.createElement('div');
|
const div = document.createElement('div');
|
||||||
div.innerHTML = svgSrc;
|
div.innerHTML = svgSrc;
|
||||||
return div.querySelector('svg')!;
|
return div.querySelector('svg') as SVGElement;
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,7 @@ export class CustomIconRegistry extends MatIconRegistry {
|
||||||
// SECURITY: the source for the SVG icons is provided in code by trusted developers
|
// SECURITY: the source for the SVG icons is provided in code by trusted developers
|
||||||
div.innerHTML = svgIcon.svgSource;
|
div.innerHTML = svgIcon.svgSource;
|
||||||
|
|
||||||
const svgElement = div.querySelector('svg')!;
|
const svgElement = div.querySelector('svg') as SVGElement;
|
||||||
nsIconMap[svgIcon.name] = svgElement;
|
nsIconMap[svgIcon.name] = svgElement;
|
||||||
|
|
||||||
return svgElement;
|
return svgElement;
|
||||||
|
|
|
@ -235,7 +235,7 @@ describe('ScrollSpyService', () => {
|
||||||
|
|
||||||
it('should remember and emit the last active item to new subscribers', () => {
|
it('should remember and emit the last active item to new subscribers', () => {
|
||||||
const items = [{index: 1}, {index: 2}, {index: 3}] as ScrollItem[];
|
const items = [{index: 1}, {index: 2}, {index: 3}] as ScrollItem[];
|
||||||
let lastActiveItem: ScrollItem|null;
|
let lastActiveItem = null as unknown as ScrollItem|null;
|
||||||
|
|
||||||
const info = scrollSpyService.spyOn([]);
|
const info = scrollSpyService.spyOn([]);
|
||||||
const spiedElemGroup = getSpiedElemGroups()[0];
|
const spiedElemGroup = getSpiedElemGroups()[0];
|
||||||
|
@ -247,12 +247,12 @@ describe('ScrollSpyService', () => {
|
||||||
spiedElemGroup.activeScrollItem.next(items[1]);
|
spiedElemGroup.activeScrollItem.next(items[1]);
|
||||||
info.active.subscribe(item => lastActiveItem = item);
|
info.active.subscribe(item => lastActiveItem = item);
|
||||||
|
|
||||||
expect(lastActiveItem!).toBe(items[1]);
|
expect(lastActiveItem).toBe(items[1]);
|
||||||
|
|
||||||
spiedElemGroup.activeScrollItem.next(null);
|
spiedElemGroup.activeScrollItem.next(null);
|
||||||
info.active.subscribe(item => lastActiveItem = item);
|
info.active.subscribe(item => lastActiveItem = item);
|
||||||
|
|
||||||
expect(lastActiveItem!).toBeNull();
|
expect(lastActiveItem).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should only emit distinct values on `active`', () => {
|
it('should only emit distinct values on `active`', () => {
|
||||||
|
|
|
@ -114,7 +114,7 @@ describe('ScrollService', () => {
|
||||||
|
|
||||||
it('should not break when cookies are disabled in the browser', () => {
|
it('should not break when cookies are disabled in the browser', () => {
|
||||||
expect(() => {
|
expect(() => {
|
||||||
const originalSessionStorage = Object.getOwnPropertyDescriptor(window, 'sessionStorage')!;
|
const originalSessionStorage = Object.getOwnPropertyDescriptor(window, 'sessionStorage') as PropertyDescriptor;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Simulate `window.sessionStorage` being inaccessible, when cookies are disabled.
|
// Simulate `window.sessionStorage` being inaccessible, when cookies are disabled.
|
||||||
|
|
|
@ -33,7 +33,7 @@ export class ScrollService implements OnDestroy {
|
||||||
const toolbar = this.document.querySelector('.app-toolbar');
|
const toolbar = this.document.querySelector('.app-toolbar');
|
||||||
this._topOffset = (toolbar && toolbar.clientHeight || 0) + topMargin;
|
this._topOffset = (toolbar && toolbar.clientHeight || 0) + topMargin;
|
||||||
}
|
}
|
||||||
return this._topOffset!;
|
return this._topOffset as number;
|
||||||
}
|
}
|
||||||
|
|
||||||
get topOfPageElement() {
|
get topOfPageElement() {
|
||||||
|
|
|
@ -98,10 +98,10 @@ function splitPages(allPages: SearchResult[]) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
while (priorityPages.length < 5 && pages.length) {
|
while (priorityPages.length < 5 && pages.length) {
|
||||||
priorityPages.push(pages.shift()!);
|
priorityPages.push(pages.shift() as SearchResult);
|
||||||
}
|
}
|
||||||
while (priorityPages.length < 5 && deprecated.length) {
|
while (priorityPages.length < 5 && deprecated.length) {
|
||||||
priorityPages.push(deprecated.shift()!);
|
priorityPages.push(deprecated.shift() as SearchResult);
|
||||||
}
|
}
|
||||||
pages.sort(compareResults);
|
pages.sort(compareResults);
|
||||||
|
|
||||||
|
|
|
@ -35,10 +35,10 @@ describe('SelectComponent', () => {
|
||||||
|
|
||||||
describe('button', () => {
|
describe('button', () => {
|
||||||
it('should display the label if provided', () => {
|
it('should display the label if provided', () => {
|
||||||
expect(getButton().textContent!.trim()).toEqual('');
|
expect(getButton().textContent?.trim()).toEqual('');
|
||||||
host.label = 'Label:';
|
host.label = 'Label:';
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(getButton().textContent!.trim()).toEqual('Label:');
|
expect(getButton().textContent?.trim()).toEqual('Label:');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should contain a symbol if hasSymbol is true', () => {
|
it('should contain a symbol if hasSymbol is true', () => {
|
||||||
|
@ -53,7 +53,7 @@ describe('SelectComponent', () => {
|
||||||
host.selected = options[0];
|
host.selected = options[0];
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(getButton().textContent).toContain(options[0].title);
|
expect(getButton().textContent).toContain(options[0].title);
|
||||||
expect(getButtonSymbol()!.className).toContain(options[0].value);
|
expect(getButtonSymbol()?.className).toContain(options[0].value);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should toggle the visibility of the options list when clicked', () => {
|
it('should toggle the visibility of the options list when clicked', () => {
|
||||||
|
@ -108,7 +108,7 @@ describe('SelectComponent', () => {
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(host.onChange).toHaveBeenCalledWith({ option: options[0], index: 0 });
|
expect(host.onChange).toHaveBeenCalledWith({ option: options[0], index: 0 });
|
||||||
expect(getButton().textContent).toContain(options[0].title);
|
expect(getButton().textContent).toContain(options[0].title);
|
||||||
expect(getButtonSymbol()!.className).toContain(options[0].value);
|
expect(getButtonSymbol()?.className).toContain(options[0].value);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should select the current option when enter is pressed', () => {
|
it('should select the current option when enter is pressed', () => {
|
||||||
|
@ -117,7 +117,7 @@ describe('SelectComponent', () => {
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(host.onChange).toHaveBeenCalledWith({ option: options[0], index: 0 });
|
expect(host.onChange).toHaveBeenCalledWith({ option: options[0], index: 0 });
|
||||||
expect(getButton().textContent).toContain(options[0].title);
|
expect(getButton().textContent).toContain(options[0].title);
|
||||||
expect(getButtonSymbol()!.className).toContain(options[0].value);
|
expect(getButtonSymbol()?.className).toContain(options[0].value);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should select the current option when space is pressed', () => {
|
it('should select the current option when space is pressed', () => {
|
||||||
|
@ -126,7 +126,7 @@ describe('SelectComponent', () => {
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(host.onChange).toHaveBeenCalledWith({ option: options[0], index: 0 });
|
expect(host.onChange).toHaveBeenCalledWith({ option: options[0], index: 0 });
|
||||||
expect(getButton().textContent).toContain(options[0].title);
|
expect(getButton().textContent).toContain(options[0].title);
|
||||||
expect(getButtonSymbol()!.className).toContain(options[0].value);
|
expect(getButtonSymbol()?.className).toContain(options[0].value);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should hide when an option is clicked', () => {
|
it('should hide when an option is clicked', () => {
|
||||||
|
|
|
@ -237,23 +237,23 @@ describe('TocService', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have href with docId and heading\'s id', () => {
|
it('should have href with docId and heading\'s id', () => {
|
||||||
const tocItem = lastTocList.find(item => item.title === 'Heading one')!;
|
const tocItem = lastTocList.find(item => item.title === 'Heading one');
|
||||||
expect(tocItem.href).toEqual(`${docId}#heading-one-special-id`);
|
expect(tocItem?.href).toEqual(`${docId}#heading-one-special-id`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have level "h1" for an <h1>', () => {
|
it('should have level "h1" for an <h1>', () => {
|
||||||
const tocItem = lastTocList.find(item => item.title === 'Fun with TOC')!;
|
const tocItem = lastTocList.find(item => item.title === 'Fun with TOC');
|
||||||
expect(tocItem.level).toEqual('h1');
|
expect(tocItem?.level).toEqual('h1');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have level "h2" for an <h2>', () => {
|
it('should have level "h2" for an <h2>', () => {
|
||||||
const tocItem = lastTocList.find(item => item.title === 'Heading one')!;
|
const tocItem = lastTocList.find(item => item.title === 'Heading one');
|
||||||
expect(tocItem.level).toEqual('h2');
|
expect(tocItem?.level).toEqual('h2');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have level "h3" for an <h3>', () => {
|
it('should have level "h3" for an <h3>', () => {
|
||||||
const tocItem = lastTocList.find(item => item.title === 'H3 3a')!;
|
const tocItem = lastTocList.find(item => item.title === 'H3 3a');
|
||||||
expect(tocItem.level).toEqual('h3');
|
expect(tocItem?.level).toEqual('h3');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have title which is heading\'s textContent ', () => {
|
it('should have title which is heading\'s textContent ', () => {
|
||||||
|
@ -275,8 +275,8 @@ describe('TocService', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have href with docId and calculated heading id', () => {
|
it('should have href with docId and calculated heading id', () => {
|
||||||
const tocItem = lastTocList.find(item => item.title === 'H2 Two')!;
|
const tocItem = lastTocList.find(item => item.title === 'H2 Two');
|
||||||
expect(tocItem.href).toEqual(`${docId}#h2-two`);
|
expect(tocItem?.href).toEqual(`${docId}#h2-two`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should ignore HTML in heading when calculating id', () => {
|
it('should ignore HTML in heading when calculating id', () => {
|
||||||
|
|
|
@ -70,7 +70,7 @@ export class TocService {
|
||||||
// Remove any remaining `a` elements (but keep their content).
|
// Remove any remaining `a` elements (but keep their content).
|
||||||
querySelectorAll(div, 'a').forEach(anchorLink => {
|
querySelectorAll(div, 'a').forEach(anchorLink => {
|
||||||
// We want to keep the content of this anchor, so move it into its parent.
|
// We want to keep the content of this anchor, so move it into its parent.
|
||||||
const parent = anchorLink.parentNode!;
|
const parent = anchorLink.parentNode as Node;
|
||||||
while (anchorLink.childNodes.length) {
|
while (anchorLink.childNodes.length) {
|
||||||
parent.insertBefore(anchorLink.childNodes[0], anchorLink);
|
parent.insertBefore(anchorLink.childNodes[0], anchorLink);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ export class MockLocationService {
|
||||||
urlSubject = new BehaviorSubject<string>(this.initialUrl);
|
urlSubject = new BehaviorSubject<string>(this.initialUrl);
|
||||||
currentUrl = this.urlSubject.asObservable().pipe(map(url => this.stripSlashes(url)));
|
currentUrl = this.urlSubject.asObservable().pipe(map(url => this.stripSlashes(url)));
|
||||||
// strip off query and hash
|
// strip off query and hash
|
||||||
currentPath = this.currentUrl.pipe(map(url => url.match(/[^?#]*/)![0]));
|
currentPath = this.currentUrl.pipe(map(url => url.match(/[^?#]*/)?.[0] || ''));
|
||||||
search = jasmine.createSpy('search').and.returnValue({});
|
search = jasmine.createSpy('search').and.returnValue({});
|
||||||
setSearch = jasmine.createSpy('setSearch');
|
setSearch = jasmine.createSpy('setSearch');
|
||||||
fullPageNavigationNeeded = jasmine.createSpy('Location.fullPageNavigationNeeded');
|
fullPageNavigationNeeded = jasmine.createSpy('Location.fullPageNavigationNeeded');
|
||||||
|
@ -23,4 +23,3 @@ export class MockLocationService {
|
||||||
return url.replace(/^\/+/, '').replace(/\/+(\?|#|$)/, '$1');
|
return url.replace(/^\/+/, '').replace(/\/+(\?|#|$)/, '$1');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ describe('site App', () => {
|
||||||
|
|
||||||
// Test all headings (and sub-headings).
|
// Test all headings (and sub-headings).
|
||||||
expect(await navItemHeadings.count()).toBeGreaterThan(0);
|
expect(await navItemHeadings.count()).toBeGreaterThan(0);
|
||||||
await navItemHeadings.each(heading => testNavItemHeading(heading!, 1));
|
await navItemHeadings.each(heading => heading && testNavItemHeading(heading, 1));
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
async function expectToBeCollapsed(elementFinder: ElementFinder) {
|
async function expectToBeCollapsed(elementFinder: ElementFinder) {
|
||||||
|
@ -63,7 +63,7 @@ describe('site App', () => {
|
||||||
// Recursively test child-headings (while this heading is expanded).
|
// Recursively test child-headings (while this heading is expanded).
|
||||||
const nextLevel = level + 1;
|
const nextLevel = level + 1;
|
||||||
const childNavItemHeadings = page.getNavItemHeadings(children, nextLevel);
|
const childNavItemHeadings = page.getNavItemHeadings(children, nextLevel);
|
||||||
await childNavItemHeadings.each(childHeading => testNavItemHeading(childHeading!, nextLevel));
|
await childNavItemHeadings.each(childHeading => childHeading && testNavItemHeading(childHeading, nextLevel));
|
||||||
|
|
||||||
// Ensure heading does not cause navigation when collapsing.
|
// Ensure heading does not cause navigation when collapsing.
|
||||||
await page.click(heading);
|
await page.click(heading);
|
||||||
|
|
|
@ -61,8 +61,7 @@
|
||||||
true,
|
true,
|
||||||
"ignore-params"
|
"ignore-params"
|
||||||
],
|
],
|
||||||
// TODO(gkalpak): Fix the code and enable this to align with CLI. (Failures: 59)
|
"no-non-null-assertion": true,
|
||||||
// "no-non-null-assertion": true,
|
|
||||||
"no-redundant-jsdoc": true,
|
"no-redundant-jsdoc": true,
|
||||||
"no-switch-case-fall-through": true,
|
"no-switch-case-fall-through": true,
|
||||||
"no-var-requires": false,
|
"no-var-requires": false,
|
||||||
|
|
Loading…
Reference in New Issue