Skip to content

Commit

Permalink
feat(esl-media-query): ingore tuple values if query syntax passed
Browse files Browse the repository at this point in the history
  • Loading branch information
fshovchko committed Jul 16, 2024
1 parent 1090871 commit 1899484
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 33 deletions.
3 changes: 2 additions & 1 deletion eslint/src/rules/4/deprecated.media-rule-list-parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ import type {ESLintReplacementMethodCfg} from '../../core/deprecated-class-metho

const AVAILABLE_SINCE = '5.0.0-beta.24';
const isActual = lte(ESL_PACKAGE_VERSION, AVAILABLE_SINCE);
const isTest = process.env.NODE_ENV === 'test';

/**
* Rule for deprecated 'parse' method of {@link ESLMediaRuleList}
*/
export default isActual ?
export default isActual || isTest ?
buildRule({
className: 'ESLMediaRuleList',
deprecatedMethod: 'parse',
Expand Down
12 changes: 7 additions & 5 deletions src/modules/esl-media-query/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,20 +204,22 @@ ESLMediaRuleList.parse('1 | @XS => 2', String); // the same as sample above
ESLMediaRuleList.parse('1 | @XS => 2', Number); // first query from the sample above that store numeric values
ESLMediaRuleList.parse('@XS => {option: 1} | @+SM => {option: 2}', ESLMediaRuleList.OBJECT_PARSER); // second query from the sample above with an object payloads
ESLMediaRuleList.parse('@XS => {option: 1} | @+SM => {option: 2}', evaluate); // the same as the sample above
ESLMediaRuleList.parse('1|2|3|4|5', '@xs|@sm|@md|@lg|@xl') // parses tuple payloads

// Tupple parsing
ESLMediaRuleList.parseTuple('@xs|@sm|@md|@lg|@xl', '1|2|3|4|5') // String payload example
ESLMediaRuleList.parseTuple('@xs|@sm|@md|@lg|@xl', '1|2|3|4|5', Number) // Numeric payload sample
```
**Note**: Method `ESLMediaRuleList.parse` is deprecated, and will be reintroduced in ESL v5.0.0 with a different signature. For now use `ESLMediaRuleList.parseTuple` or `ESLMediaRuleList.parseQuery` instead.

#### ESLMediaRuleList API

- `ESLMediaRuleList.parse(ruleset: string)` - parse media ruleset defined with classic syntax mentioned in section above.
Rules separated by `|` symbol, query and value separated by `=>` for each rule, query is optional.
- `ESLMediaRuleList.parseTuple(queries: string, values: string)` - parse media ruleset from tuple of queries and values, all separated via `|` symbol.

- `ESLMediaRuleList.parseTuple(queries: string, values: string)` - parse media ruleset from tuple of
queries and values, all separated via `|` symbol
- `ESLMediaRuleList.parseQuery(ruleset: string)` - parse media ruleset defined with syntax, where query and value are a single argument separated by `=>` for each rule.

- `ESLMediaRuleList.parse(values: string, queries: string)` - parse media ruleset defined with tuple syntax, where query and value are separate arguments.

- `ESLMediaRuleList.parse(ruleset: string)` - parse media ruleset defined with same syntax as `ESLMediaRuleList.parseQuery`.

- `ESLMediaRuleList.prototype.rules` - array of rules that defines `ESLMediaRuleList` object
- `ESLMediaRuleList.prototype.active` - array of active (matched) rules
Expand Down
36 changes: 14 additions & 22 deletions src/modules/esl-media-query/core/esl-media-rule-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,64 +35,56 @@ export class ESLMediaRuleList<T = any> extends SyntheticEventTarget {
public static OBJECT_PARSER = <U = any>(val: string): U | undefined => evaluate(val);

/**
* @deprecated Method will be reintroduced in v5.0.0 with a different signature. For now use ESLMediaRuleList.parseQuery instead
*
* Creates `ESLMediaRuleList` from string query representation
* Creates {@link ESLMediaRuleList} from string query representation
* Expect serialized {@link ESLMediaRule}s separated by '|'
* Uses exact strings as rule list values
*
* @param query - query string
*/
public static parse(query: string): ESLMediaRuleList<string>;
/**
* @deprecated Method will be reintroduced in v5.0.0 with a different signature. For now use ESLMediaRuleList.parseQuery instead
*
* Creates `ESLMediaRuleList` from string query representation.
* Creates {@link ESLMediaRuleList} from string query representation.
* Expect serialized {@link ESLMediaRule}s separated by '|'
*
* @param query - query string
* @param parser - value parser function
*/
public static parse<U>(query: string, parser: RulePayloadParser<U>): ESLMediaRuleList<U>;
/**
* @deprecated Method will be reintroduced in v5.0.0 with a different signature. For now use ESLMediaRuleList.parseTuple instead
* Creates `ESLMediaRuleList` from two strings with conditions and values sequences
* Creates {@link ESLMediaRuleList} from two strings with conditions and values sequences
*
* @param mask - media conditions tuple string (uses '|' as separator)
* @param values - values tuple string (uses '|' as separator)
* @param mask - media conditions tuple string (uses '|' as separator)
*
* @example
* ```ts
* ESLMediaRuleList.parse('@XS|@SM|@MD|@LG|@XL', '1|2|3|4|5')
* ```
*/
public static parse(mask: string, values: string): ESLMediaRuleList<string>;
public static parse(values: string, mask: string): ESLMediaRuleList<string>;
/**
* @deprecated Method will be reintroduced in v5.0.0 with a different signature. For now use ESLMediaRuleList.parseTuple instead
*
* Creates `ESLMediaRuleList` from two strings with conditions and values sequences
* Creates {@link ESLMediaRuleList} from two strings with conditions and values sequences
*
* @param mask - media conditions tuple string (uses '|' as separator)
* @param values - values tuple string (uses '|' as separator)
* @param mask - media conditions tuple string (uses '|' as separator)
* @param parser - value parser function
*
* @example
* ```ts
* ESLMediaRuleList.parseTuple('@XS|@SM|@MD|@LG|@XL', '1|2|3|4|5', Number)
* ```
*/
public static parse<U>(mask: string, values: string, parser: RulePayloadParser<U>): ESLMediaRuleList<U>;
public static parse<U>(values: string, mask: string, parser: RulePayloadParser<U>): ESLMediaRuleList<U>;
public static parse(query: string, ...common: (string | RulePayloadParser<any>)[]): ESLMediaRuleList {
const parser: RulePayloadParser<any> = typeof common[common.length - 1] === 'function' ? common.pop() as any : String;
const value = common.pop();
return typeof value === 'string' ?
ESLMediaRuleList.parseTuple(query, value, parser) :
const mask = common.pop();
return typeof mask === 'string' ?
ESLMediaRuleList.parseTuple(mask, query, parser) :
ESLMediaRuleList.parseQuery(query, parser);
}

/**
* Creates `ESLMediaRuleList` from string query representation
* Creates {@link ESLMediaRuleList} from string query representation
* Uses exact strings as rule list values
* @param query - query string
*/
Expand All @@ -111,7 +103,7 @@ export class ESLMediaRuleList<T = any> extends SyntheticEventTarget {
}

/**
* Creates `ESLMediaRuleList` from two strings with conditions and values sequences
* Creates {@link ESLMediaRuleList} from two strings with conditions and values sequences
*
* @param mask - media conditions tuple string (uses '|' as separator)
* @param values - values tuple string (uses '|' as separator)
Expand All @@ -123,7 +115,7 @@ export class ESLMediaRuleList<T = any> extends SyntheticEventTarget {
*/
public static parseTuple(mask: string, values: string): ESLMediaRuleList<string>;
/**
* Creates `ESLMediaRuleList` from two strings with conditions and values sequences
* Creates {@link ESLMediaRuleList} from two strings with conditions and values sequences
*
* @param mask - media conditions tuple string (uses '|' as separator)
* @param values - values tuple string (uses '|' as separator)
Expand Down
40 changes: 35 additions & 5 deletions src/modules/esl-media-query/test/esl-media-rule-list.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ describe('ESLMediaRuleList', () => {

describe('Integration cases:', () => {
test('Basic case: "1 | @sm => 2 | @md => 3" parsed correctly', () => {
const mrl = ESLMediaRuleList.parseQuery('1 | @sm => 2 | @md => 3');
const mrl = ESLMediaRuleList.parse('1 | @sm => 2 | @md => 3');

Check failure on line 11 in src/modules/esl-media-query/test/esl-media-rule-list.test.ts

View workflow job for this annotation

GitHub Actions / Linting

[ESL Lint]: Deprecated static method ESLMediaRuleList.parse, use ESLMediaRuleList.parseQuery instead
expect(mrl.rules.length).toBe(3);

mockSmMatchMedia.matches = false;
Expand Down Expand Up @@ -57,7 +57,7 @@ describe('ESLMediaRuleList', () => {
});

test('Extended media case parsed correctly: "1 | @sm or @md => 2"', () => {
const mrl = ESLMediaRuleList.parseQuery('1 | @sm or @md => 2');
const mrl = ESLMediaRuleList.parse('1 | @sm or @md => 2');

Check failure on line 60 in src/modules/esl-media-query/test/esl-media-rule-list.test.ts

View workflow job for this annotation

GitHub Actions / Linting

[ESL Lint]: Deprecated static method ESLMediaRuleList.parse, use ESLMediaRuleList.parseQuery instead
const listener = jest.fn();

expect(mrl.rules.length).toBe(2);
Expand Down Expand Up @@ -112,20 +112,20 @@ describe('ESLMediaRuleList', () => {

describe('Basic cases:', () => {
test('Single value parsed to the single "all" rule', () => {
const mrl = ESLMediaRuleList.parseQuery('123');
const mrl = ESLMediaRuleList.parse('123');

Check failure on line 115 in src/modules/esl-media-query/test/esl-media-rule-list.test.ts

View workflow job for this annotation

GitHub Actions / Linting

[ESL Lint]: Deprecated static method ESLMediaRuleList.parse, use ESLMediaRuleList.parseQuery instead
expect(mrl.rules.length).toBe(1);
expect(mrl.active.length).toBeGreaterThan(0);
expect(mrl.value).toBe('123');
expect(mrl.activeValue).toBe('123');
});

test('Single rule with media query "@sm => 1"', () => {
const mrl = ESLMediaRuleList.parseQuery('@sm => 1');
const mrl = ESLMediaRuleList.parse('@sm => 1');

Check failure on line 123 in src/modules/esl-media-query/test/esl-media-rule-list.test.ts

View workflow job for this annotation

GitHub Actions / Linting

[ESL Lint]: Deprecated static method ESLMediaRuleList.parse, use ESLMediaRuleList.parseQuery instead
expect(mrl.rules.length).toBe(1);
});

test('Single rule "@sm => 1" response to the matcher correctly', () => {
const mrl = ESLMediaRuleList.parseQuery('@sm => 1');
const mrl = ESLMediaRuleList.parse('@sm => 1');

Check failure on line 128 in src/modules/esl-media-query/test/esl-media-rule-list.test.ts

View workflow job for this annotation

GitHub Actions / Linting

[ESL Lint]: Deprecated static method ESLMediaRuleList.parse, use ESLMediaRuleList.parseQuery instead

mockSmMatchMedia.matches = false;
expect(mrl.value).toBe(undefined);
Expand Down Expand Up @@ -178,4 +178,34 @@ describe('ESLMediaRuleList', () => {
expect(() => ESLMediaRuleList.parseTuple('@xs', '1|2|3')).toThrowError();
});
});

describe('Adaptive cases parsing', () => {
test('Should throw error if arrow syntax provided instead of tuple\'s mask', () => {
try {
ESLMediaRuleList.parse('(min-width: 100px) => 123', '3|4');

Check failure on line 185 in src/modules/esl-media-query/test/esl-media-rule-list.test.ts

View workflow job for this annotation

GitHub Actions / Linting

[ESL Lint]: Deprecated static method ESLMediaRuleList.parse, use ESLMediaRuleList.parseTuple instead
} catch (e) {
expect(e.toString()).toBe('Error: Value doesn\'t correspond to mask');
}
});

test('Handle tuple with equal mask/value pair as regular', () => {
const mask = '@sm|@md|@lg';
const values = '1|2|3';
const mrl = ESLMediaRuleList.parse(values, mask);

Check failure on line 194 in src/modules/esl-media-query/test/esl-media-rule-list.test.ts

View workflow job for this annotation

GitHub Actions / Linting

[ESL Lint]: Deprecated static method ESLMediaRuleList.parse, use ESLMediaRuleList.parseQuery or ESLMediaRuleList.parseTuple instead
expect(mrl.toString()).toBe(ESLMediaRuleList.parseTuple(mask, values).toString());
expect(mrl.toString()).toBe(
'(min-width: 768px) and (max-width: 991px) => 1|(min-width: 992px) and (max-width: 1199px) => 2|(min-width: 1200px) and (max-width: 1599px) => 3');
});


test.each([
[['1'], 'all => 1'],
[['0 | (min-width: 100px) => 1 | (min-width: 200px) => 2'], 'all => 0|(min-width: 100px) => 1|(min-width: 200px) => 2'],
[['0 | 1', '@+xs | @+sm'], '(min-width: 1px) => 0|(min-width: 768px) => 1'],
[['1|2|3', 'all|@sm|@md'], 'all => 1|(min-width: 768px) and (max-width: 991px) => 2|(min-width: 992px) and (max-width: 1199px) => 3'],
[['1 | @+sm => 2 | @+md => 3'], 'all => 1|(min-width: 768px) => 2|(min-width: 992px) => 3'],
])('Should correctly parse "%s" with media condition "%s"', (params: any[], canonical: string) => {
expect(ESLMediaRuleList.parse.apply(null, params).toString()).toBe(canonical);

Check failure on line 208 in src/modules/esl-media-query/test/esl-media-rule-list.test.ts

View workflow job for this annotation

GitHub Actions / Linting

[ESL Lint]: Deprecated static method ESLMediaRuleList.parse, use ESLMediaRuleList.parseQuery or ESLMediaRuleList.parseTuple instead
});
});
});

0 comments on commit 1899484

Please sign in to comment.