-
-
Notifications
You must be signed in to change notification settings - Fork 180
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Improve script/category name validation
- Use better error messages with more context. - Unify their validation logic and share tests. - Validate also type of the name. - Refactor node (Script/Category) parser tests for easier future changes and cleaner test code (using `TestBuilder` to do dirty work in unified way). - Add more tests. Custom `Error` properties are compared manually due to `chai` not supporting deep equality checks (chaijs/chai#1065, chaijs/chai#1405).
- Loading branch information
1 parent
65902e5
commit b210aad
Showing
17 changed files
with
853 additions
and
192 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import type { ScriptData, CategoryData } from '@/application/collections/'; | ||
|
||
export type NodeData = CategoryData | ScriptData; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { NodeType } from './NodeType'; | ||
import { NodeData } from './NodeData'; | ||
|
||
export class NodeDataError extends Error { | ||
constructor(message: string, public readonly context: INodeDataErrorContext) { | ||
super(createMessage(message, context)); | ||
Object.setPrototypeOf(this, new.target.prototype); // https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html#support-for-newtarget | ||
this.name = new.target.name; | ||
} | ||
} | ||
|
||
export interface INodeDataErrorContext { | ||
readonly type?: NodeType; | ||
readonly selfNode: NodeData; | ||
readonly parentNode?: NodeData; | ||
} | ||
|
||
function createMessage(errorMessage: string, context: INodeDataErrorContext) { | ||
let message = ''; | ||
if (context.type !== undefined) { | ||
message += `${NodeType[context.type]}: `; | ||
} | ||
message += errorMessage; | ||
message += `\n${dump(context)}`; | ||
return message; | ||
} | ||
|
||
function dump(context: INodeDataErrorContext): string { | ||
const printJson = (obj: unknown) => JSON.stringify(obj, undefined, 2); | ||
let output = `Self: ${printJson(context.selfNode)}`; | ||
if (context.parentNode) { | ||
output += `\nParent: ${printJson(context.parentNode)}`; | ||
} | ||
return output; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export enum NodeType { | ||
Script, | ||
Category, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { INodeDataErrorContext, NodeDataError } from './NodeDataError'; | ||
import { NodeData } from './NodeData'; | ||
|
||
export class NodeValidator { | ||
constructor(private readonly context: INodeDataErrorContext) { | ||
|
||
} | ||
|
||
public assertValidName(nameValue: string) { | ||
return this | ||
.assert( | ||
() => Boolean(nameValue), | ||
'missing name', | ||
) | ||
.assert( | ||
() => typeof nameValue === 'string', | ||
`Name (${JSON.stringify(nameValue)}) is not a string but ${typeof nameValue}.`, | ||
); | ||
} | ||
|
||
public assertDefined(node: NodeData) { | ||
return this.assert( | ||
() => node !== undefined && node !== null && Object.keys(node).length > 0, | ||
'missing node data', | ||
); | ||
} | ||
|
||
public assert(validationPredicate: () => boolean, errorMessage: string) { | ||
if (!validationPredicate()) { | ||
this.throw(errorMessage); | ||
} | ||
return this; | ||
} | ||
|
||
public throw(errorMessage: string) { | ||
throw new NodeDataError(errorMessage, this.context); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.