Skip to content

Commit

Permalink
test: Added unit tests for css media query-scoped selectors
Browse files Browse the repository at this point in the history
  • Loading branch information
CatchABus committed May 5, 2024
1 parent 0f8603f commit fe788de
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 19 deletions.
2 changes: 1 addition & 1 deletion packages/core/application/application.ios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ export class iOSApplication extends ApplicationCommon implements IiOSApplication
if (__VISIONOS__) {
statusBarOrientation = NativeScriptEmbedder.sharedInstance().windowScene.interfaceOrientation;
} else {
statusBarOrientation = UIApplication.sharedApplication?.statusBarOrientation ?? UIInterfaceOrientation.Unknown;
statusBarOrientation = UIApplication.sharedApplication.statusBarOrientation;
}
return this.getOrientationValue(statusBarOrientation);
}
Expand Down
4 changes: 3 additions & 1 deletion packages/core/jest.setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ global.interop = {
},
};
global.UIApplication = {
sharedApplication: null,
sharedApplication: {
statusBarOrientation: 1, // Portrait by default
},
};
global.UIDevice = {
currentDevice: {
Expand Down
122 changes: 105 additions & 17 deletions packages/core/ui/styling/css-selector.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { parse } from '../../css/reworkcss';
import { Screen } from '../../platform';
import { createSelector, RuleSet, StyleSheetSelectorScope, fromAstNode, Node, Changes } from './css-selector';
import { _populateRules } from './style-scope';

describe('css-selector', () => {
it('button[attr]', () => {
Expand All @@ -17,20 +19,23 @@ describe('css-selector', () => {
).toBeFalsy();
});

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

return { rules, map };
_populateRules(rulesAst, rulesets, []);

const selectorScope = new StyleSheetSelectorScope(rulesets);

return { rulesets, selectorScope };
}

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

return rules[0];
return rulesets[0];
}

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

it('narrow selection', () => {
const { map } = create(`
const { selectorScope } = create(`
.login { color: blue; }
button { color: red; }
image { color: green; }
`);

const buttonQuerry = map.query({ cssType: 'button' }).selectors;
expect(buttonQuerry.length).toBe(1);
expect(buttonQuerry[0].ruleset.declarations).toEqual([{ property: 'color', value: 'red' }]);
const buttonQuery = selectorScope.query({ cssType: 'button' }).selectors;
expect(buttonQuery.length).toBe(1);
expect(buttonQuery[0].ruleset.declarations).toEqual([{ property: 'color', value: 'red' }]);

const imageQuerry = map.query({ cssType: 'image', cssClasses: new Set(['login']) }).selectors;
expect(imageQuerry.length).toBe(2);
const imageQuery = selectorScope.query({ cssType: 'image', cssClasses: new Set(['login']) }).selectors;
expect(imageQuery.length).toBe(2);
// Note class before type
expect(imageQuerry[0].ruleset.declarations).toEqual([{ property: 'color', value: 'blue' }]);
expect(imageQuerry[1].ruleset.declarations).toEqual([{ property: 'color', value: 'green' }]);
expect(imageQuery[0].ruleset.declarations).toEqual([{ property: 'color', value: 'blue' }]);
expect(imageQuery[1].ruleset.declarations).toEqual([{ property: 'color', value: 'green' }]);
});

const positiveMatches = {
Expand Down Expand Up @@ -271,10 +276,93 @@ describe('css-selector', () => {
},
}),
).toBe(false);
// TODO: Re-add this when decorators actually work with ts-jest
// TODO: Re-add this when decorators actually work properly on ts-jest
//expect(rule.selectors[0].specificity).toEqual(0);
});

describe('media queries', () => {
const { widthDIPs } = Screen.mainScreen;

it('should apply css rules of matching media query', () => {
const { selectorScope } = create(`
@media only screen and (max-width: ${widthDIPs}) {
.login { color: blue; }
button { color: red; }
image { color: green; }
}
`);

const { selectors: buttonSelectors } = selectorScope.query({ cssType: 'button' });
expect(buttonSelectors.length).toBe(1);
expect(buttonSelectors[0].ruleset.declarations).toEqual([{ property: 'color', value: 'red' }]);

const { selectors: imageSelectors } = selectorScope.query({ cssType: 'image', cssClasses: new Set(['login']) });
expect(imageSelectors.length).toBe(2);
// Note class before type
expect(imageSelectors[0].ruleset.declarations).toEqual([{ property: 'color', value: 'blue' }]);
expect(imageSelectors[1].ruleset.declarations).toEqual([{ property: 'color', value: 'green' }]);
});

it('should not apply css rules of non-matching media query', () => {
const { selectorScope } = create(`
@media only screen and (max-width: ${widthDIPs - 1}) {
.login { color: blue; }
button { color: red; }
image { color: green; }
}
`);

const { selectors: buttonSelectors } = selectorScope.query({ cssType: 'button' });
expect(buttonSelectors.length).toBe(0);

const { selectors: imageSelectors } = selectorScope.query({ cssType: 'image', cssClasses: new Set(['login']) });
expect(imageSelectors.length).toBe(0);
});

it('should apply css rules of matching media and nested media queries', () => {
const { selectorScope } = create(`
@media only screen and (max-width: ${widthDIPs}) {
.login { color: blue; }
button { color: red; }
@media only screen and (orientation: portrait) {
image { color: green; }
}
}
`);

const { selectors: buttonSelectors } = selectorScope.query({ cssType: 'button' });
expect(buttonSelectors.length).toBe(1);
expect(buttonSelectors[0].ruleset.declarations).toEqual([{ property: 'color', value: 'red' }]);

const { selectors: imageSelectors } = selectorScope.query({ cssType: 'image', cssClasses: new Set(['login']) });
expect(imageSelectors.length).toBe(2);
// Note class before type
expect(imageSelectors[0].ruleset.declarations).toEqual([{ property: 'color', value: 'blue' }]);
expect(imageSelectors[1].ruleset.declarations).toEqual([{ property: 'color', value: 'green' }]);
});

it('should apply css rules of matching media queries but not non-matching nested media queries', () => {
const { selectorScope } = create(`
@media only screen and (max-width: ${widthDIPs}) {
.login { color: blue; }
@media only screen and (orientation: none) {
button { color: red; }
image { color: green; }
}
}
`);

const { selectors: buttonSelectors } = selectorScope.query({ cssType: 'button' });
expect(buttonSelectors.length).toBe(0);

const { selectors: imageSelectors } = selectorScope.query({ cssType: 'image', cssClasses: new Set(['login']) });
expect(imageSelectors.length).toBe(1);

expect(imageSelectors[0].ruleset.declarations).toEqual([{ property: 'color', value: 'blue' }]);
});
});

function toString() {
return this.cssType;
}
Expand Down

0 comments on commit fe788de

Please sign in to comment.