Skip to content

Initial updates to add tests that cause the failure #52

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

Open
wants to merge 5 commits into
base: master
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 60 additions & 60 deletions packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,62 +1,62 @@
{
"name": "react-forms-processor",
"version": "0.0.35",
"description": "A forms processor for statically declaring forms with dynamic behaviour",
"main": "dist/index.js",
"scripts": {
"test": "jest",
"glow": "glow",
"glow:watch": "glow --watch",
"start": "webpack-dev-server --mode development",
"transpile": "babel src -d dist --copy-files",
"prepublishOnly": "npm run transpile",
"build": "webpack --mode production",
"dev:watch": "webpack --mode development --watch",
"postbuild": "yarn build:flow",
"build:flow": "../../node_modules/flow-copy-source/bin/flow-copy-source.js --verbose --ignore '**/*{story,test}.js' src dist"
},
"license": "MIT",
"peerDependencies": {
"react": "^16.4",
"react-dom": "^16.4"
},
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-core": "^6.26.3",
"babel-jest": "^22.4.3",
"babel-loader": "^7.1.4",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-preset-env": "^1.7.0",
"babel-preset-jest": "^22.4.3",
"babel-preset-react": "^6.24.1",
"chai": "^4.2.0",
"chai-enzyme": "^1.0.0-beta.1",
"css-loader": "^0.28.11",
"enzyme": "^3.7.0",
"enzyme-adapter-react-16.3": "^1.3.0",
"flow-bin": "0.79.1",
"flow-types": "^1.0.0",
"gh-pages": "^1.1.0",
"glow": "^1.1.1",
"html-webpack-plugin": "^3.2.0",
"jest": "^22.4.3",
"react": "^16.4",
"react-dom": "^16.4",
"react-test-renderer": "^16.4",
"regenerator-runtime": "^0.11.1",
"style-loader": "^0.21.0",
"webpack": "^4.8.1",
"webpack-cli": "^2.1.3",
"webpack-dev-server": "^3.1.4"
},
"dependencies": {
"flow-copy-source": "^2.0.2",
"lodash": "^4.17.10"
},
"jest": {
"verbose": true,
"bail": false,
"rootDir": "src"
}
"name": "react-forms-processor",
"version": "0.0.35",
"description": "A forms processor for statically declaring forms with dynamic behaviour",
"main": "dist/index.js",
"scripts": {
"test": "jest",
"glow": "glow",
"glow:watch": "glow --watch",
"start": "webpack-dev-server --mode development",
"transpile": "babel src -d dist --copy-files",
"prepublishOnly": "npm run transpile",
"build": "webpack --mode production",
"dev:watch": "webpack --mode development --watch",
"postbuild": "yarn build:flow",
"build:flow": "../../node_modules/flow-copy-source/bin/flow-copy-source.js --verbose --ignore '**/*{story,test}.js' src dist"
},
"license": "MIT",
"peerDependencies": {
"react": "^16.4",
"react-dom": "^16.4"
},
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-core": "^6.26.3",
"babel-jest": "^22.4.3",
"babel-loader": "^7.1.4",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-preset-env": "^1.7.0",
"babel-preset-jest": "^22.4.3",
"babel-preset-react": "^6.24.1",
"chai": "^4.2.0",
"chai-enzyme": "^1.0.0-beta.1",
"css-loader": "^0.28.11",
"enzyme": "^3.7.0",
"enzyme-adapter-react-16.3": "^1.3.0",
"flow-bin": "0.79.1",
"flow-types": "^1.0.0",
"gh-pages": "^1.1.0",
"glow": "^1.1.1",
"html-webpack-plugin": "^3.2.0",
"jest": "^22.4.3",
"react": "^16.4",
"react-dom": "^16.4",
"react-test-renderer": "^16.4",
"regenerator-runtime": "^0.11.1",
"style-loader": "^0.21.0",
"webpack": "^4.8.1",
"webpack-cli": "^2.1.3",
"webpack-dev-server": "^3.1.4"
},
"dependencies": {
"flow-copy-source": "^2.0.2",
"lodash": "^4.17.10"
},
"jest": {
"verbose": false,
"bail": false,
"rootDir": "src"
}
}
50 changes: 33 additions & 17 deletions packages/core/src/components/Form.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,6 @@ const valueHasChanged = (
prevState: FormComponentState
) => nextProps.value && nextProps.value !== prevState.value;

const defaultValueHasChanged = (
nextProps: FormComponentProps,
prevState: FormComponentState
) => nextProps.value && nextProps.value !== prevState.defaultValue;

const formDisabledStateHasChanged = (
nextProps: FormComponentProps,
prevState: FormComponentState
Expand All @@ -59,8 +54,8 @@ export default class Form extends Component<
super(props);
this.state = {
fields: [],
defaultValue: props.value || {},
value: props.value || {},
defaultValue: props.defaultValue || {},
value: props.value || props.defaultValue || {},
isValid: false,
defaultFields: [],
disabled: props.disabled || false,
Expand Down Expand Up @@ -90,17 +85,22 @@ export default class Form extends Component<
prevState: FormComponentState
) {
const defaultFieldsChange = defaultFieldsHaveChanged(nextProps, prevState);
const defaultValueChange = defaultValueHasChanged(nextProps, prevState);
const valueChange = valueHasChanged(nextProps, prevState);
if (
defaultFieldsChange ||
valueHasChanged(nextProps, prevState) ||
valueChange ||
formDisabledStateHasChanged(nextProps, prevState) ||
formTouchedBehaviourHasChanged(nextProps, prevState)
) {
const { fields: fieldsFromState, value: valueFromState } = prevState;
const {
fields: fieldsFromState,
defaultValue: defaultValueFromState,
value: valueFromState
} = prevState;

let {
defaultFields: defaultFieldsFromProps,
defaultValue: defaultValueFromProps,
value: valueFromProps,
disabled = false
} = nextProps;
Expand All @@ -111,10 +111,23 @@ export default class Form extends Component<
showValidationBeforeTouched = false
} = nextProps;

// If a new value has been passed to the Form as a prop then it should take precedence over the last calculated state
const value = valueFromProps || valueFromState || {};
const value = {
...defaultValueFromProps,
...valueFromState,
...valueFromProps
};

const defaultFields = defaultFieldsFromProps || fieldsFromState;

// TODO: Don't use the field value if the value prop has changed...
if (!valueChange) {
defaultFields.forEach(field => {
if (field.value) {
value[field.name] = field.value;
}
});
}

let fields;
if (defaultFieldsFromProps && defaultFieldsChange) {
fields = registerFields(defaultFieldsFromProps, value);
Expand All @@ -125,7 +138,7 @@ export default class Form extends Component<

// We should reset the touched state of all the fields if the value passed as a prop to the form
// changes...
const resetTouchedState = defaultValueChange;
const resetTouchedState = valueChange;

const nextState = getNextStateFromFields({
fields,
Expand All @@ -139,12 +152,13 @@ export default class Form extends Component<
return {
...nextState,
defaultFields: defaultFieldsFromProps,
defaultValue: defaultValueFromProps || defaultValueFromState,
disabled,
showValidationBeforeTouched
showValidationBeforeTouched,
value
};
} else {
return null;
}
return null;
}

onFieldChange(id: string, value: Value) {
Expand All @@ -158,6 +172,7 @@ export default class Form extends Component<
let { fields } = this.state;
fields = updateFieldTouchedState(id, true, fields);
fields = updateFieldValue(id, value, fields);

const nextState = getNextStateFromFields({
fields,
lastFieldUpdated: id,
Expand Down Expand Up @@ -254,7 +269,7 @@ export default class Form extends Component<
}

createFormContext() {
const { fields, value, isValid } = this.state;
const { fields, defaultValue, value, isValid } = this.state;
const {
renderer = defaultRenderer,
optionsHandler,
Expand All @@ -271,6 +286,7 @@ export default class Form extends Component<
const context: FormContextData = {
fields,
isValid,
defaultValue,
value,
registerField: this.registerField.bind(this),
renderer,
Expand Down
38 changes: 31 additions & 7 deletions packages/core/src/components/Form.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ describe("Context", () => {
<Form
defaultFields={singleField}
onChange={onFormChange}
value={propValue}
defaultValue={propValue}
>
<FormContext.Consumer>
{context => {
Expand All @@ -58,7 +58,7 @@ describe("Context", () => {
const propValue = { prop1: "value1" };
let value;
const form = mount(
<Form onChange={onFormChange} value={propValue}>
<Form onChange={onFormChange} defaultValue={propValue}>
<FormFragment defaultFields={singleField} />
</Form>
);
Expand Down Expand Up @@ -91,7 +91,7 @@ describe("validation warnings", () => {

describe("shown immediately", () => {
const form = mount(
<Form value={formValue} showValidationBeforeTouched>
<Form defaultValue={formValue} showValidationBeforeTouched>
<FormFragment defaultFields={fields} />
<FormButton onClick={onButtonClick} />
</Form>
Expand All @@ -116,7 +116,7 @@ describe("validation warnings", () => {

describe("shown when touched", () => {
const form = mount(
<Form value={formValue}>
<Form defaultValue={formValue}>
<FormFragment defaultFields={fields} />
<FormButton onClick={onButtonClick} />
</Form>
Expand Down Expand Up @@ -199,7 +199,7 @@ describe("changing form value prop", () => {
};

const form = mount(
<Form value={formValue1}>
<Form defaultValue={formValue1}>
<FormFragment defaultFields={fields} />
</Form>
);
Expand Down Expand Up @@ -264,19 +264,43 @@ describe("Form and FormFragment behave the same with defaultFields and value", (

test("Form field has correct value from value", () => {
const form = mount(
<Form defaultFields={fruit} value={{ fruit: "melon" }} />
<Form defaultFields={fruit} defaultValue={{ fruit: "melon" }} />
);
const fieldValue = form.find("select").prop("value");
expect(fieldValue).toEqual(["melon"]);
});

test("FormFragment field has correct value from value", () => {
const form = mount(
<Form value={{ fruit: "melon" }}>
<Form defaultValue={{ fruit: "melon" }}>
<FormFragment defaultFields={fruit} />
</Form>
);
const fieldValue = form.find("select").prop("value");
expect(fieldValue).toEqual(["melon"]);
});
});

describe("Form with initial value updates value on field change", () => {
const fields: FieldDef[] = [
{
id: "FIELD1",
type: "text",
name: "field1"
}
];
const formValue1 = {
field1: "value1"
};

const form = mount(
<Form defaultValue={formValue1}>
<FormFragment defaultFields={fields} />
</Form>
);

test("moomin", () => {
form.find("input").prop("onChange")({ target: { value: "updated" } });
expect(form.state().value.field1).toBe("updated");
});
});
14 changes: 9 additions & 5 deletions packages/core/src/components/FormFragment.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,18 @@ class FormFragment extends Component<
> {
constructor(props: FormFragmentComponentWithContextProps) {
super(props);
const { defaultFields = [], registerField, fields = [] } = props;
defaultFields.forEach(field =>
registerFieldIfNew(field, fields, registerField)
);
const { defaultFields = [], registerField, fields = [], value } = props;
defaultFields.forEach(field => {
field.defaultValue =
value[field.name] !== undefined
? value[field.name]
: field.defaultValue;
registerFieldIfNew(field, fields, registerField);
});
}

render() {
const { defaultFields = [] } = this.props;
const { defaultFields = [], value } = this.props;
const renderedFields = defaultFields.map(field =>
renderFieldIfVisible(field, this.props)
);
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@ export type OmitFieldValue = FieldDef => boolean;

export type FormContextData = {
fields: FieldDef[],
defaultValue: FormValue,
value: FormValue,
isValid: boolean,
options: {
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/types/components.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import type {

export type FormComponentProps = {
defaultFields?: FieldDef[],
defaultValue?: FormValue,
value?: FormValue,
onChange?: OnFormChange,
onFieldFocus?: OnFieldFocus,
Expand Down