Repository: eslint/eslint (js)

Issue:
Inconsistent evaluation of strings in no-constant-condition
<!--
    ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).

    This template is for bug reports. If you are here for another reason, please see below:

    1. To propose a new rule: https://eslint.org/docs/developer-guide/contributing/new-rules
    2. To request a rule change: https://eslint.org/docs/developer-guide/contributing/rule-changes
    3. To request a change that is not a bug fix, rule change, or new rule: https://eslint.org/docs/developer-guide/contributing/changes
    4. 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**

* **ESLint Version: 5.9.0**
* **Node Version: 11.3.0**
* **npm Version: 6.4.1**

**What parser are you using?**
babel-eslint

**Please show your full configuration:**

<details>
<summary>Configuration</summary>

<!-- Paste your configuration below: -->
```js
{
    "parser": "babel-eslint",
    "parserOptions": {
        "sourceType": "module",
        "allowImportExportEverywhere": true
    },
    "extends": [
        "airbnb",
        "plugin:lodash/recommended"
    ],
    "env": {
        "browser": true,
        "jquery": true,
        "node": true,
        "mocha": true
    },
    "globals": {
        "expect": true,
        "cy": true,
        "Cypress": true,
        "__VERSION__": true,
        "__RELEASED__": true,
        "__INTERCOMID__": true
    },
    "plugins": [
        "backbone",
        "compat",
        "mocha",
        "chai-friendly",
        "lodash",
        "json"
    ],
    "settings": {
        "backbone": {
            "Collection": ["BaseCollection"],
            "Model": ["BaseModel"],
            "View": ["BaseView"]
        }
    },
    "rules": {
        "no-unused-vars": [1, { "vars": "all", "args": "after-used", "ignoreRestSiblings": true, "varsIgnorePattern": "^_", "argsIgnorePattern": "^_" }],
        "no-unused-expressions": 0,
        "chai-friendly/no-unused-expressions": 2,
        "arrow-parens": ["error", "always"],
        "indent": ["error", 4, { "SwitchCase": 1 }],
        "quotes": [1, "double"],
        "comma-dangle": ["error", "never"],
        "new-cap": ["error", { "capIsNew": false }],
        "brace-style": [1, "1tbs", { "allowSingleLine": true }],
        "camelcase": 0,
        "no-plusplus": 0,
        "no-param-reassign": 0,
        "no-underscore-dangle": 0,
        "max-len": 0,
        "no-console": 0,
        "default-case": 0,
        "func-names": 0,
        "no-new": 0,
        "global-require": 0,
        "eol-last": 1,
        "class-methods-use-this": 0,
        "no-cond-assign": [1, "except-parens"],
        "newline-per-chained-call": [2, {"ignoreChainWithDepth": 5}],
        "eqeqeq": ["error", "always"],
        "valid-jsdoc": ["error", { "prefer": { "return": "returns", "extends": "extends" }, "preferType": { "object": "Object" }, "requireReturn": false, "requireReturnType": true, "requireReturnDescription": false, "matchDescription": ".+" }],
        "react/require-extension": [0, { "extensions": [".js"] }],
        "prefer-destructuring": [2, { "array": false, "object": true }, { "enforceForRenamedProperties": false }],
        "import/no-extraneous-dependencies": [0, {}],
        "import/no-unresolved": [2, { "ignore": ["env"] }],
        "import/extensions": 0,
        "import/no-cycle": 0,
        "mocha/no-exclusive-tests": "error",
        "backbone/collection-model": 0,
        "backbone/defaults-on-top": 2,
        "backbone/events-on-top": [2, ["el"]],
        "backbone/initialize-on-top": [2, { "View": ["el", "events"] }],
        "backbone/model-defaults": 0,
        "backbone/no-constructor": 2,
        "backbone/no-el-assign": 2,
        "backbone/no-native-jquery": [2, "selector"],
        "lodash/prefer-lodash-method": 0,
        "lodash/prefer-noop": 1,
        "lodash/import-scope": 0,
        "lodash/prefer-constant": 0,
        "lodash/prefer-filter": 0,
        "lodash/prefer-flat-map": 1,
        "lodash/collection-method-value": 0,
        "lodash/collection-return": 0,
        "lodash/prefer-lodash-chain": 1,
        "lodash/prop-shorthand": 0,
        "lodash/matches-syntax": 0,
        "lodash/matches-shorthand": 0
    }
}
```

</details>

**What did you do? Please include the actual source code causing the issue, as well as the command that you used to run ESLint.**

<!-- Paste the source code below: -->
```js
if (category === "voucher" || "custom") { }
```

<!-- Paste the command you used to run ESLint: -->
```bash
eslint --fix app
```

**What did you expect to happen?**
An error should be thrown as a string will always evaluate to true. This would be consistent with the following examples where errors are thrown.

```js
if (category === "voucher" || true) { }
```

```js
if ("foo" || "bar") { }
```

**What actually happened? Please include the actual, raw output from ESLint.**
No error was thrown.

**Are you willing to submit a pull request to fix this bug?**
Happy to have a go if somebody can point me in the right direction :)

Pull request:
Fix: warn constant on RHS of || in no-constant-condition (fixes #11181)
<!--
    ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).
-->

**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:

**Tell us about your environment**

* **ESLint Version: 5.9.0**
* **Node Version: 11.3.0**
* **npm Version: 6.4.1**

**What parser (default, Babel-ESLint, etc.) are you using?**
babel-eslint

**Please show your full configuration:**

<details>
<summary>Configuration</summary>

<!-- Paste your configuration below: -->
```js
{
    "parser": "babel-eslint",
    "parserOptions": {
        "sourceType": "module",
        "allowImportExportEverywhere": true
    },
    "extends": [
        "airbnb",
        "plugin:lodash/recommended"
    ],
    "env": {
        "browser": true,
        "jquery": true,
        "node": true,
        "mocha": true
    },
    "globals": {
        "expect": true,
        "cy": true,
        "Cypress": true,
        "__VERSION__": true,
        "__RELEASED__": true,
        "__INTERCOMID__": true
    },
    "plugins": [
        "backbone",
        "compat",
        "mocha",
        "chai-friendly",
        "lodash",
        "json"
    ],
    "settings": {
        "backbone": {
            "Collection": ["BaseCollection"],
            "Model": ["BaseModel"],
            "View": ["BaseView"]
        }
    },
    "rules": {
        "no-unused-vars": [1, { "vars": "all", "args": "after-used", "ignoreRestSiblings": true, "varsIgnorePattern": "^_", "argsIgnorePattern": "^_" }],
        "no-unused-expressions": 0,
        "chai-friendly/no-unused-expressions": 2,
        "arrow-parens": ["error", "always"],
        "indent": ["error", 4, { "SwitchCase": 1 }],
        "quotes": [1, "double"],
        "comma-dangle": ["error", "never"],
        "new-cap": ["error", { "capIsNew": false }],
        "brace-style": [1, "1tbs", { "allowSingleLine": true }],
        "camelcase": 0,
        "no-plusplus": 0,
        "no-param-reassign": 0,
        "no-underscore-dangle": 0,
        "max-len": 0,
        "no-console": 0,
        "default-case": 0,
        "func-names": 0,
        "no-new": 0,
        "global-require": 0,
        "eol-last": 1,
        "class-methods-use-this": 0,
        "no-cond-assign": [1, "except-parens"],
        "newline-per-chained-call": [2, {"ignoreChainWithDepth": 5}],
        "eqeqeq": ["error", "always"],
        "valid-jsdoc": ["error", { "prefer": { "return": "returns", "extends": "extends" }, "preferType": { "object": "Object" }, "requireReturn": false, "requireReturnType": true, "requireReturnDescription": false, "matchDescription": ".+" }],
        "react/require-extension": [0, { "extensions": [".js"] }],
        "prefer-destructuring": [2, { "array": false, "object": true }, { "enforceForRenamedProperties": false }],
        "import/no-extraneous-dependencies": [0, {}],
        "import/no-unresolved": [2, { "ignore": ["env"] }],
        "import/extensions": 0,
        "import/no-cycle": 0,
        "mocha/no-exclusive-tests": "error",
        "backbone/collection-model": 0,
        "backbone/defaults-on-top": 2,
        "backbone/events-on-top": [2, ["el"]],
        "backbone/initialize-on-top": [2, { "View": ["el", "events"] }],
        "backbone/model-defaults": 0,
        "backbone/no-constructor": 2,
        "backbone/no-el-assign": 2,
        "backbone/no-native-jquery": [2, "selector"],
        "lodash/prefer-lodash-method": 0,
        "lodash/prefer-noop": 1,
        "lodash/import-scope": 0,
        "lodash/prefer-constant": 0,
        "lodash/prefer-filter": 0,
        "lodash/prefer-flat-map": 1,
        "lodash/collection-method-value": 0,
        "lodash/collection-return": 0,
        "lodash/prefer-lodash-chain": 1,
        "lodash/prop-shorthand": 0,
        "lodash/matches-syntax": 0,
        "lodash/matches-shorthand": 0
    }
}
```

</details>

**What did you do? Please include the actual source code causing the issue.**

```js
if (category === "voucher" || "custom") { }
```

**What did you expect to happen?**
An error should be thrown as the condition will always evaluate to true.

**What actually happened? Please include the actual, raw output from ESLint.**
No error was thrown.


**What changes did you make? (Give an overview)**
- Added tests.
- Changed the return statement in the `isConstant` function. 

**Is there anything you'd like reviewers to focus on?**
When using logical _or_, if the right side of the condition is a constant **and** truthy then the condition will always resolve to true. The changes to the return statement test for this eventuality.



Patch:
diff --git a/README.md b/README.md
index 65ee43400..cba920372 100644
--- a/README.md
+++ b/README.md
@@ -133,7 +133,7 @@ If you are trying to run locally:
 * Make sure your plugins (and ESLint) are both in your project's `package.json` as devDependencies (or dependencies, if your project uses ESLint at runtime).
 * Make sure you have run `npm install` and all your dependencies are installed.
 
-In all cases, make sure your plugins' peerDependencies have been installed as well. You can use `npm view eslint-plugin-myplugin peerDepencies` to see what peer dependencies `eslint-plugin-myplugin` has.
+In all cases, make sure your plugins' peerDependencies have been installed as well. You can use `npm view eslint-plugin-myplugin peerDependencies` to see what peer dependencies `eslint-plugin-myplugin` has.
 
 ### Does ESLint support JSX?
 
diff --git a/docs/developer-guide/working-with-custom-formatters.md b/docs/developer-guide/working-with-custom-formatters.md
index fe4c91464..58fe55936 100644
--- a/docs/developer-guide/working-with-custom-formatters.md
+++ b/docs/developer-guide/working-with-custom-formatters.md
@@ -1,25 +1,49 @@
 # Working with Custom Formatters
 
-Writing an ESLint custom formatter is simple. All that is needed is a module that exports a function that will receive the results from the execution of ESLint.
+While ESLint has some built-in formatters available to format the linting results, it's also possible to create and distribute your own custom formatters. You can include custom formatters in your project directly or create an npm package to distribute them separately.
 
-The simplest formatter will be something like:
+Each formatter is just a function that receives a `results` object and returns a string. For example, the following is how the `json` built-in formatter is implemented:
 
-```javascript
+```js
 //my-awesome-formatter.js
 module.exports = function(results) {
     return JSON.stringify(results, null, 2);
 };
 ```
 
-And to run `eslint` with this custom formatter:
+To run ESLint with this formatter, you can use the `-f` (or `--formatter`) command line flag:
 
 ```bash
-eslint -f './my-awesome-formatter.js' src/
+eslint -f ./my-awesome-formatter.js src/
 ```
 
-The output of the previous command will be something like this
+In order to use a local file as a custom formatter, you must begin the filename with a dot (such as `./my-awesome-formatter.js` or `../formatters/my-awesome-formatter.js`).
 
-```javascript
+## Packaging the Custom Formatter
+
+Custom formatters can also be distributed through npm packages. To do so, create an npm package with a name in the format of `eslint-formatter-*`, where `*` is the name of your formatter (such as `eslint-formatter-awesome`). Projects should then install the package and can use the custom formatter with the `-f` (or `--formatter`) flag like this:
+
+```bash
+eslint -f awesome src/
+```
+
+Because ESLint knows to look for packages beginning with `eslint-formatter-` when the specified formatter doesn't begin with a dot, there is no need to type `eslint-formatter-` when using a packaged custom formatter.
+
+Tips for `package.json`:
+
+* The `main` entry should be the JavaScript file implementing your custom formatter.
+* Add these `keywords` to help users find your formatter:
+    * `"eslint"`
+    * `"eslint-formatter"`
+    * `"eslintformatter"`
+
+See all [formatters on npm](https://www.npmjs.com/search?q=eslint-formatter);
+
+## The `results` Object
+
+The `results` object passed into a formatter is an array of objects containing the lint results for individual files. Here's some example output:
+
+```js
 [
     {
         filePath: "path/to/file.js",
@@ -56,30 +80,28 @@ The output of the previous command will be something like this
         fixableErrorCount: 0,
         fixableWarningCount: 0
     }
-];
+]
 ```
 
-As you can see the argument passed to the custom formatter function is just a list of results objects.
-
-## Description of the results
+### The `result` Object
 
-### the result object
+<!-- This section is copied from the "Node.js API" page. Changes to this section should
+also be manually applied to that page. -->
 
-You will receive a result object from each file `eslint` validates, each one of them containing
-the list of messages for `errors` and/or `warnings`.
+Each object in the `results` array is a `result` object. Each `result` object contains the path of the file that was linted and information about linting issues that were encountered. Here are the properties available on each `result` object:
 
-The following are the fields of the result object:
-
-*   **filePath**: The path to the file relative to the current working directory (the path from which ESLint was executed).
-*   **messages**: An array of message objects. See below for more info about messages.
+*   **filePath**: The absolute path to the file that was linted.
+*   **messages**: An array of `message` objects. See below for more info about messages.
 *   **errorCount**: The number of errors for the given file.
 *   **warningCount**: The number of warnings for the given file.
 *   **source**: The source code for the given file. This property is omitted if this file has no errors/warnings or if the `output` property is present.
 *   **output**: The source code for the given file with as many fixes applied as possible. This property is omitted if no fix is available.
 
-### The message object
+### The `message` Object
+
+Each `message` object contains information about the ESLint rule that was triggered by some source code. The properties available on each `message` object are:
 
-*   **ruleId**: the id of the rule that produced the error or warning.
+*   **ruleId**: the ID of the rule that produced the error or warning.
 *   **severity**: the severity of the failure, `1` for warnings and `2` for errors.
 *   **message**: the human readable description of the error.
 *   **line**: the line where the issue is located.
@@ -121,7 +143,7 @@ module.exports = function(results) {
 Running `eslint` with the previous custom formatter,
 
 ```bash
-eslint -f './my-awesome-formatter.js' src/
+eslint -f ./my-awesome-formatter.js src/
 ```
 
 Will produce the following output:
@@ -193,7 +215,7 @@ module.exports = function(results) {
 So running `eslint` with this custom formatter:
 
 ```bash
-eslint -f './my-awesome-formatter.js' src/
+eslint -f ./my-awesome-formatter.js src/
 ```
 
 The output will be
@@ -213,13 +235,15 @@ warning no-unused-vars
   src/configs/clean.js:3:6
 ```
 
-## Passing arguments to formatters:
+## Passing Arguments to Formatters
 
-### Using environment variables:
+While custom formatter do not receive arguments in addition to the results object, it is possible to pass additional data into formatters.
 
-Let's say we want to show only the messages that are actual errors and discard the warnings.
+## Using Environment Variables
 
-```javascript
+Custom formatters have access to environment variables and so can change their behavior based on environment variable data. Here's an example that uses a `AF_SKIP_WARNINGS` environment variable to determine whether or not to show warnings in the results:
+
+```js
 module.exports = function(results) {
     var skipWarnings = process.env.AF_SKIP_WARNINGS === "true"; //af stands for awesome-formatter
 
@@ -278,13 +302,13 @@ module.exports = function(results) {
 };
 ```
 
-So running `eslint` with this custom formatter:
+You would run ESLint with this custom formatter and an environment variable set like this:
 
 ```bash
-AF_SKIP_WARNINGS=true eslint -f './my-awesome-formatter.js' src/
+AF_SKIP_WARNINGS=true eslint -f ./my-awesome-formatter.js src/
 ```
 
-The output will not print the warnings
+The output would be:
 
 ```bash
 error space-infix-ops
@@ -294,24 +318,21 @@ error semi
   src/configs/bundler.js:6:10
 ```
 
-### Outputting to a standard format for other programs to consume
 
-You can use ESLint's built-in JSON formatter first, and pipe the output to another program that accepts JSON linter results.
+### Complex Argument Passing
+
+If you find the custom formatter pattern doesn't provide enough options for the way you'd like to format ESLint results, the best option is to use ESLint's built-in [JSON formatter](https://eslint.org/docs/user-guide/formatters/) and pipe the output to a second program. For example:
 
 ```bash
-eslint -f json src/ | your-program-that-reads-JSON
+eslint -f json src/ | your-program-that-reads-JSON --option
 ```
 
-You can read more about the built-in JSON formatter [here](https://eslint.org/docs/user-guide/formatters/).
+In this example, the `your-program-that-reads-json` program can accept the raw JSON of ESLint results and process it before outputting its own format of the results. You can pass as many command line arguments to that program as are necessary to customize the output.
 
-## Final words
+## Note: Formatting for Terminals
 
-More complex formatters could be written by grouping differently the errors and warnings and/or grouping the data by the ruleIds.
-
-When printing the files a recommended format will be something like this:
+Modern terminals like [iTerm2](https://www.iterm2.com/) or [Guake](http://guake-project.org/) expect a specific results format to automatically open filenames when they are clicked. Most terminals support this format for that purpose:
 
 ```bash
 file:line:column
 ```
-
-Since that allows modern fancy terminals (like [iTerm2](https://www.iterm2.com/) or [Guake](http://guake-project.org/)) to make them link to files that open in your favorite text editor.
diff --git a/docs/rules/sort-imports.md b/docs/rules/sort-imports.md
index d885c9c1c..f6fd04f06 100644
--- a/docs/rules/sort-imports.md
+++ b/docs/rules/sort-imports.md
@@ -146,22 +146,22 @@ Examples of **incorrect** code for this rule with the default `{ "ignoreDeclarat
 
 ```js
 /*eslint sort-imports: ["error", { "ignoreDeclarationSort": false }]*/
-import 'foo.js'
-import 'bar.js'
+import b from 'foo.js'
+import a from 'bar.js'
 ```
 
 Examples of **correct** code for this rule with the `{ "ignoreDeclarationSort": true }` option:
 
 ```js
 /*eslint sort-imports: ["error", { "ignoreDeclarationSort": true }]*/
-import 'foo.js'
-import 'bar.js'
+import a from 'foo.js'
+import b from 'bar.js'
 ```
 
 ```js
 /*eslint sort-imports: ["error", { "ignoreDeclarationSort": true }]*/
-import 'bar.js'
-import 'foo.js'
+import b from 'foo.js'
+import a from 'bar.js'
 ```
 
 Default is `false`.
diff --git a/docs/user-guide/getting-started.md b/docs/user-guide/getting-started.md
index 4b98eb075..2e6e6617a 100644
--- a/docs/user-guide/getting-started.md
+++ b/docs/user-guide/getting-started.md
@@ -37,6 +37,14 @@ After that, you can run ESLint in your project's root directory like this:
 $ ./node_modules/.bin/eslint yourfile.js
 ```
 
+Instead of navigating to `./node_modules/.bin/` you may also use `npx` to run `eslint`:
+
+```
+$ npx eslint
+```
+
+**Note:** If ESLint wasn't manually installed (via `npm`), `npx` will install `eslint` to a temporary directory and execute it.
+
 Any plugins or shareable configs that you use must also be installed locally to work with a locally-installed ESLint.
 
 ### Global Installation and Usage
diff --git a/lib/formatters/tap.js b/lib/formatters/tap.js
index 9651a2bcf..354872a0c 100644
--- a/lib/formatters/tap.js
+++ b/lib/formatters/tap.js
@@ -20,7 +20,6 @@ function getMessageType(message) {
         return "error";
     }
     return "warning";
-
 }
 
 /**
@@ -50,12 +49,11 @@ module.exports = function(results) {
         let diagnostics = {};
 
         if (messages.length > 0) {
-            testResult = "not ok";
-
             messages.forEach(message => {
+                const severity = getMessageType(message);
                 const diagnostic = {
                     message: message.message,
-                    severity: getMessageType(message),
+                    severity,
                     data: {
                         line: message.line || 0,
                         column: message.column || 0,
@@ -63,6 +61,11 @@ module.exports = function(results) {
                     }
                 };
 
+                // This ensures a warning message is not flagged as error
+                if (severity === "error") {
+                    testResult = "not ok";
+                }
+
                 /*
                  * If we have multiple messages place them under a messages key
                  * The first error will be logged as message key
diff --git a/lib/rules/no-constant-condition.js b/lib/rules/no-constant-condition.js
index 8d7934d8a..39c2928ee 100644
--- a/lib/rules/no-constant-condition.js
+++ b/lib/rules/no-constant-condition.js
@@ -109,7 +109,10 @@ module.exports = {
                     const isLeftShortCircuit = (isLeftConstant && isLogicalIdentity(node.left, node.operator));
                     const isRightShortCircuit = (isRightConstant && isLogicalIdentity(node.right, node.operator));
 
-                    return (isLeftConstant && isRightConstant) || isLeftShortCircuit || isRightShortCircuit;
+                    return (isLeftConstant && isRightConstant) ||
+                        (node.operator === "||" && isRightConstant && node.right.value) || // in the case of an "OR", we need to know if the right constant value is truthy
+                        isLeftShortCircuit ||
+                        isRightShortCircuit;
                 }
 
                 case "AssignmentExpression":


Test patch:
diff --git a/tests/lib/formatters/tap.js b/tests/lib/formatters/tap.js
index 7fc080a53..903af6a8b 100644
--- a/tests/lib/formatters/tap.js
+++ b/tests/lib/formatters/tap.js
@@ -72,7 +72,7 @@ describe("formatter:tap", () => {
             }]
         }];
 
-        it("should return a an error string", () => {
+        it("should return an error string", () => {
             const result = formatter(code);
 
             assert.include(result, "not ok");
@@ -80,7 +80,70 @@ describe("formatter:tap", () => {
         });
     });
 
-    describe("when passed multiple messages", () => {
+    describe("when passed a message with a severity of 1", () => {
+        const code = [{
+            filePath: "foo.js",
+            messages: [{
+                message: "Unexpected foo.",
+                severity: 1,
+                line: 5,
+                column: 10,
+                ruleId: "foo"
+            }]
+        }];
+
+        it("should return a warning string", () => {
+            const result = formatter(code);
+
+            assert.include(result, "ok");
+            assert.notInclude(result, "not ok");
+            assert.include(result, "warning");
+        });
+    });
+
+    describe("when passed multiple messages with a severity of 1", () => {
+        const code = [{
+            filePath: "foo.js",
+            messages: [{
+                message: "Foo.",
+                severity: 1,
+                line: 5,
+                column: 10,
+                ruleId: "foo"
+            }, {
+                message: "Bar.",
+                severity: 1,
+                line: 6,
+                column: 11,
+                ruleId: "bar"
+            }, {
+                message: "Baz.",
+                severity: 1,
+                line: 7,
+                column: 12,
+                ruleId: "baz"
+            }]
+        }];
+
+        it("should return a string with multiple entries", () => {
+            const result = formatter(code);
+
+            assert.include(result, "ok");
+            assert.notInclude(result, "not ok");
+            assert.include(result, "messages");
+            assert.include(result, "Foo.");
+            assert.include(result, "line: 5");
+            assert.include(result, "column: 10");
+            assert.include(result, "Bar.");
+            assert.include(result, "line: 6");
+            assert.include(result, "column: 11");
+            assert.include(result, "Baz.");
+            assert.include(result, "line: 7");
+            assert.include(result, "column: 12");
+        });
+    });
+
+    describe("when passed multiple messages with different error severity", () => {
         const code = [{
             filePath: "foo.js",
             messages: [{
@@ -146,7 +209,8 @@ describe("formatter:tap", () => {
             const result = formatter(code);
 
             assert.include(result, "not ok 1");
-            assert.include(result, "not ok 2");
+            assert.include(result, "ok 2");
+            assert.notInclude(result, "not ok 2");
         });
     });
 
diff --git a/tests/lib/rules/no-constant-condition.js b/tests/lib/rules/no-constant-condition.js
index 69a90dd38..c89f9080d 100644
--- a/tests/lib/rules/no-constant-condition.js
+++ b/tests/lib/rules/no-constant-condition.js
@@ -55,6 +55,12 @@ ruleTester.run("no-constant-condition", rule, {
         "if(true && abc==='str' || def ==='str'){}",
         "if(true && typeof abc==='string'){}",
 
+        // #11181, string literals
+        "if('str' || a){}",
+        "if('str1' && a){}",
+        "if(a && 'str'){}",
+        "if('str' || abc==='str'){}",
+
         // { checkLoops: false }
         { code: "while(true);", options: [{ checkLoops: false }] },
         { code: "for(;true;);", options: [{ checkLoops: false }] },
@@ -116,6 +122,12 @@ ruleTester.run("no-constant-condition", rule, {
         { code: "if(false || true){}", errors: [{ messageId: "unexpected", type: "LogicalExpression" }] },
         { code: "if(typeof abc==='str' || true){}", errors: [{ messageId: "unexpected", type: "LogicalExpression" }] },
 
+        // #11181, string literals
+        { code: "if('str1' || 'str2'){}", errors: [{ messageId: "unexpected", type: "LogicalExpression" }] },
+        { code: "if('str1' && 'str2'){}", errors: [{ messageId: "unexpected", type: "LogicalExpression" }] },
+        { code: "if(abc==='str' || 'str'){}", errors: [{ messageId: "unexpected", type: "LogicalExpression" }] },
+        { code: "if(a || 'str'){}", errors: [{ messageId: "unexpected", type: "LogicalExpression" }] },
+
         {
             code: "function* foo(){while(true){} yield 'foo';}",
             errors: [{ messageId: "unexpected", type: "Literal" }]