Skip to content
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

✨ subscription shape #264

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
35 changes: 35 additions & 0 deletions src/FinalForm.subscribing.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -857,6 +857,41 @@ describe('FinalForm.subscribing', () => {
expect(spy.mock.calls[3][0].values).toEqual({})
})

it('should allow subscribing to form values with complex projection', () => {
const form = createForm({ onSubmit: onSubmitMock })
const spy = jest.fn()
form.subscribe(spy, {
values: {
name: true,
email: true
}
})
expect(spy).toHaveBeenCalled()
expect(spy).toHaveBeenCalledTimes(1)
expect(spy.mock.calls[0][0]).toEqual({
values: {}
})

form.registerField('name', () => {}, {})
form.registerField('email', () => {}, {})
form.registerField('phone', () => {}, {})

form.change('name', 'erikras')
expect(spy).toHaveBeenCalledTimes(2)
expect(spy.mock.calls[1][0]).toEqual({
values: { name: 'erikras' }
})

form.change('phone', '867-5309')
expect(spy).toHaveBeenCalledTimes(2)

form.change('email', '[email protected]') // not real, nosy!
expect(spy).toHaveBeenCalledTimes(3)
expect(spy.mock.calls[2][0]).toEqual({
values: { name: 'erikras', email: '[email protected]' }
})
})

it('should allow subscribing to active in form', () => {
const { spy, focus, blur } = prepareFormSubscriber('foo', {
active: true
Expand Down
223 changes: 222 additions & 1 deletion src/filterFieldState.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ describe('filterFieldState', () => {
expect(result).toBeUndefined()
})

it(`should not notify when ${key} changes`, () => {
it(`should notify when ${key} changes`, () => {
const result = filterFieldState({ ...state, [key]: newValue }, state, {
[key]: true
})
Expand All @@ -42,6 +42,41 @@ describe('filterFieldState', () => {
})
}

const testShapeValueNotify = ({
key,
state,
newValue,
subscriptionValue,
shouldNotify = true
}) => {
it(`should ${shouldNotify ? '' : 'not'} notify when ${key} changes`, () => {
const result = filterFieldState({ ...state, [key]: newValue }, state, {
[key]: subscriptionValue
})
if (shouldNotify) {
expect(result).toEqual({
[key]: newValue,
name
})
} else {
expect(result).toBeUndefined()
}
})

it(`should notify when ${key} doesn't change, but is forced`, () => {
const result = filterFieldState(
state,
state,
{ [key]: subscriptionValue },
true
)
expect(result).toEqual({
[key]: state[key],
name
})
})
}

describe('filterFieldState.active', () => {
testValue('active', state, !state.active)
})
Expand Down Expand Up @@ -85,4 +120,190 @@ describe('filterFieldState', () => {
describe('filterFieldState.visited', () => {
testValue('visited', state, !state.visited)
})

describe('filterFieldState.value - shape value', () => {
const currentKey = 'value'
const currentValue = {
keyA: false,
keyB: { foo: false, bar: false },
keyC: undefined
}
const nextValueA = {
...currentValue,
keyA: true
}
const nextValueB = {
...currentValue,
keyB: { foo: true, bar: false }
}
const nextValueC = {
...currentValue,
keyC: null
}
const subscriptionValueA = {
keyA: true
}
const subscriptionValueB = {
keyB: true
}
const subscriptionValueC = {
keyC: true
}
const subscriptionValueFoo = {
keyB: { foo: true }
}
const subscriptionValueBar = {
keyB: { bar: true }
}
const subscriptionValueAll = {
keyA: true,
keyB: true,
keyC: true
}
const subscriptionValueWild = {
wildKey: {
whoAmI: true
}
}
describe('primitive value changes when subscription contains the key', () => {
testShapeValueNotify({
key: currentKey,
state: {
...state,
value: currentValue
},
newValue: nextValueA,
subscriptionValue: subscriptionValueA,
shouldNotify: true
})
testShapeValueNotify({
key: currentKey,
state: {
...state,
value: currentValue
},
newValue: nextValueA,
subscriptionValue: subscriptionValueAll,
shouldNotify: true
})
})
describe('primitive value does not change when subscription contains the key', () => {
testShapeValueNotify({
key: currentKey,
state: {
...state,
value: currentValue
},
newValue: currentValue,
subscriptionValue: subscriptionValueA,
shouldNotify: false
})
})
describe('primitive value changes when subscription does not contain the key', () => {
testShapeValueNotify({
key: currentKey,
state: {
...state,
value: currentValue
},
newValue: nextValueA,
subscriptionValue: subscriptionValueB,
shouldNotify: false
})
})
describe('object type value changes when subscription contains the key', () => {
testShapeValueNotify({
key: currentKey,
state: {
...state,
value: currentValue
},
newValue: nextValueB,
subscriptionValue: subscriptionValueB,
shouldNotify: true
})
testShapeValueNotify({
key: currentKey,
state: {
...state,
value: currentValue
},
newValue: nextValueB,
subscriptionValue: subscriptionValueAll,
shouldNotify: true
})
})
describe('object type value does not change when subscription contains the key', () => {
testShapeValueNotify({
key: currentKey,
state: {
...state,
value: currentValue
},
newValue: nextValueA,
subscriptionValue: subscriptionValueB,
shouldNotify: false
})
})
describe('object type value changes when subscription does not contain the key', () => {
testShapeValueNotify({
key: currentKey,
state: {
...state,
value: currentValue
},
newValue: nextValueB,
subscriptionValue: subscriptionValueA,
shouldNotify: false
})
})
describe('object type value partial changes when subscription contains the nested key', () => {
testShapeValueNotify({
key: currentKey,
state: {
...state,
value: currentValue
},
newValue: nextValueB,
subscriptionValue: subscriptionValueFoo,
shouldNotify: true
})
})
describe('object type value partial changes when subscription does not contain the nested key', () => {
testShapeValueNotify({
key: currentKey,
state: {
...state,
value: currentValue
},
newValue: nextValueB,
subscriptionValue: subscriptionValueBar,
shouldNotify: false
})
})
describe('undefined value changes to null value when subscription contains the key', () => {
testShapeValueNotify({
key: currentKey,
state: {
...state,
value: currentValue
},
newValue: nextValueC,
subscriptionValue: subscriptionValueC,
shouldNotify: true
})
})
describe('subscription contains a irrelative key', () => {
testShapeValueNotify({
key: currentKey,
state: {
...state,
value: currentValue
},
newValue: nextValueB,
subscriptionValue: subscriptionValueWild,
shouldNotify: false
})
})
})
})