@testgorilla/tgo-linting 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Readme.md +124 -0
- package/package.json +42 -0
- package/src/configs/recommended.d.ts +7 -0
- package/src/configs/recommended.js +9 -0
- package/src/configs/recommended.js.map +1 -0
- package/src/index.d.ts +16 -0
- package/src/index.js +10 -0
- package/src/index.js.map +1 -0
- package/src/rules/index.d.ts +5 -0
- package/src/rules/index.js +8 -0
- package/src/rules/index.js.map +1 -0
- package/src/rules/require-data-testid.d.ts +9 -0
- package/src/rules/require-data-testid.js +74 -0
- package/src/rules/require-data-testid.js.map +1 -0
package/Readme.md
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# @testgorilla/tgo-linting
|
|
2
|
+
|
|
3
|
+
Linting rules and code quality standards for TestGorilla projects.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @testgorilla/tgo-linting --save-dev
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
Add the plugin to your ESLint configuration:
|
|
14
|
+
|
|
15
|
+
### Flat Config (ESLint 9+)
|
|
16
|
+
|
|
17
|
+
```javascript
|
|
18
|
+
import tgoPlugin from '@testgorilla/tgo-linting';
|
|
19
|
+
|
|
20
|
+
export default [
|
|
21
|
+
{
|
|
22
|
+
plugins: {
|
|
23
|
+
tgo: tgoPlugin,
|
|
24
|
+
},
|
|
25
|
+
rules: {
|
|
26
|
+
'tgo/require-data-testid': 'warn',
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
];
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Or use the recommended configuration:
|
|
33
|
+
|
|
34
|
+
```javascript
|
|
35
|
+
import tgoPlugin from '@testgorilla/tgo-linting';
|
|
36
|
+
|
|
37
|
+
export default [
|
|
38
|
+
tgoPlugin.configs.recommended,
|
|
39
|
+
// Your other configurations
|
|
40
|
+
];
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Rules
|
|
44
|
+
|
|
45
|
+
### `tgo/require-data-testid`
|
|
46
|
+
|
|
47
|
+
Ensures that specific HTML elements have a `data-testid` attribute for testing purposes.
|
|
48
|
+
|
|
49
|
+
**Note:** This rule requires an ESLint setup that parses template ASTs (e.g., `@angular-eslint/template-parser` for Angular projects). It will not run against plain JS/TS ASTs.
|
|
50
|
+
|
|
51
|
+
#### Default Elements
|
|
52
|
+
|
|
53
|
+
By default, this rule checks the following elements:
|
|
54
|
+
- `button`
|
|
55
|
+
- `mat-checkbox`
|
|
56
|
+
- `input`
|
|
57
|
+
- `mat-radio-button`
|
|
58
|
+
- `mat-radio-group`
|
|
59
|
+
- `h1`
|
|
60
|
+
- `table`, `header-table`, `mat-table`
|
|
61
|
+
- `img`
|
|
62
|
+
- `textarea`
|
|
63
|
+
- `ng-select`
|
|
64
|
+
- `video`
|
|
65
|
+
- `app-tgo-choice`
|
|
66
|
+
- `testgorilla-confirm-dialog`
|
|
67
|
+
- `mat-form-field`
|
|
68
|
+
- `tgo-checkout-message`
|
|
69
|
+
- `mat-dialog-actions`
|
|
70
|
+
- `ui-button`
|
|
71
|
+
|
|
72
|
+
#### Configuration
|
|
73
|
+
|
|
74
|
+
You can customize which elements to check:
|
|
75
|
+
|
|
76
|
+
```javascript
|
|
77
|
+
{
|
|
78
|
+
rules: {
|
|
79
|
+
'tgo/require-data-testid': ['warn', {
|
|
80
|
+
tags: ['button', 'input', 'custom-element']
|
|
81
|
+
}]
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
#### Examples
|
|
87
|
+
|
|
88
|
+
❌ **Incorrect**
|
|
89
|
+
|
|
90
|
+
```html
|
|
91
|
+
<button>Click me</button>
|
|
92
|
+
<input type="text" />
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
✅ **Correct**
|
|
96
|
+
|
|
97
|
+
```html
|
|
98
|
+
<button data-testid="submit-button">Click me</button>
|
|
99
|
+
<input type="text" data-testid="email-input" />
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Development
|
|
103
|
+
|
|
104
|
+
### Building
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
nx build tgo-linting
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Testing
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
nx test tgo-linting
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Linting
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
nx lint tgo-linting
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## License
|
|
123
|
+
|
|
124
|
+
PROPRIETARY - © TestGorilla
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@testgorilla/tgo-linting",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Linting rules and code quality standards for TestGorilla projects",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"eslint",
|
|
7
|
+
"eslintplugin",
|
|
8
|
+
"eslint-plugin",
|
|
9
|
+
"testgorilla",
|
|
10
|
+
"angular",
|
|
11
|
+
"testing",
|
|
12
|
+
"linting",
|
|
13
|
+
"code-quality",
|
|
14
|
+
"accessibility"
|
|
15
|
+
],
|
|
16
|
+
"author": "TestGorilla",
|
|
17
|
+
"license": "PROPRIETARY",
|
|
18
|
+
"main": "./src/index.js",
|
|
19
|
+
"types": "./src/index.d.ts",
|
|
20
|
+
"files": [
|
|
21
|
+
"**/*"
|
|
22
|
+
],
|
|
23
|
+
"sideEffects": false,
|
|
24
|
+
"private": false,
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public",
|
|
27
|
+
"registry": "https://registry.npmjs.org/"
|
|
28
|
+
},
|
|
29
|
+
"peerDependencies": {
|
|
30
|
+
"eslint": "^8 || ^9",
|
|
31
|
+
"tslib": "^2.0.0"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@typescript-eslint/utils": "^8.54.0"
|
|
35
|
+
},
|
|
36
|
+
"displayName": "TGO Linting",
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "https://github.com/testgorilla/tgo-fe-libraries"
|
|
40
|
+
},
|
|
41
|
+
"type": "commonjs"
|
|
42
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recommended.js","sourceRoot":"","sources":["../../../../../packages/tgo-linting/src/configs/recommended.ts"],"names":[],"mappings":";;AAAA,kBAAe;IACb,OAAO,EAAE,CAAC,KAAK,CAAC;IAChB,KAAK,EAAE;QACL,yBAAyB,EAAE,OAAO;KACnC;CACF,CAAA","sourcesContent":["export default {\n plugins: ['tgo'],\n rules: {\n 'tgo/require-data-testid': 'error',\n },\n}"]}
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
declare const _default: {
|
|
2
|
+
rules: {
|
|
3
|
+
'require-data-testid': import("@typescript-eslint/utils/dist/ts-eslint").RuleModule<"missingTestId", [{
|
|
4
|
+
tags?: string[];
|
|
5
|
+
}?], unknown, import("@typescript-eslint/utils/dist/ts-eslint").RuleListener>;
|
|
6
|
+
};
|
|
7
|
+
configs: {
|
|
8
|
+
recommended: {
|
|
9
|
+
plugins: string[];
|
|
10
|
+
rules: {
|
|
11
|
+
'tgo/require-data-testid': string;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
export = _default;
|
package/src/index.js
ADDED
package/src/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/tgo-linting/src/index.ts"],"names":[],"mappings":";AAAA,mCAA+B;AAC/B,uDAA+C;AAE/C,iBAAS;IACP,KAAK,EAAL,aAAK;IACL,OAAO,EAAE;QACP,WAAW,EAAX,qBAAW;KACZ;CACF,CAAA","sourcesContent":["import { rules } from './rules'\nimport recommended from './configs/recommended'\n\nexport = {\n rules,\n configs: {\n recommended,\n },\n}\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.rules = void 0;
|
|
4
|
+
const require_data_testid_1 = require("./require-data-testid");
|
|
5
|
+
exports.rules = {
|
|
6
|
+
'require-data-testid': require_data_testid_1.default,
|
|
7
|
+
};
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/tgo-linting/src/rules/index.ts"],"names":[],"mappings":";;;AAAA,+DAAqD;AAExC,QAAA,KAAK,GAAG;IACnB,qBAAqB,EAAE,6BAAiB;CACzC,CAAA","sourcesContent":["import requireDataTestId from './require-data-testid'\n\nexport const rules = {\n 'require-data-testid': requireDataTestId,\n}"]}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const DEFAULT_TAGS = [
|
|
4
|
+
'button',
|
|
5
|
+
'mat-checkbox',
|
|
6
|
+
'input',
|
|
7
|
+
'mat-radio-button',
|
|
8
|
+
'mat-radio-group',
|
|
9
|
+
'h1',
|
|
10
|
+
'table',
|
|
11
|
+
'header-table',
|
|
12
|
+
'mat-table',
|
|
13
|
+
'img',
|
|
14
|
+
'textarea',
|
|
15
|
+
'ng-select',
|
|
16
|
+
'video',
|
|
17
|
+
'app-tgo-choice',
|
|
18
|
+
'testgorilla-confirm-dialog',
|
|
19
|
+
'mat-form-field',
|
|
20
|
+
'tgo-checkout-message',
|
|
21
|
+
'mat-dialog-actions',
|
|
22
|
+
'ui-button',
|
|
23
|
+
];
|
|
24
|
+
const rule = {
|
|
25
|
+
meta: {
|
|
26
|
+
type: 'suggestion',
|
|
27
|
+
docs: {
|
|
28
|
+
description: 'Ensures specific elements have data-testid attribute',
|
|
29
|
+
},
|
|
30
|
+
schema: [
|
|
31
|
+
{
|
|
32
|
+
type: 'object',
|
|
33
|
+
properties: {
|
|
34
|
+
tags: {
|
|
35
|
+
type: 'array',
|
|
36
|
+
items: { type: 'string' },
|
|
37
|
+
uniqueItems: true,
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
additionalProperties: false,
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
messages: {
|
|
44
|
+
missingTestId: "<{{tag}}> must have 'data-testid' attribute",
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
create(context) {
|
|
48
|
+
var _a, _b;
|
|
49
|
+
const configuration = (_a = context.options[0]) !== null && _a !== void 0 ? _a : {};
|
|
50
|
+
const tagsToCheck = (_b = configuration.tags) !== null && _b !== void 0 ? _b : DEFAULT_TAGS;
|
|
51
|
+
return {
|
|
52
|
+
Element(node) {
|
|
53
|
+
var _a, _b, _c;
|
|
54
|
+
if (!tagsToCheck.includes(node.name)) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const hasTestId = ((_a = node.attributes) === null || _a === void 0 ? void 0 : _a.some((attr) => attr.name === 'data-testid')) ||
|
|
58
|
+
((_b = node.inputs) === null || _b === void 0 ? void 0 : _b.some((attr) => attr.name === 'data-testid')) ||
|
|
59
|
+
((_c = node.inputs) === null || _c === void 0 ? void 0 : _c.some((attr) => attr.name === 'attr.data-testid'));
|
|
60
|
+
if (!hasTestId) {
|
|
61
|
+
context.report({
|
|
62
|
+
node: node,
|
|
63
|
+
messageId: 'missingTestId',
|
|
64
|
+
data: {
|
|
65
|
+
tag: node.name,
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
exports.default = rule;
|
|
74
|
+
//# sourceMappingURL=require-data-testid.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"require-data-testid.js","sourceRoot":"","sources":["../../../../../packages/tgo-linting/src/rules/require-data-testid.ts"],"names":[],"mappings":";;AAUA,MAAM,YAAY,GAAG;IACnB,QAAQ;IACR,cAAc;IACd,OAAO;IACP,kBAAkB;IAClB,iBAAiB;IACjB,IAAI;IACJ,OAAO;IACP,cAAc;IACd,WAAW;IACX,KAAK;IACL,UAAU;IACV,WAAW;IACX,OAAO;IACP,gBAAgB;IAChB,4BAA4B;IAC5B,gBAAgB;IAChB,sBAAsB;IACtB,oBAAoB;IACpB,WAAW;CACZ,CAAA;AAED,MAAM,IAAI,GAA6C;IACrD,IAAI,EAAE;QACJ,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE;YACJ,WAAW,EAAE,sDAAsD;SACpE;QACD,MAAM,EAAE;YACN;gBACE,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,IAAI,EAAE;wBACJ,IAAI,EAAE,OAAO;wBACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;wBACzB,WAAW,EAAE,IAAI;qBAClB;iBACF;gBACD,oBAAoB,EAAE,KAAK;aAC5B;SACF;QACD,QAAQ,EAAE;YACR,aAAa,EAAE,6CAA6C;SAC7D;KACF;IAED,MAAM,CAAC,OAAO;;QACZ,MAAM,aAAa,GAAG,MAAA,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,mCAAI,EAAE,CAAA;QAC9C,MAAM,WAAW,GAAG,MAAA,aAAa,CAAC,IAAI,mCAAI,YAAY,CAAA;QAEtD,OAAO;YACL,OAAO,CAAC,IAAiI;;gBACvI,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;oBACrC,OAAM;gBACR,CAAC;gBAED,MAAM,SAAS,GACb,CAAA,MAAA,IAAI,CAAC,UAAU,0CAAE,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,aAAa,CAAC;qBAC5D,MAAA,IAAI,CAAC,MAAM,0CAAE,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,aAAa,CAAC,CAAA;qBACxD,MAAA,IAAI,CAAC,MAAM,0CAAE,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,kBAAkB,CAAC,CAAA,CAAA;gBAE/D,IAAI,CAAC,SAAS,EAAE,CAAC;oBACf,OAAO,CAAC,MAAM,CAAC;wBACb,IAAI,EAAE,IAAgC;wBACtC,SAAS,EAAE,eAAe;wBAC1B,IAAI,EAAE;4BACJ,GAAG,EAAE,IAAI,CAAC,IAAI;yBACf;qBACF,CAAC,CAAA;gBACJ,CAAC;YACH,CAAC;SACF,CAAA;IACH,CAAC;CACF,CAAA;AAED,kBAAe,IAAI,CAAA","sourcesContent":["import { TSESLint, TSESTree } from '@typescript-eslint/utils'\n\ntype Options = [\n {\n tags?: string[]\n }?\n]\n\ntype MessageIds = 'missingTestId'\n\nconst DEFAULT_TAGS = [\n 'button',\n 'mat-checkbox',\n 'input',\n 'mat-radio-button',\n 'mat-radio-group',\n 'h1',\n 'table',\n 'header-table',\n 'mat-table',\n 'img',\n 'textarea',\n 'ng-select',\n 'video',\n 'app-tgo-choice',\n 'testgorilla-confirm-dialog',\n 'mat-form-field',\n 'tgo-checkout-message',\n 'mat-dialog-actions',\n 'ui-button',\n]\n\nconst rule: TSESLint.RuleModule<MessageIds, Options> = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Ensures specific elements have data-testid attribute',\n },\n schema: [\n {\n type: 'object',\n properties: {\n tags: {\n type: 'array',\n items: { type: 'string' },\n uniqueItems: true,\n },\n },\n additionalProperties: false,\n },\n ],\n messages: {\n missingTestId: \"<{{tag}}> must have 'data-testid' attribute\",\n },\n },\n\n create(context) {\n const configuration = context.options[0] ?? {}\n const tagsToCheck = configuration.tags ?? DEFAULT_TAGS\n\n return {\n Element(node: TSESLint.RuleListener['Element'] & { name: string; attributes?: Array<{ name: string }>; inputs?: Array<{ name: string }> }) {\n if (!tagsToCheck.includes(node.name)) {\n return\n }\n\n const hasTestId =\n node.attributes?.some((attr) => attr.name === 'data-testid') ||\n node.inputs?.some((attr) => attr.name === 'data-testid') ||\n node.inputs?.some((attr) => attr.name === 'attr.data-testid')\n\n if (!hasTestId) {\n context.report({\n node: node as unknown as TSESTree.Node,\n messageId: 'missingTestId',\n data: {\n tag: node.name,\n },\n })\n }\n },\n }\n },\n}\n\nexport default rule\n"]}
|