-
Notifications
You must be signed in to change notification settings - Fork 235
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(rule): autofocus attribute should not be used (#749)
- Loading branch information
1 parent
512a5bd
commit 799382f
Showing
3 changed files
with
114 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { AttrAst, BoundElementPropertyAst } from '@angular/compiler'; | ||
import { IRuleMetadata, RuleFailure, Rules } from 'tslint/lib'; | ||
import { SourceFile } from 'typescript/lib/typescript'; | ||
import { NgWalker } from './angular/ngWalker'; | ||
import { BasicTemplateAstVisitor } from './angular/templates/basicTemplateAstVisitor'; | ||
|
||
export class Rule extends Rules.AbstractRule { | ||
static readonly metadata: IRuleMetadata = { | ||
description: 'Ensure that autofocus property is not used', | ||
options: null, | ||
optionsDescription: 'Not configurable.', | ||
rationale: 'autofocus attribute reduces usability and accessibility for users.', | ||
ruleName: 'template-no-autofocus', | ||
type: 'functionality', | ||
typescriptOnly: true | ||
}; | ||
|
||
static readonly FAILURE_STRING = 'autofocus attribute should not be used, as it reduces usability and accessibility for users.'; | ||
|
||
apply(sourceFile: SourceFile): RuleFailure[] { | ||
return this.applyWithWalker( | ||
new NgWalker(sourceFile, this.getOptions(), { | ||
templateVisitorCtrl: TemplateConditionalComplexityVisitor | ||
}) | ||
); | ||
} | ||
} | ||
|
||
class TemplateConditionalComplexityVisitor extends BasicTemplateAstVisitor { | ||
visitAttr(ast: AttrAst, context: any) { | ||
this.validateAttribute(ast); | ||
super.visitAttr(ast, context); | ||
} | ||
|
||
visitElementProperty(ast: BoundElementPropertyAst) { | ||
this.validateAttribute(ast); | ||
super.visitElementProperty(ast, context); | ||
} | ||
|
||
validateAttribute(ast: AttrAst | BoundElementPropertyAst) { | ||
if (ast.name === 'autofocus') { | ||
const { | ||
sourceSpan: { | ||
end: { offset: endOffset }, | ||
start: { offset: startOffset } | ||
} | ||
} = ast; | ||
this.addFailureFromStartToEnd(startOffset, endOffset, Rule.FAILURE_STRING); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import { assertAnnotated, assertMultipleAnnotated, assertSuccess } from './testHelper'; | ||
import { Rule } from '../src/templateNoAutofocusRule'; | ||
|
||
const { | ||
FAILURE_STRING, | ||
metadata: { ruleName } | ||
} = Rule; | ||
|
||
describe(ruleName, () => { | ||
describe('failure', () => { | ||
it('should fail if autofocus attribute is used', () => { | ||
const source = ` | ||
@Component({ | ||
selector: 'test', | ||
template: '<div autofocus>Autofocus</div>' | ||
~~~~~~~~~ | ||
}) | ||
class Test { | ||
constructor(foo: Observable<Boolean>) {} | ||
} | ||
`; | ||
assertAnnotated({ | ||
message: FAILURE_STRING, | ||
ruleName: ruleName, | ||
source | ||
}); | ||
}); | ||
|
||
it('should fail if autofocus input is used', () => { | ||
const source = ` | ||
@Component({ | ||
selector: 'test', | ||
template: '<div [attr.autofocus]="false">Autofocus</div>' | ||
~~~~~~~~~~~~~~~~~~~~~~~~ | ||
}) | ||
class Test { | ||
constructor(foo: Observable<Boolean>) {} | ||
} | ||
`; | ||
assertAnnotated({ | ||
message: FAILURE_STRING, | ||
ruleName: ruleName, | ||
source | ||
}); | ||
}); | ||
}); | ||
|
||
describe('success', () => { | ||
it('should succeed if autofocus is not used', () => { | ||
const source = ` | ||
@Component({ | ||
selector: 'test', | ||
template: '<div>No Autofocus</div>' | ||
}) | ||
class Test { | ||
constructor(foo: Observable<Boolean>) {} | ||
} | ||
`; | ||
assertSuccess(ruleName, source); | ||
}); | ||
}); | ||
}); |