Skip to content

Commit d6cc784

Browse files
authored
refactor(multiple): remove declare global usages (#32991)
Removes all our usages of `declare global`, because they appear to cause breakages with some recent tooling updates.
1 parent 9055ac5 commit d6cc784

File tree

7 files changed

+112
-143
lines changed

7 files changed

+112
-143
lines changed

docs/src/app/shared/analytics/analytics.ts

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,6 @@ import {Injectable} from '@angular/core';
1111
import {environment} from '../../../environments/environment';
1212
import {formatErrorEventForAnalytics} from './format-error';
1313

14-
/** Extension of `Window` with potential Google Analytics fields. */
15-
declare global {
16-
interface Window {
17-
dataLayer?: any[];
18-
gtag?(...args: any[]): void;
19-
/** Legacy Universal Analytics `analytics.js` field. */
20-
ga?(...args: any[]): void;
21-
}
22-
}
23-
2414
/**
2515
* Google Analytics Service - captures app behaviors and sends them to Google Analytics.
2616
*
@@ -34,6 +24,13 @@ declare global {
3424
@Injectable({providedIn: 'root'})
3525
export class AnalyticsService {
3626
private _previousUrl: string | undefined;
27+
private _gaWindow = window as Window &
28+
typeof globalThis & {
29+
dataLayer?: any[];
30+
gtag?(...args: any[]): void;
31+
/** Legacy Universal Analytics `analytics.js` field. */
32+
ga?(...args: any[]): void;
33+
};
3734

3835
constructor() {
3936
this._installGlobalSiteTag();
@@ -71,34 +68,31 @@ export class AnalyticsService {
7168
}
7269

7370
private _legacyGa(...args: any[]) {
74-
if (window.ga) {
75-
window.ga(...args);
76-
}
71+
this._gaWindow.ga?.(...args);
7772
}
7873

7974
private _gtag(...args: any[]) {
80-
if (window.gtag) {
81-
window.gtag(...args);
82-
}
75+
this._gaWindow.gtag?.(...args);
8376
}
8477

8578
private _installGlobalSiteTag() {
79+
const gaWindow = this._gaWindow;
8680
const url = `https://www.googletagmanager.com/gtag/js?id=${environment.googleAnalyticsMaterialId}`;
8781

8882
// Note: This cannot be an arrow function as `gtag.js` expects an actual `Arguments`
8983
// instance with e.g. `callee` to be set. Do not attempt to change this and keep this
9084
// as much as possible in sync with the tracking code snippet suggested by the Google
9185
// Analytics 4 web UI under `Data Streams`.
92-
window.dataLayer = window.dataLayer || [];
93-
window.gtag = function () {
94-
window.dataLayer?.push(arguments);
86+
gaWindow.dataLayer = gaWindow.dataLayer || [];
87+
gaWindow.gtag = function () {
88+
gaWindow.dataLayer?.push(arguments);
9589
};
96-
window.gtag('js', new Date());
90+
gaWindow.gtag('js', new Date());
9791

9892
// Configure properties before loading the script. This is necessary to avoid
9993
// loading multiple instances of the gtag JS scripts.
100-
window.gtag('config', environment.googleAnalyticsOverallDomainId);
101-
window.gtag('config', environment.googleAnalyticsMaterialId);
94+
gaWindow.gtag('config', environment.googleAnalyticsOverallDomainId);
95+
gaWindow.gtag('config', environment.googleAnalyticsMaterialId);
10296

10397
// skip `gtag` for Protractor e2e tests.
10498
if (window.name.includes('NG_DEFER_BOOTSTRAP')) {

src/cdk/testing/selenium-webdriver/selenium-web-driver-harness-environment.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ declare interface FrameworkStabilizer {
1818
(callback: (didWork: boolean) => void): void;
1919
}
2020

21-
declare global {
22-
interface Window {
21+
type WindowWithStabiliziers = Window &
22+
typeof globalThis & {
2323
/**
2424
* These hooks are exposed by Angular to register a callback for when the application is stable
2525
* (no more pending tasks).
@@ -28,8 +28,7 @@ declare global {
2828
* angular/angular/blob/main/packages/platform-browser/src/browser/testability.ts#L30-L49
2929
*/
3030
frameworkStabilizers: FrameworkStabilizer[];
31-
}
32-
}
31+
};
3332

3433
/** Options to configure the environment. */
3534
export interface WebDriverHarnessEnvironmentOptions {
@@ -48,17 +47,19 @@ const defaultEnvironmentOptions: WebDriverHarnessEnvironmentOptions = {
4847
* and invokes the specified `callback` when the application is stable (no more pending tasks).
4948
*/
5049
function whenStable(callback: (didWork: boolean[]) => void): void {
51-
Promise.all(window.frameworkStabilizers.map(stabilizer => new Promise(stabilizer))).then(
52-
callback,
53-
);
50+
Promise.all(
51+
(window as WindowWithStabiliziers).frameworkStabilizers.map(
52+
stabilizer => new Promise(stabilizer),
53+
),
54+
).then(callback);
5455
}
5556

5657
/**
5758
* This function is meant to be executed in the browser. It checks whether the Angular framework has
5859
* bootstrapped yet.
5960
*/
6061
function isBootstrapped() {
61-
return !!window.frameworkStabilizers;
62+
return !!(window as WindowWithStabiliziers).frameworkStabilizers;
6263
}
6364

6465
/** Waits for angular to be ready after the page load. */

src/material-experimental/column-resize/column-resize.spec.ts

Lines changed: 33 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -351,27 +351,12 @@ class ElementDataSource extends DataSource<PeriodicElement> {
351351
}
352352

353353
// There's 1px of variance between different browsers in terms of positioning.
354-
const approximateMatcher: jasmine.CustomMatcherFactories = {
355-
isApproximately: () => ({
356-
compare: (actual: number, expected: number) => {
357-
const result = {
358-
pass: false,
359-
message: `Expected ${actual} to be within 1 of ${expected}`,
360-
};
361-
362-
result.pass = actual === expected || actual === expected + 1 || actual === expected - 1;
363-
364-
return result;
365-
},
366-
}),
367-
};
368-
369-
interface NumberMatchers extends jasmine.Matchers<number> {
370-
isApproximately(expected: number): void;
371-
not: NumberMatchers;
372-
}
373-
declare global {
374-
function expect(actual: number): NumberMatchers;
354+
function expectApproximate(actual: number, expected: number, shouldBeApproximate = true) {
355+
expect(actual === expected || actual === expected + 1 || actual === expected - 1)
356+
.withContext(
357+
`Expected ${actual}${shouldBeApproximate ? '' : ' not'} to be within 1 of ${expected}`,
358+
)
359+
.toBe(shouldBeApproximate);
375360
}
376361

377362
const testCases = [
@@ -391,7 +376,6 @@ describe('Material Popover Edit', () => {
391376
let fixture: ComponentFixture<BaseTestComponent>;
392377

393378
beforeEach(fakeAsync(() => {
394-
jasmine.addMatchers(approximateMatcher);
395379
fixture = TestBed.createComponent(componentClass);
396380
component = fixture.componentInstance;
397381
fixture.detectChanges();
@@ -415,8 +399,8 @@ describe('Material Popover Edit', () => {
415399
component.getOverlayThumbElement(2).classList.contains('mat-column-resize-overlay-thumb'),
416400
).toBe(true);
417401

418-
expect(component.getOverlayThumbElement(0).offsetHeight).isApproximately(headerRowHeight);
419-
expect(component.getOverlayThumbElement(2).offsetHeight).isApproximately(headerRowHeight);
402+
expectApproximate(component.getOverlayThumbElement(0).offsetHeight, headerRowHeight);
403+
expectApproximate(component.getOverlayThumbElement(2).offsetHeight, headerRowHeight);
420404

421405
component.beginColumnResizeWithMouse(0);
422406

@@ -427,11 +411,9 @@ describe('Material Popover Edit', () => {
427411
component.getOverlayThumbElement(2).classList.contains('mat-column-resize-overlay-thumb'),
428412
).toBe(true);
429413

430-
expect(component.getOverlayThumbElement(0).offsetHeight).isApproximately(tableHeight);
431-
expect(component.getOverlayThumbTopElement(0).offsetHeight).isApproximately(
432-
headerRowHeight,
433-
);
434-
expect(component.getOverlayThumbElement(2).offsetHeight).isApproximately(headerRowHeight);
414+
expectApproximate(component.getOverlayThumbElement(0).offsetHeight, tableHeight);
415+
expectApproximate(component.getOverlayThumbTopElement(0).offsetHeight, headerRowHeight);
416+
expectApproximate(component.getOverlayThumbElement(2).offsetHeight, headerRowHeight);
435417

436418
component.completeResizeWithMouseInProgress(0);
437419
component.endHoverState();
@@ -462,31 +444,31 @@ describe('Material Popover Edit', () => {
462444
let columnPositionDelta = component.getColumnOriginPosition(1) - initialColumnPosition;
463445
// let nextColumnPositionDelta =
464446
// component.getColumnOriginPosition(2) - initialNextColumnPosition;
465-
expect(thumbPositionDelta).isApproximately(columnPositionDelta);
447+
expectApproximate(thumbPositionDelta, columnPositionDelta);
466448
// TODO: This was commented out after switching from the legacy table to the current
467449
// MDC-based table. This failed by being inaccurate by several pixels.
468-
// expect(nextColumnPositionDelta).isApproximately(columnPositionDelta);
450+
// expAppexpectApproximateect(nextColumnPositionDelta, columnPositionDelta);
469451

470452
// TODO: This was commented out after switching from the legacy table to the current
471453
// MDC-based table. This failed by being inaccurate by several pixels.
472-
// expect(component.getTableWidth()).isApproximately(initialTableWidth + 5);
473-
expect(component.getColumnWidth(1)).isApproximately(initialColumnWidth + 5);
454+
// expAppexpectApproximateect(component.getTableWidth(), initialTableWidth + 5);
455+
expectApproximate(component.getColumnWidth(1), initialColumnWidth + 5);
474456

475457
component.updateResizeWithMouseInProgress(1);
476458
fixture.detectChanges();
477459
flush();
478460

479461
thumbPositionDelta = component.getOverlayThumbPosition(1) - initialThumbPosition;
480462
columnPositionDelta = component.getColumnOriginPosition(1) - initialColumnPosition;
481-
expect(thumbPositionDelta).isApproximately(columnPositionDelta);
463+
expectApproximate(thumbPositionDelta, columnPositionDelta);
482464

483-
expect(component.getTableWidth()).isApproximately(initialTableWidth + 1);
484-
expect(component.getColumnWidth(1)).isApproximately(initialColumnWidth + 1);
465+
expectApproximate(component.getTableWidth(), initialTableWidth + 1);
466+
expectApproximate(component.getColumnWidth(1), initialColumnWidth + 1);
485467

486468
component.completeResizeWithMouseInProgress(1);
487469
flush();
488470

489-
expect(component.getColumnWidth(1)).isApproximately(initialColumnWidth + 1);
471+
expectApproximate(component.getColumnWidth(1), initialColumnWidth + 1);
490472

491473
component.endHoverState();
492474
fixture.detectChanges();
@@ -509,7 +491,7 @@ describe('Material Popover Edit', () => {
509491
flush();
510492

511493
let thumbPositionDelta = component.getOverlayThumbPosition(1) - initialThumbPosition;
512-
expect(thumbPositionDelta).isApproximately(5);
494+
expectApproximate(thumbPositionDelta, 5);
513495
expect(component.getColumnWidth(1)).toBe(initialColumnWidth);
514496

515497
component.updateResizeWithMouseInProgress(1);
@@ -524,8 +506,8 @@ describe('Material Popover Edit', () => {
524506
component.completeResizeWithMouseInProgress(1);
525507
flush();
526508

527-
expect(component.getTableWidth()).isApproximately(initialTableWidth + 1);
528-
expect(component.getColumnWidth(1)).isApproximately(initialColumnWidth + 1);
509+
expectApproximate(component.getTableWidth(), initialTableWidth + 1);
510+
expectApproximate(component.getColumnWidth(1), initialColumnWidth + 1);
529511

530512
component.endHoverState();
531513
fixture.detectChanges();
@@ -565,18 +547,18 @@ describe('Material Popover Edit', () => {
565547

566548
let thumbPositionDelta = component.getOverlayThumbPosition(1) - initialThumbPosition;
567549
let columnPositionDelta = component.getColumnOriginPosition(1) - initialColumnPosition;
568-
expect(thumbPositionDelta).isApproximately(columnPositionDelta);
550+
expectApproximate(thumbPositionDelta, columnPositionDelta);
569551

570-
expect(component.getColumnWidth(1)).isApproximately(initialColumnWidth + 5);
552+
expectApproximate(component.getColumnWidth(1), initialColumnWidth + 5);
571553
// TODO: This was commented out after switching from the legacy table to the current
572554
// MDC-based table. This failed by being inaccurate by several pixels.
573-
// expect(component.getTableWidth()).isApproximately(initialTableWidth + 5);
555+
// expAppexpectApproximateect(component.getTableWidth(), initialTableWidth + 5);
574556

575557
dispatchKeyboardEvent(document, 'keyup', ESCAPE);
576558
flush();
577559

578-
expect(component.getColumnWidth(1)).isApproximately(initialColumnWidth);
579-
expect(component.getTableWidth()).isApproximately(initialTableWidth);
560+
expectApproximate(component.getColumnWidth(1), initialColumnWidth);
561+
expectApproximate(component.getTableWidth(), initialTableWidth);
580562

581563
component.endHoverState();
582564
fixture.detectChanges();
@@ -631,12 +613,12 @@ describe('Material Popover Edit', () => {
631613

632614
it('performs a column resize triggered via ColumnResizeNotifier', fakeAsync(() => {
633615
// Pre-verify that we are not updating the size to the initial size.
634-
expect(component.getColumnWidth(1)).not.isApproximately(173);
616+
expectApproximate(component.getColumnWidth(1), 173, false);
635617

636618
component.columnResize.columnResizeNotifier.resize('name', 173);
637619
flush();
638620

639-
expect(component.getColumnWidth(1)).isApproximately(173);
621+
expectApproximate(component.getColumnWidth(1), 173);
640622
}));
641623
});
642624
}
@@ -647,8 +629,6 @@ describe('Material Popover Edit', () => {
647629
let columnSizeStore: FakeColumnSizeStore;
648630

649631
beforeEach(fakeAsync(() => {
650-
jasmine.addMatchers(approximateMatcher);
651-
652632
TestBed.configureTestingModule({
653633
providers: [
654634
FakeColumnSizeStore,
@@ -663,13 +643,13 @@ describe('Material Popover Edit', () => {
663643
}));
664644

665645
it('applies the persisted size', fakeAsync(() => {
666-
expect(component.getColumnWidth(1)).not.isApproximately(300);
646+
expectApproximate(component.getColumnWidth(1), 300, false);
667647

668648
columnSizeStore.emitSize('theTable', 'name', 300);
669649

670650
flush();
671651

672-
expect(component.getColumnWidth(1)).isApproximately(300);
652+
expectApproximate(component.getColumnWidth(1), 300);
673653
}));
674654

675655
it('persists the user-triggered size update', fakeAsync(() => {
@@ -693,7 +673,7 @@ describe('Material Popover Edit', () => {
693673
const {tableId, columnId, sizePx} = columnSizeStore.setSizeCalls[0];
694674
expect(tableId).toBe('theTable');
695675
expect(columnId).toBe('name');
696-
expect(sizePx).isApproximately(initialColumnWidth + 5);
676+
expectApproximate(sizePx, initialColumnWidth + 5);
697677
}));
698678

699679
it('persists the user-triggered size update (live updates off)', fakeAsync(() => {
@@ -719,7 +699,7 @@ describe('Material Popover Edit', () => {
719699
const {tableId, columnId, sizePx} = columnSizeStore.setSizeCalls[0];
720700
expect(tableId).toBe('theTable');
721701
expect(columnId).toBe('name');
722-
expect(sizePx).isApproximately(initialColumnWidth + 5);
702+
expectApproximate(sizePx, initialColumnWidth + 5);
723703
}));
724704
});
725705
});

src/material/table/table-data-source.spec.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,6 @@ import {ComponentFixture, fakeAsync, TestBed, tick} from '@angular/core/testing'
33
import {MatSort, MatSortModule} from '@angular/material/sort';
44
import {Component, ViewChild} from '@angular/core';
55

6-
declare global {
7-
interface Window {
8-
ngDevMode?: object | null;
9-
}
10-
}
11-
126
describe('MatTableDataSource', () => {
137
describe('sort', () => {
148
let dataSource: MatTableDataSource<{'prop': string | number}>;
@@ -95,7 +89,7 @@ describe('MatTableDataSource', () => {
9589

9690
it('does not warn in non-dev mode when filtering non-object data', fakeAsync(() => {
9791
const warnSpy = spyOn(console, 'warn');
98-
window.ngDevMode = null;
92+
(window as any).ngDevMode = null;
9993
dataSource.data = [1, 2, 3, 4, 5] as unknown as {'prop': number}[];
10094

10195
dataSource.filter = '1';
@@ -107,7 +101,7 @@ describe('MatTableDataSource', () => {
107101

108102
it('displays the warning in dev mode when filtering non-object data', fakeAsync(() => {
109103
const warnSpy = spyOn(console, 'warn');
110-
window.ngDevMode = {};
104+
(window as any).ngDevMode = {};
111105
dataSource.data = [1, 2, 3, 4, 5] as unknown as {'prop': number}[];
112106

113107
dataSource.filter = '1';

0 commit comments

Comments
 (0)