Skip to content

Commit

Permalink
adds decorated data path (atlassian#28)
Browse files Browse the repository at this point in the history
* adds decorated data path

* keep standard json pointer path

* migrate tests

* remove integration test
  • Loading branch information
supertong authored and torifat committed Sep 17, 2018
1 parent f61f2fa commit a9cd8b0
Show file tree
Hide file tree
Showing 10 changed files with 71 additions and 10 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
/node_modules/
/coverage/
*.log
.vscode
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
},
"jest": {
"testMatch": [
"<rootDir>/src/**/__tests__/*.js"
"<rootDir>/src/**/__tests__/**/*.js"
]
},
"prettier": {
Expand Down
36 changes: 36 additions & 0 deletions src/json/get-decorated-data-pah.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
export default function getDecoratedDataPath(jsonAst, dataPath) {
// TODO: Handle json pointer escape notation and better error handling
const pointers = dataPath.split('/').slice(1);
let decoratedPath = '';
pointers.reduce((obj, pointer, idx) => {
switch (obj.type) {
case 'Object': {
decoratedPath += `/${pointer}`;
const filtered = obj.children.filter(
child => child.key.value === pointer
);
if (filtered.length !== 1) {
throw new Error(`Couldn't find property ${pointer} of ${dataPath}`);
}
return filtered[0].value;
}
case 'Array':
decoratedPath += `/${pointer}${getTypeName(obj.children[pointer])}`;
return obj.children[pointer];
default:
// eslint-disable-next-line no-console
console.log(obj);
}
}, jsonAst);
return decoratedPath;
}

function getTypeName(obj) {
const type = obj.children.filter(child => child.key.value === 'type');

if (!type.length) {
return '';
}

return (type[0].value && `:${type[0].value.value}`) || '';
}
1 change: 1 addition & 0 deletions src/json/index.js
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { default as getMetaFromPath } from './get-meta-from-path';
export { default as getDecoratedDataPath } from './get-decorated-data-pah';
6 changes: 5 additions & 1 deletion src/validation-errors/__tests__/__snapshots__/main.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ Array [
"line": 1,
"offset": 26,
},
"error": "Property baz is not expected to be here",
"error": " Property baz is not expected to be here",
"path": "",
"start": Object {
"column": 22,
"line": 1,
Expand All @@ -27,6 +28,7 @@ Array [
"offset": 24,
},
"error": "/id: type should be number",
"path": "/id",
"start": Object {
"column": 7,
"line": 1,
Expand All @@ -45,6 +47,7 @@ Array [
"offset": 11,
},
"error": "/id should be equal to one of the allowed values: foo, bar",
"path": "/id",
"start": Object {
"column": 7,
"line": 1,
Expand All @@ -59,6 +62,7 @@ exports[`Main should support js output format for required errors 1`] = `
Array [
Object {
"error": "/nested should have required property 'id'",
"path": "/nested",
"start": Object {
"column": 11,
"line": 1,
Expand Down
5 changes: 4 additions & 1 deletion src/validation-errors/additional-prop.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ export default class AdditionalPropValidationError extends BaseValidationError {

return {
...this.getLocation(`${dataPath}/${params.additionalProperty}`),
error: `Property ${params.additionalProperty} is not expected to be here`,
error: `${this.getDecoratedPath(dataPath)} Property ${
params.additionalProperty
} is not expected to be here`,
path: dataPath,
};
}
}
7 changes: 6 additions & 1 deletion src/validation-errors/base.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { codeFrameColumns } from '@babel/code-frame';
import { getMetaFromPath } from '../json';
import { getMetaFromPath, getDecoratedDataPath } from '../json';

export default class BaseValidationError {
constructor(
Expand All @@ -26,6 +26,11 @@ export default class BaseValidationError {
};
}

getDecoratedPath(dataPath = this.options.dataPath) {
const decoratedPath = getDecoratedDataPath(this.jsonAst, dataPath);
return decoratedPath;
}

getCodeFrame(message, dataPath = this.options.dataPath) {
return codeFrameColumns(this.jsonRaw, this.getLocation(dataPath), {
highlightCode: true,
Expand Down
3 changes: 2 additions & 1 deletion src/validation-errors/default.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ export default class DefaultValidationError extends BaseValidationError {

return {
...this.getLocation(),
error: `${dataPath}: ${keyword} ${message}`,
error: `${this.getDecoratedPath(dataPath)}: ${keyword} ${message}`,
path: dataPath,
};
}
}
15 changes: 12 additions & 3 deletions src/validation-errors/enum.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import BaseValidationError from './base';

export default class EnumValidationError extends BaseValidationError {
print() {
const { message, params: { allowedValues } } = this.options;
const {
message,
params: { allowedValues },
} = this.options;
const bestMatch = this.findBestMatch();

const output = [
Expand All @@ -28,7 +31,10 @@ export default class EnumValidationError extends BaseValidationError {

const output = {
...this.getLocation(),
error: `${dataPath} ${message}: ${params.allowedValues.join(', ')}`,
error: `${this.getDecoratedPath(
dataPath
)} ${message}: ${params.allowedValues.join(', ')}`,
path: dataPath,
};

if (bestMatch !== null) {
Expand All @@ -39,7 +45,10 @@ export default class EnumValidationError extends BaseValidationError {
}

findBestMatch() {
const { dataPath, params: { allowedValues } } = this.options;
const {
dataPath,
params: { allowedValues },
} = this.options;
const currentValue = pointer.get(this.data, dataPath);

if (!currentValue) {
Expand Down
5 changes: 3 additions & 2 deletions src/validation-errors/required.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@ export default class RequiredValidationError extends BaseValidationError {
}

getError() {
const { message, dataPath, params } = this.options;
const { message, dataPath } = this.options;

return {
...this.getLocation(),
error: `${dataPath} ${message}`,
error: `${this.getDecoratedPath(dataPath)} ${message}`,
path: dataPath,
};
}
}

0 comments on commit a9cd8b0

Please sign in to comment.