Skip to content

Commit fe788de

Browse files
committed
test: Added unit tests for css media query-scoped selectors
1 parent 0f8603f commit fe788de

File tree

3 files changed

+109
-19
lines changed

3 files changed

+109
-19
lines changed

packages/core/application/application.ios.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ export class iOSApplication extends ApplicationCommon implements IiOSApplication
343343
if (__VISIONOS__) {
344344
statusBarOrientation = NativeScriptEmbedder.sharedInstance().windowScene.interfaceOrientation;
345345
} else {
346-
statusBarOrientation = UIApplication.sharedApplication?.statusBarOrientation ?? UIInterfaceOrientation.Unknown;
346+
statusBarOrientation = UIApplication.sharedApplication.statusBarOrientation;
347347
}
348348
return this.getOrientationValue(statusBarOrientation);
349349
}

packages/core/jest.setup.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ global.interop = {
4949
},
5050
};
5151
global.UIApplication = {
52-
sharedApplication: null,
52+
sharedApplication: {
53+
statusBarOrientation: 1, // Portrait by default
54+
},
5355
};
5456
global.UIDevice = {
5557
currentDevice: {

packages/core/ui/styling/css-selector.spec.ts

Lines changed: 105 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { parse } from '../../css/reworkcss';
2+
import { Screen } from '../../platform';
23
import { createSelector, RuleSet, StyleSheetSelectorScope, fromAstNode, Node, Changes } from './css-selector';
4+
import { _populateRules } from './style-scope';
35

46
describe('css-selector', () => {
57
it('button[attr]', () => {
@@ -17,20 +19,23 @@ describe('css-selector', () => {
1719
).toBeFalsy();
1820
});
1921

20-
function create(css: string, source = 'css-selectors.ts@test'): { rules: RuleSet[]; map: StyleSheetSelectorScope<any> } {
22+
function create(css: string, source = 'css-selectors.ts@test'): { rulesets: RuleSet[]; selectorScope: StyleSheetSelectorScope<any> } {
2123
const parsed = parse(css, { source });
22-
const rulesAst = parsed.stylesheet.rules.filter((n) => n.type === 'rule');
23-
const rules = rulesAst.map((rule) => fromAstNode(rule));
24-
const map = new StyleSheetSelectorScope(rules);
24+
const rulesAst = parsed.stylesheet.rules;
25+
const rulesets = [];
2526

26-
return { rules, map };
27+
_populateRules(rulesAst, rulesets, []);
28+
29+
const selectorScope = new StyleSheetSelectorScope(rulesets);
30+
31+
return { rulesets, selectorScope };
2732
}
2833

2934
function createOne(css: string, source = 'css-selectors.ts@test'): RuleSet {
30-
const { rules } = create(css, source);
31-
expect(rules.length).toBe(1);
35+
const { rulesets } = create(css, source);
36+
expect(rulesets.length).toBe(1);
3237

33-
return rules[0];
38+
return rulesets[0];
3439
}
3540

3641
it('single selector', () => {
@@ -48,21 +53,21 @@ describe('css-selector', () => {
4853
});
4954

5055
it('narrow selection', () => {
51-
const { map } = create(`
56+
const { selectorScope } = create(`
5257
.login { color: blue; }
5358
button { color: red; }
5459
image { color: green; }
5560
`);
5661

57-
const buttonQuerry = map.query({ cssType: 'button' }).selectors;
58-
expect(buttonQuerry.length).toBe(1);
59-
expect(buttonQuerry[0].ruleset.declarations).toEqual([{ property: 'color', value: 'red' }]);
62+
const buttonQuery = selectorScope.query({ cssType: 'button' }).selectors;
63+
expect(buttonQuery.length).toBe(1);
64+
expect(buttonQuery[0].ruleset.declarations).toEqual([{ property: 'color', value: 'red' }]);
6065

61-
const imageQuerry = map.query({ cssType: 'image', cssClasses: new Set(['login']) }).selectors;
62-
expect(imageQuerry.length).toBe(2);
66+
const imageQuery = selectorScope.query({ cssType: 'image', cssClasses: new Set(['login']) }).selectors;
67+
expect(imageQuery.length).toBe(2);
6368
// Note class before type
64-
expect(imageQuerry[0].ruleset.declarations).toEqual([{ property: 'color', value: 'blue' }]);
65-
expect(imageQuerry[1].ruleset.declarations).toEqual([{ property: 'color', value: 'green' }]);
69+
expect(imageQuery[0].ruleset.declarations).toEqual([{ property: 'color', value: 'blue' }]);
70+
expect(imageQuery[1].ruleset.declarations).toEqual([{ property: 'color', value: 'green' }]);
6671
});
6772

6873
const positiveMatches = {
@@ -271,10 +276,93 @@ describe('css-selector', () => {
271276
},
272277
}),
273278
).toBe(false);
274-
// TODO: Re-add this when decorators actually work with ts-jest
279+
// TODO: Re-add this when decorators actually work properly on ts-jest
275280
//expect(rule.selectors[0].specificity).toEqual(0);
276281
});
277282

283+
describe('media queries', () => {
284+
const { widthDIPs } = Screen.mainScreen;
285+
286+
it('should apply css rules of matching media query', () => {
287+
const { selectorScope } = create(`
288+
@media only screen and (max-width: ${widthDIPs}) {
289+
.login { color: blue; }
290+
button { color: red; }
291+
image { color: green; }
292+
}
293+
`);
294+
295+
const { selectors: buttonSelectors } = selectorScope.query({ cssType: 'button' });
296+
expect(buttonSelectors.length).toBe(1);
297+
expect(buttonSelectors[0].ruleset.declarations).toEqual([{ property: 'color', value: 'red' }]);
298+
299+
const { selectors: imageSelectors } = selectorScope.query({ cssType: 'image', cssClasses: new Set(['login']) });
300+
expect(imageSelectors.length).toBe(2);
301+
// Note class before type
302+
expect(imageSelectors[0].ruleset.declarations).toEqual([{ property: 'color', value: 'blue' }]);
303+
expect(imageSelectors[1].ruleset.declarations).toEqual([{ property: 'color', value: 'green' }]);
304+
});
305+
306+
it('should not apply css rules of non-matching media query', () => {
307+
const { selectorScope } = create(`
308+
@media only screen and (max-width: ${widthDIPs - 1}) {
309+
.login { color: blue; }
310+
button { color: red; }
311+
image { color: green; }
312+
}
313+
`);
314+
315+
const { selectors: buttonSelectors } = selectorScope.query({ cssType: 'button' });
316+
expect(buttonSelectors.length).toBe(0);
317+
318+
const { selectors: imageSelectors } = selectorScope.query({ cssType: 'image', cssClasses: new Set(['login']) });
319+
expect(imageSelectors.length).toBe(0);
320+
});
321+
322+
it('should apply css rules of matching media and nested media queries', () => {
323+
const { selectorScope } = create(`
324+
@media only screen and (max-width: ${widthDIPs}) {
325+
.login { color: blue; }
326+
button { color: red; }
327+
@media only screen and (orientation: portrait) {
328+
image { color: green; }
329+
}
330+
}
331+
`);
332+
333+
const { selectors: buttonSelectors } = selectorScope.query({ cssType: 'button' });
334+
expect(buttonSelectors.length).toBe(1);
335+
expect(buttonSelectors[0].ruleset.declarations).toEqual([{ property: 'color', value: 'red' }]);
336+
337+
const { selectors: imageSelectors } = selectorScope.query({ cssType: 'image', cssClasses: new Set(['login']) });
338+
expect(imageSelectors.length).toBe(2);
339+
// Note class before type
340+
expect(imageSelectors[0].ruleset.declarations).toEqual([{ property: 'color', value: 'blue' }]);
341+
expect(imageSelectors[1].ruleset.declarations).toEqual([{ property: 'color', value: 'green' }]);
342+
});
343+
344+
it('should apply css rules of matching media queries but not non-matching nested media queries', () => {
345+
const { selectorScope } = create(`
346+
@media only screen and (max-width: ${widthDIPs}) {
347+
.login { color: blue; }
348+
349+
@media only screen and (orientation: none) {
350+
button { color: red; }
351+
image { color: green; }
352+
}
353+
}
354+
`);
355+
356+
const { selectors: buttonSelectors } = selectorScope.query({ cssType: 'button' });
357+
expect(buttonSelectors.length).toBe(0);
358+
359+
const { selectors: imageSelectors } = selectorScope.query({ cssType: 'image', cssClasses: new Set(['login']) });
360+
expect(imageSelectors.length).toBe(1);
361+
362+
expect(imageSelectors[0].ruleset.declarations).toEqual([{ property: 'color', value: 'blue' }]);
363+
});
364+
});
365+
278366
function toString() {
279367
return this.cssType;
280368
}

0 commit comments

Comments
 (0)