Repository: yannickcr/eslint-plugin-react
Pull request #1177 (2017-05-07 13:20:06)

Enable curly spacing check for children
This is a feature discussed in #857.

### TODO:
- [x] move all the bugfixes to separate branches
- [x] merge the master after the fixes are merged
- [x] add more tests for attributes and children
- [x] add more tests for config inheritance
- [x] restore the old config behavior alongside the new one
- [x] update the README

fatfisz: I think I'll add a few tests that have both attributes and children set to check that the defaults are being properly set.
fatfisz: I mistakenly removed the branch -.-
ljharb: Seems like with #1179 and #1180 merged, this needs a rebase?
fatfisz: Sure.
ljharb: @fatfisz please rebase on the command line so there's no merge commits
fatfisz: Rebased.

Just curious, why do you want to avoid merge commits? It's less time-consuming to solve the conflicts once; also the history is being lost.
fatfisz: I've added back the old tests (avoiding duplication) and restored the old config behavior. Should I leave any comments about what is from where?
ljharb: Git logs aren't history, they're change logs - nobody ever needs to know how many times you merged master. Also, merge conflict resolutions in a rebase are preserved for future cherry pickers; conflicts resolved in a merge potentially force developers to re-resolve the same conflicts. It also generally takes precisely the same amount of time to solve a conflict in a merge as it does in a rebase.
fatfisz: I was asking because in my experience it takes much longer to do a rebase, especially when there are many commits already. E.g. yesterday merge took < 5 mins, but the rebase took over half an hour. But the argument about cherry-picking speaks to me.

Just for the future reference - would it be ok to squash the commits next time while rebasing?
ljharb: Commits should ideally be atomic and thus each represent a conceptual change. Naive squashing is fine, but it can cause two changes to be combined where they should be separate.
fatfisz: Sorry, forgot about updating the docs. Will do that around tomorrow, I'm pumped out after work today.
fatfisz: Took a bit more time, but here it is.
fatfisz: Would it be possible for some other collaborators to review this?
fatfisz: It seems that resolving conflicts through GitHub results in a merge. Will rebase instead.

Patch:
diff --git a/README.md b/README.md
index 0e017e3f..bf7bcd08 100644
--- a/README.md
+++ b/README.md
@@ -123,7 +123,7 @@ Finally, enable all of the rules that you would like to use.  Use [our preset](#
 * [react/jsx-boolean-value](docs/rules/jsx-boolean-value.md): Enforce boolean attributes notation in JSX (fixable)
 * [react/jsx-closing-bracket-location](docs/rules/jsx-closing-bracket-location.md): Validate closing bracket location in JSX (fixable)
 * [react/jsx-closing-tag-location](docs/rules/jsx-closing-tag-location.md): Validate closing tag location in JSX (fixable)
-* [react/jsx-curly-spacing](docs/rules/jsx-curly-spacing.md): Enforce or disallow spaces inside of curly braces in JSX attributes (fixable)
+* [react/jsx-curly-spacing](docs/rules/jsx-curly-spacing.md): Enforce or disallow spaces inside of curly braces in JSX attributes and expressions (fixable)
 * [react/jsx-equals-spacing](docs/rules/jsx-equals-spacing.md): Enforce or disallow spaces around equal signs in JSX attributes (fixable)
 * [react/jsx-filename-extension](docs/rules/jsx-filename-extension.md): Restrict file extensions that may contain JSX
 * [react/jsx-first-prop-new-line](docs/rules/jsx-first-prop-new-line.md): Enforce position of the first prop in JSX (fixable)
diff --git a/docs/rules/jsx-curly-spacing.md b/docs/rules/jsx-curly-spacing.md
index 471f276e..47c27c0c 100644
--- a/docs/rules/jsx-curly-spacing.md
+++ b/docs/rules/jsx-curly-spacing.md
@@ -1,4 +1,4 @@
-# Enforce or disallow spaces inside of curly braces in JSX attributes. (react/jsx-curly-spacing)
+# Enforce or disallow spaces inside of curly braces in JSX attributes and expressions. (react/jsx-curly-spacing)
 
 While formatting preferences are very personal, a number of style guides require or disallow spaces between curly braces.
 
@@ -6,31 +6,55 @@ While formatting preferences are very personal, a number of style guides require
 
 ## Rule Details
 
-This rule aims to maintain consistency around the spacing inside of JSX attributes.
+This rule aims to maintain consistency around the spacing inside of JSX attributes and expressions inside element children.
 
 It either requires or disallows spaces between those braces and the values inside of them.
 
-### Options
+## Rule Options
 
 There are two main options for the rule:
 
-* `"always"` enforces a space inside of curly braces
-* `"never"` disallows spaces inside of curly braces (default)
+* `{"when": "always"}` enforces a space inside of curly braces
+* `{"when": "never"}` disallows spaces inside of curly braces (default)
 
-Depending on your coding conventions, you can choose either option by specifying it in your configuration:
+There are also two properties that allow specifying how the rule should work with the attributes (`attributes`) and the expressions (`children`). The possible values are:
 
-```json
-"react/jsx-curly-spacing": [2, "always"]
+* `true` enables checking for the spacing using the options (default for `attributes`), e.g. `{"attributes": false}` disables checking the attributes
+* `false` disables checking for the spacing (default for `children`, for backward compatibility), e.g. `{"children": true}` enables checking the expressions
+* an object containing options that override the global options, e.g. `{"when": "always", "children": {"when": "never"}}` enforces a space inside attributes, but disallows spaces inside expressions
+
+### never
+
+When `{"when": "never"}` is set, the following patterns are considered warnings:
+
+```jsx
+<Hello name={ firstname } />;
+<Hello name={ firstname} />;
+<Hello name={firstname } />;
 ```
 
-#### never
+The following patterns are not warnings:
+
+```jsx
+<Hello name={firstname} />;
+<Hello name={{ firstname: 'John', lastname: 'Doe' }} />;
+<Hello name={
+  firstname
+} />;
+<Hello>{firstname}</Hello>;
+<Hello>{ firstname }</Hello>;
+<Hello>{
+  firstname
+}</Hello>;
+```
 
-When `"never"` is set, the following patterns are considered warnings:
+When `{"when": "never", "children": true}` is set, the following patterns are considered warnings:
 
 ```jsx
 <Hello name={ firstname } />;
 <Hello name={ firstname} />;
 <Hello name={firstname } />;
+<Hello>{ firstname }</Hello>;
 ```
 
 The following patterns are not warnings:
@@ -41,11 +65,15 @@ The following patterns are not warnings:
 <Hello name={
   firstname
 } />;
+<Hello>{firstname}</Hello>;
+<Hello>{
+  firstname
+}</Hello>;
 ```
 
-#### always
+### always
 
-When `"always"` is used, the following patterns are considered warnings:
+When `{"when": "always"}` is set, the following patterns are considered warnings:
 
 ```jsx
 <Hello name={firstname} />;
@@ -61,14 +89,42 @@ The following patterns are not warnings:
 <Hello name={
   firstname
 } />;
+<Hello>{ firstname }</Hello>;
+<Hello>{firstname}</Hello>;
+<Hello>{
+  firstname
+}</Hello>;
+```
+
+When `{"when": "always", "children": true}` is set, the following patterns are considered warnings:
+
+```jsx
+<Hello name={firstname} />;
+<Hello name={ firstname} />;
+<Hello name={firstname } />;
+<Hello>{firstname}</Hello>;
+```
+
+The following patterns are not warnings:
+
+```jsx
+<Hello name={ firstname } />;
+<Hello name={ {firstname: 'John', lastname: 'Doe'} } />;
+<Hello name={
+  firstname
+} />;
+<Hello>{ firstname }</Hello>;
+<Hello>{
+  firstname
+}</Hello>;
 ```
 
-#### Braces spanning multiple lines
+### Braces spanning multiple lines
 
 By default, braces spanning multiple lines are allowed with either setting. If you want to disallow them you can specify an additional `allowMultiline` property with the value `false`:
 
 ```json
-"react/jsx-curly-spacing": [2, "never", {"allowMultiline": false}]
+"react/jsx-curly-spacing": [2, {"when": "never", "allowMultiline": false}]
 ```
 
 When `"never"` is used and `allowMultiline` is `false`, the following patterns are considered warnings:
@@ -87,6 +143,11 @@ The following patterns are not warnings:
 ```jsx
 <Hello name={firstname} />;
 <Hello name={{ firstname: 'John', lastname: 'Doe' }} />;
+<Hello>{firstname}</Hello>;
+<Hello>{ firstname }</Hello>;
+<Hello>{
+  firstname
+}</Hello>;
 ```
 
 When `"always"` is used and `allowMultiline` is `false`, the following patterns are considered warnings:
@@ -105,14 +166,39 @@ The following patterns are not warnings:
 ```jsx
 <Hello name={ firstname } />;
 <Hello name={ {firstname: 'John', lastname: 'Doe'} } />;
+<Hello>{firstname}</Hello>;
+<Hello>{ firstname }</Hello>;
+<Hello>{
+  firstname
+}</Hello>;
+```
+
+When `{"when": "never", "attributes": {"allowMultiline": false}, "children": true}` is set, the following patterns are considered warnings:
+
+```jsx
+<Hello name={ firstname } />;
+<Hello name={
+  firstname
+} />;
+<Hello>{ firstname }</Hello>;
 ```
 
-#### Granular spacing controls
+The following patterns are not warnings:
+
+```jsx
+<Hello name={firstname} />;
+<Hello>{firstname}</Hello>;
+<Hello>{
+  firstname
+}</Hello>;
+```
+
+### Granular spacing controls
 
 You can specify an additional `spacing` property that is an object with the following possible values:
 
 ```json
-"react/jsx-curly-spacing": [2, "always", {"spacing": {
+"react/jsx-curly-spacing": [2, {"when": "always", "spacing": {
   "objectLiterals": "never"
 }}]
 ```
@@ -135,6 +221,41 @@ When `"never"` is used and `objectLiterals` is `"always"`, the following pattern
 
 Please note that spacing of the object literal curly braces themselves is controlled by the built-in [`object-curly-spacing`](http://eslint.org/docs/rules/object-curly-spacing) rule.
 
+### Shorthand options
+
+To preserve backward compatibility, two additional options are supported:
+
+```json
+"react/jsx-curly-spacing": [2, "always"]
+```
+
+which is a shorthand for
+
+```json
+"react/jsx-curly-spacing": [2, {"when": "always"}]
+```
+
+and
+
+```json
+"react/jsx-curly-spacing": [2, "never"]
+```
+
+which is a shorthand for
+
+```json
+"react/jsx-curly-spacing": [2, {"when": "never"}]
+```
+
+When using the shorthand options, only attributes will be checked. To specify other options, use another argument:
+
+```json
+"react/jsx-curly-spacing": [2, "never", {
+  "allowMultiline": false,
+  "spacing": {"objectLiterals": "always"}
+}]
+```
+
 ## When Not To Use It
 
-You can turn this rule off if you are not concerned with the consistency around the spacing inside of JSX attributes.
+You can turn this rule off if you are not concerned with the consistency around the spacing inside of JSX attributes or expressions.
diff --git a/lib/rules/jsx-curly-spacing.js b/lib/rules/jsx-curly-spacing.js
index 90563798..3e161e57 100644
--- a/lib/rules/jsx-curly-spacing.js
+++ b/lib/rules/jsx-curly-spacing.js
@@ -32,7 +32,52 @@ module.exports = {
     fixable: 'code',
 
     schema: [{
-      enum: SPACING_VALUES
+      definitions: {
+        basicConfig: {
+          type: 'object',
+          properties: {
+            when: {
+              enum: SPACING_VALUES
+            },
+            allowMultiline: {
+              type: 'boolean'
+            },
+            spacing: {
+              type: 'object',
+              properties: {
+                objectLiterals: {
+                  enum: SPACING_VALUES
+                }
+              }
+            }
+          }
+        },
+        basicConfigOrBoolean: {
+          oneOf: [{
+            $ref: '#/definitions/basicConfig'
+          }, {
+            type: 'boolean'
+          }]
+        }
+      },
+
+      oneOf: [{
+        allOf: [{
+          $ref: '#/definitions/basicConfig'
+        }, {
+          type: 'object',
+          properties: {
+            attributes: {
+              $ref: '#/definitions/basicConfigOrBoolean'
+            },
+            children: {
+              $ref: '#/definitions/basicConfigOrBoolean'
+            }
+          }
+        }]
+      }, {
+        enum: SPACING_VALUES
+      }]
     }, {
       type: 'object',
       properties: {
@@ -54,15 +99,42 @@ module.exports = {
 
   create: function(context) {
 
-    var DEFAULT_SPACING = SPACING.never;
+    function normalizeConfig(configOrTrue, defaults, lastPass) {
+      var config = configOrTrue === true ? {} : configOrTrue;
+      var when = config.when || defaults.when;
+      var allowMultiline = has(config, 'allowMultiline') ? config.allowMultiline : defaults.allowMultiline;
+      var spacing = config.spacing || {};
+      var objectLiteralSpaces = spacing.objectLiterals || defaults.objectLiteralSpaces;
+      if (lastPass) {
+        // On the final pass assign the values that should be derived from others if they are still undefined
+        objectLiteralSpaces = objectLiteralSpaces || when;
+      }
+
+      return {
+        when,
+        allowMultiline,
+        objectLiteralSpaces
+      };
+    }
+
+    var DEFAULT_WHEN = SPACING.never;
     var DEFAULT_ALLOW_MULTILINE = true;
+    var DEFAULT_ATTRIBUTES = true;
+    var DEFAULT_CHILDREN = false;
 
     var sourceCode = context.getSourceCode();
-    var baseSpacing = context.options[0] || DEFAULT_SPACING;
-    var config = context.options[1] || {};
-    var multiline = has(config, 'allowMultiline') ? config.allowMultiline : DEFAULT_ALLOW_MULTILINE;
-    var spacingConfig = config.spacing || {};
-    var objectLiteralSpacing = spacingConfig.objectLiterals || baseSpacing;
+    var originalConfig = context.options[0] || {};
+    if (SPACING_VALUES.indexOf(originalConfig) !== -1) {
+      originalConfig = Object.assign({when: context.options[0]}, context.options[1]);
+    }
+    var defaultConfig = normalizeConfig(originalConfig, {
+      when: DEFAULT_WHEN,
+      allowMultiline: DEFAULT_ALLOW_MULTILINE
+    });
+    var attributes = has(originalConfig, 'attributes') ? originalConfig.attributes : DEFAULT_ATTRIBUTES;
+    var attributesConfig = attributes ? normalizeConfig(attributes, defaultConfig, true) : null;
+    var children = has(originalConfig, 'children') ? originalConfig.children : DEFAULT_CHILDREN;
+    var childrenConfig = children ? normalizeConfig(children, defaultConfig, true) : null;
 
     // --------------------------------------------------------------------------
     // Helpers
@@ -196,10 +268,24 @@ module.exports = {
      * @returns {void}
      */
     function validateBraceSpacing(node) {
-      // Only validate attributes
-      if (node.parent.type === 'JSXElement') {
+      var config;
+      switch (node.parent.type) {
+        case 'JSXAttribute':
+        case 'JSXOpeningElement':
+          config = attributesConfig;
+          break;
+
+        case 'JSXElement':
+          config = childrenConfig;
+          break;
+
+        default:
+          return;
+      }
+      if (config === null) {
         return;
       }
+
       var first = context.getFirstToken(node);
       var last = sourceCode.getLastToken(node);
       var second = context.getTokenAfter(first, {includeComments: true});
@@ -217,28 +303,28 @@ module.exports = {
       }
 
       var isObjectLiteral = first.value === second.value;
-      var spacing = isObjectLiteral ? objectLiteralSpacing : baseSpacing;
+      var spacing = isObjectLiteral ? config.objectLiteralSpaces : config.when;
       if (spacing === SPACING.always) {
         if (!sourceCode.isSpaceBetweenTokens(first, second)) {
           reportRequiredBeginningSpace(node, first);
-        } else if (!multiline && isMultiline(first, second)) {
+        } else if (!config.allowMultiline && isMultiline(first, second)) {
           reportNoBeginningNewline(node, first, spacing);
         }
         if (!sourceCode.isSpaceBetweenTokens(penultimate, last)) {
           reportRequiredEndingSpace(node, last);
-        } else if (!multiline && isMultiline(penultimate, last)) {
+        } else if (!config.allowMultiline && isMultiline(penultimate, last)) {
           reportNoEndingNewline(node, last, spacing);
         }
       } else if (spacing === SPACING.never) {
         if (isMultiline(first, second)) {
-          if (!multiline) {
+          if (!config.allowMultiline) {
             reportNoBeginningNewline(node, first, spacing);
           }
         } else if (sourceCode.isSpaceBetweenTokens(first, second)) {
           reportNoBeginningSpace(node, first);
         }
         if (isMultiline(penultimate, last)) {
-          if (!multiline) {
+          if (!config.allowMultiline) {
             reportNoEndingNewline(node, last, spacing);
           }
         } else if (sourceCode.isSpaceBetweenTokens(penultimate, last)) {


Test patch:
diff --git a/tests/lib/rules/jsx-curly-spacing.js b/tests/lib/rules/jsx-curly-spacing.js
index cebe4eee..a5da5215 100644
--- a/tests/lib/rules/jsx-curly-spacing.js
+++ b/tests/lib/rules/jsx-curly-spacing.js
@@ -28,170 +28,1676 @@ var ruleTester = new RuleTester({parserOptions});
 ruleTester.run('jsx-curly-spacing', rule, {
   valid: [{
     code: '<App foo={bar} />;'
+  }, {
+    code: '<App foo={bar}>{bar}</App>;'
+  }, {
+    code: '<App foo={bar}>{ bar }</App>;'
+  }, {
+    code: [
+      '<App foo={',
+      'bar',
+      '}>',
+      '{bar}',
+      '</App>;'
+    ].join('\n')
+  }, {
+    code: '<App foo={{ bar: true, baz: true }}>{{ bar: true, baz: true }}</App>;'
+  }, {
+    code: '<App foo={{ bar: true, baz: true }}>{ { bar: true, baz: true } }</App>;'
   }, {
     code: [
       '<App foo={',
       '{ bar: true, baz: true }',
       '} />;'
     ].join('\n')
+  }, {
+    code: [
+      '<App foo={',
+      '{ bar: true, baz: true }',
+      '}>',
+      '{{ bar: true, baz: true }}',
+      '</App>;'
+    ].join('\n')
+  }, {
+    code: '<App>{ foo /* comment */ }</App>'
+  }, {
+    code: '<App>{ /* comment */ foo }</App>'
   }, {
     code: '<App foo={bar} />;',
-    options: ['never']
+    options: [{attributes: true}]
+  }, {
+    code: [
+      '<App foo={',
+      'bar',
+      '} />;'
+    ].join('\n'),
+    options: [{attributes: true}]
+  }, {
+    code: '<App foo={{ bar: true, baz: true }} />;',
+    options: [{attributes: true}]
   }, {
     code: [
       '<App foo={',
       '{ bar: true, baz: true }',
       '} />;'
     ].join('\n'),
-    options: ['never', {spacing: {objectLiterals: 'never'}}]
+    options: [{attributes: true}]
+  }, {
+    code: '<App foo={bar} />;',
+    options: [{attributes: false}]
+  }, {
+    code: [
+      '<App foo={',
+      'bar',
+      '} />;'
+    ].join('\n'),
+    options: [{attributes: false}]
+  }, {
+    code: '<App foo={{ bar: true, baz: true }} />;',
+    options: [{attributes: false}]
+  }, {
+    code: [
+      '<App foo={',
+      '{ bar: true, baz: true }',
+      '} />;'
+    ].join('\n'),
+    options: [{attributes: false}]
   }, {
     code: '<App foo={ bar } />;',
-    options: ['always']
+    options: [{attributes: false}]
+  }, {
+    code: '<App foo={ { bar: true, baz: true } } />;',
+    options: [{attributes: false}]
+  }, {
+    code: '<App>{bar}</App>;',
+    options: [{children: true}]
+  }, {
+    code: [
+      '<App>{',
+      'bar',
+      '}</App>;'
+    ].join('\n'),
+    options: [{children: true}]
+  }, {
+    code: '<App>{{ bar: true, baz: true }}</App>;',
+    options: [{children: true}]
+  }, {
+    code: [
+      '<App>{',
+      '{ bar: true, baz: true }',
+      '}</App>;'
+    ].join('\n'),
+    options: [{children: true}]
+  }, {
+    code: '<App>{bar}</App>;',
+    options: [{children: false}]
+  }, {
+    code: [
+      '<App>{',
+      'bar',
+      '}</App>;'
+    ].join('\n'),
+    options: [{children: false}]
+  }, {
+    code: '<App>{{ bar: true, baz: true }}</App>;',
+    options: [{children: false}]
+  }, {
+    code: [
+      '<App>{',
+      '{ bar: true, baz: true }',
+      '}</App>;'
+    ].join('\n'),
+    options: [{children: false}]
+  }, {
+    code: '<App>{ bar }</App>;',
+    options: [{children: false}]
+  }, {
+    code: '<App>{ { bar: true, baz: true } }</App>;',
+    options: [{children: false}]
+  }, {
+    code: '<App foo={bar} />;',
+    options: [{when: 'never'}]
+  }, {
+    code: '<App foo={bar} />;',
+    options: [{when: 'never', allowMultiline: false}]
+  }, {
+    code: '<App foo={bar} />;',
+    options: [{when: 'never', allowMultiline: true}]
+  }, {
+    code: [
+      '<App foo={',
+      'bar',
+      '} />;'
+    ].join('\n'),
+    options: [{when: 'never', allowMultiline: true}]
+  }, {
+    code: '<App foo={{ bar: true, baz: true }} />;',
+    options: [{when: 'never', spacing: {objectLiterals: 'never'}}]
+  }, {
+    code: [
+      '<App foo={',
+      '{ bar: true, baz: true }',
+      '} />;'
+    ].join('\n'),
+    options: [{when: 'never', spacing: {objectLiterals: 'never'}}]
   }, {
     code: '<App foo={ bar } />;',
-    options: ['always', {allowMultiline: false}]
+    options: [{when: 'always'}]
+  }, {
+    code: '<App foo={ bar } />;',
+    options: [{when: 'always', allowMultiline: false}]
+  }, {
+    code: '<App foo={ bar } />;',
+    options: [{when: 'always', allowMultiline: true}]
+  }, {
+    code: [
+      '<App foo={',
+      'bar',
+      '} />;'
+    ].join('\n'),
+    options: [{when: 'always', allowMultiline: true}]
+  }, {
+    code: '<App foo={{ bar: true, baz: true }} />;',
+    options: [{when: 'always', spacing: {objectLiterals: 'never'}}]
+  }, {
+    code: [
+      '<App foo={',
+      '{ bar: true, baz: true }',
+      '} />;'
+    ].join('\n'),
+    options: [{when: 'always', spacing: {objectLiterals: 'never'}}]
+  }, {
+    code: '<App foo={bar} />;',
+    options: [{attributes: {when: 'never'}}]
+  }, {
+    code: '<App foo={ bar } />;',
+    options: [{attributes: {when: 'always'}}]
+  }, {
+    code: '<App foo={ bar } />;',
+    options: [{attributes: {when: 'always', allowMultiline: false}}]
   }, {
     code: '<App foo={{ bar:baz }} />;',
-    options: ['never']
+    options: [{attributes: {when: 'never'}}]
   }, {
     code: [
       '<App foo={',
       '{ bar: true, baz: true }',
       '} />;'
     ].join('\n'),
-    options: ['never']
+    options: [{attributes: {when: 'never'}}]
   }, {
     code: '<App foo={ {bar:baz} } />;',
-    options: ['always']
+    options: [{attributes: {when: 'always'}}]
   }, {
     code: [
       '<App foo={',
       '{ bar: true, baz: true }',
       '} />;'
     ].join('\n'),
-    options: ['always']
+    options: [{attributes: {when: 'always'}}]
   }, {
     code: [
       '<App foo={',
       'bar',
       '} />;'
     ].join('\n'),
-    options: ['always']
+    options: [{attributes: {when: 'always'}}]
   }, {
     code: [
       '<App foo={',
       'bar',
       '} />;'
     ].join('\n'),
-    options: ['never']
+    options: [{attributes: {when: 'always', allowMultiline: true}}]
+  }, {
+    code: [
+      '<App foo={',
+      'bar',
+      '} />;'
+    ].join('\n'),
+    options: [{attributes: {when: 'never'}}]
+  }, {
+    code: [
+      '<App foo={',
+      'bar',
+      '} />;'
+    ].join('\n'),
+    options: [{attributes: {when: 'never', allowMultiline: true}}]
+  }, {
+    code: '<App foo={bar/* comment */} />;',
+    options: [{attributes: {when: 'never'}}]
+  }, {
+    code: '<App foo={ bar } />;',
+    options: [{attributes: {when: 'always', spacing: {}}}]
+  }, {
+    code: [
+      '<App foo={',
+      'bar',
+      '} />;'
+    ].join('\n'),
+    options: [{attributes: {when: 'always', spacing: {}}}]
+  }, {
+    code: '<App foo={{ bar: true, baz: true }} />;',
+    options: [{attributes: {when: 'always', spacing: {objectLiterals: 'never'}}}]
+  }, {
+    code: [
+      '<App foo={',
+      '{ bar: true, baz: true }',
+      '} />;'
+    ].join('\n'),
+    options: [{attributes: {when: 'always', spacing: {objectLiterals: 'never'}}}]
+  }, {
+    code: '<App>{bar}</App>;',
+    options: [{children: {when: 'never'}}]
+  }, {
+    code: '<App>{ bar }</App>;',
+    options: [{children: {when: 'always'}}]
+  }, {
+    code: '<App>{ bar }</App>;',
+    options: [{children: {when: 'always', allowMultiline: false}}]
+  }, {
+    code: '<App>{{ bar:baz }}</App>;',
+    options: [{children: {when: 'never'}}]
+  }, {
+    code: [
+      '<App>{',
+      '{ bar: true, baz: true }',
+      '}</App>;'
+    ].join('\n'),
+    options: [{children: {when: 'never'}}]
+  }, {
+    code: '<App>{ {bar:baz} }</App>;',
+    options: [{children: {when: 'always'}}]
+  }, {
+    code: [
+      '<App>{',
+      '{ bar: true, baz: true }',
+      '}</App>;'
+    ].join('\n'),
+    options: [{children: {when: 'always'}}]
+  }, {
+    code: [
+      '<App>{',
+      'bar',
+      '}</App>;'
+    ].join('\n'),
+    options: [{children: {when: 'always'}}]
+  }, {
+    code: [
+      '<App>{',
+      'bar',
+      '}</App>;'
+    ].join('\n'),
+    options: [{children: {when: 'always', allowMultiline: true}}]
+  }, {
+    code: [
+      '<App>{',
+      'bar',
+      '}</App>;'
+    ].join('\n'),
+    options: [{children: {when: 'never'}}]
+  }, {
+    code: [
+      '<App>{',
+      'bar',
+      '}</App>;'
+    ].join('\n'),
+    options: [{children: {when: 'never', allowMultiline: true}}]
+  }, {
+    code: [
+      '<App>{/* comment */}</App>;'
+    ].join('\n'),
+    options: [{children: {when: 'never'}}]
+  }, {
+    code: '<App>{bar/* comment */}</App>;',
+    options: [{children: {when: 'never'}}]
+  }, {
+    code: '<App>{ bar }</App>;',
+    options: [{children: {when: 'always', spacing: {}}}]
+  }, {
+    code: [
+      '<App>{',
+      'bar',
+      '}</App>;'
+    ].join('\n'),
+    options: [{children: {when: 'always', spacing: {}}}]
+  }, {
+    code: '<App>{{ bar: true, baz: true }}</App>;',
+    options: [{children: {when: 'always', spacing: {objectLiterals: 'never'}}}]
+  }, {
+    code: [
+      '<App>{',
+      '{ bar: true, baz: true }',
+      '}</App>;'
+    ].join('\n'),
+    options: [{children: {when: 'always', spacing: {objectLiterals: 'never'}}}]
+  }, {
+    code: '<App {...bar} />;'
+  }, {
+    code: '<App {...bar} />;',
+    options: [{attributes: {when: 'never'}}]
+  }, {
+    code: '<App { ...bar } />;',
+    options: [{attributes: {when: 'always'}}]
+  }, {
+    code: '<App { ...bar } />;',
+    options: [{attributes: {when: 'always', allowMultiline: false}}]
+  }, {
+    code: [
+      '<App {',
+      '...bar',
+      '} />;'
+    ].join('\n'),
+    options: [{attributes: {when: 'always'}}]
+  }, {
+    code: [
+      '<App {',
+      '...bar',
+      '} />;'
+    ].join('\n'),
+    options: [{attributes: {when: 'always', allowMultiline: true}}]
+  }, {
+    code: [
+      '<App {',
+      '...bar',
+      '} />;'
+    ].join('\n'),
+    options: [{attributes: {when: 'never'}}]
+  }, {
+    code: [
+      '<App {',
+      '...bar',
+      '} />;'
+    ].join('\n'),
+    options: [{attributes: {when: 'never', allowMultiline: true}}]
+  }, {
+    code: '<App {...bar/* comment */} />;',
+    options: [{attributes: {when: 'never'}}]
+  }, {
+    code: '<App foo={bar} {...baz} />;'
+  }, {
+    code: '<App foo={bar} {...baz} />;',
+    options: [{attributes: {when: 'never'}}]
+  }, {
+    code: '<App foo={ bar } { ...baz } />;',
+    options: [{attributes: {when: 'always'}}]
+  }, {
+    code: '<App foo={ bar } { ...baz } />;',
+    options: [{attributes: {when: 'always', allowMultiline: false}}]
+  }, {
+    code: '<App foo={{ bar:baz }} {...baz} />;',
+    options: [{attributes: {when: 'never'}}]
+  }, {
+    code: '<App foo={ {bar:baz} } { ...baz } />;',
+    options: [{attributes: {when: 'always'}}]
+  }, {
+    code: [
+      '<App foo={',
+      'bar',
+      '} {',
+      '...bar',
+      '} />;'
+    ].join('\n'),
+    options: [{attributes: {when: 'always'}}]
+  }, {
+    code: '<App foo={bar/* comment */} {...baz/* comment */} />;',
+    options: [{attributes: {when: 'never'}}]
+  }, {
+    code: '<App foo={3} bar={ {a: 2} } />',
+    options: [{attributes: {when: 'never', spacing: {objectLiterals: 'always'}}}]
+  }, {
+    code: '<App>{bar/* comment */}</App>;',
+    options: [{children: {when: 'never'}}]
+  }, {
+    code: '<App>{bar} {baz}</App>;'
+  }, {
+    code: '<App>{bar} {baz}</App>;',
+    options: [{children: {when: 'never'}}]
+  }, {
+    code: '<App>{ bar } { baz }</App>;',
+    options: [{children: {when: 'always'}}]
+  }, {
+    code: '<App>{ bar } { baz }</App>;',
+    options: [{children: {when: 'always', allowMultiline: false}}]
+  }, {
+    code: '<App>{{ bar:baz }} {baz}</App>;',
+    options: [{children: {when: 'never'}}]
+  }, {
+    code: '<App>{ {bar:baz} } { baz }</App>;',
+    options: [{children: {when: 'always'}}]
+  }, {
+    code: [
+      '<App>{',
+      'bar',
+      '} {',
+      'bar',
+      '}</App>;'
+    ].join('\n'),
+    options: [{children: {when: 'always'}}]
+  }, {
+    code: '<App>{bar/* comment */} {baz/* comment */}</App>;',
+    options: [{children: {when: 'never'}}]
+  }, {
+    code: '<App>{3} { {a: 2} }</App>',
+    options: [{children: {when: 'never', spacing: {objectLiterals: 'always'}}}]
+  }, {
+    code: '<App foo={ bar }>{bar}</App>',
+    options: [{attributes: {when: 'always'}}]
+  }, {
+    code: '<App foo={ bar }>{bar}</App>',
+    options: [{attributes: {when: 'always'}}]
+  }, {
+    code: [
+      '<App foo={ 42 } { ...bar } baz={{ 4: 2 }}>',
+      '{foo} {{ bar: baz }}',
+      '</App>'
+    ].join('\n'),
+    options: [{
+      when: 'never',
+      attributes: {when: 'always', spacing: {objectLiterals: 'never'}},
+      children: true
+    }]
+  }, {
+    code: [
+      '<App foo={42} {...bar} baz={ { 4: 2 } }>',
+      '{foo} { { bar: baz } }',
+      '</App>'
+    ].join('\n'),
+    options: [{
+      when: 'never',
+      spacing: {objectLiterals: 'always'},
+      attributes: true,
+      children: {when: 'never'}
+    }]
+  }, {
+    code: [
+      '<App foo={42} {...bar} baz={ { 4: 2 } }>',
+      '{foo} { { bar: baz } }',
+      '</App>'
+    ].join('\n'),
+    options: [{
+      spacing: {objectLiterals: 'always'},
+      attributes: {when: 'never', spacing: {objectLiterals: 'always'}},
+      children: {when: 'never'}
+    }]
+  }, {
+    code: '<App foo={bar} />;',
+    options: ['never']
+  }, {
+    code: [
+      '<App foo={',
+      '{ bar: true, baz: true }',
+      '} />;'
+    ].join('\n'),
+    options: ['never', {spacing: {objectLiterals: 'never'}}]
+  }, {
+    code: '<App foo={ bar } />;',
+    options: ['always']
+  }, {
+    code: '<App foo={ bar } />;',
+    options: ['always', {allowMultiline: false}]
+  }, {
+    code: '<App foo={{ bar:baz }} />;',
+    options: ['never']
+  }, {
+    code: [
+      '<App foo={',
+      '{ bar: true, baz: true }',
+      '} />;'
+    ].join('\n'),
+    options: ['never']
+  }, {
+    code: '<App foo={ {bar:baz} } />;',
+    options: ['always']
+  }, {
+    code: [
+      '<App foo={',
+      '{ bar: true, baz: true }',
+      '} />;'
+    ].join('\n'),
+    options: ['always']
+  }, {
+    code: [
+      '<App foo={',
+      'bar',
+      '} />;'
+    ].join('\n'),
+    options: ['always']
+  }, {
+    code: [
+      '<App foo={',
+      'bar',
+      '} />;'
+    ].join('\n'),
+    options: ['never']
+  }, {
+    code: [
+      '<App>{/* comment */}</App>;'
+    ].join('\n'),
+    options: ['never']
+  }, {
+    code: '<App foo={bar/* comment */} />;',
+    options: ['never']
+  }, {
+    code: '<App foo={ bar } />;',
+    options: ['always', {spacing: {}}]
+  }, {
+    code: [
+      '<App foo={',
+      'bar',
+      '} />;'
+    ].join('\n'),
+    options: ['always', {spacing: {}}]
+  }, {
+    code: '<App foo={{ bar: true, baz: true }} />;',
+    options: ['always', {spacing: {objectLiterals: 'never'}}]
+  }, {
+    code: [
+      '<App foo={',
+      'bar',
+      '} />;'
+    ].join('\n'),
+    options: ['always', {allowMultiline: true}]
+  }, {
+    code: [
+      '<App foo={',
+      '{ bar: true, baz: true }',
+      '} />;'
+    ].join('\n'),
+    options: ['always', {spacing: {objectLiterals: 'never'}}]
+  }, {
+    code: '<App {...bar} />;',
+    options: ['never']
+  }, {
+    code: '<App { ...bar } />;',
+    options: ['always']
+  }, {
+    code: '<App { ...bar } />;',
+    options: ['always', {allowMultiline: false}]
+  }, {
+    code: [
+      '<App {',
+      '...bar',
+      '} />;'
+    ].join('\n'),
+    options: ['always']
+  }, {
+    code: [
+      '<App {',
+      '...bar',
+      '} />;'
+    ].join('\n'),
+    options: ['always']
+  }, {
+    code: [
+      '<App {',
+      '...bar',
+      '} />;'
+    ].join('\n'),
+    options: ['never']
+  }, {
+    code: '<App {...bar/* comment */} />;',
+    options: ['never']
+  }, {
+    code: '<App foo={bar} {...baz} />;',
+    options: ['never']
+  }, {
+    code: '<App foo={ bar } { ...baz } />;',
+    options: ['always']
+  }, {
+    code: '<App foo={ bar } { ...baz } />;',
+    options: ['always', {allowMultiline: false}]
+  }, {
+    code: '<App foo={{ bar:baz }} {...baz} />;',
+    options: ['never']
+  }, {
+    code: '<App foo={ {bar:baz} } { ...baz } />;',
+    options: ['always']
+  }, {
+    code: [
+      '<App foo={',
+      'bar',
+      '} {',
+      '...bar',
+      '}/>;'
+    ].join('\n'),
+    options: ['always']
+  }, {
+    code: '<App foo={bar/* comment */} {...baz/* comment */} />;',
+    options: ['never']
+  }, {
+    code: '<App foo={3} bar={ {a: 2} } />',
+    options: ['never', {spacing: {objectLiterals: 'always'}}]
+  }, {
+    code: '<App foo={ bar }>{bar}</App>',
+    options: ['always']
+  }],
+
+  invalid: [{
+    code: '<App foo={ bar }>{bar}</App>;',
+    output: '<App foo={bar}>{bar}</App>;',
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }]
+  }, {
+    code: '<App foo={ bar }>{ bar }</App>;',
+    output: '<App foo={bar}>{ bar }</App>;',
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }]
+  }, {
+    code: '<App foo={ { bar: true, baz: true } }>{{ bar: true, baz: true }}</App>;',
+    output: '<App foo={{ bar: true, baz: true }}>{{ bar: true, baz: true }}</App>;',
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }]
+  }, {
+    code: '<App foo={ { bar: true, baz: true } }>{ { bar: true, baz: true } }</App>;',
+    output: '<App foo={{ bar: true, baz: true }}>{ { bar: true, baz: true } }</App>;',
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }]
+  }, {
+    code: '<App foo={ bar } />;',
+    output: '<App foo={bar} />;',
+    options: [{attributes: true}],
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }]
+  }, {
+    code: '<App foo={ { bar: true, baz: true } } />;',
+    output: '<App foo={{ bar: true, baz: true }} />;',
+    options: [{attributes: true}],
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }]
+  }, {
+    code: '<App>{ bar }</App>;',
+    output: '<App>{bar}</App>;',
+    options: [{children: true}],
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }]
+  }, {
+    code: '<App>{ { bar: true, baz: true } }</App>;',
+    output: '<App>{{ bar: true, baz: true }}</App>;',
+    options: [{children: true}],
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }]
+  }, {
+    code: '<App foo={ bar } />;',
+    output: '<App foo={bar} />;',
+    options: [{when: 'never'}],
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }]
+  }, {
+    code: [
+      '<App foo={',
+      'bar',
+      '} />;'
+    ].join('\n'),
+    output: '<App foo={bar} />;',
+    options: [{when: 'never', allowMultiline: false}],
+    errors: [{
+      message: 'There should be no newline after \'{\''
+    }, {
+      message: 'There should be no newline before \'}\''
+    }]
+  }, {
+    code: '<App foo={ { bar: true, baz: true } } />;',
+    output: '<App foo={{ bar: true, baz: true }} />;',
+    options: [{when: 'never', spacing: {objectLiterals: 'never'}}],
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }]
+  }, {
+    code: [
+      '<App foo={',
+      '{ bar: true, baz: true }',
+      '} />;'
+    ].join('\n'),
+    output: '<App foo={{ bar: true, baz: true }} />;',
+    options: [{when: 'never', allowMultiline: false, spacing: {objectLiterals: 'never'}}],
+    errors: [{
+      message: 'There should be no newline after \'{\''
+    }, {
+      message: 'There should be no newline before \'}\''
+    }]
+  }, {
+    code: '<App foo={{ bar: true, baz: true }} />;',
+    output: '<App foo={ { bar: true, baz: true } } />;',
+    options: [{when: 'never', spacing: {objectLiterals: 'always'}}],
+    errors: [{
+      message: 'A space is required after \'{\''
+    }, {
+      message: 'A space is required before \'}\''
+    }]
+  }, {
+    code: [
+      '<App foo={',
+      '{ bar: true, baz: true }',
+      '} />;'
+    ].join('\n'),
+    output: '<App foo={ { bar: true, baz: true } } />;',
+    options: [{when: 'never', allowMultiline: false, spacing: {objectLiterals: 'always'}}],
+    errors: [{
+      message: 'There should be no newline after \'{\''
+    }, {
+      message: 'There should be no newline before \'}\''
+    }]
+  }, {
+    code: '<App foo={bar} />;',
+    output: '<App foo={ bar } />;',
+    options: [{when: 'always'}],
+    errors: [{
+      message: 'A space is required after \'{\''
+    }, {
+      message: 'A space is required before \'}\''
+    }]
+  }, {
+    code: [
+      '<App foo={',
+      'bar',
+      '} />;'
+    ].join('\n'),
+    output: '<App foo={ bar } />;',
+    options: [{when: 'always', allowMultiline: false}],
+    errors: [{
+      message: 'There should be no newline after \'{\''
+    }, {
+      message: 'There should be no newline before \'}\''
+    }]
+  }, {
+    code: '<App foo={ { bar: true, baz: true } } />;',
+    output: '<App foo={{ bar: true, baz: true }} />;',
+    options: [{when: 'always', spacing: {objectLiterals: 'never'}}],
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }]
+  }, {
+    code: [
+      '<App foo={',
+      '{ bar: true, baz: true }',
+      '} />;'
+    ].join('\n'),
+    output: '<App foo={{ bar: true, baz: true }} />;',
+    options: [{when: 'always', allowMultiline: false, spacing: {objectLiterals: 'never'}}],
+    errors: [{
+      message: 'There should be no newline after \'{\''
+    }, {
+      message: 'There should be no newline before \'}\''
+    }]
+  }, {
+    code: '<App foo={{ bar: true, baz: true }} />;',
+    output: '<App foo={ { bar: true, baz: true } } />;',
+    options: [{when: 'always', spacing: {objectLiterals: 'always'}}],
+    errors: [{
+      message: 'A space is required after \'{\''
+    }, {
+      message: 'A space is required before \'}\''
+    }]
+  }, {
+    code: [
+      '<App foo={',
+      '{ bar: true, baz: true }',
+      '} />;'
+    ].join('\n'),
+    output: '<App foo={ { bar: true, baz: true } } />;',
+    options: [{when: 'always', allowMultiline: false, spacing: {objectLiterals: 'always'}}],
+    errors: [{
+      message: 'There should be no newline after \'{\''
+    }, {
+      message: 'There should be no newline before \'}\''
+    }]
+  }, {
+    code: '<App foo={ bar } />;',
+    output: '<App foo={bar} />;',
+    options: [{attributes: true, when: 'never'}],
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }]
+  }, {
+    code: [
+      '<App foo={',
+      'bar',
+      '} />;'
+    ].join('\n'),
+    output: '<App foo={bar} />;',
+    options: [{attributes: true, when: 'never', allowMultiline: false}],
+    errors: [{
+      message: 'There should be no newline after \'{\''
+    }, {
+      message: 'There should be no newline before \'}\''
+    }]
+  }, {
+    code: '<App foo={ { bar: true, baz: true } } />;',
+    output: '<App foo={{ bar: true, baz: true }} />;',
+    options: [{attributes: true, when: 'never', spacing: {objectLiterals: 'never'}}],
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }]
+  }, {
+    code: '<App foo={{ bar: true, baz: true }} />;',
+    output: '<App foo={ { bar: true, baz: true } } />;',
+    options: [{attributes: true, when: 'never', spacing: {objectLiterals: 'always'}}],
+    errors: [{
+      message: 'A space is required after \'{\''
+    }, {
+      message: 'A space is required before \'}\''
+    }]
+  }, {
+    code: '<App foo={bar} />;',
+    output: '<App foo={ bar } />;',
+    options: [{attributes: true, when: 'always'}],
+    errors: [{
+      message: 'A space is required after \'{\''
+    }, {
+      message: 'A space is required before \'}\''
+    }]
+  }, {
+    code: [
+      '<App foo={',
+      'bar',
+      '} />;'
+    ].join('\n'),
+    output: '<App foo={ bar } />;',
+    options: [{attributes: true, when: 'always', allowMultiline: false}],
+    errors: [{
+      message: 'There should be no newline after \'{\''
+    }, {
+      message: 'There should be no newline before \'}\''
+    }]
+  }, {
+    code: '<App foo={ { bar: true, baz: true } } />;',
+    output: '<App foo={{ bar: true, baz: true }} />;',
+    options: [{attributes: true, when: 'always', spacing: {objectLiterals: 'never'}}],
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }]
+  }, {
+    code: '<App foo={{ bar: true, baz: true }} />;',
+    output: '<App foo={ { bar: true, baz: true } } />;',
+    options: [{attributes: true, when: 'always', spacing: {objectLiterals: 'always'}}],
+    errors: [{
+      message: 'A space is required after \'{\''
+    }, {
+      message: 'A space is required before \'}\''
+    }]
+  }, {
+    code: '<App foo={ bar } />;',
+    output: '<App foo={bar} />;',
+    options: [{attributes: {when: 'never'}}],
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }]
+  }, {
+    code: '<App foo={ bar } />;',
+    output: '<App foo={bar} />;',
+    options: [{attributes: {when: 'never', allowMultiline: false}}],
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }]
+  }, {
+    code: '<App foo={bar} />;',
+    output: '<App foo={ bar } />;',
+    options: [{attributes: {when: 'always'}}],
+    errors: [{
+      message: 'A space is required after \'{\''
+    }, {
+      message: 'A space is required before \'}\''
+    }]
+  }, {
+    code: '<App foo={bar} />;',
+    output: '<App foo={ bar } />;',
+    options: [{attributes: {when: 'always', allowMultiline: false}}],
+    errors: [{
+      message: 'A space is required after \'{\''
+    }, {
+      message: 'A space is required before \'}\''
+    }]
+  }, {
+    code: '<App foo={ bar} />;',
+    output: '<App foo={ bar } />;',
+    options: [{attributes: {when: 'always'}}],
+    errors: [{
+      message: 'A space is required before \'}\''
+    }]
+  }, {
+    code: '<App foo={bar } />;',
+    output: '<App foo={ bar } />;',
+    options: [{attributes: {when: 'always'}}],
+    errors: [{
+      message: 'A space is required after \'{\''
+    }]
+  }, {
+    code: '<App foo={ bar} />;',
+    output: '<App foo={bar} />;',
+    options: [{attributes: {when: 'never'}}],
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }]
+  }, {
+    code: '<App foo={bar } />;',
+    output: '<App foo={bar} />;',
+    options: [{attributes: {when: 'never'}}],
+    errors: [{
+      message: 'There should be no space before \'}\''
+    }]
+  }, {
+    code: [
+      '<App foo={',
+      'bar',
+      '} />;'
+    ].join('\n'),
+    output: '<App foo={bar} />;',
+    options: [{attributes: {when: 'never', allowMultiline: false}}],
+    errors: [{
+      message: 'There should be no newline after \'{\''
+    }, {
+      message: 'There should be no newline before \'}\''
+    }]
+  }, {
+    code: [
+      '<App foo={',
+      'bar',
+      '} />;'
+    ].join('\n'),
+    output: '<App foo={ bar } />;',
+    options: [{attributes: {when: 'always', allowMultiline: false}}],
+    errors: [{
+      message: 'There should be no newline after \'{\''
+    }, {
+      message: 'There should be no newline before \'}\''
+    }]
+  }, {
+    code: '<App foo={bar} />;',
+    output: '<App foo={ bar } />;',
+    options: [{attributes: {when: 'always', spacing: {}}}],
+    errors: [{
+      message: 'A space is required after \'{\''
+    }, {
+      message: 'A space is required before \'}\''
+    }]
+  }, {
+    code: '<App foo={ bar} />;',
+    output: '<App foo={ bar } />;',
+    options: [{attributes: {when: 'always', spacing: {}}}],
+    errors: [{
+      message: 'A space is required before \'}\''
+    }]
+  }, {
+    code: '<App foo={bar } />;',
+    output: '<App foo={ bar } />;',
+    options: [{attributes: {when: 'always', spacing: {}}}],
+    errors: [{
+      message: 'A space is required after \'{\''
+    }]
+  }, {
+    code: '<App foo={ {bar: true, baz: true} } />;',
+    output: '<App foo={{bar: true, baz: true}} />;',
+    options: [{attributes: {when: 'always', spacing: {objectLiterals: 'never'}}}],
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }]
+  }, {
+    code: '<App>{ bar }</App>;',
+    output: '<App>{bar}</App>;',
+    options: [{children: true, when: 'never'}],
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }]
+  }, {
+    code: [
+      '<App>{',
+      'bar',
+      '}</App>;'
+    ].join('\n'),
+    output: '<App>{bar}</App>;',
+    options: [{children: true, when: 'never', allowMultiline: false}],
+    errors: [{
+      message: 'There should be no newline after \'{\''
+    }, {
+      message: 'There should be no newline before \'}\''
+    }]
+  }, {
+    code: '<App>{ { bar: true, baz: true } }</App>;',
+    output: '<App>{{ bar: true, baz: true }}</App>;',
+    options: [{children: true, when: 'never', spacing: {objectLiterals: 'never'}}],
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }]
+  }, {
+    code: '<App>{{ bar: true, baz: true }}</App>;',
+    output: '<App>{ { bar: true, baz: true } }</App>;',
+    options: [{children: true, when: 'never', spacing: {objectLiterals: 'always'}}],
+    errors: [{
+      message: 'A space is required after \'{\''
+    }, {
+      message: 'A space is required before \'}\''
+    }]
+  }, {
+    code: '<App>{bar}</App>;',
+    output: '<App>{ bar }</App>;',
+    options: [{children: true, when: 'always'}],
+    errors: [{
+      message: 'A space is required after \'{\''
+    }, {
+      message: 'A space is required before \'}\''
+    }]
+  }, {
+    code: [
+      '<App>{',
+      'bar',
+      '}</App>;'
+    ].join('\n'),
+    output: '<App>{ bar }</App>;',
+    options: [{children: true, when: 'always', allowMultiline: false}],
+    errors: [{
+      message: 'There should be no newline after \'{\''
+    }, {
+      message: 'There should be no newline before \'}\''
+    }]
+  }, {
+    code: '<App>{ { bar: true, baz: true } }</App>;',
+    output: '<App>{{ bar: true, baz: true }}</App>;',
+    options: [{children: true, when: 'always', spacing: {objectLiterals: 'never'}}],
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }]
+  }, {
+    code: '<App>{{ bar: true, baz: true }}</App>;',
+    output: '<App>{ { bar: true, baz: true } }</App>;',
+    options: [{children: true, when: 'always', spacing: {objectLiterals: 'always'}}],
+    errors: [{
+      message: 'A space is required after \'{\''
+    }, {
+      message: 'A space is required before \'}\''
+    }]
+  }, {
+    code: '<App>{ bar }</App>;',
+    output: '<App>{bar}</App>;',
+    options: [{children: {when: 'never'}}],
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }]
+  }, {
+    code: '<App>{ bar }</App>;',
+    output: '<App>{bar}</App>;',
+    options: [{children: {when: 'never', allowMultiline: false}}],
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }]
+  }, {
+    code: '<App>{bar}</App>;',
+    output: '<App>{ bar }</App>;',
+    options: [{children: {when: 'always'}}],
+    errors: [{
+      message: 'A space is required after \'{\''
+    }, {
+      message: 'A space is required before \'}\''
+    }]
+  }, {
+    code: '<App>{bar}</App>;',
+    output: '<App>{ bar }</App>;',
+    options: [{children: {when: 'always', allowMultiline: false}}],
+    errors: [{
+      message: 'A space is required after \'{\''
+    }, {
+      message: 'A space is required before \'}\''
+    }]
+  }, {
+    code: '<App>{ bar}</App>;',
+    output: '<App>{ bar }</App>;',
+    options: [{children: {when: 'always'}}],
+    errors: [{
+      message: 'A space is required before \'}\''
+    }]
+  }, {
+    code: '<App>{bar }</App>;',
+    output: '<App>{ bar }</App>;',
+    options: [{children: {when: 'always'}}],
+    errors: [{
+      message: 'A space is required after \'{\''
+    }]
+  }, {
+    code: '<App>{ bar}</App>;',
+    output: '<App>{bar}</App>;',
+    options: [{children: {when: 'never'}}],
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }]
+  }, {
+    code: '<App>{bar }</App>;',
+    output: '<App>{bar}</App>;',
+    options: [{children: {when: 'never'}}],
+    errors: [{
+      message: 'There should be no space before \'}\''
+    }]
+  }, {
+    code: [
+      '<App>{',
+      'bar',
+      '}</App>;'
+    ].join('\n'),
+    output: '<App>{bar}</App>;',
+    options: [{children: {when: 'never', allowMultiline: false}}],
+    errors: [{
+      message: 'There should be no newline after \'{\''
+    }, {
+      message: 'There should be no newline before \'}\''
+    }]
+  }, {
+    code: [
+      '<App>{',
+      'bar',
+      '}</App>;'
+    ].join('\n'),
+    output: '<App>{ bar }</App>;',
+    options: [{children: {when: 'always', allowMultiline: false}}],
+    errors: [{
+      message: 'There should be no newline after \'{\''
+    }, {
+      message: 'There should be no newline before \'}\''
+    }]
+  }, {
+    code: '<App>{bar}</App>;',
+    output: '<App>{ bar }</App>;',
+    options: [{children: {when: 'always', spacing: {}}}],
+    errors: [{
+      message: 'A space is required after \'{\''
+    }, {
+      message: 'A space is required before \'}\''
+    }]
+  }, {
+    code: '<App>{ bar}</App>;',
+    output: '<App>{ bar }</App>;',
+    options: [{children: {when: 'always', spacing: {}}}],
+    errors: [{
+      message: 'A space is required before \'}\''
+    }]
+  }, {
+    code: '<App>{bar }</App>;',
+    output: '<App>{ bar }</App>;',
+    options: [{children: {when: 'always', spacing: {}}}],
+    errors: [{
+      message: 'A space is required after \'{\''
+    }]
+  }, {
+    code: '<App>{ {bar: true, baz: true} }</App>;',
+    output: '<App>{{bar: true, baz: true}}</App>;',
+    options: [{children: {when: 'always', spacing: {objectLiterals: 'never'}}}],
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }]
+  }, {
+    code: '<App { ...bar } />;',
+    output: '<App {...bar} />;',
+    options: [{attributes: {when: 'never'}}],
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }]
+  }, {
+    code: '<App { ...bar } />;',
+    output: '<App {...bar} />;',
+    options: [{attributes: {when: 'never', allowMultiline: false}}],
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }]
+  }, {
+    code: '<App {...bar} />;',
+    output: '<App { ...bar } />;',
+    options: [{attributes: {when: 'always'}}],
+    errors: [{
+      message: 'A space is required after \'{\''
+    }, {
+      message: 'A space is required before \'}\''
+    }]
+  }, {
+    code: '<App {...bar} />;',
+    output: '<App { ...bar } />;',
+    options: [{attributes: {when: 'always', allowMultiline: false}}],
+    errors: [{
+      message: 'A space is required after \'{\''
+    }, {
+      message: 'A space is required before \'}\''
+    }]
+  }, {
+    code: '<App { ...bar} />;',
+    output: '<App { ...bar } />;',
+    options: [{attributes: {when: 'always'}}],
+    errors: [{
+      message: 'A space is required before \'}\''
+    }]
+  }, {
+    code: '<App {...bar } />;',
+    output: '<App { ...bar } />;',
+    options: [{attributes: {when: 'always'}}],
+    errors: [{
+      message: 'A space is required after \'{\''
+    }]
+  }, {
+    code: '<App { ...bar} />;',
+    output: '<App {...bar} />;',
+    options: [{attributes: {when: 'never'}}],
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }]
+  }, {
+    code: '<App {...bar } />;',
+    output: '<App {...bar} />;',
+    options: [{attributes: {when: 'never'}}],
+    errors: [{
+      message: 'There should be no space before \'}\''
+    }]
+  }, {
+    code: [
+      '<App {',
+      '...bar',
+      '} />;'
+    ].join('\n'),
+    output: '<App {...bar} />;',
+    options: [{attributes: {when: 'never', allowMultiline: false}}],
+    errors: [{
+      message: 'There should be no newline after \'{\''
+    }, {
+      message: 'There should be no newline before \'}\''
+    }]
+  }, {
+    code: [
+      '<App {',
+      '...bar',
+      '} />;'
+    ].join('\n'),
+    output: '<App { ...bar } />;',
+    options: [{attributes: {when: 'always', allowMultiline: false}}],
+    errors: [{
+      message: 'There should be no newline after \'{\''
+    }, {
+      message: 'There should be no newline before \'}\''
+    }]
+  }, {
+    code: '<App foo={ bar } { ...baz } />;',
+    output: '<App foo={bar} {...baz} />;',
+    options: [{attributes: {when: 'never'}}],
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }, {
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }]
+  }, {
+    code: '<App foo={ bar } { ...baz } />;',
+    output: '<App foo={bar} {...baz} />;',
+    options: [{attributes: {when: 'never', allowMultiline: false}}],
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }, {
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }]
+  }, {
+    code: '<App foo={bar} {...baz} />;',
+    output: '<App foo={ bar } { ...baz } />;',
+    options: [{attributes: {when: 'always'}}],
+    errors: [{
+      message: 'A space is required after \'{\''
+    }, {
+      message: 'A space is required before \'}\''
+    }, {
+      message: 'A space is required after \'{\''
+    }, {
+      message: 'A space is required before \'}\''
+    }]
+  }, {
+    code: '<App foo={bar} {...baz} />;',
+    output: '<App foo={ bar } { ...baz } />;',
+    options: [{attributes: {when: 'always', allowMultiline: false}}],
+    errors: [{
+      message: 'A space is required after \'{\''
+    }, {
+      message: 'A space is required before \'}\''
+    }, {
+      message: 'A space is required after \'{\''
+    }, {
+      message: 'A space is required before \'}\''
+    }]
+  }, {
+    code: '<App foo={ bar} { ...baz} />;',
+    output: '<App foo={ bar } { ...baz } />;',
+    options: [{attributes: {when: 'always'}}],
+    errors: [{
+      message: 'A space is required before \'}\''
+    }, {
+      message: 'A space is required before \'}\''
+    }]
   }, {
-    code: [
-      '<div>{/* comment */}</div>;'
-    ].join('\n'),
-    options: ['never']
+    code: '<App foo={bar } {...baz } />;',
+    output: '<App foo={ bar } { ...baz } />;',
+    options: [{attributes: {when: 'always'}}],
+    errors: [{
+      message: 'A space is required after \'{\''
+    }, {
+      message: 'A space is required after \'{\''
+    }]
   }, {
-    code: '<App foo={bar/* comment */} />;',
-    options: ['never']
+    code: '<App foo={ bar} { ...baz} />;',
+    output: '<App foo={bar} {...baz} />;',
+    options: [{attributes: {when: 'never'}}],
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space after \'{\''
+    }]
   }, {
-    code: '<App foo={ bar } />;',
-    options: ['always', {spacing: {}}]
+    code: '<App foo={bar } {...baz } />;',
+    output: '<App foo={bar} {...baz} />;',
+    options: [{attributes: {when: 'never'}}],
+    errors: [{
+      message: 'There should be no space before \'}\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }]
   }, {
     code: [
       '<App foo={',
       'bar',
+      '} {',
+      '...baz',
       '} />;'
     ].join('\n'),
-    options: ['always', {spacing: {}}]
-  }, {
-    code: '<App foo={{ bar: true, baz: true }} />;',
-    options: ['always', {spacing: {objectLiterals: 'never'}}]
+    output: '<App foo={bar} {...baz} />;',
+    options: [{attributes: {when: 'never', allowMultiline: false}}],
+    errors: [{
+      message: 'There should be no newline after \'{\''
+    }, {
+      message: 'There should be no newline before \'}\''
+    }, {
+      message: 'There should be no newline after \'{\''
+    }, {
+      message: 'There should be no newline before \'}\''
+    }]
   }, {
     code: [
       '<App foo={',
       'bar',
+      '} {',
+      '...baz',
       '} />;'
     ].join('\n'),
-    options: ['always', {allowMultiline: true}]
-  }, {
-    code: [
-      '<App foo={',
-      '{ bar: true, baz: true }',
-      '} />;'
-    ].join('\n'),
-    options: ['always', {spacing: {objectLiterals: 'never'}}]
+    output: '<App foo={ bar } { ...baz } />;',
+    options: [{attributes: {when: 'always', allowMultiline: false}}],
+    errors: [{
+      message: 'There should be no newline after \'{\''
+    }, {
+      message: 'There should be no newline before \'}\''
+    }, {
+      message: 'There should be no newline after \'{\''
+    }, {
+      message: 'There should be no newline before \'}\''
+    }]
   }, {
-    code: '<App {...bar} />;'
+    code: '<App foo={ 3 } bar={{a: 2}} />',
+    output: '<App foo={3} bar={ {a: 2} } />',
+    options: [{attributes: {when: 'never', spacing: {objectLiterals: 'always'}}}],
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }, {
+      message: 'A space is required after \'{\''
+    }, {
+      message: 'A space is required before \'}\''
+    }]
   }, {
-    code: '<App {...bar} />;',
-    options: ['never']
+    code: '<App foo={ foo /* comment */ } />',
+    output: '<App foo={foo /* comment */} />',
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }]
   }, {
-    code: '<App { ...bar } />;',
-    options: ['always']
+    code: '<App foo={foo /* comment */} />',
+    output: '<App foo={ foo /* comment */ } />',
+    options: [{attributes: {when: 'always'}}],
+    errors: [{
+      message: 'A space is required after \'{\''
+    }, {
+      message: 'A space is required before \'}\''
+    }]
   }, {
-    code: '<App { ...bar } />;',
-    options: ['always', {allowMultiline: false}]
+    code: '<App foo={ /* comment */ foo } />',
+    output: '<App foo={/* comment */ foo} />',
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }]
   }, {
-    code: [
-      '<App {',
-      '...bar',
-      '} />;'
-    ].join('\n'),
-    options: ['always']
+    code: '<App foo={/* comment */ foo} />',
+    output: '<App foo={ /* comment */ foo } />',
+    options: [{attributes: {when: 'always'}}],
+    errors: [{
+      message: 'A space is required after \'{\''
+    }, {
+      message: 'A space is required before \'}\''
+    }]
   }, {
-    code: [
-      '<App {',
-      '...bar',
-      '} />;'
-    ].join('\n'),
-    options: ['always']
+    code: '<App>{ bar } { baz }</App>;',
+    output: '<App>{bar} {baz}</App>;',
+    options: [{children: {when: 'never'}}],
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }, {
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }]
   }, {
-    code: [
-      '<App {',
-      '...bar',
-      '} />;'
-    ].join('\n'),
-    options: ['never']
+    code: '<App>{ bar } { baz }</App>;',
+    output: '<App>{bar} {baz}</App>;',
+    options: [{children: {when: 'never', allowMultiline: false}}],
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }, {
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }]
   }, {
-    code: '<App {...bar/* comment */} />;',
-    options: ['never']
+    code: '<App>{bar} {baz}</App>;',
+    output: '<App>{ bar } { baz }</App>;',
+    options: [{children: {when: 'always'}}],
+    errors: [{
+      message: 'A space is required after \'{\''
+    }, {
+      message: 'A space is required before \'}\''
+    }, {
+      message: 'A space is required after \'{\''
+    }, {
+      message: 'A space is required before \'}\''
+    }]
   }, {
-    code: '<App foo={bar} {...baz} />;'
+    code: '<App>{bar} {baz}</App>;',
+    output: '<App>{ bar } { baz }</App>;',
+    options: [{children: {when: 'always', allowMultiline: false}}],
+    errors: [{
+      message: 'A space is required after \'{\''
+    }, {
+      message: 'A space is required before \'}\''
+    }, {
+      message: 'A space is required after \'{\''
+    }, {
+      message: 'A space is required before \'}\''
+    }]
   }, {
-    code: '<App foo={bar} {...baz} />;',
-    options: ['never']
+    code: '<App>{ bar} { baz}</App>;',
+    output: '<App>{ bar } { baz }</App>;',
+    options: [{children: {when: 'always'}}],
+    errors: [{
+      message: 'A space is required before \'}\''
+    }, {
+      message: 'A space is required before \'}\''
+    }]
   }, {
-    code: '<App foo={ bar } { ...baz } />;',
-    options: ['always']
+    code: '<App>{bar } {baz }</App>;',
+    output: '<App>{ bar } { baz }</App>;',
+    options: [{children: {when: 'always'}}],
+    errors: [{
+      message: 'A space is required after \'{\''
+    }, {
+      message: 'A space is required after \'{\''
+    }]
   }, {
-    code: '<App foo={ bar } { ...baz } />;',
-    options: ['always', {allowMultiline: false}]
+    code: '<App>{ bar} { baz}</App>;',
+    output: '<App>{bar} {baz}</App>;',
+    options: [{children: {when: 'never'}}],
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space after \'{\''
+    }]
   }, {
-    code: '<App foo={{ bar:baz }} {...baz} />;',
-    options: ['never']
+    code: '<App>{bar } {baz }</App>;',
+    output: '<App>{bar} {baz}</App>;',
+    options: [{children: {when: 'never'}}],
+    errors: [{
+      message: 'There should be no space before \'}\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }]
   }, {
-    code: '<App foo={ {bar:baz} } { ...baz } />;',
-    options: ['always']
+    code: [
+      '<App>{',
+      'bar',
+      '} {',
+      'baz',
+      '}</App>;'
+    ].join('\n'),
+    output: '<App>{bar} {baz}</App>;',
+    options: [{children: {when: 'never', allowMultiline: false}}],
+    errors: [{
+      message: 'There should be no newline after \'{\''
+    }, {
+      message: 'There should be no newline before \'}\''
+    }, {
+      message: 'There should be no newline after \'{\''
+    }, {
+      message: 'There should be no newline before \'}\''
+    }]
   }, {
     code: [
-      '<App foo={',
+      '<App>{',
       'bar',
       '} {',
-      '...bar',
-      '}/>;'
+      'baz',
+      '}</App>;'
     ].join('\n'),
-    options: ['always']
+    output: '<App>{ bar } { baz }</App>;',
+    options: [{children: {when: 'always', allowMultiline: false}}],
+    errors: [{
+      message: 'There should be no newline after \'{\''
+    }, {
+      message: 'There should be no newline before \'}\''
+    }, {
+      message: 'There should be no newline after \'{\''
+    }, {
+      message: 'There should be no newline before \'}\''
+    }]
   }, {
-    code: '<App foo={bar/* comment */} {...baz/* comment */} />;',
-    options: ['never']
+    code: '<App>{ 3 } bar={{a: 2}}</App>',
+    output: '<App>{3} bar={ {a: 2} }</App>',
+    options: [{children: {when: 'never', spacing: {objectLiterals: 'always'}}}],
+    errors: [{
+      message: 'There should be no space after \'{\''
+    }, {
+      message: 'There should be no space before \'}\''
+    }, {
+      message: 'A space is required after \'{\''
+    }, {
+      message: 'A space is required before \'}\''
+    }]
   }, {
-    code: '<App foo={3} bar={ {a: 2} } />',
-    options: ['never', {spacing: {objectLiterals: 'always'}}]
+    code: '<App>{foo /* comment */}</App>',
+    output: '<App>{ foo /* comment */ }</App>',
+    options: [{children: {when: 'always'}}],
+    errors: [{
+      message: 'A space is required after \'{\''
+    }, {
+      message: 'A space is required before \'}\''
+    }]
+  }, {
+    code: '<App>{/* comment */ foo}</App>',
+    output: '<App>{ /* comment */ foo }</App>',
+    options: [{children: {when: 'always'}}],
+    errors: [{
+      message: 'A space is required after \'{\''
+    }, {
+      message: 'A space is required before \'}\''
+    }]
   }, {
-    code: '<div foo={ bar }>{bar}</div>',
-    options: ['always']
-  }],
-
-  invalid: [{
     code: '<App foo={ bar } />;',
     output: '<App foo={bar} />;',
     options: ['never'],
@@ -595,16 +2101,8 @@ ruleTester.run('jsx-curly-spacing', rule, {
       message: 'A space is required before \'}\''
     }]
   }, {
-    code: '<div foo={ foo /* comment */ } />',
-    output: '<div foo={foo /* comment */} />',
-    errors: [{
-      message: 'There should be no space after \'{\''
-    }, {
-      message: 'There should be no space before \'}\''
-    }]
-  }, {
-    code: '<div foo={foo /* comment */} />',
-    output: '<div foo={ foo /* comment */ } />',
+    code: '<App foo={foo /* comment */} />',
+    output: '<App foo={ foo /* comment */ } />',
     options: ['always'],
     errors: [{
       message: 'A space is required after \'{\''
@@ -612,16 +2110,8 @@ ruleTester.run('jsx-curly-spacing', rule, {
       message: 'A space is required before \'}\''
     }]
   }, {
-    code: '<div foo={ /* comment */ foo } />',
-    output: '<div foo={/* comment */ foo} />',
-    errors: [{
-      message: 'There should be no space after \'{\''
-    }, {
-      message: 'There should be no space before \'}\''
-    }]
-  }, {
-    code: '<div foo={/* comment */ foo} />',
-    output: '<div foo={ /* comment */ foo } />',
+    code: '<App foo={/* comment */ foo} />',
+    output: '<App foo={ /* comment */ foo } />',
     options: ['always'],
     errors: [{
       message: 'A space is required after \'{\''