From bbc3c3019fc60b2368c6bbd56434fa33efa7ed41 Mon Sep 17 00:00:00 2001 From: Erik Rasmussen Date: Mon, 15 Jul 2019 08:24:01 -0400 Subject: [PATCH] pop() wasn't removing field meta state --- src/pop.js | 16 ++++- src/pop.test.js | 161 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 171 insertions(+), 6 deletions(-) diff --git a/src/pop.js b/src/pop.js index eeb5c9b..a135c22 100644 --- a/src/pop.js +++ b/src/pop.js @@ -7,15 +7,27 @@ const pop: Mutator = ( { changeValue }: Tools ) => { let result + let removedIndex: ?number changeValue(state, name, (array: ?(any[])): ?(any[]) => { if (array) { if (!array.length) { return [] } - result = array[array.length - 1] - return array.slice(0, array.length - 1) + removedIndex = array.length - 1 + result = array[removedIndex] + return array.slice(0, removedIndex) } }) + + // now we have to remove any subfields for our index, + if (removedIndex !== undefined) { + const pattern = new RegExp(`^${name}\\[${removedIndex}].*`) + Object.keys(state.fields).forEach(key => { + if (pattern.test(key)) { + delete state.fields[key] + } + }) + } return result } diff --git a/src/pop.test.js b/src/pop.test.js index fd684d5..af4b363 100644 --- a/src/pop.test.js +++ b/src/pop.test.js @@ -1,9 +1,28 @@ import pop from './pop' +import { getIn, setIn } from 'final-form' describe('pop', () => { it('should call changeValue once', () => { const changeValue = jest.fn() - const state = {} + const state = { + formState: { + values: { + foo: ['one', 'two'] + } + }, + fields: { + 'foo[0]': { + name: 'foo[0]', + touched: true, + error: 'First Error' + }, + 'foo[1]': { + name: 'foo[1]', + touched: false, + error: 'Second Error' + } + } + } const result = pop(['foo'], state, { changeValue }) expect(result).toBeUndefined() expect(changeValue).toHaveBeenCalled() @@ -15,7 +34,26 @@ describe('pop', () => { it('should return undefined if array is undefined', () => { const changeValue = jest.fn() - const returnValue = pop(['foo'], {}, { changeValue }) + const state = { + formState: { + values: { + foo: ['one', 'two'] + } + }, + fields: { + 'foo[0]': { + name: 'foo[0]', + touched: true, + error: 'First Error' + }, + 'foo[1]': { + name: 'foo[1]', + touched: false, + error: 'Second Error' + } + } + } + const returnValue = pop(['foo'], state, { changeValue }) const op = changeValue.mock.calls[0][2] expect(returnValue).toBeUndefined() const result = op(undefined) @@ -24,7 +62,26 @@ describe('pop', () => { it('should return empty array if array is empty', () => { const changeValue = jest.fn() - const returnValue = pop(['foo'], {}, { changeValue }) + const state = { + formState: { + values: { + foo: ['one', 'two'] + } + }, + fields: { + 'foo[0]': { + name: 'foo[0]', + touched: true, + error: 'First Error' + }, + 'foo[1]': { + name: 'foo[1]', + touched: false, + error: 'Second Error' + } + } + } + const returnValue = pop(['foo'], state, { changeValue }) const op = changeValue.mock.calls[0][2] expect(returnValue).toBeUndefined() const result = op([]) @@ -37,9 +94,105 @@ describe('pop', () => { const changeValue = jest.fn((args, state, op) => { result = op(['a', 'b', 'c']) }) - const returnValue = pop(['foo'], {}, { changeValue }) + const state = { + formState: { + values: { + foo: ['one', 'two'] + } + }, + fields: { + 'foo[0]': { + name: 'foo[0]', + touched: true, + error: 'First Error' + }, + 'foo[1]': { + name: 'foo[1]', + touched: false, + error: 'Second Error' + } + } + } + const returnValue = pop(['foo'], state, { changeValue }) expect(returnValue).toBe('c') expect(Array.isArray(result)).toBe(true) expect(result).toEqual(['a', 'b']) }) + + it('should pop value off the end of array and return it', () => { + const array = ['a', 'b', 'c', 'd'] + // implementation of changeValue taken directly from Final Form + const changeValue = (state, name, mutate) => { + const before = getIn(state.formState.values, name) + const after = mutate(before) + state.formState.values = setIn(state.formState.values, name, after) || {} + } + const state = { + formState: { + values: { + foo: array, + anotherField: 42 + } + }, + fields: { + 'foo[0]': { + name: 'foo[0]', + touched: true, + error: 'A Error' + }, + 'foo[1]': { + name: 'foo[1]', + touched: false, + error: 'B Error' + }, + 'foo[2]': { + name: 'foo[2]', + touched: true, + error: 'C Error' + }, + 'foo[3]': { + name: 'foo[3]', + touched: false, + error: 'D Error' + }, + anotherField: { + name: 'anotherField', + touched: false + } + } + } + const returnValue = pop(['foo'], state, { changeValue }) + expect(returnValue).toBe('d') + expect(Array.isArray(state.formState.values.foo)).toBe(true) + expect(state.formState.values.foo).not.toBe(array) // copied + expect(state).toEqual({ + formState: { + values: { + foo: ['a', 'b', 'c'], + anotherField: 42 + } + }, + fields: { + 'foo[0]': { + name: 'foo[0]', + touched: true, + error: 'A Error' + }, + 'foo[1]': { + name: 'foo[1]', + touched: false, + error: 'B Error' + }, + 'foo[2]': { + name: 'foo[2]', + touched: true, + error: 'C Error' + }, + anotherField: { + name: 'anotherField', + touched: false + } + } + }) + }) })