-
Notifications
You must be signed in to change notification settings - Fork 10
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
[RMBWEB-2780] Support for structured validation results #87
Changes from 7 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 |
---|---|---|
|
@@ -373,4 +373,43 @@ describe('FieldState validation', () => { | |
assertType<string>(res.value) | ||
} | ||
}) | ||
|
||
describe('should work well with resolved error object', () => { | ||
it('should work well with sync resolved', async () => { | ||
const state = new FieldState('').withValidator( | ||
_ => ({ message: 'error-object-msg'}) | ||
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. 好多这种少了右空格的 😂 |
||
) | ||
|
||
const res = await state.validate() | ||
expect(state.hasError).toBe(true) | ||
expect(state.error).toBe('error-object-msg') | ||
expect(state.rawError).toEqual({ message: 'error-object-msg'}) | ||
expect(res).toEqual({ hasError: true, error: 'error-object-msg'}) | ||
}) | ||
|
||
it('should work well with sync resolved empty message', async () => { | ||
const state = new FieldState('').withValidator( | ||
_ => ({ message: ''}) | ||
) | ||
|
||
const res = await state.validate() | ||
expect(state.hasError).toBe(true) | ||
expect(state.error).toBe('') | ||
expect(state.rawError).toEqual({ message: ''}) | ||
expect(res).toEqual({ hasError: true, error: ''}) | ||
}) | ||
|
||
it('should work well with async resolved', async () => { | ||
const state = new FieldState('').withValidator( | ||
_ => null, | ||
_ => delayValue({ message: 'error-object-msg' }, 100) | ||
) | ||
|
||
const res = await state.validate() | ||
expect(state.hasError).toBe(true) | ||
expect(state.error).toBe('error-object-msg') | ||
expect(state.rawError).toEqual({ message: 'error-object-msg'}) | ||
expect(res).toEqual({ hasError: true, error: 'error-object-msg'}) | ||
}) | ||
}) | ||
}) |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -1,7 +1,7 @@ | ||||||
import { action, autorun, computed, makeObservable, observable, when } from 'mobx' | ||||||
import { ValidationError, IState, Validation, ValidateResult, ValidateStatus, Validator } from './types' | ||||||
import { ValidationRawError, ValidationError, IState, Validation, ValidateResult, ValidateStatus, Validator } from './types' | ||||||
import Disposable from './disposable' | ||||||
import { applyValidators, isValid, isPromiseLike } from './utils' | ||||||
import { applyValidators, isPromiseLike, normalizeRawError, normalizeError } from './utils' | ||||||
|
||||||
/** Extraction for some basic features of State */ | ||||||
export abstract class BaseState extends Disposable implements Pick< | ||||||
|
@@ -11,7 +11,7 @@ export abstract class BaseState extends Disposable implements Pick< | |||||
abstract error: ValidationError | ||||||
|
||||||
@computed get hasError() { | ||||||
return !!this.error | ||||||
return this.error !== undefined | ||||||
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. 不会产生 breaking change 吗? 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. 不会 breaking,因为之前 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. 哦算上 P.S. 这个使用姿势需要补个 test case 覆盖下 @Luncher 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. 如果没有开启 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. @Luncher 不能这么说,那样是使用姿势有问题了 不使用 TS 的项目还有可能 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.
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.
我没问题;不过如果给 warning 了,那最好也调整下文档,让使用者通过文档能知道我们说的“error info” 的概念,其值作为字符串时应当是非空的 对了,我在想,是不是应该给使用者设置 raw error(而不是 error)的能力才是更合理的? |
||||||
} | ||||||
|
||||||
abstract ownError: ValidationError | ||||||
|
@@ -56,10 +56,14 @@ export abstract class ValidatableState<V> extends BaseState implements IState<V> | |||||
/** | ||||||
* The original error info of validation. | ||||||
*/ | ||||||
@observable protected _error: ValidationError | ||||||
@observable protected _error: ValidationRawError | ||||||
|
||||||
@computed get rawError() { | ||||||
return this.disabled ? undefined : this._error | ||||||
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.
Suggested change
|
||||||
} | ||||||
|
||||||
@computed get ownError() { | ||||||
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. 这个是不是能挪到 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. 不太明确 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.
举个例子, 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.
基于这个标准看的话,现在 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. 假如我们有 packaged raw error,那么我们其实是能实现出这样一份对所有 state 都适用的逻辑的: ownError = normalizeError(rawError)
error = normalizeError(packagedRawError)
hasError = !isPassed(packagedRawError) 这样不同的 state,它们去实现各自的 不过现在我们没有
就不太对了;既然我们已经通过 throw 确保了 error object 的 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.
我之前在这里就说了啊..,现在要把实现改回去吗? 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.
那边我没看懂你的意思..
我倾向改回去,如果确实 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. ba4b45e |
||||||
return this.disabled ? undefined : this._error | ||||||
return normalizeError(this.rawError) | ||||||
} | ||||||
|
||||||
@computed get error() { | ||||||
|
@@ -69,7 +73,7 @@ export abstract class ValidatableState<V> extends BaseState implements IState<V> | |||||
/** | ||||||
* Set error info. | ||||||
*/ | ||||||
@action setError(error: ValidationError) { | ||||||
@action setError(error: ValidationRawError) { | ||||||
this._error = error | ||||||
} | ||||||
|
||||||
|
@@ -104,13 +108,13 @@ export abstract class ValidatableState<V> extends BaseState implements IState<V> | |||||
action('end-validation', () => { | ||||||
this.validation = undefined | ||||||
this._validateStatus = ValidateStatus.Validated | ||||||
this.setError(isValid(result) ? undefined : result) | ||||||
this.setError(normalizeRawError(result)) | ||||||
})() | ||||||
} | ||||||
|
||||||
@computed protected get validateResult(): ValidateResult<V> { | ||||||
return ( | ||||||
this.error | ||||||
this.error !== undefined | ||||||
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. 这样行为是不是变了啊? |
||||||
? { hasError: true, error: this.error } as const | ||||||
: { hasError: false, value: this.value } as const | ||||||
) | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -389,6 +389,19 @@ describe('TransformedState (for FieldState) validation', () => { | |
expect(state.ownError).toBe('non positive') | ||
}) | ||
|
||
it('should work well with resolved error object', async () => { | ||
const state = createNumState(0).withValidator( | ||
_ => ({ message: 'empty' }) | ||
) | ||
|
||
state.validate() | ||
|
||
await delay() | ||
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. NIP: 类似这种为什么不直接 |
||
expect(state.hasError).toBe(true) | ||
expect(state.error).toBe('empty') | ||
expect(state.ownError).toBe('empty') | ||
expect(state.rawError).toEqual({ message: 'empty' }) | ||
}) | ||
}) | ||
|
||
interface Host { | ||
|
@@ -738,4 +751,18 @@ describe('TransformedState (for FormState) validation', () => { | |
expect(state.hasOwnError).toBe(false) | ||
expect(state.ownError).toBeUndefined() | ||
}) | ||
|
||
it('should work well with resolved error object', async () => { | ||
const state = createHostState('127.0.0.1').withValidator( | ||
_ => ({ message: 'mock msg'}) | ||
) | ||
|
||
state.validate() | ||
|
||
await delay() | ||
expect(state.hasError).toBe(true) | ||
expect(state.error).toBe('mock msg') | ||
expect(state.ownError).toBe('mock msg') | ||
expect(state.rawError).toEqual({ message: 'mock msg' }) | ||
}) | ||
}) |
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.
在实现
DebouncedState
的时候,也应该去通过 overriderawError
来实现,而不是 overrideownError
?如 #87 (comment) 这里所述,
ownError = normalizeError(rawError)
这个逻辑对于DebouncedState
也应该是成立的?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.
没注意这里有个 override,我看怎么改下。
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.
031f8a1
done