eslint-plugin-wdio
Version:
Eslint rules for WebdriverIO
408 lines (394 loc) • 10.6 kB
JavaScript
// src/constants.ts
var MATCHERS = [
"toBeChecked",
"toBeClickable",
"toBeDisabled",
"toBeDisplayed",
"toBeDisplayedInViewport",
"toBeElementsArrayOfSize",
"toBeEnabled",
"toBeExisting",
"toBeFocused",
"toBePresent",
"toBeRequested",
"toBeRequestedTimes",
"toBeRequestedWith",
"toBeRequestedWithResponse",
"toBeSelected",
"toExist",
"toHaveAttr",
"toHaveAttribute",
"toHaveAttributeAndValue",
"toHaveChildren",
"toHaveClass",
"toHaveClassContaining",
"toHaveClipboardText",
"toHaveComputedLabel",
"toHaveComputedRole",
"toHaveElementClass",
"toHaveElementProperty",
"toHaveHTML",
"toHaveHeight",
"toHaveHref",
"toHaveId",
"toHaveLink",
"toHaveLocalStorageItem",
"toHaveSize",
"toHaveStyle",
"toHaveText",
"toHaveTitle",
"toHaveUrl",
"toHaveValue",
"toHaveWidth"
];
// src/rules/await-expect.ts
var rule = {
meta: {
type: "problem",
docs: {
description: "expect must be prefixed with await",
category: "Possible Errors",
url: "https://github.com/webdriverio/webdriverio/blob/main/packages/eslint-plugin-wdio/docs/rules/await-expect.md",
recommended: false
},
messages: {
missingAwait: "Missing await before an expect statement"
},
hasSuggestions: true
},
create: function(context) {
return {
CallExpression(node) {
if (node.callee.type !== "MemberExpression" || node.callee.object.type !== "CallExpression" || node.callee.object.callee.name !== "expect") {
return;
}
const propertyName = node.callee.property.name;
const isWdioMatcher = MATCHERS.includes(propertyName);
const isSnapshotMatcher = ["toMatchSnapshot", "toMatchInlineSnapshot"].includes(propertyName);
if (!isWdioMatcher && !isSnapshotMatcher) {
return;
}
if (isSnapshotMatcher) {
const selectorFunctions = ["$", "$$"];
const expectArg = node.callee.object.arguments[0];
const isLikelyWdioElement = expectArg.type === "CallExpression" && expectArg.callee.type === "Identifier" && selectorFunctions.includes(expectArg.callee.name) || expectArg.type === "CallExpression" && expectArg.callee.type === "MemberExpression" && expectArg.callee.property.name && selectorFunctions.includes(expectArg.callee.property.name);
if (!isLikelyWdioElement) {
return;
}
}
if (
/**
* expect is called without an `await` and as part of an
* expression
*/
node.parent.type === "ExpressionStatement"
) {
context.report({ node, messageId: "missingAwait" });
}
}
};
}
};
var await_expect_default = rule;
// src/utils/helpers.ts
var isCommand = function(expression, command, instances = ["browser"]) {
const callee = expression?.callee;
return callee && "object" in callee && "name" in callee.object && instances.includes(callee.object?.name) && "property" in callee && "name" in callee.property && callee.property?.name === command;
};
// src/rules/no-debug.ts
var rule2 = {
meta: {
type: "problem",
docs: {
description: "Disallow browser.debug() in tests",
category: "Possible Errors",
url: "https://github.com/webdriverio/webdriverio/blob/main/packages/eslint-plugin-wdio/docs/rules/no-debug.md",
recommended: false
},
messages: {
unexpectedDebug: "Unexpected browser.debug() not allowed"
},
hasSuggestions: true,
schema: [{
type: "object",
properties: {
instances: {
type: "array",
items: {
type: "string"
},
description: 'List of browser instances to check (default: ["browser"])',
default: ["browser"]
}
},
additionalProperties: false
}]
},
create: function(context) {
const options = context.options[0] || {};
const instances = options.instances || ["browser"];
return {
CallExpression(node) {
if (isCommand(node, "debug", instances)) {
context.report({
node,
messageId: "unexpectedDebug",
data: { instance: instances.join(", ") }
});
}
}
};
}
};
var no_debug_default = rule2;
// src/rules/no-pause.ts
var rule3 = {
meta: {
type: "problem",
docs: {
description: "Disallow browser.pause() in tests",
category: "Possible Errors",
url: "https://github.com/webdriverio/webdriverio/blob/main/packages/eslint-plugin-wdio/docs/rules/no-pause.md",
recommended: false
},
messages: {
unexpectedPause: "Unexpected browser.pause() not allowed"
},
hasSuggestions: true,
schema: [{
type: "object",
properties: {
instances: {
type: "array",
items: {
type: "string"
},
description: 'List of browser instances to check (default: ["browser"])',
default: ["browser"]
}
},
additionalProperties: false
}]
},
create: function(context) {
const options = context.options[0] || {};
const instances = options.instances || ["browser"];
return {
CallExpression(node) {
if (isCommand(node, "pause", instances)) {
context.report({
node,
messageId: "unexpectedPause",
data: { instance: instances.join(", ") }
});
}
}
};
}
};
var no_pause_default = rule3;
// src/plugin.ts
var index = {
configs: {},
rules: {
"await-expect": await_expect_default,
"no-debug": no_debug_default,
"no-pause": no_pause_default
}
};
var plugin_default = index;
// src/globals.ts
import globals from "globals";
var sharedGlobals = {
$: false,
$$: false,
browser: false,
driver: false,
expect: false,
multiremotebrowser: false,
multiRemoteBrowser: false,
// To be more user friendly we add mocha and node globals as well, else the use need to configure themself
...globals.mocha,
...globals.node
};
// src/configs/js-recommended.ts
var js_recommended_default = {
languageOptions: {
globals: sharedGlobals
},
plugins: {
wdio: plugin_default
},
rules: {
"wdio/await-expect": "error",
"wdio/no-debug": "error",
"wdio/no-pause": "error"
}
};
// src/configs/ts-recommended.ts
import { createRequire as createRequire3 } from "node:module";
// src/rules/no-floating-promise.ts
import { createRequire } from "node:module";
var require2 = createRequire(import.meta.url);
var tryRequire = (moduleName) => {
try {
return require2(moduleName);
} catch {
return null;
}
};
var tsEslintPlugin = tryRequire("@typescript-eslint/eslint-plugin");
var tsRule = tsEslintPlugin?.rules["no-floating-promises"];
var error;
var rule4 = {
meta: tsRule?.meta ?? {
type: "problem",
docs: {
description: "Check for unhandled promises",
url: "https://github.com/webdriverio/webdriverio/blob/main/packages/eslint-plugin-wdio/docs/rules/no-floating-promise.md"
},
schema: []
},
create: function(context) {
try {
return tsRule?.create(context) ?? {};
} catch {
console.error("Error in no-floating-promise rule:", error);
return {};
}
}
};
var no_floating_promise_default = rule4;
// src/utils/typeAware.ts
import { createRequire as createRequire2 } from "node:module";
var require3 = createRequire2(import.meta.url);
var isTypeAware = (() => {
try {
require3("typescript-eslint");
return true;
} catch {
return false;
}
})();
// src/configs/ts-recommended.ts
var require4 = createRequire3(import.meta.url);
var tsRecommended = () => {
const tseslint = require4("typescript-eslint");
const typescriptPlugin = {
...plugin_default,
rules: {
...plugin_default.rules,
"no-floating-promise": no_floating_promise_default
}
};
return {
languageOptions: {
globals: sharedGlobals,
parser: tseslint.parser,
parserOptions: {
projectService: true
}
},
plugins: {
wdio: typescriptPlugin
},
rules: {
"wdio/await-expect": "off",
"wdio/no-debug": "error",
"wdio/no-pause": "error",
"wdio/no-floating-promise": "error"
},
// Because of the required `projectService: true,` above we see `Parsing error`, doing the below remove that eslint error.
ignores: ["eslint.config.js", "eslint.config.cjs", "eslint.config.mjs"]
};
};
var rules = {
...plugin_default.rules,
"no-floating-promise": no_floating_promise_default
};
var ts_recommended_default = isTypeAware ? tsRecommended() : void 0;
// package.json
var package_default = {
name: "eslint-plugin-wdio",
version: "9.29.0",
description: "Eslint rules for WebdriverIO",
author: "Christian Bromann <mail@bromann.dev>",
homepage: "https://github.com/webdriverio/webdriverio/tree/main/packages/eslint-plugin-wdio",
license: "MIT",
main: "./build/index.cjs",
module: "./build/index.js",
types: "./build/index.d.ts",
exports: {
".": {
types: "./build/index.d.ts",
import: "./build/index.js",
require: "./build/index.cjs"
}
},
type: "module",
typeScriptVersion: "3.8.3",
engines: {
node: ">=18.20.0"
},
repository: {
type: "git",
url: "git+https://github.com/webdriverio/webdriverio.git",
directory: "packages/eslint-plugin-wdio"
},
keywords: [
"eslint",
"eslintplugin",
"eslint-plugin",
"webdriver",
"wdio"
],
bugs: {
url: "https://github.com/webdriverio/webdriverio/issues"
},
devDependencies: {
"@types/estree": "^1.0.8",
eslint: "^9.39.2",
"expect-webdriverio": "^5.6.5",
globals: "^16.5.0",
"typescript-eslint": "^8.54.0"
},
peerDependencies: {
eslint: "^9.39.2",
globals: "^16.5.0",
"typescript-eslint": "^8.54.0"
},
peerDependenciesMeta: {
"typescript-eslint": {
optional: true
}
}
};
// src/index.ts
var legacyConfig = {
rules: {
"wdio/await-expect": "error",
"wdio/no-debug": "error",
"wdio/no-pause": "error"
},
globals: sharedGlobals,
plugins: ["wdio"]
};
var flatConfig = ts_recommended_default ?? js_recommended_default;
var configs = {
"flat/recommended": flatConfig,
recommended: legacyConfig
};
var rules2 = ts_recommended_default?.rules ?? plugin_default.rules;
var index_default = {
meta: {
name: package_default.name,
version: package_default.version
},
configs,
rules: rules2
};
export {
configs,
index_default as default,
rules2 as rules
};