Skip to content

Commit

Permalink
feat(core): improve validation
Browse files Browse the repository at this point in the history
  • Loading branch information
P0lip committed Jan 27, 2022
1 parent e7b5816 commit 704bc83
Show file tree
Hide file tree
Showing 48 changed files with 1,177 additions and 615 deletions.
2 changes: 1 addition & 1 deletion docs/guides/4-custom-rulesets.md
Expand Up @@ -31,7 +31,7 @@ It has a specific syntax known as [JSONPath](https://goessner.net/articles/JsonP
Both of them support all the main JSONPath functionality and a little bit more, but this syntax may differ slightly from other JSONPath implementations.

Your `given` value can be a string containing any valid JSONPath expression, or an array of expressions to apply a rule to multiple parts of a document.
You can also consume your (aliases)[#aliases] here if you have some defined.
You can also consume your [aliases](#aliases) here if you have some defined.

Use the [JSONPath Online Evaluator](http://jsonpath.com/) to determine what `given` path you want.

Expand Down
4 changes: 1 addition & 3 deletions jest.config.js
Expand Up @@ -8,9 +8,7 @@ const projectDefault = {
preset: 'ts-jest',
moduleNameMapper: {
...mapValues(pathsToModuleNameMapper(compilerOptions.paths), v => path.join(__dirname, v)),
'^@stoplight/spectral-test-utils$': '<rootDir>/test-utils/node/index.ts',
'^nimma/fallbacks$': '<rootDir>/node_modules/nimma/dist/cjs/fallbacks/index.js',
'^nimma/legacy$': '<rootDir>/node_modules/nimma/dist/legacy/cjs/index.js',
'^@stoplight/spectral\\-test\\-utils$': '<rootDir>/test-utils/node/index.ts',
},
testEnvironment: 'node',
globals: {
Expand Down
5 changes: 4 additions & 1 deletion karma.conf.ts
@@ -1,6 +1,7 @@
// Karma configuration
// Generated on Tue Jul 02 2019 17:18:30 GMT+0200 (Central European Summer Time)

import * as path from 'path';
import type { TransformCallback, TransformContext } from 'karma-typescript';
import type { Config } from 'karma';

Expand All @@ -14,7 +15,7 @@ module.exports = (config: Config): void => {
frameworks: ['jasmine', 'karma-typescript'],

// list of files / patterns to load in the browser
files: ['./__karma__/jest.ts', 'packages/*/src/**/*.ts'],
files: ['./__karma__/jest.ts', './test-utils/*.ts', 'packages/*/src/**/*.ts'],

// list of files / patterns to exclude
exclude: ['packages/cli/**', '**/*.jest.test.ts'],
Expand All @@ -24,6 +25,7 @@ module.exports = (config: Config): void => {
preprocessors: {
'packages/*/src/**/*.ts': ['karma-typescript'],
'./__karma__/**/*.ts': ['karma-typescript'],
'./test-utils/*.ts': ['karma-typescript'],
},

// @ts-expect-error: non-standard - karmaTypeScriptConfig
Expand All @@ -35,6 +37,7 @@ module.exports = (config: Config): void => {
resolve: {
alias: {
'@stoplight/spectral-test-utils': require.resolve('./test-utils/browser/index.js'),
'@stoplight/spectral-test-utils/matchers': path.join(__dirname, './test-utils/matchers.ts'),
nimma: require.resolve('./node_modules/nimma/dist/legacy/cjs/index.js'),
'nimma/fallbacks': require.resolve('./node_modules/nimma/dist/legacy/cjs/fallbacks/index.js'),
'nimma/legacy': require.resolve('./node_modules/nimma/dist/legacy/cjs/index.js'),
Expand Down
5 changes: 2 additions & 3 deletions package.json
Expand Up @@ -30,7 +30,7 @@
"lint": "yarn lint.prettier && yarn lint.eslint",
"lint.fix": "yarn lint.prettier --write && yarn lint.eslint --fix",
"lint.eslint": "eslint --cache --cache-location .cache/.eslintcache --ext=.js,.mjs,.ts packages test-harness",
"lint.prettier": "prettier --ignore-path .eslintignore --ignore-unknown --check packages/core/src/meta/*.json packages/*/CHANGELOG.md docs/**/*.md README.md",
"lint.prettier": "prettier --ignore-path .eslintignore --ignore-unknown --check packages/core/src/ruleset/meta/*.json packages/*/CHANGELOG.md docs/**/*.md README.md",
"pretest": "yarn workspace @stoplight/spectral-ruleset-migrator pretest",
"test": "yarn pretest && yarn test.karma && yarn test.jest",
"test.harness": "jest -c ./test-harness/jest.config.js",
Expand Down Expand Up @@ -83,7 +83,6 @@
"jest": "^27.4.3",
"jest-mock": "^27.4.2",
"jest-when": "^3.4.2",
"json-schema": "^0.4.0",
"karma": "^6.1.1",
"karma-chrome-launcher": "^3.1.0",
"karma-jasmine": "^3.3.1",
Expand All @@ -109,7 +108,7 @@
"README.md": [
"prettier --write"
],
"packages/core/src/meta/*.json": [
"packages/core/src/ruleset/meta/*.json": [
"prettier --ignore-path .eslintignore --write"
]
},
Expand Down
58 changes: 54 additions & 4 deletions packages/cli/src/services/__tests__/linter.test.ts
@@ -1,10 +1,14 @@
import '@stoplight/spectral-test-utils/matchers';

import { join, resolve } from '@stoplight/path';
import nock from 'nock';
import * as yargs from 'yargs';
import lintCommand from '../../commands/lint';
import { lint } from '../linter';
import { DiagnosticSeverity } from '@stoplight/types';
import { RulesetValidationError } from '@stoplight/spectral-core';
import '@stoplight/spectral-test-utils/matchers';
import AggregateError = require('es-aggregate-error');

jest.mock('../output');

Expand Down Expand Up @@ -204,8 +208,32 @@ describe('Linter service', () => {
});

it('fails trying to extend an invalid relative ruleset', () => {
return expect(run(`lint ${validCustomOas3SpecPath} -r ${invalidNestedRulesetPath}`)).rejects.toThrowError(
RulesetValidationError,
return expect(
run(`lint ${validCustomOas3SpecPath} -r ${invalidNestedRulesetPath}`),
).rejects.toThrowAggregateError(
new AggregateError([
new RulesetValidationError('must be equal to one of the allowed values', [
'rules',
'rule-with-invalid-enum',
]),
new RulesetValidationError('the rule must have at least "given" and "then" properties', [
'rules',
'rule-without-given-nor-them',
]),
new RulesetValidationError('allowed types are "style" and "validation"', [
'rules',
'rule-with-invalid-enum',
'type',
]),
new RulesetValidationError('must be equal to one of the allowed values', [
'rules',
'rule-without-given-nor-them',
]),
new RulesetValidationError(
'the value has to be one of: 0, 1, 2, 3 or "error", "warn", "info", "hint", "off"',
['rules', 'rule-with-invalid-enum', 'severity'],
),
]),
);
});
});
Expand All @@ -218,8 +246,30 @@ describe('Linter service', () => {
});

it('outputs "invalid ruleset" error', () => {
return expect(run(`lint ${validOas3SpecPath} -r ${invalidRulesetPath}`)).rejects.toThrowError(
RulesetValidationError,
return expect(run(`lint ${validOas3SpecPath} -r ${invalidRulesetPath}`)).rejects.toThrowAggregateError(
new AggregateError([
new RulesetValidationError('must be equal to one of the allowed values', [
'rules',
'rule-with-invalid-enum',
]),
new RulesetValidationError('the rule must have at least "given" and "then" properties', [
'rules',
'rule-without-given-nor-them',
]),
new RulesetValidationError('allowed types are "style" and "validation"', [
'rules',
'rule-with-invalid-enum',
'type',
]),
new RulesetValidationError('must be equal to one of the allowed values', [
'rules',
'rule-without-given-nor-them',
]),
new RulesetValidationError(
'the value has to be one of: 0, 1, 2, 3 or "error", "warn", "info", "hint", "off"',
['rules', 'rule-with-invalid-enum', 'severity'],
),
]),
);
});

Expand Down
7 changes: 4 additions & 3 deletions packages/core/package.json
Expand Up @@ -29,12 +29,14 @@
"@stoplight/spectral-parsers": "^1.0.0",
"@stoplight/spectral-ref-resolver": "^1.0.0",
"@stoplight/spectral-runtime": "^1.0.0",
"@stoplight/types": "12.3.0",
"@stoplight/types": "12.5.0",
"@types/es-aggregate-error": "^1.0.2",
"@types/json-schema": "^7.0.7",
"ajv": "^8.6.0",
"ajv-errors": "~3.0.0",
"ajv-formats": "~2.1.0",
"blueimp-md5": "2.18.0",
"json-schema": "0.4.0",
"es-aggregate-error": "^1.0.7",
"jsonpath-plus": "6.0.1",
"lodash": "~4.17.21",
"lodash.topath": "^4.5.2",
Expand All @@ -48,7 +50,6 @@
"@stoplight/spectral-functions": "*",
"@stoplight/spectral-parsers": "*",
"@stoplight/yaml": "^4.2.2",
"@types/json-schema": "^7.0.7",
"@types/minimatch": "^3.0.5",
"@types/treeify": "^1.0.0",
"nock": "^13.1.0",
Expand Down

This file was deleted.

14 changes: 0 additions & 14 deletions packages/core/src/ruleset/__tests__/__fixtures__/foo-ruleset.json

This file was deleted.

This file was deleted.

Expand Up @@ -22,7 +22,9 @@ const ruleset: RulesetDefinition = {
then: {
function: schema,
functionOptions: {
type: 'number',
schema: {
type: 'number',
},
},
},
},
Expand All @@ -39,7 +41,9 @@ const ruleset: RulesetDefinition = {
then: {
function: schema,
functionOptions: {
type: 'boolean',
schema: {
type: 'boolean',
},
},
},
},
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

6 changes: 3 additions & 3 deletions packages/core/src/ruleset/__tests__/ruleset.test.ts
Expand Up @@ -6,10 +6,10 @@ import { DiagnosticSeverity } from '@stoplight/types';
import { Ruleset } from '../ruleset';
import { RulesetDefinition } from '../types';
import { print } from './__helpers__/print';
import { RulesetValidationError } from '../validation';
import { RulesetValidationError } from '../validation/index';
import { isPlainObject } from '@stoplight/json';
import { Format } from '../format';
import { JSONSchema4, JSONSchema6, JSONSchema7 } from 'json-schema';
import type { JSONSchema4, JSONSchema6, JSONSchema7 } from 'json-schema';
import { FormatsSet } from '../utils/formatsSet';

async function loadRuleset(mod: Promise<{ default: RulesetDefinition }>, source?: string): Promise<Ruleset> {
Expand Down Expand Up @@ -247,7 +247,7 @@ describe('Ruleset', () => {
describe('error handling', () => {
it('given empty ruleset, should throw a user friendly error', () => {
expect(() => new Ruleset({})).toThrowError(
new RulesetValidationError('Ruleset must have rules or extends or overrides defined'),
new RulesetValidationError('Ruleset must have rules or extends or overrides defined', []),
);
});
});
Expand Down

0 comments on commit 704bc83

Please sign in to comment.