Skip to content

Commit c1890fd

Browse files
authored
feat(rules): add ion-radio-attributes-renamed rule (#24)
1 parent 92ade8f commit c1890fd

File tree

3 files changed

+170
-1
lines changed

3 files changed

+170
-1
lines changed

README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,9 +370,19 @@ We are looking for contributors to help build these rules out! See [`CONTRIBUTIN
370370
<td></td>
371371
</tr>
372372
<tr>
373-
<th rowspan="2">
373+
<th rowspan="3">
374374
<a href="https://github.com/ionic-team/ionic/blob/master/angular/BREAKING.md#radio">Radio</a>
375375
</th>
376+
<td>:wrench:</td>
377+
<td>:white_check_mark:</td>
378+
<td>
379+
<code>ion-radio-attributes-renamed</code>
380+
</td>
381+
<td>
382+
<a href="https://github.com/dwieeb">@dwieeb</a>
383+
</td>
384+
</tr>
385+
<tr>
376386
<td>:wrench:</td>
377387
<td>:white_check_mark:</td>
378388
<td>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { NgWalker } from 'codelyzer/angular/ngWalker';
2+
import * as Lint from 'tslint';
3+
import * as ts from 'typescript';
4+
5+
import { createAttributesRenamedTemplateVisitorClass } from './helpers/attributesRenamed';
6+
7+
export const ruleName = 'ion-radio-attributes-renamed';
8+
9+
const replacementMap = new Map([['item-left', 'slot="start"'], ['item-right', 'slot="end"']]);
10+
11+
const IonFabAttributesRenamedTemplateVisitor = createAttributesRenamedTemplateVisitorClass('ion-radio', replacementMap);
12+
13+
export class Rule extends Lint.Rules.AbstractRule {
14+
public static metadata: Lint.IRuleMetadata = {
15+
ruleName: ruleName,
16+
type: 'functionality',
17+
description: 'Attributes of ion-radio have been renamed.',
18+
options: null,
19+
optionsDescription: 'Not configurable.',
20+
typescriptOnly: false,
21+
hasFix: true
22+
};
23+
24+
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
25+
return this.applyWithWalker(
26+
new NgWalker(sourceFile, this.getOptions(), {
27+
templateVisitorCtrl: IonFabAttributesRenamedTemplateVisitor
28+
})
29+
);
30+
}
31+
}
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
import { expect } from 'chai';
2+
import { Replacement, Utils } from 'tslint';
3+
import { ruleName } from '../src/ionRadioAttributesRenamedRule';
4+
import { assertAnnotated, assertFailure, assertFailures, assertMultipleAnnotated, assertSuccess } from './testHelper';
5+
6+
describe(ruleName, () => {
7+
describe('success', () => {
8+
it('should work with proper style', () => {
9+
let source = `
10+
@Component({
11+
template: \`<ion-radio slot="start"><ion-radio>\`
12+
})
13+
class Bar{}
14+
`;
15+
assertSuccess(ruleName, source);
16+
});
17+
});
18+
19+
describe('failure', () => {
20+
it('should fail when item-left is used', () => {
21+
let source = `
22+
@Component({
23+
template: \`
24+
<ion-radio item-left></ion-radio>\`
25+
~~~~~~~~~
26+
})
27+
class Bar{}
28+
`;
29+
30+
assertAnnotated({
31+
ruleName,
32+
message: 'The item-left attribute of ion-radio has been renamed. Use slot="start" instead.',
33+
source
34+
});
35+
});
36+
37+
it('should fail when item-right is used', () => {
38+
let source = `
39+
@Component({
40+
template: \`
41+
<ion-radio item-right></ion-radio>\`
42+
~~~~~~~~~~
43+
})
44+
class Bar{}
45+
`;
46+
47+
assertAnnotated({
48+
ruleName,
49+
message: 'The item-right attribute of ion-radio has been renamed. Use slot="end" instead.',
50+
source
51+
});
52+
});
53+
});
54+
55+
describe('replacements', () => {
56+
it('should replace item-left with slot="start"', () => {
57+
let source = `
58+
@Component({
59+
template: \`<ion-radio item-left></ion-radio>
60+
\`
61+
})
62+
class Bar {}
63+
`;
64+
65+
const fail = {
66+
message: 'The item-left attribute of ion-radio has been renamed. Use slot="start" instead.',
67+
startPosition: {
68+
line: 2,
69+
character: 32
70+
},
71+
endPosition: {
72+
line: 2,
73+
character: 41
74+
}
75+
};
76+
77+
const failures = assertFailure(ruleName, source, fail);
78+
const fixes = failures.map(f => f.getFix());
79+
const res = Replacement.applyAll(source, Utils.flatMap(fixes, Utils.arrayify));
80+
81+
let expected = `
82+
@Component({
83+
template: \`<ion-radio slot="start"></ion-radio>
84+
\`
85+
})
86+
class Bar {}
87+
`;
88+
89+
expect(res).to.eq(expected);
90+
});
91+
92+
it('should replace item-right with slot="end"', () => {
93+
let source = `
94+
@Component({
95+
template: \`<ion-radio item-right></ion-radio>
96+
\`
97+
})
98+
class Bar {}
99+
`;
100+
101+
const fail = {
102+
message: 'The item-right attribute of ion-radio has been renamed. Use slot="end" instead.',
103+
startPosition: {
104+
line: 2,
105+
character: 32
106+
},
107+
endPosition: {
108+
line: 2,
109+
character: 42
110+
}
111+
};
112+
113+
const failures = assertFailure(ruleName, source, fail);
114+
const fixes = failures.map(f => f.getFix());
115+
const res = Replacement.applyAll(source, Utils.flatMap(fixes, Utils.arrayify));
116+
117+
let expected = `
118+
@Component({
119+
template: \`<ion-radio slot="end"></ion-radio>
120+
\`
121+
})
122+
class Bar {}
123+
`;
124+
125+
expect(res).to.eq(expected);
126+
});
127+
});
128+
});

0 commit comments

Comments
 (0)