test(docs-infra): remove deprecated `ReflectiveInjector` (#38408)

This commit replaces the old and slow `ReflectiveInjector` that was
deprecated in v5 with the new `Injector`. Note: This change was only
done in the spec files inside the `aio` folder.

While changing this, it was not possible to directly use `Injector.get`
to get the correct typing for the mocked classes. For example:

```typescript
locationService = injector.get<TestLocationService>(LocationService);
```

Fails with:

> Argument of type 'typeof LocationService' is not assignable to parameter
of type 'Type<TestLocationService> | InjectionToken<TestLocationService> |
AbstractType<TestLocationService>'.
  Type 'typeof LocationService' is not assignable to type 'Type<TestLocationService>'.
    Property 'searchResult' is missing in type 'LocationService' but required in type
    'TestLocationService'.

Therefore, it was necessary to first convert to `unknown` and then to
`TestLocationService`.

```typescript
locationService = injector.get(LocationService) as unknown as TestLocationService;
```

PR Close #38408
This commit is contained in:
Sonu Kapoor 2020-08-10 19:02:47 -04:00 committed by Andrew Scott
parent 945751e2e8
commit 175c79d1d8
12 changed files with 118 additions and 98 deletions

View File

@ -1,4 +1,4 @@
import { ReflectiveInjector } from '@angular/core'; import { Injector } from '@angular/core';
import { of } from 'rxjs'; import { of } from 'rxjs';
@ -12,20 +12,22 @@ import { LocationService } from 'app/shared/location.service';
describe('ContributorListComponent', () => { describe('ContributorListComponent', () => {
let component: ContributorListComponent; let component: ContributorListComponent;
let injector: ReflectiveInjector; let injector: Injector;
let contributorService: TestContributorService; let contributorService: TestContributorService;
let locationService: TestLocationService; let locationService: TestLocationService;
let contributorGroups: ContributorGroup[]; let contributorGroups: ContributorGroup[];
beforeEach(() => { beforeEach(() => {
injector = ReflectiveInjector.resolveAndCreate([ injector = Injector.create({
ContributorListComponent, providers: [
{provide: ContributorService, useClass: TestContributorService }, {provide: ContributorListComponent, deps: [ContributorService, LocationService] },
{provide: LocationService, useClass: TestLocationService } {provide: ContributorService, useClass: TestContributorService, deps: [] },
]); {provide: LocationService, useClass: TestLocationService, deps: [] }
]
});
locationService = injector.get(LocationService); locationService = injector.get(LocationService) as unknown as TestLocationService;
contributorService = injector.get(ContributorService); contributorService = injector.get(ContributorService) as unknown as TestContributorService;
contributorGroups = contributorService.testContributors; contributorGroups = contributorService.testContributors;
}); });

View File

@ -1,4 +1,4 @@
import { ReflectiveInjector } from '@angular/core'; import { Injector } from '@angular/core';
import { of } from 'rxjs'; import { of } from 'rxjs';
@ -12,20 +12,22 @@ import { Category } from './resource.model';
describe('ResourceListComponent', () => { describe('ResourceListComponent', () => {
let component: ResourceListComponent; let component: ResourceListComponent;
let injector: ReflectiveInjector; let injector: Injector;
let resourceService: TestResourceService; let resourceService: TestResourceService;
let locationService: TestLocationService; let locationService: TestLocationService;
let categories: Category[]; let categories: Category[];
beforeEach(() => { beforeEach(() => {
injector = ReflectiveInjector.resolveAndCreate([ injector = Injector.create({
ResourceListComponent, providers: [
{provide: ResourceService, useClass: TestResourceService }, {provide: ResourceListComponent, deps: [ResourceService, LocationService] },
{provide: LocationService, useClass: TestLocationService } {provide: ResourceService, useClass: TestResourceService, deps: [] },
]); {provide: LocationService, useClass: TestLocationService, deps: [] }
]
});
locationService = injector.get(LocationService); locationService = injector.get(LocationService) as unknown as TestLocationService;
resourceService = injector.get(ResourceService); resourceService = injector.get(ResourceService) as unknown as TestResourceService;
categories = resourceService.testCategories; categories = resourceService.testCategories;
}); });

View File

@ -1,4 +1,4 @@
import { ReflectiveInjector, NgZone } from '@angular/core'; import { Injector, NgZone } from '@angular/core';
import { fakeAsync, tick } from '@angular/core/testing'; import { fakeAsync, tick } from '@angular/core/testing';
import { of } from 'rxjs'; import { of } from 'rxjs';
import { SearchService } from './search.service'; import { SearchService } from './search.service';
@ -6,7 +6,7 @@ import { WebWorkerClient } from 'app/shared/web-worker';
describe('SearchService', () => { describe('SearchService', () => {
let injector: ReflectiveInjector; let injector: Injector;
let service: SearchService; let service: SearchService;
let sendMessageSpy: jasmine.Spy; let sendMessageSpy: jasmine.Spy;
let mockWorker: WebWorkerClient; let mockWorker: WebWorkerClient;
@ -16,10 +16,13 @@ describe('SearchService', () => {
mockWorker = { sendMessage: sendMessageSpy } as any; mockWorker = { sendMessage: sendMessageSpy } as any;
spyOn(WebWorkerClient, 'create').and.returnValue(mockWorker); spyOn(WebWorkerClient, 'create').and.returnValue(mockWorker);
injector = ReflectiveInjector.resolveAndCreate([ injector = Injector.create({
SearchService, providers: [
{ provide: NgZone, useFactory: () => new NgZone({ enableLongStackTrace: false }) } { provide: SearchService, deps: [NgZone]},
]); { provide: NgZone, useFactory: () => new NgZone({ enableLongStackTrace: false }), deps: [] }
]
});
service = injector.get(SearchService); service = injector.get(SearchService);
}); });

View File

@ -1,4 +1,4 @@
import { ReflectiveInjector } from '@angular/core'; import { Injector } from '@angular/core';
import { environment } from 'environments/environment'; import { environment } from 'environments/environment';
import { LocationService } from 'app/shared/location.service'; import { LocationService } from 'app/shared/location.service';
import { MockLocationService } from 'testing/location.service'; import { MockLocationService } from 'testing/location.service';
@ -15,7 +15,7 @@ describe('Deployment service', () => {
it('should get the mode from the `mode` query parameter if available', () => { it('should get the mode from the `mode` query parameter if available', () => {
const injector = getInjector(); const injector = getInjector();
const locationService: MockLocationService = injector.get(LocationService); const locationService = injector.get(LocationService) as unknown as MockLocationService;
locationService.search.and.returnValue({ mode: 'bar' }); locationService.search.and.returnValue({ mode: 'bar' });
const deployment = injector.get(Deployment); const deployment = injector.get(Deployment);
@ -25,8 +25,8 @@ describe('Deployment service', () => {
}); });
function getInjector() { function getInjector() {
return ReflectiveInjector.resolveAndCreate([ return Injector.create({providers: [
Deployment, { provide: Deployment, deps: [LocationService] },
{ provide: LocationService, useFactory: () => new MockLocationService('') } { provide: LocationService, useFactory: () => new MockLocationService(''), deps: [] }
]); ]});
} }

View File

@ -1,18 +1,23 @@
import { ReflectiveInjector } from '@angular/core'; import { Injector } from '@angular/core';
import { GaService } from 'app/shared/ga.service'; import { GaService } from 'app/shared/ga.service';
import { WindowToken } from 'app/shared/window'; import { WindowToken } from 'app/shared/window';
describe('GaService', () => { describe('GaService', () => {
let gaService: GaService; let gaService: GaService;
let injector: ReflectiveInjector; let injector: Injector;
let gaSpy: jasmine.Spy; let gaSpy: jasmine.Spy;
let mockWindow: any; let mockWindow: any;
beforeEach(() => { beforeEach(() => {
gaSpy = jasmine.createSpy('ga'); gaSpy = jasmine.createSpy('ga');
mockWindow = { ga: gaSpy }; mockWindow = { ga: gaSpy };
injector = ReflectiveInjector.resolveAndCreate([GaService, { provide: WindowToken, useFactory: () => mockWindow }]); injector = Injector.create({
providers: [
{ provide: GaService, deps: [WindowToken] },
{ provide: WindowToken, useFactory: () => mockWindow, deps: [] }
]});
gaService = injector.get(GaService); gaService = injector.get(GaService);
}); });

View File

@ -1,4 +1,4 @@
import { ReflectiveInjector } from '@angular/core'; import { Injector } from '@angular/core';
import { Location, LocationStrategy, PlatformLocation } from '@angular/common'; import { Location, LocationStrategy, PlatformLocation } from '@angular/common';
import { MockLocationStrategy } from '@angular/common/testing'; import { MockLocationStrategy } from '@angular/common/testing';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
@ -9,26 +9,28 @@ import { LocationService } from './location.service';
import { ScrollService } from './scroll.service'; import { ScrollService } from './scroll.service';
describe('LocationService', () => { describe('LocationService', () => {
let injector: ReflectiveInjector; let injector: Injector;
let location: MockLocationStrategy; let location: MockLocationStrategy;
let service: LocationService; let service: LocationService;
let swUpdates: MockSwUpdatesService; let swUpdates: MockSwUpdatesService;
let scrollService: MockScrollService; let scrollService: MockScrollService;
beforeEach(() => { beforeEach(() => {
injector = ReflectiveInjector.resolveAndCreate([ injector = Injector.create({
LocationService, providers: [
Location, { provide: LocationService, deps: [GaService, Location, ScrollService, PlatformLocation, SwUpdatesService] },
{ provide: GaService, useClass: TestGaService }, { provide: Location, deps: [LocationStrategy, PlatformLocation] },
{ provide: LocationStrategy, useClass: MockLocationStrategy }, { provide: GaService, useClass: TestGaService, deps: [] },
{ provide: PlatformLocation, useClass: MockPlatformLocation }, { provide: LocationStrategy, useClass: MockLocationStrategy, deps: [] },
{ provide: SwUpdatesService, useClass: MockSwUpdatesService }, { provide: PlatformLocation, useClass: MockPlatformLocation, deps: [] },
{ provide: ScrollService, useClass: MockScrollService } { provide: SwUpdatesService, useClass: MockSwUpdatesService, deps: [] },
]); { provide: ScrollService, useClass: MockScrollService, deps: [] }
]
});
location = injector.get(LocationStrategy); location = injector.get(LocationStrategy) as unknown as MockLocationStrategy;
service = injector.get(LocationService); service = injector.get(LocationService);
swUpdates = injector.get(SwUpdatesService); swUpdates = injector.get(SwUpdatesService) as unknown as MockSwUpdatesService;
scrollService = injector.get(ScrollService); scrollService = injector.get(ScrollService);
}); });
@ -380,7 +382,7 @@ describe('LocationService', () => {
let platformLocation: MockPlatformLocation; let platformLocation: MockPlatformLocation;
beforeEach(() => { beforeEach(() => {
platformLocation = injector.get(PlatformLocation); platformLocation = injector.get(PlatformLocation) as unknown as MockPlatformLocation;
}); });
it('should call replaceState on PlatformLocation', () => { it('should call replaceState on PlatformLocation', () => {
@ -577,7 +579,7 @@ describe('LocationService', () => {
let gaLocationChanged: jasmine.Spy; let gaLocationChanged: jasmine.Spy;
beforeEach(() => { beforeEach(() => {
const gaService = injector.get(GaService); const gaService = injector.get(GaService) as unknown as TestGaService;
gaLocationChanged = gaService.locationChanged; gaLocationChanged = gaService.locationChanged;
// execute currentPath observable so that gaLocationChanged is called // execute currentPath observable so that gaLocationChanged is called
service.currentPath.subscribe(); service.currentPath.subscribe();

View File

@ -1,4 +1,4 @@
import { ErrorHandler, ReflectiveInjector } from '@angular/core'; import { ErrorHandler, Injector } from '@angular/core';
import { Logger } from './logger.service'; import { Logger } from './logger.service';
describe('logger service', () => { describe('logger service', () => {
@ -10,10 +10,10 @@ describe('logger service', () => {
beforeEach(() => { beforeEach(() => {
logSpy = spyOn(console, 'log'); logSpy = spyOn(console, 'log');
warnSpy = spyOn(console, 'warn'); warnSpy = spyOn(console, 'warn');
const injector = ReflectiveInjector.resolveAndCreate([ const injector = Injector.create({providers: [
Logger, { provide: Logger, deps: [ErrorHandler] },
{ provide: ErrorHandler, useClass: MockErrorHandler } { provide: ErrorHandler, useClass: MockErrorHandler, deps: [] }
]); ]});
logger = injector.get(Logger); logger = injector.get(Logger);
errorHandler = injector.get(ErrorHandler); errorHandler = injector.get(ErrorHandler);
}); });

View File

@ -1,4 +1,4 @@
import { ErrorHandler, ReflectiveInjector } from '@angular/core'; import { ErrorHandler, Injector } from '@angular/core';
import { TestBed } from '@angular/core/testing'; import { TestBed } from '@angular/core/testing';
import { WindowToken } from 'app/shared/window'; import { WindowToken } from 'app/shared/window';
import { AppModule } from 'app/app.module'; import { AppModule } from 'app/app.module';
@ -14,11 +14,12 @@ describe('ReportingErrorHandler service', () => {
onerrorSpy = jasmine.createSpy('onerror'); onerrorSpy = jasmine.createSpy('onerror');
superHandler = spyOn(ErrorHandler.prototype, 'handleError'); superHandler = spyOn(ErrorHandler.prototype, 'handleError');
const injector = ReflectiveInjector.resolveAndCreate([ const injector = Injector.create({providers: [
{ provide: ErrorHandler, useClass: ReportingErrorHandler }, { provide: ErrorHandler, useClass: ReportingErrorHandler, deps: [WindowToken] },
{ provide: WindowToken, useFactory: () => ({ onerror: onerrorSpy }) } { provide: WindowToken, useFactory: () => ({ onerror: onerrorSpy }), deps: [] }
]); ]});
handler = injector.get(ErrorHandler);
handler = injector.get(ErrorHandler) as unknown as ReportingErrorHandler;
}); });
it('should be registered on the AppModule', () => { it('should be registered on the AppModule', () => {

View File

@ -1,4 +1,4 @@
import { Injector, ReflectiveInjector } from '@angular/core'; import { Injector } from '@angular/core';
import { fakeAsync, tick } from '@angular/core/testing'; import { fakeAsync, tick } from '@angular/core/testing';
import { DOCUMENT } from '@angular/common'; import { DOCUMENT } from '@angular/common';
@ -151,11 +151,11 @@ describe('ScrollSpyService', () => {
let scrollSpyService: ScrollSpyService; let scrollSpyService: ScrollSpyService;
beforeEach(() => { beforeEach(() => {
injector = ReflectiveInjector.resolveAndCreate([ injector = Injector.create({providers: [
{ provide: DOCUMENT, useValue: { body: {} } }, { provide: DOCUMENT, useValue: { body: {} } },
{ provide: ScrollService, useValue: { topOffset: 50 } }, { provide: ScrollService, useValue: { topOffset: 50 } },
ScrollSpyService { provide: ScrollSpyService, deps: [DOCUMENT, ScrollService] }
]); ]});
scrollSpyService = injector.get(ScrollSpyService); scrollSpyService = injector.get(ScrollSpyService);
}); });

View File

@ -1,7 +1,7 @@
import {Location, LocationStrategy, PlatformLocation, ViewportScroller} from '@angular/common'; import {Location, LocationStrategy, PlatformLocation, ViewportScroller} from '@angular/common';
import {DOCUMENT} from '@angular/common'; import {DOCUMENT} from '@angular/common';
import {MockLocationStrategy, SpyLocation} from '@angular/common/testing'; import {MockLocationStrategy, SpyLocation} from '@angular/common/testing';
import {ReflectiveInjector} from '@angular/core'; import {Injector} from '@angular/core';
import {fakeAsync, tick} from '@angular/core/testing'; import {fakeAsync, tick} from '@angular/core/testing';
import {ScrollService, topMargin} from './scroll.service'; import {ScrollService, topMargin} from './scroll.service';
@ -15,7 +15,7 @@ describe('ScrollService', () => {
}; };
const topOfPageElem = {} as Element; const topOfPageElem = {} as Element;
let injector: ReflectiveInjector; let injector: Injector;
let document: MockDocument; let document: MockDocument;
let platformLocation: MockPlatformLocation; let platformLocation: MockPlatformLocation;
let scrollService: ScrollService; let scrollService: ScrollService;
@ -41,21 +41,25 @@ describe('ScrollService', () => {
jasmine.createSpyObj('viewportScroller', ['getScrollPosition', 'scrollToPosition']); jasmine.createSpyObj('viewportScroller', ['getScrollPosition', 'scrollToPosition']);
beforeEach(() => { beforeEach(() => {
injector = ReflectiveInjector.resolveAndCreate([ injector = Injector.create( {
{ providers: [
provide: ScrollService, {
useFactory: createScrollService, provide: ScrollService,
deps: [DOCUMENT, PlatformLocation, ViewportScroller, Location], useFactory: createScrollService,
}, deps: [DOCUMENT, PlatformLocation, ViewportScroller, Location],
{provide: Location, useClass: SpyLocation}, {provide: DOCUMENT, useClass: MockDocument}, },
{provide: PlatformLocation, useClass: MockPlatformLocation}, {provide: Location, useClass: SpyLocation, deps: [] },
{provide: ViewportScroller, useValue: viewportScrollerStub}, {provide: DOCUMENT, useClass: MockDocument, deps: []},
{provide: LocationStrategy, useClass: MockLocationStrategy} {provide: PlatformLocation, useClass: MockPlatformLocation, deps: []},
]); {provide: ViewportScroller, useValue: viewportScrollerStub},
{provide: LocationStrategy, useClass: MockLocationStrategy, deps: []}
]
});
platformLocation = injector.get(PlatformLocation); platformLocation = injector.get(PlatformLocation);
document = injector.get(DOCUMENT); document = injector.get(DOCUMENT) as unknown as MockDocument;
scrollService = injector.get(ScrollService); scrollService = injector.get(ScrollService);
location = injector.get(Location); location = injector.get(Location) as unknown as SpyLocation;
spyOn(window, 'scrollBy'); spyOn(window, 'scrollBy');
}); });

View File

@ -1,5 +1,5 @@
import { DOCUMENT } from '@angular/common'; import { DOCUMENT } from '@angular/common';
import { ReflectiveInjector } from '@angular/core'; import { Injector } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
@ -7,7 +7,7 @@ import { ScrollItem, ScrollSpyInfo, ScrollSpyService } from 'app/shared/scroll-s
import { TocItem, TocService } from './toc.service'; import { TocItem, TocService } from './toc.service';
describe('TocService', () => { describe('TocService', () => {
let injector: ReflectiveInjector; let injector: Injector;
let scrollSpyService: MockScrollSpyService; let scrollSpyService: MockScrollSpyService;
let tocService: TocService; let tocService: TocService;
let lastTocList: TocItem[]; let lastTocList: TocItem[];
@ -21,13 +21,14 @@ describe('TocService', () => {
} }
beforeEach(() => { beforeEach(() => {
injector = ReflectiveInjector.resolveAndCreate([ injector = Injector.create({providers: [
{ provide: DomSanitizer, useClass: TestDomSanitizer }, { provide: DomSanitizer, useClass: TestDomSanitizer, deps: [] },
{ provide: DOCUMENT, useValue: document }, { provide: DOCUMENT, useValue: document },
{ provide: ScrollSpyService, useClass: MockScrollSpyService }, { provide: ScrollSpyService, useClass: MockScrollSpyService, deps: [] },
TocService, { provide: TocService, deps: [DOCUMENT, DomSanitizer, ScrollSpyService] },
]); ]});
scrollSpyService = injector.get(ScrollSpyService);
scrollSpyService = injector.get(ScrollSpyService) as unknown as MockScrollSpyService;
tocService = injector.get(TocService); tocService = injector.get(TocService);
tocService.tocList.subscribe(tocList => lastTocList = tocList); tocService.tocList.subscribe(tocList => lastTocList = tocList);
}); });
@ -330,7 +331,7 @@ describe('TocService', () => {
}); });
it('should have bypassed HTML sanitizing of heading\'s innerHTML ', () => { it('should have bypassed HTML sanitizing of heading\'s innerHTML ', () => {
const domSanitizer: TestDomSanitizer = injector.get(DomSanitizer); const domSanitizer: TestDomSanitizer = injector.get(DomSanitizer) as unknown as TestDomSanitizer;
expect(domSanitizer.bypassSecurityTrustHtml) expect(domSanitizer.bypassSecurityTrustHtml)
.toHaveBeenCalledWith('Setup to develop <i>locally</i>.'); .toHaveBeenCalledWith('Setup to develop <i>locally</i>.');
}); });

View File

@ -1,4 +1,4 @@
import { ApplicationRef, ReflectiveInjector } from '@angular/core'; import { ApplicationRef, Injector } from '@angular/core';
import { discardPeriodicTasks, fakeAsync, tick } from '@angular/core/testing'; import { discardPeriodicTasks, fakeAsync, tick } from '@angular/core/testing';
import { SwUpdate } from '@angular/service-worker'; import { SwUpdate } from '@angular/service-worker';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
@ -8,7 +8,7 @@ import { SwUpdatesService } from './sw-updates.service';
describe('SwUpdatesService', () => { describe('SwUpdatesService', () => {
let injector: ReflectiveInjector; let injector: Injector;
let appRef: MockApplicationRef; let appRef: MockApplicationRef;
let service: SwUpdatesService; let service: SwUpdatesService;
let swu: MockSwUpdate; let swu: MockSwUpdate;
@ -21,16 +21,16 @@ describe('SwUpdatesService', () => {
// run `setup()`/`tearDown()` in `beforeEach()`/`afterEach()` blocks. We use the `run()` helper // run `setup()`/`tearDown()` in `beforeEach()`/`afterEach()` blocks. We use the `run()` helper
// to call them inside each test's zone. // to call them inside each test's zone.
const setup = (isSwUpdateEnabled: boolean) => { const setup = (isSwUpdateEnabled: boolean) => {
injector = ReflectiveInjector.resolveAndCreate([ injector = Injector.create({providers: [
{ provide: ApplicationRef, useClass: MockApplicationRef }, { provide: ApplicationRef, useClass: MockApplicationRef, deps: [] },
{ provide: Logger, useClass: MockLogger }, { provide: Logger, useClass: MockLogger, deps: [] },
{ provide: SwUpdate, useFactory: () => new MockSwUpdate(isSwUpdateEnabled) }, { provide: SwUpdate, useFactory: () => new MockSwUpdate(isSwUpdateEnabled), deps: [] },
SwUpdatesService { provide: SwUpdatesService, deps: [ApplicationRef, Logger, SwUpdate] }
]); ]});
appRef = injector.get(ApplicationRef); appRef = injector.get(ApplicationRef) as unknown as MockApplicationRef;
service = injector.get(SwUpdatesService); service = injector.get(SwUpdatesService);
swu = injector.get(SwUpdate); swu = injector.get(SwUpdate) as unknown as MockSwUpdate;
checkInterval = (service as any).checkInterval; checkInterval = (service as any).checkInterval;
}; };
const tearDown = () => service.ngOnDestroy(); const tearDown = () => service.ngOnDestroy();