Repository: prettier/prettier-eslint (ts)

Issue:
Custom Fallback Options if a Setting is Not Inferrable from ESlint
This is, admittedly, purely needed for prettier-atom. In prettier-atom, if you turn ESlint integration on, it's going to stay on regardless of whether the project you've got open actually has all prettier-related rules set in their config. 

If the project doesn't have an ESlint rule needed for prettier, users are wanting to fall back to the prettier setting they've set inside of their prettier-atom config instead of falling back to the default value for that prettier option (which is how it currently works if I'm not mistaken). If I could pass fall-back options to prettier-eslint when using it to format, that would be great. Note that this is different than the current API which only allows manual overrides as opposed to fall-backs.

Any thoughts on adding this to the API?

Pull request:
Fallback Prettier Options
The first commit makes some quick changes to the CONTRIBUTING file. 

The second commit resolves #72. Previously we were using `ruleValue` to assign defaults, but these defaults were eslint defaults. Because people are going to be assigning fallback options as prettier option defaults, not eslint defaults, I decided to move the defaults into the `ruleValueToPrettierOption` functions and convert them to their prettier analogs.

Patch:
diff --git a/.all-contributorsrc b/.all-contributorsrc
index 5702001..a1de10a 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -150,6 +150,16 @@
         "bug",
         "code"
       ]
+    },
+    {
+      "login": "robwise",
+      "name": "Rob Wise",
+      "avatar_url": "https://avatars0.githubusercontent.com/u/6173488?v=3",
+      "profile": "https://robwise.github.io",
+      "contributions": [
+        "doc",
+        "code"
+      ]
     }
   ]
 }
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index bfa8552..ca44f79 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -8,11 +8,11 @@ Thanks for being willing to contribute!
 ## Project setup
 
 1. Fork and clone the repo
-2. `$ npm install` to install dependencies
-3. `$ npm start validate` to validate you've got it working
+2. `$ yarn install` to install dependencies
+3. `$ yarn start validate` to validate you've got it working
 4. Create a branch for your PR
 
-This project uses [`nps`][nps] and you can run `npm start` to see what scripts are available.
+This project uses [`nps`][nps] and you can run `yarn start` to see what scripts are available.
 
 ## Add yourself as a contributor
 
@@ -20,7 +20,7 @@ This project follows the [all contributors][all-contributors] specification. To
 contributors on the README.md, please use the automated script as part of your PR:
 
 ```console
-npm start contributors.add
+yarn start contributors.add
 ```
 
 Follow the prompt. If you've already added yourself to the list and are making a new type of contribution, you can run
@@ -36,8 +36,8 @@ You can use `commitizen` to help you to follow [the convention][convention]
 
 Once you are ready to commit the changes, please use the below commands
 
-1. `git add <files to be comitted>`
-2. `$ npm start commit`
+1. `git add <files to be committed>`
+2. `$ yarn start commit`
 
 ... and follow the instruction of the interactive prompt.
 
diff --git a/README.md b/README.md
index c72e197..cdeaf2b 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@ Formats your JavaScript using [`prettier`][prettier] followed by [`eslint --fix`
 [![downloads][downloads-badge]][npm-stat]
 [![MIT License][license-badge]][LICENSE]
 
-[![All Contributors](https://img.shields.io/badge/all_contributors-15-orange.svg?style=flat-square)](#contributors)
+[![All Contributors](https://img.shields.io/badge/all_contributors-16-orange.svg?style=flat-square)](#contributors)
 [![PRs Welcome][prs-badge]][prs]
 [![Donate][donate-badge]][donate]
 [![Code of Conduct][coc-badge]][coc]
@@ -65,6 +65,9 @@ const options = {
   prettierOptions: {
     bracketSpacing: true,
   },
+  fallbackPrettierOptions: {
+    singleQuote: false,
+  }
 }
 
 const formatted = format(options)
@@ -94,6 +97,16 @@ The options to pass for formatting with `prettier`. If not provided, `prettier-e
 options based on the `eslintConfig` (whether that's provided or derived via `filePath`). You can also provide _some_ of
 the options and have the remaining options derived via your eslint config. This is useful for options like `parser`.
 
+**NOTE:** these options _override_ the eslint config. If you want fallback options to be used only in the case that the
+rule cannot be inferred from eslint, see "fallbackPrettierOptions" below.
+
+#### fallbackPrettierOptions (?Object)
+
+The options to pass for formatting with `prettier` if `prettier-eslint` is not able to create the options based on the
+the `eslintConfig` (whether that's provided or derived via `filePath`). These options will only be used in the case that
+the corresponding eslint rule cannot be found and the prettier option has not been manually defined in `prettierOptions`.
+If the fallback is not given, `prettier-eslint` will just use the default `prettier` value in this scenario.
+
 #### logLevel (?Enum: ['trace', 'debug', 'info', 'warn', 'error', 'silent'])
 
 `prettier-eslint` does quite a bit of logging if you want it to. Pass this to set the amount of logs you want to see.
@@ -210,7 +223,7 @@ Thanks goes to these people ([emoji key][emojis]):
 | [<img src="https://avatars.githubusercontent.com/u/1500684?v=3" width="100px;"/><br /><sub>Kent C. Dodds</sub>](https://kentcdodds.com)<br />[💻](https://github.com/prettier/prettier-eslint/commits?author=kentcdodds) [📖](https://github.com/prettier/prettier-eslint/commits?author=kentcdodds) 🚇 [⚠️](https://github.com/prettier/prettier-eslint/commits?author=kentcdodds) | [<img src="https://avatars.githubusercontent.com/u/5554486?v=3" width="100px;"/><br /><sub>Gyandeep Singh</sub>](http://gyandeeps.com)<br />👀 | [<img src="https://avatars.githubusercontent.com/u/682584?v=3" width="100px;"/><br /><sub>Igor Pnev</sub>](https://github.com/exdeniz)<br />[🐛](https://github.com/prettier/prettier-eslint/issues?q=author%3Aexdeniz) | [<img src="https://avatars.githubusercontent.com/u/813865?v=3" width="100px;"/><br /><sub>Benjamin Tan</sub>](https://demoneaux.github.io/)<br />💬 👀 | [<img src="https://avatars.githubusercontent.com/u/622118?v=3" width="100px;"/><br /><sub>Eric McCormick</sub>](https://ericmccormick.io)<br />[💻](https://github.com/prettier/prettier-eslint/commits?author=edm00se) [📖](https://github.com/prettier/prettier-eslint/commits?author=edm00se) [⚠️](https://github.com/prettier/prettier-eslint/commits?author=edm00se) | [<img src="https://avatars.githubusercontent.com/u/2142817?v=3" width="100px;"/><br /><sub>Simon Lydell</sub>](https://github.com/lydell)<br />[📖](https://github.com/prettier/prettier-eslint/commits?author=lydell) | [<img src="https://avatars0.githubusercontent.com/u/981957?v=3" width="100px;"/><br /><sub>Tom McKearney</sub>](https://github.com/tommck)<br />[📖](https://github.com/prettier/prettier-eslint/commits?author=tommck) 💡 |
 | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
 | [<img src="https://avatars.githubusercontent.com/u/463105?v=3" width="100px;"/><br /><sub>Patrik Åkerstrand</sub>](https://github.com/PAkerstrand)<br />[💻](https://github.com/prettier/prettier-eslint/commits?author=PAkerstrand) | [<img src="https://avatars.githubusercontent.com/u/1560301?v=3" width="100px;"/><br /><sub>Lochlan Bunn</sub>](https://twitter.com/loklaan)<br />[💻](https://github.com/prettier/prettier-eslint/commits?author=loklaan) | [<img src="https://avatars.githubusercontent.com/u/25886902?v=3" width="100px;"/><br /><sub>Daniël Terwiel</sub>](https://github.com/danielterwiel)<br />🔌 🔧 | [<img src="https://avatars1.githubusercontent.com/u/1834413?v=3" width="100px;"/><br /><sub>Robin Malfait</sub>](https://robinmalfait.com)<br />🔧 | [<img src="https://avatars0.githubusercontent.com/u/8161781?v=3" width="100px;"/><br /><sub>Michael McDermott</sub>](http://mgmcdermott.com)<br />[💻](https://github.com/prettier/prettier-eslint/commits?author=mgmcdermott) | [<img src="https://avatars3.githubusercontent.com/u/292365?v=3" width="100px;"/><br /><sub>Adam Stankiewicz</sub>](http://sheerun.net)<br />[💻](https://github.com/prettier/prettier-eslint/commits?author=sheerun) | [<img src="https://avatars3.githubusercontent.com/u/487068?v=3" width="100px;"/><br /><sub>Stephen John Sorensen</sub>](http://www.stephenjohnsorensen.com/)<br />[💻](https://github.com/prettier/prettier-eslint/commits?author=spudly) |
-| [<img src="https://avatars2.githubusercontent.com/u/1597820?v=3" width="100px;"/><br /><sub>Brian Di Palma</sub>](https://github.com/briandipalma)<br />[🐛](https://github.com/prettier/prettier-eslint/issues?q=author%3Abriandipalma) [💻](https://github.com/prettier/prettier-eslint/commits?author=briandipalma) |
+| [<img src="https://avatars2.githubusercontent.com/u/1597820?v=3" width="100px;"/><br /><sub>Brian Di Palma</sub>](https://github.com/briandipalma)<br />[🐛](https://github.com/prettier/prettier-eslint/issues?q=author%3Abriandipalma) [💻](https://github.com/prettier/prettier-eslint/commits?author=briandipalma) | [<img src="https://avatars0.githubusercontent.com/u/6173488?v=3" width="100px;"/><br /><sub>Rob Wise</sub>](https://robwise.github.io)<br />[📖](https://github.com/prettier/prettier-eslint/commits?author=robwise) [💻](https://github.com/prettier/prettier-eslint/commits?author=robwise) |
 <!-- ALL-CONTRIBUTORS-LIST:END -->
 
 This project follows the [all-contributors][all-contributors] specification. Contributions of any kind welcome!
diff --git a/src/index.js b/src/index.js
index c413c34..8211394 100644
--- a/src/index.js
+++ b/src/index.js
@@ -29,6 +29,9 @@ module.exports = format
  * @param {Object} options.prettierOptions - the options to pass for
  *  formatting with `prettier`. If not provided, prettier-eslint will attempt
  *  to create the options based on the eslintConfig
+ * @param {Object} options.fallbackPrettierOptions - the options to pass for
+ *  formatting with `prettier` if the given option is not inferrable from the
+ *  eslintConfig.
  * @param {String} options.logLevel - the level for the logs
  *  (error, warn, info, debug, trace)
  * @param {Boolean} options.prettierLast - Run Prettier Last
@@ -46,6 +49,7 @@ function format(options) {
     prettierPath = getModulePath(filePath, 'prettier'),
     prettierOptions,
     prettierLast,
+    fallbackPrettierOptions,
   } = options
 
   const eslintConfig = defaultEslintConfig(
@@ -56,6 +60,7 @@ function format(options) {
   const formattingOptions = getOptionsForFormatting(
     eslintConfig,
     prettierOptions,
+    fallbackPrettierOptions,
   )
 
   logger.debug(
diff --git a/src/utils.js b/src/utils.js
index 00eb860..2ede922 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -5,38 +5,39 @@ import merge from 'lodash.merge'
 
 const logger = getLogger({prefix: 'prettier-eslint'})
 const RULE_DISABLED = {}
+const RULE_NOT_CONFIGURED = 'RULE_NOT_CONFIGURED'
 const OPTION_GETTERS = {
   printWidth: {
-    ruleValue: rules => getRuleValue(rules, 'max-len', 80, 'code'),
-    ruleValueToPrettierOption: value => value,
+    ruleValue: rules => getRuleValue(rules, 'max-len', 'code'),
+    ruleValueToPrettierOption: getPrintWidth,
   },
   tabWidth: {
-    ruleValue: rules => getRuleValue(rules, 'indent', 2),
-    ruleValueToPrettierOption: value => getTabWidth(value),
+    ruleValue: rules => getRuleValue(rules, 'indent'),
+    ruleValueToPrettierOption: getTabWidth,
   },
   parser: {
-    ruleValue: getParser,
+    ruleValue: () => RULE_NOT_CONFIGURED,
     ruleValueToPrettierOption: getParser,
   },
   singleQuote: {
-    ruleValue: rules => getRuleValue(rules, 'quotes', 'single'),
-    ruleValueToPrettierOption: value => getSingleQuote(value),
+    ruleValue: rules => getRuleValue(rules, 'quotes'),
+    ruleValueToPrettierOption: getSingleQuote,
   },
   trailingComma: {
     ruleValue: rules => getRuleValue(rules, 'comma-dangle'),
-    ruleValueToPrettierOption: (value, rules) => getTrailingComma(value, rules),
+    ruleValueToPrettierOption: getTrailingComma,
   },
   bracketSpacing: {
-    ruleValue: rules => getRuleValue(rules, 'object-curly-spacing', 'never'),
-    ruleValueToPrettierOption: value => getBraketSpacing(value),
+    ruleValue: rules => getRuleValue(rules, 'object-curly-spacing'),
+    ruleValueToPrettierOption: getBracketSpacing,
   },
   semi: {
-    ruleValue: rules => getRuleValue(rules, 'semi', 'always'),
-    ruleValueToPrettierOption: value => value === 'always',
+    ruleValue: rules => getRuleValue(rules, 'semi'),
+    ruleValueToPrettierOption: getSemi,
   },
   useTabs: {
-    ruleValue: rules => getRuleValue(rules, 'indent', 2),
-    ruleValueToPrettierOption: value => value === 'tab',
+    ruleValue: rules => getRuleValue(rules, 'indent'),
+    ruleValueToPrettierOption: getUseTabs,
   },
 }
 
@@ -47,9 +48,17 @@ function defaultEslintConfig(eslintConfig = {}, defaultConfig = {}) {
   return merge({}, defaultConfig, eslintConfig)
 }
 
-function getOptionsForFormatting(eslintConfig, prettierOptions = {}) {
+function getOptionsForFormatting(
+  eslintConfig,
+  prettierOptions = {},
+  fallbackPrettierOptions = {},
+) {
   const eslint = getRelevantESLintConfig(eslintConfig)
-  const prettier = getPrettierOptionsFromESLintRules(eslint, prettierOptions)
+  const prettier = getPrettierOptionsFromESLintRules(
+    eslint,
+    prettierOptions,
+    fallbackPrettierOptions,
+  )
   return {eslint, prettier}
 }
 
@@ -103,18 +112,35 @@ function getRelevantESLintConfig(eslintConfig) {
  * This accepts an eslintConfig object and converts
  * it to the `prettier` options object
  */
-function getPrettierOptionsFromESLintRules(eslintConfig, prettierOptions) {
+function getPrettierOptionsFromESLintRules(
+  eslintConfig,
+  prettierOptions,
+  fallbackPrettierOptions,
+) {
   const {rules} = eslintConfig
 
   return Object.keys(OPTION_GETTERS).reduce(
-    (options, key) => configureOptions(prettierOptions, key, options, rules),
+    (options, key) =>
+      configureOptions(
+        prettierOptions,
+        fallbackPrettierOptions,
+        key,
+        options,
+        rules,
+      ),
     {},
   )
 }
 
 // If an ESLint rule that prettier can be configured with is enabled create a
 // prettier configuration object that reflects the ESLint rule configuration.
-function configureOptions(prettierOptions, key, options, rules) {
+function configureOptions(
+  prettierOptions,
+  fallbackPrettierOptions,
+  key,
+  options,
+  rules,
+) {
   const givenOption = prettierOptions[key]
   const optionIsGiven = givenOption !== undefined
 
@@ -127,6 +153,7 @@ function configureOptions(prettierOptions, key, options, rules) {
     if (eslintRuleValue !== RULE_DISABLED) {
       const prettierOptionValue = ruleValueToPrettierOption(
         eslintRuleValue,
+        fallbackPrettierOptions,
         rules,
       )
 
@@ -139,44 +166,108 @@ function configureOptions(prettierOptions, key, options, rules) {
   return options
 }
 
-function getTabWidth(value) {
+function getPrintWidth(eslintValue, fallbacks) {
+  return makePrettierOption('printWidth', eslintValue, fallbacks, 80)
+}
+
+function getTabWidth(eslintValue, fallbacks) {
   // if it's set to tabs, then the tabWidth value doesn't matter
-  return value === 'tab' ? RULE_DISABLED : value
+  const prettierValue = eslintValue === 'tab' ? RULE_DISABLED : eslintValue
+
+  return makePrettierOption('tabWidth', prettierValue, fallbacks, 2)
 }
 
-function getParser() {
+function getParser(eslintValue, fallbacks) {
   // TODO: handle flow parser config
-  return 'babylon'
+  return makePrettierOption('parser', eslintValue, fallbacks, 'babylon')
 }
 
-function getSingleQuote(value) {
-  return value === 'single'
+function getSingleQuote(eslintValue, fallbacks) {
+  let prettierValue
+
+  if (eslintValue === 'single') {
+    prettierValue = true
+  } else if (eslintValue === 'double') {
+    prettierValue = false
+  } else {
+    prettierValue = eslintValue
+  }
+
+  return makePrettierOption('singleQuote', prettierValue, fallbacks, true)
 }
 
-function getTrailingComma(value, rules) {
-  if (typeof value === 'undefined') {
-    const actualValue = rules['comma-dangle']
-    if (typeof actualValue === 'object') {
-      return getValFromObjectConfig(actualValue)
-    }
+function getTrailingComma(value, fallbacks, rules) {
+  let prettierValue
+  const actualValue = rules['comma-dangle']
+
+  if (value === 'never') {
+    prettierValue = 'none'
+  } else if (value === 'always') {
+    prettierValue = 'es5'
+  } else if (typeof actualValue === 'object') {
+    prettierValue = getValFromTrailingCommaConfig(actualValue)
+  } else {
+    prettierValue = RULE_NOT_CONFIGURED
   }
 
-  return value === 'never' ? 'none' : 'es5'
+  return makePrettierOption('trailingComma', prettierValue, fallbacks, 'es5')
+}
 
-  function getValFromObjectConfig(eslintValue) {
-    const [, {arrays, objects, functions}] = eslintValue
-    const es5 = [arrays, objects].some(isAlways)
-    const fns = isAlways(functions)
-    // eslint-disable-next-line no-nested-ternary
-    return fns ? 'all' : es5 ? 'es5' : 'none'
+function getValFromTrailingCommaConfig(objectConfig) {
+  const [, {arrays, objects, functions}] = objectConfig
+  const fns = isAlways(functions)
+  const es5 = [arrays, objects].some(isAlways)
+
+  if (fns) {
+    return 'all'
+  } else if (es5) {
+    return 'es5'
+  } else {
+    return 'none'
+  }
+}
+
+function getBracketSpacing(eslintValue, fallbacks) {
+  let prettierValue
+
+  if (eslintValue === 'never') {
+    prettierValue = false
+  } else if (eslintValue === 'always') {
+    prettierValue = true
+  } else {
+    prettierValue = eslintValue
   }
+
+  return makePrettierOption('bracketSpacing', prettierValue, fallbacks, false)
 }
 
-function getBraketSpacing(value) {
-  return value !== 'never'
+function getSemi(eslintValue, fallbacks) {
+  let prettierValue
+
+  if (eslintValue === 'never') {
+    prettierValue = false
+  } else if (eslintValue === 'always') {
+    prettierValue = true
+  } else {
+    prettierValue = eslintValue
+  }
+
+  return makePrettierOption('semi', prettierValue, fallbacks, true)
 }
 
-function extractRuleValue(objPath, name, value, defaultValue) {
+function getUseTabs(eslintValue, fallbacks) {
+  let prettierValue
+
+  if (eslintValue === 'tab') {
+    prettierValue = true
+  } else {
+    prettierValue = RULE_NOT_CONFIGURED
+  }
+
+  return makePrettierOption('useTabs', prettierValue, fallbacks, false)
+}
+
+function extractRuleValue(objPath, name, value) {
   if (objPath) {
     logger.trace(
       oneLine`
@@ -185,7 +276,7 @@ function extractRuleValue(objPath, name, value, defaultValue) {
       `,
     )
 
-    return delve(value, objPath, defaultValue)
+    return delve(value, objPath, RULE_NOT_CONFIGURED)
   }
 
   logger.debug(
@@ -201,7 +292,7 @@ function extractRuleValue(objPath, name, value, defaultValue) {
   return undefined
 }
 
-function getRuleValue(rules, name, defaultValue, objPath) {
+function getRuleValue(rules, name, objPath) {
   const ruleConfig = rules[name]
 
   if (Array.isArray(ruleConfig)) {
@@ -210,13 +301,14 @@ function getRuleValue(rules, name, defaultValue, objPath) {
     // If `ruleSetting` is set to disable the ESLint rule don't use `value` as
     // it might be a value provided by an overriden config package e.g. airbnb
     // overriden by config-prettier. The airbnb values are provided even though
-    // config-prettier disables the rule. Instead fallback to prettier defaults.
+    // config-prettier disables the rule. Instead use fallback or prettier
+    // default.
     if (ruleSetting === 0 || ruleSetting === 'off') {
       return RULE_DISABLED
     }
 
     if (typeof value === 'object') {
-      return extractRuleValue(objPath, name, value, defaultValue)
+      return extractRuleValue(objPath, name, value)
     } else {
       logger.trace(
         oneLine`
@@ -228,17 +320,42 @@ function getRuleValue(rules, name, defaultValue, objPath) {
     }
   }
 
+  return RULE_NOT_CONFIGURED
+}
+
+function isAlways(val) {
+  return val.indexOf('always') === 0
+}
+
+function makePrettierOption(
+  prettierRuleName,
+  prettierRuleValue,
+  fallbacks,
+  defaultValue,
+) {
+  if (
+    prettierRuleValue !== RULE_NOT_CONFIGURED &&
+    typeof prettierRuleValue !== 'undefined'
+  ) {
+    return prettierRuleValue
+  }
+
+  const fallback = fallbacks[prettierRuleName]
+  if (typeof fallback !== 'undefined') {
+    logger.debug(
+      oneLine`
+        The ${prettierRuleName} rule is not configured,
+        using provided fallback of ${fallback}
+      `,
+    )
+    return fallback
+  }
+
   logger.debug(
     oneLine`
-      The ${name} rule is not configured,
+      The ${prettierRuleName} rule is not configured,
       using default of ${defaultValue}
     `,
   )
-
-  // no value configured
   return defaultValue
 }
-
-function isAlways(val) {
-  return val.indexOf('always') === 0
-}


Test patch:
diff --git a/src/index.test.js b/src/index.test.js
index c8de21d..17c080b 100644
--- a/src/index.test.js
+++ b/src/index.test.js
@@ -77,6 +77,16 @@ const tests = [
     },
     output: 'const {foo} = bar',
   },
+  {
+    title: 'with an empty config and fallbacks',
+    input: {
+      text: 'const { foo } = bar;',
+      eslintConfig: {},
+      filePath: path.resolve('./mock/default-config'),
+      fallbackPrettierOptions: {bracketSpacing: false},
+    },
+    output: 'const {foo} = bar',
+  },
   {
     title: 'without a filePath and no config',
     input: {text: defaultInputText()},
diff --git a/src/utils.test.js b/src/utils.test.js
index 3a7d8fb..c576a20 100644
--- a/src/utils.test.js
+++ b/src/utils.test.js
@@ -167,9 +167,12 @@ const getPrettierOptionsFromESLintRulesTests = [
     options: {trailingComma: 'none'},
   },
   {rules: {'max-len': ['error', {code: 120}]}, options: {printWidth: 120}},
+  {rules: {quotes: [2, 'double']}, options: {singleQuote: false}},
+
   // If an ESLint rule is disabled fall back to prettier defaults.
   {rules: {'max-len': [0, {code: 120}]}, options: {}},
   {rules: {quotes: ['off', {code: 120}]}, options: {}},
+  {rules: {quotes: ['backtick', {code: 120}]}, options: {}},
   {rules: {semi: 'off'}, options: {}},
   {rules: {semi: ['off', 'never']}, options: {}},
   {rules: {semi: ['warn', 'always']}, options: {}},
@@ -192,9 +195,18 @@ defaultEslintConfigTests.forEach(({config, defaults, result}, index) => {
   })
 })
 
-getPrettierOptionsFromESLintRulesTests.forEach(({rules, options}, index) => {
+getPrettierOptionsFromESLintRulesTests.forEach(({
+  rules,
+  options,
+  prettierOptions,
+  fallbackPrettierOptions,
+}, index) => {
   test(`getPrettierOptionsFromESLintRulesTests ${index}`, () => {
-    const {prettier} = getOptionsForFormatting({rules})
+    const {prettier} = getOptionsForFormatting(
+      {rules},
+      prettierOptions,
+      fallbackPrettierOptions,
+    )
     expect(prettier).toMatchObject(options)
   })
 })
@@ -209,6 +221,13 @@ test('if prettierOptions are provided, those are preferred', () => {
   expect(prettier).toMatchObject({singleQuote: false})
 })
 
+test('if fallbacks are provided, those are used if not found in eslint', () => {
+  const {prettier} = getOptionsForFormatting({rules: {}}, undefined, {
+    singleQuote: false,
+  })
+  expect(prettier).toMatchObject({singleQuote: false})
+})
+
 test('eslint config has only necessary properties', () => {
   const {eslint} = getOptionsForFormatting({
     globals: {window: false},