Skip to content
This repository was archived by the owner on Nov 6, 2020. It is now read-only.

Commit 9dbeb29

Browse files
feat: introduce counterparts for ui-core form components (#108)
* refactor(radio-group): match ui-core implementation * refactor(checkbox): adjust to new API in ui-core * feat: checkbox-group radio-group and switch-group plus project structure * chore(email-validator): rename email validator * fix: align with changes in ui-core v4.0.0 * feat: extract logic from checkbox into toggle and introduce switch * feat(input): introduce input component and story * feat(text-area): introduce component and stories * chore(file-input): cherry pick file-input work - part 1 * chore(file-input): cherry pick file-input work - part 2 * fix(file-input): align with ui-core v4.0.0 * fix(file-input): remove undefined imported variable * fix(file-input): prevent prop error by returning undefined, not false * chore(toggle-group): fix ESLint violation and remove console.log * chore(array-transformer): remove log statement * feat(single-select): introduce SingleSelect component and story * feat(multi-select): introduce MultiSelect component and stories * refactor(toggle-group): implement as functional component * docs: remove note about known issues that have been resolved by now * refactor: form-decorator Moved to the `./.storybook` folder Switched to logging values directly, which is good for non-serializable things, such as File instances * refactor: simplify code base - Stop using Toggle components to extract shared logic because it gets hard to reason about all these nested components - Implement shared hooks and propTypes to replace Toggle components - Update Checkbox/Switch(Group) to work with these shared hooks and proptypes - Remove `useOnChange` prop from FieldAdapter component, because this way of working is also hard to reason about - Refactor Checkbox and Switch to now implement onChange logic internally instead of delegating it to the FieldAdapter * fix: make sure all components work without a transformer on the field * fix(multi-select): use correct prop definition (is already an array) * fix(multi-select): simplify render function and handle optional options * refactor(multi-select): use plural noun for array * chore(deps): upgrade to ui-core 4.0.0 * fix(multi-select): prevent prop validation error when value is empty * refactor: make prop required in component module, not in shared prop * fix(single-select): ensure options is always array and simplify render * fix(email validator): remove required check * fix(switch-group): remove SwitchGroup component * refactor: implement hooks as helpers * chore(deps): upgrade ui-core to 4.0.1 to fix button errors * fix(multi-select): adjust prop-types to prevent error * refactor(file-input): implement as functional component * refactor: remove field-adapter and replace with normalize-props helper * fix: correct broken import * chore(field): add propTypes * chore(deps): remove redundant classnames package and move jest to dev * chore: add testing stories and enable testing it * chore: enable testing stories * chore: add form testing story * fix: use correct repository and translation namespace * chore(testing form): add text area to form testing story * chore: setup cypress (#133) * chore(cypress): add basic setup * chore(cypress): tweak cypress setup so it actually works * test(checkbox): try to make initial test pass * test(checkbox): fix initial feature and test * chore(eslint): format .eslintrc.js * refactor: use named function in testing story form-spy * fix: expose all react-final-form exports * fix(testing-story): tweak so we can do without useFormState * chore: improve cypress implementation after introduction to project (#134) * chore(cypress config): remove baseUrl, already set in scripts * chore(checkbox test): make sure checkbox is not checked initially * chore(visit story helper): replace colon with nothing * chore(file-input): add tests (#136) * chore(cypress file upload): provide helper commands * chore(form testing story): add single- and multie-file inputs * test(file input): add test for single & multiple files * fix: use storybook helper for getting the story id * test: complete checkbox test and introduce shared submit step * refactor: create helpers for common storybook and cypress operations * fix: improve form-decorator so form values include initial values * fix: use null as value for unchecked checkbox with value prop Previously we were using '' but this clears the form values property when the checkbox is unchecked by the user and this could be problematic, because upon submission it looks like the field has not been interacted with * test(checkbox): add additional feature+test and use dedicated test story * chore: fix feature file capitalization * chore: remove checkbox folder to remove duplicates from remote * chore: restore checkbox folder and duplicates be gone * test: add component tests (#146) * chore(storybook form decorator): add forceUpdate api when testing * chore(cypress common steps): rename shared to common & remove imports * chore(checkbox tests): remove unnecessary tests * chore(checkbox error test): rename "And" to "When" * chore(single select): add testing story * test(single select): add tests for selecting and error * chore(cypress support): add "getFormValue" helper * chore(cypress support): add "selectMultiSelectNthOption" helper * chore(multi select): add testing story * chore(cypress support): repurpose helper to select both select's options * chore(multi select): add tests for chaning the value and error display * chore(input): add testing story * test(input): add tests for typing and error * chore(input): remove unnecessary cypress common folder * chore(text area): add testing stories * test(text area): add tests for typing and error * chore(form decorator): render spy after children * chore(checkbos): use cypress helper to test form value * chore(switch): add testing stories * test(switch): add tests for typing and error * chore(checkbox group): add testing story * chore(radio group): add testing story * test(checkbox group): add tests for typing and error * test(radio group): add tests for typing and error * test(switch): add tests for boolean values * test(checkbox): add tests for boolean values * refactor: fix form-decorator by using the normal component lifecycle * refactor: use single formDecorator and update logic in stories + tests * chore: fix cypress eslint config * chore: fix typos in checkbox-group feature * fix: amend checkbox group step description to indicate requiredness * chore: fix step description in file input feature * chore: fix file-input step descriptions and remove redundant code * chore: add prefix to input testing story * chore: fix various option vs options typos in step descriptions * chore: simplify input/textarea can set a value test * chore: explain the field is required in multi-select test steps * chore: stop logging to the console in multi-select test * chore: fix test step typo for single options * chore: fix typo in radio-group feature file * chore: adjust radio-group step description to two options * chore: explain the field is required in radio-group test steps * chore: explain the field is required in single-select test steps * fix(form-decorator): remove typo from clear-cypress-props * fix: improve feature step text when user types in inputs * fix: improve create-default-change-handler logic - Throw an error if the payload cannot be processed - Make sure to check for the existence of properties instead of evaluating they are thruthy * fix: align single-select and multi-select selected options with ui-core
1 parent 10d4d3f commit 9dbeb29

File tree

119 files changed

+3893
-695
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

119 files changed

+3893
-695
lines changed

.eslintrc.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,12 @@ const { config } = require('@dhis2/cli-style')
33
module.exports = {
44
parser: 'babel-eslint',
55
extends: ['eslint:recommended', 'plugin:react/recommended', config.eslint],
6+
env: {
7+
es6: true,
8+
},
9+
settings: {
10+
react: {
11+
version: 'detect',
12+
},
13+
},
614
}

.storybook/config.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,22 @@ import { CssResetWrapper } from './css-reset-decorator'
55

66
import 'typeface-roboto'
77

8+
const includeTesting = 'STORYBOOK_INCLUDE_TESTING' in process.env
9+
810
addDecorator(jsxDecorator)
911
addDecorator(withPropsTable)
1012
addDecorator(CssResetWrapper)
1113

1214
function loadStories() {
13-
const req = require.context('../stories', true, /\.stories\.js$/)
15+
const req = require.context('../stories', true, /\.stories\.js/)
16+
req.keys().forEach(filename => req(filename))
17+
}
18+
19+
function loadStoriesInclTesting() {
20+
loadStories()
21+
22+
const req = require.context('../stories', true, /\.stories\.testing\.js/)
1423
req.keys().forEach(filename => req(filename))
1524
}
1625

17-
configure(loadStories, module)
26+
configure(includeTesting ? loadStoriesInclTesting : loadStories, module)

.storybook/formDecorator.js

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import React from 'react'
2+
import propTypes from '@dhis2/prop-types'
3+
import { Button } from '@dhis2/ui-core'
4+
5+
import { Form, FormSpy } from '../src'
6+
7+
const formProps = {
8+
onSubmit: values => {
9+
console.log(
10+
'++++++++++++++++\n',
11+
'Form was submitted with values:\n',
12+
values,
13+
'\n----------------'
14+
)
15+
},
16+
mutators: {},
17+
}
18+
19+
class FormWithSpyAndSubmit extends React.Component {
20+
state = {
21+
cypressProps: {},
22+
}
23+
24+
componentDidMount() {
25+
window.updateCypressProps = this.updateCypressProps
26+
window.clearCypressProps = this.clearCypressProps
27+
}
28+
29+
componentWillUnmount() {
30+
delete window.updateCypressProps
31+
delete window.clearCypressProps
32+
}
33+
34+
updateCypressProps = updateObj => {
35+
const cypressProps = {
36+
...this.state.cypressProps,
37+
...updateObj,
38+
}
39+
this.setState({ cypressProps })
40+
}
41+
42+
clearCypressProps = () => {
43+
this.setState({ cypressProps: {} })
44+
}
45+
46+
render() {
47+
return (
48+
<Form {...formProps}>
49+
{formRenderProps => (
50+
<form onSubmit={formRenderProps.handleSubmit}>
51+
{this.props.renderChildren({
52+
formRenderProps,
53+
cypressProps: this.state.cypressProps,
54+
})}
55+
56+
<Button primary type="submit">
57+
Submit
58+
</Button>
59+
60+
{/* render after components to ensure capturing "initialValue"s */}
61+
<FormSpy>
62+
{({ values }) => {
63+
window.formValues = values
64+
return <span className="form-spy-internal" />
65+
}}
66+
</FormSpy>
67+
</form>
68+
)}
69+
</Form>
70+
)
71+
}
72+
}
73+
74+
FormWithSpyAndSubmit.propTypes = {
75+
renderChildren: propTypes.func.isRequired,
76+
}
77+
78+
export const formDecorator = fn => <FormWithSpyAndSubmit renderChildren={fn} />

README.md

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,6 @@
55
**[Online docs and demos (latest master
66
build)](https://ui-forms.dhis2.nu)**
77

8-
## Known issues
9-
10-
#### ui-core
11-
12-
Currently ui-forms relies on some components that are not available yet in the published version of ui-core. So builds are failing and to get things to work locally you have to build ui-core locally:
13-
14-
```bash
15-
cd node_modules/@dhis2/ui-core
16-
yarn install && yarn build
17-
```
18-
19-
#### prop-types
20-
21-
Currently some of the custom prop-type validations (i.e. `FileList` prop `children`) are throwing errors they shouldn't be. This issue cannot be reproduced in ui-core, and needs to be investigated further.
22-
238
## Building a form
249

2510
This library offers a `<Form />` component with the same api as react-final-form's Form api.

cypress.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"testFiles": "**/*.feature",
3+
"video": false,
4+
"projectId": "konyyu"
5+
}

cypress/.eslintrc.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module.exports = {
2+
env: { es6: true },
3+
globals: {
4+
Cypress: 'readonly',
5+
cy: 'readonly',
6+
},
7+
}

cypress/fixtures/.gitkeep

Whitespace-only changes.

cypress/fixtures/FileInput/file.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
foo bar baz

cypress/fixtures/FileInput/file.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Foo bar baz
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
Feature: The Checkbox can toggle a boolean
2+
3+
Scenario: The user checks the Checkbox
4+
Given an unchecked Checkbox without value is rendered
5+
When the user clicks on the Checkbox
6+
Then the form value that corresponds to the checkbox will be true
7+
8+
Scenario: The user unchecks the Checkbox
9+
Given a checked Checkbox without value is rendered
10+
When the user clicks on the Checkbox
11+
Then the form value that corresponds to the checkbox will be false

0 commit comments

Comments
 (0)