-
Notifications
You must be signed in to change notification settings - Fork 9
[RMBWEB-2780] Support for structured validation results #87
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
83cd99a
8d68591
f466115
db9f109
227f425
d84c44a
90e4499
78f35e5
b2f88ba
e5afe2a
3e45f64
511d66f
b8fb666
9065ddf
5d56725
2c76ca8
a8cb353
031f8a1
ba4b45e
dbba8f5
a5ec69d
82e505b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,12 +2,12 @@ import { action, computed, makeObservable, observable, override, reaction } from | |
| import { FieldState } from './fieldState' | ||
| import { ValidatableState } from './state' | ||
| import { IState, ValidateStatus, ValueOf } from './types' | ||
| import { debounce, isPassed, normalizeError } from './utils' | ||
| import { debounce } from './utils' | ||
|
|
||
| const defaultDelay = 200 // ms | ||
|
|
||
| /** Infomation synced from original state */ | ||
| type OriginalInfo<V> = Pick<IState<V>, 'activated' | 'touched' | 'error' | 'ownError' | 'hasError'> | ||
| /** Information synced from original state */ | ||
| type OriginalInfo<V> = Pick<IState<V>, 'activated' | 'touched' | 'error' | 'ownError' | 'hasError' | 'rawError'> | ||
|
||
|
|
||
| /** | ||
| * The state for debounce purpose. | ||
|
|
@@ -24,7 +24,7 @@ export class DebouncedState<S extends IState<V>, V = ValueOf<S>> extends Validat | |
| /** Debounced version of original value */ | ||
| @observable.ref value!: V | ||
|
|
||
| /** Orignal information, same version with current `value` */ | ||
| /** Original information, same version with current `value` */ | ||
| @observable.ref private synced!: OriginalInfo<V> | ||
|
|
||
| /** Original information for current `value` */ | ||
|
|
@@ -43,18 +43,19 @@ export class DebouncedState<S extends IState<V>, V = ValueOf<S>> extends Validat | |
| touched: this.$.touched, | ||
| error: this.$.error, | ||
| ownError: this.$.ownError, | ||
| hasError: this.$.hasError | ||
| hasError: this.$.hasError, | ||
| rawError: this.$.rawError | ||
| } | ||
| } | ||
|
|
||
| @computed get touched() { | ||
| return this.original.touched | ||
| } | ||
|
|
||
| @override override get ownError() { | ||
| @override override get rawError() { | ||
| if (this.disabled) return undefined | ||
| if (this.rawError) return normalizeError(this.rawError) | ||
| return this.original.ownError | ||
| if (this.validationResult) return this.validationResult | ||
|
||
| return this.original.rawError | ||
| } | ||
|
|
||
| @override override get error() { | ||
|
|
@@ -63,11 +64,6 @@ export class DebouncedState<S extends IState<V>, V = ValueOf<S>> extends Validat | |
| return this.original.error | ||
| } | ||
|
|
||
| @override override get hasError() { | ||
| if (this.disabled) return false | ||
| return !isPassed(this.rawError) || this.original.hasError | ||
| } | ||
|
|
||
| @override override get validateStatus() { | ||
| if (this.disabled) return ValidateStatus.WontValidate | ||
| if ( | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,20 +1,24 @@ | ||
| import { action, autorun, computed, makeObservable, observable, when } from 'mobx' | ||
| import { ValidationResult, ValidationError, IState, Validation, ValidateResult, ValidateStatus, Validator } from './types' | ||
| import { ValidationResult, IState, Validation, ValidateResult, ValidationError, ValidateStatus, Validator } from './types' | ||
| import Disposable from './disposable' | ||
| import { applyValidators, isPromiseLike, isPassed, normalizeError } from './utils' | ||
| import { applyValidators, isPromiseLike, normalizeError } from './utils' | ||
|
|
||
| /** Extraction for some basic features of State */ | ||
| export abstract class BaseState extends Disposable implements Pick< | ||
| IState, 'rawError' | 'ownError' | 'hasOwnError' | 'hasError' | 'validateStatus' | 'validating' | 'validated' | ||
|
||
| > { | ||
| > { | ||
|
|
||
| abstract rawError: ValidationResult | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
是预期的
啥?
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 没啥,是预期的就好 |
||
|
|
||
| abstract error: ValidationError | ||
|
|
||
| @computed get hasError() { | ||
| return !isPassed(this.rawError) | ||
| return !!this.error | ||
| } | ||
|
|
||
| abstract ownError: ValidationError | ||
| @computed get ownError() { | ||
| return normalizeError(this.rawError) | ||
| } | ||
|
|
||
| @computed get hasOwnError() { | ||
| return !!this.ownError | ||
|
|
@@ -54,16 +58,12 @@ export abstract class ValidatableState<V> extends BaseState implements IState<V> | |
| @observable activated = false | ||
|
|
||
| /** | ||
| * The original return value of validation. | ||
| * The original validation result. | ||
| */ | ||
| @observable private _error: ValidationResult | ||
| @observable protected validationResult: ValidationResult | ||
|
|
||
| @computed get rawError() { | ||
| return this.disabled ? undefined : this._error | ||
| } | ||
|
|
||
| @computed get ownError() { | ||
| return normalizeError(this.rawError) | ||
| return this.disabled ? undefined : this.validationResult | ||
| } | ||
|
|
||
| @computed get error() { | ||
|
|
@@ -74,7 +74,7 @@ export abstract class ValidatableState<V> extends BaseState implements IState<V> | |
| * Set validation result. | ||
| */ | ||
| @action setError(error: ValidationResult) { | ||
| this._error = error | ||
| this.validationResult = error | ||
| } | ||
|
|
||
| /** List of validator functions. */ | ||
|
|
@@ -167,7 +167,7 @@ export abstract class ValidatableState<V> extends BaseState implements IState<V> | |
| @action reset() { | ||
| this.activated = false | ||
| this._validateStatus = ValidateStatus.NotValidated | ||
| this._error = undefined | ||
| this.validationResult = undefined | ||
| this.validation = undefined | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -97,6 +97,7 @@ describe('isErrorObject', () => { | |
| expect(isErrorObject('foo')).toBe(false) | ||
| expect(isErrorObject({})).toBe(false) | ||
| expect(isErrorObject({ foo: 'foo' })).toBe(false) | ||
| expect(isErrorObject({ message: '' })).toBe(true) | ||
| expect(isErrorObject({ message: 'msg' })).toBe(true) | ||
| expect(isErrorObject({ message: 'msg', extra: 'ext' })).toBe(true) | ||
| expect(isErrorObject(new Error('error msg'))).toBe(true) | ||
Luncher marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
@@ -106,7 +107,6 @@ describe('isErrorObject', () => { | |
|
|
||
| class Bar extends Foo {} | ||
| expect(isErrorObject(new Bar())).toBe(true) | ||
| expect(() => isErrorObject({ message: '' })).toThrow(inValidErrorObjectMsg) | ||
| }) | ||
| }) | ||
|
|
||
|
|
@@ -115,6 +115,7 @@ describe('normalizeValidationResult', () => { | |
| expect(normalizeError(undefined)).toBe(undefined) | ||
| expect(normalizeError('')).toBe(undefined) | ||
| expect(normalizeError('foo')).toBe('foo') | ||
| expect(() => normalizeError({ message: '' })).toThrow(inValidErrorObjectMsg) | ||
| expect(normalizeError({ message: 'mewo' })).toBe('mewo') | ||
| expect(normalizeError(Error('mewo2'))).toBe('mewo2') | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 需要 |
||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,14 @@ | ||
| import { isObservableArray, IObservableArray } from 'mobx' | ||
| import { Validator, ValidatorReturned, ValidationError, ValidationErrorObject, ValidationResult } from './types' | ||
|
|
||
| export const inValidErrorObjectMsg = 'ValidationErrorObject message property cannot be empty' | ||
|
||
|
|
||
| // ValidationResult -> ValidationError | ||
| export function normalizeError(result: ValidationResult): ValidationError { | ||
| if (isErrorObject(result)) { | ||
| if (!result.message) { | ||
| throw new Error(inValidErrorObjectMsg) | ||
| } | ||
| return result.message | ||
| } | ||
|
|
||
|
|
@@ -14,13 +19,8 @@ export function normalizeError(result: ValidationResult): ValidationError { | |
| return result | ||
| } | ||
|
|
||
| export const inValidErrorObjectMsg = 'ValidationErrorObject message property cannot be empty' | ||
|
|
||
| export function isErrorObject(err: any): err is ValidationErrorObject { | ||
| if (err != null && typeof err === 'object' && 'message' in err) { | ||
| if (!err.message) { | ||
| throw new Error('ValidationErrorObject message property cannot be empty') | ||
| } | ||
| if (err != null && typeof err === 'object' && typeof err.message === 'string') { | ||
| return true | ||
| } | ||
| return false | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
多了个空格?以及第 30 行也多了个