Repository: eslint/eslint (js)

Issue:
unicode-bom fixer insert BOM in appropriate location
<!--
This template is for bug reports. If you are reporting a bug, please continue on. If you are here for another reason, please see below:

1. To propose a new rule: http://eslint.org/docs/developer-guide/contributing/new-rules
2. To request a change: http://eslint.org/docs/developer-guide/contributing/changes
3. If you have any questions, please stop by our chatroom: https://gitter.im/eslint/eslint

Note that leaving sections blank will make it difficult for us to troubleshoot and we may have to close the issue.
-->

**Tell us about your environment**
Win 10, 64bit
* **ESLint Version:** v.3.15.0
* **Node Version:** v.7.5.0
* **npm Version:** v.4.1.2
**What parser (default, Babel-ESLint, etc.) are you using?**
    default
**Please show your full configuration:**
<!-- Paste your configuration below: -->
```
"unicode-bom" :  "error"
```

**What did you do? Please include the actual source code causing the issue.**
I called `eslint --fix some.js`. 
<!-- Paste the source code below: -->
```js
// Some comments.
function someFunction() {
    // some code...
}
```

**What did you expect to happen?**
```js
<U+FEFF>// Some comments.
function someFunction() {
    // some code...
}
```

**What actually happened? Please include the actual, raw output from ESLint.**
```js
// Some comments.
<U+FEFF><U+FEFF><U+FEFF><U+FEFF><U+FEFF><U+FEFF><U+FEFF><U+FEFF><U+FEFF><U+FEFF>function someFunction() {
    // some code...
}
```


Pull request description:
Fix: unicode-bom fixer insert BOM in appropriate location (fixes #8083)
**What is the purpose of this pull request? (put an "X" next to item)**

[ ] Documentation update
[x] Bug fix ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/bug-report.md))
[ ] New rule ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/rule-proposal.md))
[ ] Changes an existing rule ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/rule-change-proposal.md))
[ ] Add autofixing to a rule
[ ] Add a CLI option
[ ] Add something to the core
[ ] Other, please explain:

<!--
    If the item you've checked above has a template, please paste the template questions below and answer them. (If this pull request is addressing an issue, you can just paste a link to the issue here instead.)
-->
See issue [#8083](https://github.com/eslint/eslint/issues/8083)
<!--
    Please ensure your pull request is ready:

    - Read the pull request guide (http://eslint.org/docs/developer-guide/contributing/pull-requests)
    - Include tests for this change
    - Update documentation for this change (if appropriate)
-->

<!--
    The following is required for all pull requests:
-->

**What changes did you make? (Give an overview)**
Insert BOM at specific location using `fixer.insertTextBeforeRange()` instead before node. Because node range doesn't include comments.

**Is there anything you'd like reviewers to focus on?**
nothing

Patch:
diff --git a/lib/rules/unicode-bom.js b/lib/rules/unicode-bom.js
index 2f16a2585..7109a49ed 100644
--- a/lib/rules/unicode-bom.js
+++ b/lib/rules/unicode-bom.js
@@ -45,7 +45,7 @@ module.exports = {
                         loc: location,
                         message: "Expected Unicode BOM (Byte Order Mark).",
                         fix(fixer) {
-                            return fixer.insertTextBefore(node, "\uFEFF");
+                            return fixer.insertTextBeforeRange([0, 1], "\uFEFF");
                         }
                     });
                 } else if (sourceCode.hasBOM && (requireBOM === "never")) {


Test patch:
diff --git a/lib/testers/rule-tester.js b/lib/testers/rule-tester.js
index 14a5cbc03..e8442f079 100644
--- a/lib/testers/rule-tester.js
+++ b/lib/testers/rule-tester.js
@@ -147,6 +147,12 @@ function RuleTester(testerConfig) {
         lodash.cloneDeep(defaultConfig),
         testerConfig
     );
+
+    /**
+     * Rule definitions to define before tests.
+     * @type {Object}
+     */
+    this.rules = {};
 }
 
 /**
@@ -239,7 +245,7 @@ RuleTester.prototype = {
      * @returns {void}
      */
     defineRule(name, rule) {
-        eslint.defineRule(name, rule);
+        this.rules[name] = rule;
     },
 
     /**
@@ -508,6 +514,7 @@ RuleTester.prototype = {
             RuleTester.describe("valid", () => {
                 test.valid.forEach(valid => {
                     RuleTester.it(valid.code || valid, () => {
+                        eslint.defineRules(this.rules);
                         testValidTemplate(ruleName, valid);
                     });
                 });
@@ -516,6 +523,7 @@ RuleTester.prototype = {
             RuleTester.describe("invalid", () => {
                 test.invalid.forEach(invalid => {
                     RuleTester.it(invalid.code, () => {
+                        eslint.defineRules(this.rules);
                         testInvalidTemplate(ruleName, invalid);
                     });
                 });
diff --git a/tests/lib/rules/unicode-bom.js b/tests/lib/rules/unicode-bom.js
index c0068586a..43d780b9c 100644
--- a/tests/lib/rules/unicode-bom.js
+++ b/tests/lib/rules/unicode-bom.js
@@ -41,6 +41,12 @@ ruleTester.run("unicode-bom", rule, {
             options: ["always"],
             output: "\uFEFFvar a = 123;"
         },
+        {
+            code: " // here's a comment \nvar a = 123;",
+            errors: [{ message: "Expected Unicode BOM (Byte Order Mark).", type: "Program" }],
+            options: ["always"],
+            output: "\uFEFF // here's a comment \nvar a = 123;"
+        },
         {
             code: "\uFEFF var a = 123;",
             errors: [{ message: "Unexpected Unicode BOM (Byte Order Mark).", type: "Program" }],