Skip to content

Commit 05b9b50

Browse files
committed
feat(rules): add 'valid-by-tagname' rule
1 parent 34368a7 commit 05b9b50

File tree

3 files changed

+220
-1
lines changed

3 files changed

+220
-1
lines changed

index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ var noCompoundClasses = require('./lib/rules/no-compound-classes')
3232
var useCountMethod = require('./lib/rules/use-count-method')
3333
var noBrowserDriver = require('./lib/rules/no-browser-driver')
3434
var validById = require('./lib/rules/valid-by-id')
35+
var validByTagName = require('./lib/rules/valid-by-tagname')
3536

3637
module.exports = {
3738
rules: {
@@ -66,7 +67,8 @@ module.exports = {
6667
'no-compound-classes': noCompoundClasses,
6768
'use-count-method': useCountMethod,
6869
'no-browser-driver': noBrowserDriver,
69-
'valid-by-id': validById
70+
'valid-by-id': validById,
71+
'valid-by-tagname': validByTagName
7072
},
7173
configs: {
7274
recommended: {

lib/rules/valid-by-tagname.js

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
'use strict'
2+
3+
/**
4+
* @fileoverview Ensure tag name is html valid when using `by.tagName()` locator.
5+
* @author Raul Gallegos
6+
*/
7+
8+
var validHTMLTagNames = [
9+
'a',
10+
'abbr',
11+
'acronym',
12+
'address',
13+
'applet',
14+
'area',
15+
'article',
16+
'aside',
17+
'audio',
18+
'b',
19+
'base',
20+
'basefont',
21+
'bdi',
22+
'bdo',
23+
'big',
24+
'blockquote',
25+
'body',
26+
'br',
27+
'button',
28+
'canvas',
29+
'caption',
30+
'center',
31+
'cite',
32+
'code',
33+
'col',
34+
'colgroup',
35+
'datalist',
36+
'dd',
37+
'del',
38+
'details',
39+
'dfn',
40+
'dialog',
41+
'dir',
42+
'div',
43+
'dl',
44+
'dt',
45+
'em',
46+
'embed',
47+
'fieldset',
48+
'figcaption',
49+
'figure',
50+
'font',
51+
'footer',
52+
'form',
53+
'frame',
54+
'frameset',
55+
'h1',
56+
'h2',
57+
'h3',
58+
'h4',
59+
'h5',
60+
'h6',
61+
'head',
62+
'header',
63+
'hr',
64+
'html',
65+
'i',
66+
'iframe',
67+
'img',
68+
'input',
69+
'ins',
70+
'kbd',
71+
'keygen',
72+
'label',
73+
'legend',
74+
'li',
75+
'link',
76+
'main',
77+
'map',
78+
'mark',
79+
'menu',
80+
'menuitem',
81+
'meta',
82+
'meter',
83+
'nav',
84+
'noframes',
85+
'noscript',
86+
'object',
87+
'ol',
88+
'optgroup',
89+
'option',
90+
'output',
91+
'p',
92+
'param',
93+
'picture',
94+
'pre',
95+
'progress',
96+
'q',
97+
'rp',
98+
'rt',
99+
'ruby',
100+
's',
101+
'samp',
102+
'script',
103+
'section',
104+
'select',
105+
'small',
106+
'source',
107+
'span',
108+
'strike',
109+
'strong',
110+
'style',
111+
'sub',
112+
'summary',
113+
'sup',
114+
'table',
115+
'tbody',
116+
'td',
117+
'textarea',
118+
'tfoot',
119+
'th',
120+
'thead',
121+
'time',
122+
'title',
123+
'tr',
124+
'track',
125+
'tt',
126+
'u',
127+
'ul',
128+
'var',
129+
'video',
130+
'wbr'
131+
]
132+
133+
module.exports = {
134+
meta: {
135+
schema: []
136+
},
137+
138+
create: function (context) {
139+
return {
140+
'CallExpression': function (node) {
141+
var object = node.callee.object
142+
var property = node.callee.property
143+
144+
var insideByTagName = object && property && object.name === 'by' && property.name === 'tagName'
145+
var argumentExists = node.arguments && node.arguments.length && node.arguments[0].value
146+
147+
if (insideByTagName && argumentExists) {
148+
var tagName = node.arguments[0].value
149+
if (validHTMLTagNames.indexOf(tagName.toLowerCase()) === -1) {
150+
context.report({
151+
node: node,
152+
message: 'Invalid TagName value: "' + tagName + '"'
153+
})
154+
}
155+
}
156+
}
157+
}
158+
}
159+
}

test/rules/valid-by-tagname.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
'use strict'
2+
3+
var rule = require('../../lib/rules/valid-by-tagname')
4+
var RuleTester = require('eslint').RuleTester
5+
6+
var eslintTester = new RuleTester()
7+
8+
eslintTester.run('valid-by-tagname', rule, {
9+
valid: [
10+
'element(by.tagName("a"));',
11+
'element(by.tagName("b"));',
12+
'element(by.tagName("i"));',
13+
'element(by.tagName("A"));',
14+
'element(by.tagName("Area"));',
15+
'element(by.tagName("BlockQuote"));',
16+
'element(by.tagName("h1"));',
17+
'element(by.tagName("H1"));'
18+
],
19+
20+
invalid: [
21+
{
22+
code: 'element(by.tagName("customTagName"));',
23+
errors: [{
24+
message: 'Invalid TagName value: "customTagName"'
25+
}]
26+
},
27+
{
28+
code: 'element(by.tagName("div.classname"));',
29+
errors: [{
30+
message: 'Invalid TagName value: "div.classname"'
31+
}]
32+
},
33+
{
34+
code: 'element(by.tagName("_blockquote"));',
35+
errors: [{
36+
message: 'Invalid TagName value: "_blockquote"'
37+
}]
38+
},
39+
{
40+
code: 'element(by.tagName("divs"));',
41+
errors: [{
42+
message: 'Invalid TagName value: "divs"'
43+
}]
44+
},
45+
{
46+
code: 'element(by.tagName(\'option[value="Test"]\'));',
47+
errors: [{
48+
message: 'Invalid TagName value: "option[value="Test"]"'
49+
}]
50+
},
51+
{
52+
code: 'element(by.tagName(" div "));',
53+
errors: [{
54+
message: 'Invalid TagName value: " div "'
55+
}]
56+
}
57+
]
58+
})

0 commit comments

Comments
 (0)