Skip to content
This repository was archived by the owner on Jan 6, 2025. It is now read-only.

Commit a9c65f3

Browse files
test(ssr): fix SSR flakes and change matchMedia variable name (#988)
* use `mediaController` as matchMedia variable name in *.spec.ts * improve use of inject() in tests
1 parent 002eb66 commit a9c65f3

File tree

28 files changed

+826
-767
lines changed

28 files changed

+826
-767
lines changed

src/lib/core/breakpoints/data/orientation-break-points.spec.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ describe('break-point-provider', () => {
5050
beforeEach(() => {
5151
// Configure testbed to prepare services
5252
TestBed.configureTestingModule({
53-
imports: [FlexLayoutModule.withConfig({}, EXTRAS)]
53+
imports: [FlexLayoutModule.withConfig({serverLoaded: true}, EXTRAS)]
5454
});
5555
});
5656
beforeEach(inject([BREAKPOINTS], (bps: BreakPoint[]) => {
@@ -86,7 +86,12 @@ describe('break-point-provider', () => {
8686
beforeEach(async (() => {
8787
// Configure testbed to prepare services
8888
TestBed.configureTestingModule({
89-
imports: [FlexLayoutModule.withConfig({addOrientationBps: true}, EXTRAS)]
89+
imports: [
90+
FlexLayoutModule.withConfig({
91+
addOrientationBps: true,
92+
serverLoaded: true,
93+
}, EXTRAS)
94+
]
9095
});
9196
}));
9297
// tslint:disable-next-line:no-shadowed-variable
@@ -127,7 +132,12 @@ describe('break-point-provider', () => {
127132
beforeEach(() => {
128133
// Configure testbed to prepare services
129134
TestBed.configureTestingModule({
130-
imports: [FlexLayoutModule.withConfig({disableDefaultBps: true}, EXTRAS)]
135+
imports: [
136+
FlexLayoutModule.withConfig({
137+
disableDefaultBps: true,
138+
serverLoaded: true,
139+
}, EXTRAS)
140+
]
131141
});
132142
});
133143
beforeEach(inject([BREAKPOINTS], (bps: BreakPoint[]) => {

src/lib/core/match-media/match-media.spec.ts

Lines changed: 90 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ import {MatchMedia} from './match-media';
1414
import {MediaObserver} from '../media-observer/media-observer';
1515

1616
describe('match-media', () => {
17-
let matchMedia: MockMatchMedia;
17+
let breakPoints: BreakPointRegistry;
18+
let mediaController: MockMatchMedia;
19+
let mediaObserver: MediaObserver;
1820

1921
beforeEach(() => {
2022
// Configure testbed to prepare services
@@ -23,16 +25,22 @@ describe('match-media', () => {
2325
});
2426
});
2527

26-
beforeEach(inject([MatchMedia], (service: MockMatchMedia) => {
27-
matchMedia = service; // inject only to manually activate mediaQuery ranges
28-
}));
28+
beforeEach(inject(
29+
[MediaObserver, MatchMedia, BreakPointRegistry],
30+
(_mediaObserver: MediaObserver, _matchMedia: MockMatchMedia,
31+
_breakPoints: BreakPointRegistry) => {
32+
breakPoints = _breakPoints;
33+
mediaController = _matchMedia; // inject only to manually activate mediaQuery ranges
34+
mediaObserver = _mediaObserver;
35+
}));
36+
2937
afterEach(() => {
30-
matchMedia.clearAll();
38+
mediaController.clearAll();
3139
});
3240

3341
it('can observe the initial, default activation for mediaQuery == "all". ', () => {
3442
let current: MediaChange = new MediaChange();
35-
let subscription = matchMedia
43+
let subscription = mediaController
3644
.observe()
3745
.subscribe((change: MediaChange) => {
3846
current = change;
@@ -48,20 +56,20 @@ describe('match-media', () => {
4856
let query2 = '(min-width: 730px) and (max-width: 950px)';
4957

5058
const queries = [query1, query2];
51-
let subscription = matchMedia.observe(queries).subscribe((change: MediaChange) => {
59+
let subscription = mediaController.observe(queries).subscribe((change: MediaChange) => {
5260
current = change;
5361
});
5462

5563
expect(current.mediaQuery).toEqual('all'); // default mediaQuery is active
56-
let activated = matchMedia.activate(query1); // simulate mediaQuery change to Query1
64+
let activated = mediaController.activate(query1); // simulate mediaQuery change to Query1
5765
expect(activated).toEqual(true);
5866
expect(current.mediaQuery).toEqual(query1);
59-
expect(matchMedia.isActive(query1)).toBeTruthy();
67+
expect(mediaController.isActive(query1)).toBeTruthy();
6068

61-
activated = matchMedia.activate(query2); // simulate mediaQuery change to Query2
69+
activated = mediaController.activate(query2); // simulate mediaQuery change to Query2
6270
expect(activated).toEqual(true);
6371
expect(current.mediaQuery).toEqual(query2); // confirm no notification
64-
expect(matchMedia.isActive(query2)).toBeTruthy();
72+
expect(mediaController.isActive(query2)).toBeTruthy();
6573

6674
subscription.unsubscribe();
6775
});
@@ -71,131 +79,108 @@ describe('match-media', () => {
7179
let query1 = 'screen and (min-width: 610px) and (max-width: 620px)';
7280
let query2 = '(min-width: 730px) and (max-width: 950px)';
7381

74-
matchMedia.registerQuery([query1, query2]);
82+
mediaController.registerQuery([query1, query2]);
7583

76-
let subscription = matchMedia.observe([query1], true).subscribe((change: MediaChange) => {
84+
let subscription = mediaController.observe([query1], true).subscribe((change: MediaChange) => {
7785
current = change;
7886
});
7987

80-
activated = matchMedia.activate(query1); // simulate mediaQuery change
88+
activated = mediaController.activate(query1); // simulate mediaQuery change
8189
expect(activated).toEqual(true);
8290
expect(current.mediaQuery).toEqual(query1);
83-
expect(matchMedia.isActive(query1)).toBeTruthy();
91+
expect(mediaController.isActive(query1)).toBeTruthy();
8492

85-
activated = matchMedia.activate(query2); // simulate mediaQuery change
93+
activated = mediaController.activate(query2); // simulate mediaQuery change
8694
expect(activated).toEqual(true);
87-
expect(matchMedia.isActive(query2)).toBeTruthy();
95+
expect(mediaController.isActive(query2)).toBeTruthy();
8896

8997
expect(current.mediaQuery).not.toEqual(query2); // confirm no notification
9098
expect(current.mediaQuery).toEqual(query1);
9199

92100
subscription.unsubscribe();
93101
});
94102

95-
});
103+
describe('match-media-observable', () => {
96104

97-
describe('match-media-observable', () => {
98-
let breakPoints: BreakPointRegistry;
99-
let matchMedia: MockMatchMedia;
100-
let mediaObserver: MediaObserver;
105+
it('can observe an existing activation', () => {
106+
let current: MediaChange = new MediaChange();
107+
let bp = breakPoints.findByAlias('md')!;
108+
mediaController.activate(bp.mediaQuery);
109+
let subscription = mediaObserver.media$.subscribe((change: MediaChange) => {
110+
current = change;
111+
});
101112

102-
beforeEach(() => {
103-
// Configure testbed to prepare services
104-
TestBed.configureTestingModule({
105-
providers: [MockMatchMediaProvider]
113+
expect(current.mediaQuery).toEqual(bp.mediaQuery);
114+
subscription.unsubscribe();
106115
});
107-
});
108116

109-
beforeEach(inject(
110-
[MediaObserver, MatchMedia, BreakPointRegistry],
111-
(_mediaObserver: MediaObserver, _matchMedia: MockMatchMedia,
112-
_breakPoints: BreakPointRegistry) => {
113-
matchMedia = _matchMedia; // inject only to manually activate mediaQuery ranges
114-
breakPoints = _breakPoints;
115-
mediaObserver = _mediaObserver;
116-
}));
117-
afterEach(() => {
118-
matchMedia.clearAll();
119-
});
117+
it('can observe the initial, default activation for mediaQuery == "all". ', () => {
118+
let current: MediaChange = new MediaChange();
119+
let subscription = mediaObserver.media$.subscribe((change: MediaChange) => {
120+
current = change;
121+
});
120122

121-
it('can observe an existing activation', () => {
122-
let current: MediaChange = new MediaChange();
123-
let bp = breakPoints.findByAlias('md')!;
124-
matchMedia.activate(bp.mediaQuery);
125-
let subscription = mediaObserver.media$.subscribe((change: MediaChange) => {
126-
current = change;
123+
expect(current.mediaQuery).toEqual('all');
124+
subscription.unsubscribe();
127125
});
128126

129-
expect(current.mediaQuery).toEqual(bp.mediaQuery);
130-
subscription.unsubscribe();
131-
});
132-
133-
it('can observe the initial, default activation for mediaQuery == "all". ', () => {
134-
let current: MediaChange = new MediaChange();
135-
let subscription = mediaObserver.media$.subscribe((change: MediaChange) => {
136-
current = change;
137-
});
138-
139-
expect(current.mediaQuery).toEqual('all');
140-
subscription.unsubscribe();
141-
});
142-
143-
it('can observe custom mediaQuery ranges', () => {
144-
let current: MediaChange = new MediaChange();
145-
let customQuery = 'screen and (min-width: 610px) and (max-width: 620px)';
146-
let subscription = mediaObserver.media$.subscribe((change: MediaChange) => {
147-
current = change;
148-
});
127+
it('can observe custom mediaQuery ranges', () => {
128+
let current: MediaChange = new MediaChange();
129+
let customQuery = 'screen and (min-width: 610px) and (max-width: 620px)';
130+
let subscription = mediaObserver.media$.subscribe((change: MediaChange) => {
131+
current = change;
132+
});
149133

150-
matchMedia.useOverlaps = true;
151-
let activated = matchMedia.activate(customQuery);
152-
expect(activated).toEqual(true);
153-
expect(current.mediaQuery).toEqual(customQuery);
134+
mediaController.useOverlaps = true;
135+
let activated = mediaController.activate(customQuery);
136+
expect(activated).toEqual(true);
137+
expect(current.mediaQuery).toEqual(customQuery);
154138

155-
subscription.unsubscribe();
156-
});
157-
158-
it('can observe registered breakpoint activations', () => {
159-
let current: MediaChange = new MediaChange();
160-
let bp = breakPoints.findByAlias('md') !;
161-
let subscription = mediaObserver.media$.subscribe((change: MediaChange) => {
162-
current = change;
139+
subscription.unsubscribe();
163140
});
164141

165-
let activated = matchMedia.activate(bp.mediaQuery);
166-
expect(activated).toEqual(true);
142+
it('can observe registered breakpoint activations', () => {
143+
let current: MediaChange = new MediaChange();
144+
let bp = breakPoints.findByAlias('md') !;
145+
let subscription = mediaObserver.media$.subscribe((change: MediaChange) => {
146+
current = change;
147+
});
167148

168-
expect(current.mediaQuery).toEqual(bp.mediaQuery);
149+
let activated = mediaController.activate(bp.mediaQuery);
150+
expect(activated).toEqual(true);
169151

170-
subscription.unsubscribe();
171-
});
152+
expect(current.mediaQuery).toEqual(bp.mediaQuery);
172153

173-
/**
174-
* Only the MediaObserver ignores de-activations;
175-
* MediaMonitor and MatchMedia report both activations and de-activations!
176-
*/
177-
it('ignores mediaQuery de-activations', () => {
178-
let activationCount = 0;
179-
let deactivationCount = 0;
180-
181-
mediaObserver.filterOverlaps = false;
182-
let subscription = mediaObserver.media$.subscribe((change: MediaChange) => {
183-
if (change.matches) {
184-
++activationCount;
185-
} else {
186-
++deactivationCount;
187-
}
154+
subscription.unsubscribe();
188155
});
189156

190-
matchMedia.activate(breakPoints.findByAlias('md')!.mediaQuery);
191-
matchMedia.activate(breakPoints.findByAlias('gt-md')!.mediaQuery);
192-
matchMedia.activate(breakPoints.findByAlias('lg')!.mediaQuery);
193-
194-
// 'all' mediaQuery is already active; total count should be (3)
195-
expect(activationCount).toEqual(4);
196-
expect(deactivationCount).toEqual(0);
157+
/**
158+
* Only the MediaObserver ignores de-activations;
159+
* MediaMonitor and MatchMedia report both activations and de-activations!
160+
*/
161+
it('ignores mediaQuery de-activations', () => {
162+
let activationCount = 0;
163+
let deactivationCount = 0;
164+
165+
mediaObserver.filterOverlaps = false;
166+
let subscription = mediaObserver.media$.subscribe((change: MediaChange) => {
167+
if (change.matches) {
168+
++activationCount;
169+
} else {
170+
++deactivationCount;
171+
}
172+
});
173+
174+
mediaController.activate(breakPoints.findByAlias('md')!.mediaQuery);
175+
mediaController.activate(breakPoints.findByAlias('gt-md')!.mediaQuery);
176+
mediaController.activate(breakPoints.findByAlias('lg')!.mediaQuery);
177+
178+
// 'all' mediaQuery is already active; total count should be (3)
179+
expect(activationCount).toEqual(4);
180+
expect(deactivationCount).toEqual(0);
181+
182+
subscription.unsubscribe();
183+
});
197184

198-
subscription.unsubscribe();
199185
});
200-
201186
});

src/lib/core/match-media/match-media.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,9 +167,9 @@ function buildQueryCss(mediaQueries: string[], _document: Document) {
167167
}
168168

169169
function constructMql(query: string, isBrowser: boolean): MediaQueryList {
170-
const canListen = isBrowser && !!(<any>window).matchMedia('all').addListener;
170+
const canListen = isBrowser && !!(<Window>window).matchMedia('all').addListener;
171171

172-
return canListen ? (<any>window).matchMedia(query) : {
172+
return canListen ? (<Window>window).matchMedia(query) : {
173173
matches: query === 'all' || query === '',
174174
media: query,
175175
addListener: () => {

0 commit comments

Comments
 (0)