Skip to content

Commit

Permalink
Merge pull request #29 from grommet/formfield-name
Browse files Browse the repository at this point in the history
Add `formfield-name`
  • Loading branch information
taysea authored Nov 14, 2021
2 parents a5d908d + bdf7d2e commit 7f346eb
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 0 deletions.
35 changes: 35 additions & 0 deletions docs/rules/formfield-name.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Rule to enforce name on FormField and its child input (formfield-name)

FormField and its child input require a matching `name` prop to ensure that data is included on form submission.

Note from [W3Schools](https://www.w3schools.com/tags/att_input_name.asp): Only form elements with a name attribute will have their values passed when submitting a form.

## Rule Details

This rule aims to ensure that a matching `name` is applied to both a FormField and its child input.

Examples of **incorrect** code for this rule:

```js
<Form>
<FormField label="Test Text Input">
<TextInput name="testinput" />
</FormField>
<FormField label="Another Test Text Input" name="testinput-2">
<TextInput name="abc" />
</FormField>
</Form>
```

Examples of **correct** code for this rule:

```js
<Form>
<FormField label="Test Text Input" name="testinput">
<TextInput name="testinput" />
</FormField>
<FormField label="Another Test Text Input" name="testinput-2">
<TextInput name="testinput-2" />
</FormField>
</Form>
```
1 change: 1 addition & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ module.exports.configs = {
'grommet/datatable-aria-describedby': 'error',
'grommet/datatable-groupby-onmore': 'error',
'grommet/formfield-htmlfor-id': 'error',
'grommet/formfield-name': 'error',
'grommet/formfield-prefer-children': 'error',
'grommet/image-alt-text': 'error',
'grommet/spinner-message': 'error',
Expand Down
72 changes: 72 additions & 0 deletions lib/rules/formfield-name.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/**
* @fileoverview Rule to enforce name on FormField and its child input
* @author Taylor Seamans
*/
'use strict';

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

module.exports = {
meta: {
docs: {
description: 'Rule to enforce name on FormField and its child input',
category: 'Best Practices',
recommended: true,
},
fixable: null, // or "code" or "whitespace"
messages: {
'formfield-name':
'FormField requires `name` prop that matches `name` prop on its child input. Only form elements with a name attribute will have their values passed when submitting a form.',
},
},

create: function (context) {
// variables should be defined here

//----------------------------------------------------------------------
// Helpers
//----------------------------------------------------------------------

// any helper functions should go here or else delete this section

//----------------------------------------------------------------------
// Public
//----------------------------------------------------------------------

return {
JSXElement(node) {
if (node.openingElement.name.name === 'FormField') {
let matchingName;

node.children.forEach((child) => {
node?.openingElement?.attributes?.forEach((attribute) => {
if (attribute?.name?.name === 'name') {
if (
child.type === 'JSXElement' &&
child.openingElement.attributes
) {
child.openingElement.attributes.forEach((childAttribute) => {
if (
childAttribute?.name?.name === 'name' &&
childAttribute?.value?.value === attribute?.value?.value
) {
matchingName = true;
}
});
}
}
});
});

if (!matchingName)
context.report({
node: node,
messageId: 'formfield-name',
});
}
},
};
},
};
52 changes: 52 additions & 0 deletions tests/lib/rules/formfield-name.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* @fileoverview Rule to enforce name on FormField and its child input
* @author Taylor Seamans
*/
'use strict';

//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------

var rule = require('../../../lib/rules/formfield-name'),
RuleTester = require('eslint').RuleTester;

//------------------------------------------------------------------------------
// Tests
//------------------------------------------------------------------------------

var ruleTester = new RuleTester({
parserOptions: { ecmaFeatures: { jsx: true } },
});
ruleTester.run('formfield-name', rule, {
valid: [
'<FormField label="Test Text Input" name="testinput"><TextInput name="testinput" /></FormField>',
],

invalid: [
{
code: '<FormField label="Label"><TextInput /></FormField>',
errors: [
{
messageId: 'formfield-name',
},
],
},
{
code: '<FormField label="Label" name="test-input"><TextInput /></FormField>',
errors: [
{
messageId: 'formfield-name',
},
],
},
{
code: '<FormField label="Label" name="test-input"><TextInput name="abc" /></FormField>',
errors: [
{
messageId: 'formfield-name',
},
],
},
],
});

0 comments on commit 7f346eb

Please sign in to comment.