jest-preset-stylelint 4.2.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![NPM version](https://img.shields.io/npm/v/jest-preset-stylelint.svg)](https://www.npmjs.org/package/jest-preset-stylelint) [![Build Status](https://github.com/stylelint/jest-preset-stylelint/workflows/CI/badge.svg)](https://github.com/stylelint/jest-preset-stylelint/actions)
4
4
 
5
- [Jest](https://facebook.github.io/jest/) preset for [stylelint](https://github.com/stylelint) plugins.
5
+ [Jest](https://facebook.github.io/jest/) preset for [Stylelint](https://github.com/stylelint) plugins.
6
6
 
7
7
  ## Installation
8
8
 
@@ -24,10 +24,10 @@ Add the preset to your `jest.config.js` or `jest` field in `package.json`:
24
24
 
25
25
  Optionally, you can avoid specifying `plugins` in every schema by defining your own setup file to configure the `testRule` function. This is useful if you have many tests. There are two additional steps to do this:
26
26
 
27
- 1. Create `jest.setup.js` in the root of your project. Provide [`plugins`](#plugins-arraystring) option to `getTestRule()`:
27
+ 1. Create `jest.setup.js` in the root of your project. Provide `plugins` option to `getTestRule()`:
28
28
 
29
29
  ```js
30
- const getTestRule = require("jest-preset-stylelint/getTestRule");
30
+ const { getTestRule } = require("jest-preset-stylelint");
31
31
 
32
32
  global.testRule = getTestRule({ plugins: ["./"] });
33
33
  ```
@@ -75,7 +75,9 @@ testRule({
75
75
  description: "camel case class selector",
76
76
  message: messages.expected(),
77
77
  line: 1,
78
- column: 1
78
+ column: 1,
79
+ endLine: 1,
80
+ endColumn: 8
79
81
  },
80
82
  {
81
83
  code: ".MyClass,\n.MyOtherClass {}",
@@ -85,12 +87,16 @@ testRule({
85
87
  {
86
88
  message: messages.expected(),
87
89
  line: 1,
88
- column: 1
90
+ column: 1,
91
+ endLine: 1,
92
+ endColumn: 8
89
93
  },
90
94
  {
91
95
  message: messages.expected(),
92
96
  line: 2,
93
- column: 1
97
+ column: 1,
98
+ endLine: 2,
99
+ endColumn: 13
94
100
  }
95
101
  ]
96
102
  }
@@ -100,117 +106,7 @@ testRule({
100
106
 
101
107
  ## Schema properties
102
108
 
103
- ### `accept` \[array\<Object\>\]
104
-
105
- Accept test cases.
106
-
107
- ### `config` \[array\]
108
-
109
- Config to pass to the rule.
110
-
111
- ### `fix` \[boolean\]
112
-
113
- Default: `false` (Optional).
114
-
115
- Turn on autofix.
116
-
117
- ### `plugins` \[array\<string\>\]
118
-
119
- Maps to Stylelint's [`plugins` configuration property](https://stylelint.io/user-guide/configure#plugins).
120
-
121
- Path to the file that exports the plugin object, relative to the root. Usually it's the same path as a `main` property in plugin's `package.json`.
122
-
123
- If you're testing a plugin pack, it's the path to the file that exports the array of plugin objects.
124
-
125
- Optional, if `plugins` option was passed to advanced configuration with `getTestRule()`.
126
-
127
- ### `reject` \[array\<Object\>\]
128
-
129
- Reject test cases.
130
-
131
- ### `ruleName` \[string\]
132
-
133
- Name of the rule being tested. Usually exported from the plugin.
134
-
135
- ### `skipBasicChecks` \[boolean\]
136
-
137
- Default: `false` (Optional).
138
-
139
- Skip [basic checks](https://github.com/stylelint/stylelint/blob/master/lib/testUtils/basicChecks.js), e.g. an empty source.
140
-
141
- ### `customSyntax` \<string\>
142
-
143
- Maps to Stylelint's [`customSyntax` option](https://stylelint.io/user-guide/usage/options#customsyntax).
144
-
145
- ### `codeFilename` \<string\>
146
-
147
- Maps to Stylelint's [`codeFilename` option](https://stylelint.io/user-guide/usage/options#codefilename).
148
-
149
- ## Shared test case properties
150
-
151
- Used within both `accept` and `reject` test cases.
152
-
153
- ### `code` \[string\]
154
-
155
- The code of the test case.
156
-
157
- ### `description` \[string\]
158
-
159
- Optional.
160
-
161
- Description of the test case.
162
-
163
- ### `skip` \[boolean\]
164
-
165
- Default: `false` (Optional).
166
-
167
- Maps to Jest's [test.skip](https://jestjs.io/docs/en/api#testskipname-fn).
168
-
169
- ### `only` \[boolean\]
170
-
171
- Default: `false` (Optional).
172
-
173
- Maps to Jest's [test.only](https://jestjs.io/docs/en/api#testonlyname-fn-timeout).
174
-
175
- ## Reject test case properties
176
-
177
- Use the `warnings` property, rather than `message`, `line` and `column`, if the test case is expected to produce more than one warning.
178
-
179
- ### `column` \[number\]
180
-
181
- Optional.
182
-
183
- Expected column number of the warning.
184
-
185
- ### `fixed` \[string\]
186
-
187
- Optional if `fix` isn't `true`.
188
-
189
- Expected fixed code of the test case.
190
-
191
- ### `line` \[number\]
192
-
193
- Optional.
194
-
195
- Expected line number of the warning.
196
-
197
- ### `message` \[string\]
198
-
199
- Optional if `warnings` is used.
200
-
201
- Expected message from the test case. Usually exported from the plugin.
202
-
203
- ### `unfixable` \[boolean\]
204
-
205
- Default: `false` (Optional).
206
-
207
- Don't check the `fixed` code.
208
-
209
- ### `warnings` \[array\<Object\>\]
210
-
211
- Optional if `message` is used.
212
-
213
- Warning Objects containing expected `message`, `line` and `column`.
109
+ See the [type definitions](index.d.ts).
214
110
 
215
111
  ## [Changelog](CHANGELOG.md)
216
112
 
package/getTestRule.js CHANGED
@@ -2,35 +2,15 @@
2
2
 
3
3
  const util = require('util');
4
4
  // eslint-disable-next-line node/no-unpublished-require -- Avoid auto-install of `stylelint` peer dependency.
5
- const { basicChecks, lint } = require('stylelint');
5
+ const { lint } = require('stylelint');
6
6
 
7
7
  /**
8
- * @typedef {Object} TestCase
9
- * @property {string} code
10
- * @property {string} [description]
11
- * @property {boolean} [only]
12
- * @property {boolean} [skip]
8
+ * @typedef {import('.').TestCase} TestCase
9
+ * @typedef {import('.').TestSchema} TestSchema
13
10
  */
14
11
 
15
- /**
16
- * @typedef {Object} TestSchema
17
- * @property {string} ruleName
18
- * @property {any} config
19
- * @property {TestCase[]} accept
20
- * @property {TestCase[]} reject
21
- * @property {string | string[]} plugins
22
- * @property {boolean} [skipBasicChecks]
23
- * @property {boolean} [fix]
24
- * @property {Syntax} [customSyntax] - PostCSS Syntax (https://postcss.org/api/#syntax)
25
- * @property {string} [codeFilename]
26
- * @property {boolean} [only]
27
- * @property {boolean} [skip]
28
- */
29
-
30
- function getTestRule(options = {}) {
31
- /**
32
- * @param {TestSchema} schema
33
- */
12
+ /** @type {import('.').getTestRule} */
13
+ module.exports = function getTestRule(options = {}) {
34
14
  return function testRule(schema) {
35
15
  describe(`${schema.ruleName}`, () => {
36
16
  const stylelintConfig = {
@@ -40,15 +20,9 @@ function getTestRule(options = {}) {
40
20
  },
41
21
  };
42
22
 
43
- let passingTestCases = schema.accept || [];
44
-
45
- if (!schema.skipBasicChecks) {
46
- passingTestCases = passingTestCases.concat(basicChecks);
47
- }
48
-
49
23
  setupTestCases({
50
24
  name: 'accept',
51
- cases: passingTestCases,
25
+ cases: schema.accept,
52
26
  schema,
53
27
  comparisons: (testCase) => async () => {
54
28
  const stylelintOptions = {
@@ -95,6 +69,7 @@ function getTestRule(options = {}) {
95
69
  (testCase.warnings || [testCase]).forEach((expected, i) => {
96
70
  const warning = actualWarnings[i];
97
71
 
72
+ // @ts-expect-error -- This is our custom matcher.
98
73
  expect(expected).toHaveMessage();
99
74
 
100
75
  expect(warning.text).toBe(expected.message);
@@ -106,6 +81,16 @@ function getTestRule(options = {}) {
106
81
  if (expected.column !== undefined) {
107
82
  expect(warning.column).toBe(expected.column);
108
83
  }
84
+
85
+ if (expected.endLine !== undefined) {
86
+ // @ts-expect-error -- TODO: `warning.endLine` is not implemented. See stylelint/stylelint#5725
87
+ expect(warning.endLine).toBe(expected.endLine);
88
+ }
89
+
90
+ if (expected.endColumn !== undefined) {
91
+ // @ts-expect-error -- TODO: `warning.endColumn` is not implemented. See stylelint/stylelint#5725
92
+ expect(warning.endColumn).toBe(expected.endColumn);
93
+ }
109
94
  });
110
95
 
111
96
  if (!schema.fix) return;
@@ -157,13 +142,24 @@ function getTestRule(options = {}) {
157
142
  }
158
143
 
159
144
  return {
145
+ message: () => '',
160
146
  pass: true,
161
147
  };
162
148
  },
163
149
  });
164
150
  };
165
- }
151
+ };
166
152
 
153
+ /**
154
+ * @template {TestCase} T
155
+ * @param {{
156
+ * name: string,
157
+ * cases: T[] | undefined,
158
+ * schema: TestSchema,
159
+ * comparisons: (testCase: T) => jest.ProvidesCallback,
160
+ * }} args
161
+ * @returns {void}
162
+ */
167
163
  function setupTestCases({ name, cases, schema, comparisons }) {
168
164
  if (cases && cases.length) {
169
165
  const testGroup = schema.only ? describe.only : schema.skip ? describe.skip : describe;
@@ -184,11 +180,16 @@ function setupTestCases({ name, cases, schema, comparisons }) {
184
180
  }
185
181
  }
186
182
 
183
+ /**
184
+ * @param {import('stylelint').LinterResult} output
185
+ * @returns {string}
186
+ */
187
187
  function getOutputCss(output) {
188
188
  const result = output.results[0]._postcssResult;
189
- const css = result.root.toString(result.opts.syntax);
190
189
 
191
- return css;
192
- }
190
+ if (result && result.root && result.opts) {
191
+ return result.root.toString(result.opts.syntax);
192
+ }
193
193
 
194
- module.exports = getTestRule;
194
+ throw new TypeError('Invalid result');
195
+ }
package/index.d.ts ADDED
@@ -0,0 +1,161 @@
1
+ export type TestCase = {
2
+ /**
3
+ * The code of the test case.
4
+ */
5
+ code: string;
6
+
7
+ /**
8
+ * Description of the test case.
9
+ */
10
+ description?: string;
11
+
12
+ /**
13
+ * Maps to Jest's `test.only`. Default: `false`.
14
+ *
15
+ * @see https://jestjs.io/docs/en/api#testonlyname-fn-timeout
16
+ */
17
+ only?: boolean;
18
+
19
+ /**
20
+ * Maps to Jest's `test.skip`. Default: `false`.
21
+ *
22
+ * @see https://jestjs.io/docs/api#testskipname-fn
23
+ */
24
+ skip?: boolean;
25
+ };
26
+
27
+ export type AcceptTestCase = TestCase;
28
+
29
+ export type Warning = {
30
+ /**
31
+ * Expected message from the test case. Usually exported from the plugin.
32
+ * Optional if `warnings` is used.
33
+ */
34
+ message?: string;
35
+
36
+ /**
37
+ * Expected line number of the warning.
38
+ */
39
+ line?: number;
40
+
41
+ /**
42
+ * Expected column number of the warning.
43
+ */
44
+ column?: number;
45
+
46
+ /**
47
+ * Expected end line number of the warning.
48
+ */
49
+ endLine?: number;
50
+
51
+ /**
52
+ * Expected end column number of the warning.
53
+ */
54
+ endColumn?: number;
55
+ };
56
+
57
+ /**
58
+ * Use the `warnings` property, rather than `message`, `line`, and `column`,
59
+ * if the test case is expected to produce more than one warning.
60
+ */
61
+ export type RejectTestCase = TestCase &
62
+ Warning & {
63
+ /**
64
+ * Expected fixed code of the test case. Optional if `fix` isn't `true`.
65
+ */
66
+ fixed?: string;
67
+
68
+ /**
69
+ * Don't check the `fixed` code. Default: `false`.
70
+ */
71
+ unfixable?: boolean;
72
+
73
+ /**
74
+ * Warning objects containing expected `message`, `line` and `column` etc.
75
+ * Optional if `message` is used.
76
+ */
77
+ warnings?: Warning[];
78
+ };
79
+
80
+ export type TestSchema = {
81
+ /**
82
+ * Name of the rule being tested. Usually exported from the plugin.
83
+ */
84
+ ruleName: string;
85
+
86
+ /**
87
+ * Config to pass to the rule.
88
+ */
89
+ config: unknown[];
90
+
91
+ /**
92
+ * Accept test cases.
93
+ */
94
+ accept?: AcceptTestCase[];
95
+
96
+ /**
97
+ * Reject test cases.
98
+ */
99
+ reject?: RejectTestCase[];
100
+
101
+ /**
102
+ * Turn on autofix. Default: `false`.
103
+ */
104
+ fix?: boolean;
105
+
106
+ /**
107
+ * Maps to Stylelint's `plugins` configuration property.
108
+ *
109
+ * Path to the file that exports the plugin object, relative to the root.
110
+ * Usually it's the same path as a `main` property in plugin's `package.json`.
111
+ *
112
+ * If you're testing a plugin pack, it's the path to the file that exports the array of plugin objects.
113
+ *
114
+ * Optional, if `plugins` option was passed to advanced configuration with `getTestRule()`.
115
+ *
116
+ * @see https://stylelint.io/user-guide/configure#plugins
117
+ */
118
+ plugins?: string | string[];
119
+
120
+ /**
121
+ * Maps to Stylelint's `customSyntax` option.
122
+ *
123
+ * @see https://stylelint.io/user-guide/usage/options#customsyntax
124
+ */
125
+ customSyntax?: string;
126
+
127
+ /**
128
+ * Maps to Stylelint's `codeFilename` option.
129
+ *
130
+ * @see https://stylelint.io/user-guide/usage/options#codefilename
131
+ */
132
+ codeFilename?: string;
133
+
134
+ /**
135
+ * Maps to Jest's `test.only`. Default: `false`.
136
+ *
137
+ * @see https://jestjs.io/docs/en/api#testonlyname-fn-timeout
138
+ */
139
+ only?: boolean;
140
+
141
+ /**
142
+ * Maps to Jest's `test.skip`. Default: `false`.
143
+ *
144
+ * @see https://jestjs.io/docs/api#testskipname-fn
145
+ */
146
+ skip?: boolean;
147
+ };
148
+
149
+ /**
150
+ * Test a rule with the specified schema.
151
+ */
152
+ export declare function testRule(schema: TestSchema): void;
153
+
154
+ /**
155
+ * Create a `testRule()` function with any specified plugins.
156
+ */
157
+ export function getTestRule(options?: { plugins?: TestSchema['plugins'] }): typeof testRule;
158
+
159
+ declare global {
160
+ var testRule: typeof testRule;
161
+ }
package/index.js ADDED
@@ -0,0 +1,5 @@
1
+ 'use strict';
2
+
3
+ const getTestRule = require('./getTestRule');
4
+
5
+ module.exports = { getTestRule };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jest-preset-stylelint",
3
- "version": "4.2.0",
3
+ "version": "5.0.0",
4
4
  "description": "Jest preset for Stylelint plugins.",
5
5
  "keywords": [
6
6
  "stylelint",
@@ -11,17 +11,21 @@
11
11
  "repository": "stylelint/jest-preset-stylelint",
12
12
  "license": "MIT",
13
13
  "author": "stylelint",
14
+ "main": "index.js",
15
+ "types": "index.d.ts",
14
16
  "files": [
15
17
  "getTestRule.js",
16
18
  "jest-preset.js",
17
- "jest-setup.js"
19
+ "jest-setup.js",
20
+ "index.d.ts"
18
21
  ],
19
22
  "scripts": {
20
23
  "format": "prettier . --write",
21
24
  "lint": "npm-run-all --parallel lint:*",
22
25
  "lint:formatting": "prettier . --check",
23
- "lint:js": "eslint . ",
24
- "lint:md": "remark . --quiet --frail ",
26
+ "lint:js": "eslint .",
27
+ "lint:md": "remark . --quiet --frail",
28
+ "lint:types": "tsc",
25
29
  "release": "np",
26
30
  "test": "jest",
27
31
  "watch": "jest --watch",
@@ -39,7 +43,9 @@
39
43
  "globals": {
40
44
  "module": true,
41
45
  "require": true
42
- }
46
+ },
47
+ "reportUnusedDisableDirectives": true,
48
+ "root": true
43
49
  },
44
50
  "remarkConfig": {
45
51
  "plugins": [
@@ -49,16 +55,18 @@
49
55
  "devDependencies": {
50
56
  "@stylelint/prettier-config": "^2.0.0",
51
57
  "@stylelint/remark-preset": "^3.0.0",
52
- "eslint": "^8.2.0",
58
+ "@types/jest": "^27.4.0",
59
+ "eslint": "^8.9.0",
53
60
  "eslint-config-stylelint": "^15.0.0",
54
61
  "husky": "^7.0.4",
55
- "jest": "^27.3.1",
56
- "lint-staged": "^11.2.6",
57
- "np": "^7.5.0",
62
+ "jest": "^27.5.1",
63
+ "lint-staged": "^12.3.4",
64
+ "np": "^7.6.0",
58
65
  "npm-run-all": "^4.1.5",
59
- "prettier": "^2.4.1",
60
- "remark-cli": "^10.0.0",
61
- "stylelint": "^14.0.1"
66
+ "prettier": "^2.5.1",
67
+ "remark-cli": "^10.0.1",
68
+ "stylelint": "^14.5.1",
69
+ "typescript": "^4.5.5"
62
70
  },
63
71
  "peerDependencies": {
64
72
  "jest": "^25.3.0 || ^26.0.1 || ^27.0.1"