Skip to content

Commit

Permalink
Add testInvalidRuleConfigs function instead of invalidConfig sche…
Browse files Browse the repository at this point in the history
…ma property
  • Loading branch information
ybiquitous committed Aug 10, 2023
1 parent 264ebf1 commit 40a332c
Show file tree
Hide file tree
Showing 9 changed files with 146 additions and 41 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Head

- Added: `invalidConfig` schema property.
- Added: `testInvalidRuleConfigs` function.

## 6.1.1

Expand Down
40 changes: 34 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,18 @@ Add the preset to your `jest.config.js` or `jest` field in `package.json`:
}
```

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:
Optionally, you can avoid specifying `plugins` in every schema by defining your own setup file to configure the `testRule`/`testInvalidRuleConfigs` functions.
This is useful if you have many tests. There are two additional steps to do this:

1. Create `jest.setup.js` in the root of your project. Provide `plugins` option to `getTestRule()`:
1. Create `jest.setup.js` in the root of your project. Provide `plugins` option to `getTestRule`/`getTestInvalidRuleConfigs`:

```js
const { getTestRule } = require("jest-preset-stylelint");

global.testRule = getTestRule({ plugins: ["./"] });
global.testInvalidRuleConfigs = getTestInvalidRuleConfigs({
plugins: ["./"]
});
```

2. Add `jest.setup.js` to your `jest.config.js` or `jest` field in `package.json`:
Expand All @@ -43,7 +47,13 @@ Optionally, you can avoid specifying `plugins` in every schema by defining your

## Usage

The preset exposes a global `testRule` function that you can use to efficiently test your plugin using a schema.
This preset exposes the following global functions as a helper.

See also the [type definitions](index.d.ts) for more details.

### `testRule`

The `testRule` function enables you to efficiently test your plugin using a schema.

For example, we can test a plugin that enforces and autofixes kebab-case class selectors:

Expand All @@ -55,7 +65,6 @@ testRule({
plugins: ["."],
ruleName,
config: [true, { type: "kebab" }],
invalidConfig: [123],
fix: true,

accept: [
Expand Down Expand Up @@ -105,9 +114,28 @@ testRule({
});
```

## Schema properties
### `testInvalidRuleConfigs`

The `testInvalidRuleConfigs` function enables you to test invalid configs for a rule.

For example:

```js
testInvalidRuleConfigs({
plugins: ["."],
ruleName,

See the [type definitions](index.d.ts).
configs: [
{
config: "invalid"
},
{
config: [/invalid/],
description: "regex is not allowed"
}
]
});
```

## [Changelog](CHANGELOG.md)

Expand Down
20 changes: 20 additions & 0 deletions __tests__/getTestInvalidRuleConfigs.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
'use strict';

const getTestInvalidRuleConfigs = require('../getTestInvalidRuleConfigs.js');

const testInvalidRuleConfigs = getTestInvalidRuleConfigs();

testInvalidRuleConfigs({
plugins: [require.resolve('./fixtures/plugin-foo.js')],
ruleName: 'plugin/foo',

configs: [
{
config: 123,
},
{
config: [/foo/],
description: 'regex is not allowed',
},
],
});
10 changes: 9 additions & 1 deletion __tests__/getTestRule.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,26 @@ testRule({
plugins: [require.resolve('./fixtures/plugin-foo.js')],
ruleName: 'plugin/foo',
config: ['.a'],
invalidConfig: [123],

accept: [
{
code: '.a {}',
},
{
code: '.a {}',
description: 'with description',
},
],

reject: [
{
code: '#a {}',
message: 'No "#a" selector (plugin/foo)',
},
{
code: '#a {}',
message: 'No "#a" selector (plugin/foo)',
description: 'with description',
},
],
});
49 changes: 49 additions & 0 deletions getTestInvalidRuleConfigs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
'use strict';

const { inspect } = require('util');

/** @type {import('.').getTestInvalidRuleConfigs} */
module.exports = function getTestInvalidRuleConfigs(options = {}) {
return function testInvalidRuleConfigs({
ruleName,
configs,
only,
skip,
plugins = options.plugins,
}) {
if (configs.length === 0) {
throw new TypeError('The "configs" property must not be empty');
}

/** @type {import('stylelint').lint} */
let lint;

beforeAll(() => {
// eslint-disable-next-line n/no-unpublished-require
lint = require('stylelint').lint;
});

const testGroup = only ? describe.only : skip ? describe.skip : describe;

testGroup(`${ruleName} invalid configs`, () => {
for (const { config, description, only: onlyTest, skip: skipTest } of configs) {
const testFn = onlyTest ? test.only : skipTest ? test.skip : test;

/* eslint-disable jest/no-standalone-expect */
testFn(`${description || inspect(config)}`, async () => {
const lintConfig = {
plugins,
rules: { [ruleName]: config },
};
const output = await lint({ code: '', config: lintConfig });

expect(output.results).toHaveLength(1);
expect(output.results[0].invalidOptionWarnings).toEqual([
{ text: expect.stringMatching(`"${ruleName}"`) },
]);
});
/* eslint-enable jest/no-standalone-expect */
}
});
};
};
34 changes: 7 additions & 27 deletions getTestRule.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
'use strict';

const { inspect } = require('util');
const util = require('util');

/**
* @typedef {import('.').TestCase} TestCase
* @typedef {import('.').TestSchema} TestSchema
*/

/** @type {import('.').getTestRule} */
// eslint-disable-next-line jest/no-export
module.exports = function getTestRule(options = {}) {
return function testRule(schema) {
const { ruleName, invalidConfig } = schema;

/** @type {import('stylelint').lint} */
let lint;

Expand All @@ -21,31 +18,14 @@ module.exports = function getTestRule(options = {}) {
lint = require('stylelint').lint;
});

describe(`${ruleName}`, () => {
describe(`${schema.ruleName}`, () => {
const stylelintConfig = {
plugins: options.plugins || schema.plugins,
rules: {
[ruleName]: schema.config,
[schema.ruleName]: schema.config,
},
};

if (invalidConfig) {
test(`invalid config ${inspect(invalidConfig)}`, async () => {
const config = {
...stylelintConfig,
rules: {
[ruleName]: invalidConfig,
},
};
const output = await lint({ code: '', config });

expect(output.results).toHaveLength(1);
expect(output.results[0].invalidOptionWarnings).toEqual([
{ text: expect.stringMatching(`"${ruleName}"`) },
]);
});
}

setupTestCases({
name: 'accept',
cases: schema.accept,
Expand Down Expand Up @@ -193,11 +173,11 @@ function setupTestCases({ name, cases, schema, comparisons }) {
testGroup(`${name}`, () => {
cases.forEach((testCase) => {
if (testCase) {
const testFn = testCase.only ? test.only : testCase.skip ? test.skip : test;
const spec = testCase.only ? it.only : testCase.skip ? it.skip : it;

describe(`${inspect(schema.config)}`, () => {
describe(`${inspect(testCase.code)}`, () => {
testFn(testCase.description || 'no description', comparisons(testCase));
describe(`${util.inspect(schema.config)}`, () => {
describe(`${util.inspect(testCase.code)}`, () => {
spec(testCase.description || 'no description', comparisons(testCase));
});
});
}
Expand Down
27 changes: 22 additions & 5 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,6 @@ export type TestSchema = {
*/
config: unknown;

/**
* Invalid configs to pass to the rule.
*/
invalidConfig?: unknown;

/**
* Accept test cases.
*/
Expand Down Expand Up @@ -161,6 +156,28 @@ export type TestRule = (schema: TestSchema) => void;
*/
export function getTestRule(options?: { plugins?: TestSchema['plugins'] }): TestRule;

/**
* Test invalid configurations for a rule.
*/
export type TestInvalidRuleConfigs = (
schema: Pick<TestSchema, 'ruleName' | 'plugins' | 'only' | 'skip'> & {
configs: {
config: unknown;
description?: string;
only?: boolean;
skip?: boolean;
}[];
},
) => void;

/**
* Create a `testInvalidRuleConfigs()` function with any specified plugins.
*/
export function getTestInvalidRuleConfigs(options?: {
plugins?: TestSchema['plugins'];
}): TestInvalidRuleConfigs;

declare global {
var testRule: TestRule;
var testInvalidRuleConfigs: TestInvalidRuleConfigs;
}
4 changes: 3 additions & 1 deletion jest-setup.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
'use strict';

const getTestRule = require('./getTestRule');
const getTestRule = require('./getTestRule.js');
const getTestInvalidRuleConfigs = require('./getTestInvalidRuleConfigs.js');

global.testRule = getTestRule();
global.testInvalidRuleConfigs = getTestInvalidRuleConfigs();
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"main": "index.js",
"types": "index.d.ts",
"files": [
"getTestInvalidRuleConfigs.js",
"getTestRule.js",
"jest-preset.js",
"jest-setup.js",
Expand Down

0 comments on commit 40a332c

Please sign in to comment.