Skip to content

Commit

Permalink
feat(rules): add new ion-button attribute rules
Browse files Browse the repository at this point in the history
  • Loading branch information
cwoolum committed May 30, 2018
1 parent 24a802b commit 7063c57
Show file tree
Hide file tree
Showing 4 changed files with 281 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ Rules without an **author** and without green checkmarks need some help! See [#c
| `ion-alert-title-and-subtitle-are-now-header-and-sub-header` | [#alert](https://github.com/ionic-team/ionic/blob/master/angular/BREAKING.md#alert) | :white_check_mark: tested<br> :white_check_mark: fixable | [@cwoolum](https://github.com/cwoolum/) |
| `ion-back-button-is-no-longer-added-to-navigation-bar` | [#back-button](https://github.com/ionic-team/ionic/blob/master/angular/BREAKING.md#back-button) | :black_square_button: tested<br> :black_square_button: fixable | |
| `ion-button-is-now-an-element` | [#button](https://github.com/ionic-team/ionic/blob/master/angular/BREAKING.md#button) | :white_check_mark: tested<br> :black_square_button: fixable | [@cwoolum](https://github.com/cwoolum/) |
| `ion-button-attributes-are-renamed` | [#attributes-renamed](https://github.com/ionic-team/ionic/blob/master/angular/BREAKING.md#attributes-renamed) | :black_square_button: tested<br> :black_square_button: fixable | |
| `ion-button-attributes-are-renamed` | [#attributes-renamed](https://github.com/ionic-team/ionic/blob/master/angular/BREAKING.md#attributes-renamed) | :white_check_mark: tested<br> :black_square_button: fixable | [@cwoolum](https://github.com/cwoolum/) |
| `ion-chip-markup-has-changed` | [#chip](https://github.com/ionic-team/ionic/blob/master/angular/BREAKING.md#chip) | :black_square_button: tested<br> :black_square_button: fixable | |
| `ion-datetime-class-has-been-renamed` | [#datetime](https://github.com/ionic-team/ionic/blob/master/angular/BREAKING.md#datetime) | :black_square_button: tested<br> :black_square_button: fixable | |
| `ion-fab-markup-has-changed` | [#fab-markup-changed](https://github.com/ionic-team/ionic/blob/master/angular/BREAKING.md#markup-changed-2) | :black_square_button: tested<br> :black_square_button: fixable | |
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export { Rule as IonTabBadgeStyleIsNowBadgeStyle } from './ionTabBadgeStyleIsNow
export { Rule as ActionSheetTitleAndSubtitleAreNowHeaderAndSubheader } from './ionActionSheetTitleAndSubtitleAreNowHeaderAndSubHeaderRule';
export { Rule as AlertTitleAndSubtitleAreNowHeaderAndSubheader } from './ionAlertTitleAndSubtitleAreNowHeaderAndSubHeaderRule';
export { Rule as IonButtonIsNowAnElementRule } from './ionButtonIsNowAnElementRule';
export { Rule as IonButtonAttributesAreRenamedRule } from './ionButtonAttributesAreRenamedRule';

export * from 'codelyzer/angular/config';

Expand Down
74 changes: 74 additions & 0 deletions src/ionButtonAttributesAreRenamedRule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import * as ast from '@angular/compiler';
import { NgWalker } from 'codelyzer/angular/ngWalker';
import { BasicTemplateAstVisitor } from 'codelyzer/angular/templates/basicTemplateAstVisitor';
import * as Lint from 'tslint';
import * as ts from 'typescript';

export const ruleName = 'ion-button-attributes-are-renamed';

class IonButtonAttributesAreRenamedTemplateVisitor extends BasicTemplateAstVisitor {
visitElement(element: ast.ElementAst, context: any): any {
if (element.name && element.name === 'ion-button') {
element.attrs.forEach(attribute => {
let message = '';

switch (attribute.name) {
case 'icon-left':
case 'icon-start':
message = `${attribute.name} has been replaced by the slot="start" attribute.`;
break;

case 'icon-right':
case 'icon-end':
message = `${attribute.name} has been replaced by the slot="end" attribute.`;
break;

case 'small':
case 'large':
message = `${attribute.name} has been replaced by the size attribute.`;
break;

case 'clear':
case 'outline':
case 'solid':
message = `${attribute.name} has been replaced by the fill attribute.`;
break;

case 'full':
case 'block':
message = `${attribute.name} has been replaced by the expand attribute.`;
break;
}

if (message) {
const start = attribute.sourceSpan.start.offset;
//const absolutePosition = this.getSourcePosition(start - 1);

this.addFailure(this.createFailure(start, attribute.name.length, message));
}
});
}

super.visitElement(element, context);
}
}

export class Rule extends Lint.Rules.AbstractRule {
public static metadata: Lint.IRuleMetadata = {
ruleName: ruleName,
type: 'functionality',
description: 'Existing Ion Button attributes have been renamed.',
options: null,
optionsDescription: 'Not configurable.',
typescriptOnly: false,
hasFix: true
};

public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
return this.applyWithWalker(
new NgWalker(sourceFile, this.getOptions(), {
templateVisitorCtrl: IonButtonAttributesAreRenamedTemplateVisitor
})
);
}
}
205 changes: 205 additions & 0 deletions test/IonButtonAttributesAreRenamed.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
import { ruleName } from '../src/ionButtonAttributesAreRenamedRule';
import { assertAnnotated, assertSuccess } from './testHelper';

describe(ruleName, () => {
describe('success', () => {
it('should work with proper style', () => {
let source = `
@Component({
template: \`<ion-button slot="start"><ion-button>\`
})
class Bar{}
`;
assertSuccess(ruleName, source);
});
});

describe('failure', () => {
it('should fail when icon-left is used', () => {
let source = `
@Component({
template: \`
<ion-button icon-left></ion-button>\`
~~~~~~~~~
})
class Bar{}
`;

assertAnnotated({
ruleName,
message: 'icon-left has been replaced by the slot="start" attribute.',
source
});
});

it('should fail when icon-start is used', () => {
let source = `
@Component({
template: \`
<ion-button icon-start></ion-button>\`
~~~~~~~~~~
})
class Bar{}
`;

assertAnnotated({
ruleName,
message: 'icon-start has been replaced by the slot="start" attribute.',
source
});
});

it('should fail when icon-right is used', () => {
let source = `
@Component({
template: \`
<ion-button icon-right></ion-button>\`
~~~~~~~~~~
})
class Bar{}
`;

assertAnnotated({
ruleName,
message: 'icon-right has been replaced by the slot="end" attribute.',
source
});
});

it('should fail when icon-end is used', () => {
let source = `
@Component({
template: \`
<ion-button icon-end></ion-button>\`
~~~~~~~~
})
class Bar{}
`;

assertAnnotated({
ruleName,
message: 'icon-end has been replaced by the slot="end" attribute.',
source
});
});

it('should fail when small is used', () => {
let source = `
@Component({
template: \`
<ion-button small></ion-button>\`
~~~~~
})
class Bar{}
`;

assertAnnotated({
ruleName,
message: 'small has been replaced by the size attribute.',
source
});
});

it('should fail when large is used', () => {
let source = `
@Component({
template: \`
<ion-button large></ion-button>\`
~~~~~
})
class Bar{}
`;

assertAnnotated({
ruleName,
message: 'large has been replaced by the size attribute.',
source
});
});

it('should fail when clear is used', () => {
let source = `
@Component({
template: \`
<ion-button clear></ion-button>\`
~~~~~
})
class Bar{}
`;

assertAnnotated({
ruleName,
message: 'clear has been replaced by the fill attribute.',
source
});
});

it('should fail when outline is used', () => {
let source = `
@Component({
template: \`
<ion-button outline></ion-button>\`
~~~~~~~
})
class Bar{}
`;

assertAnnotated({
ruleName,
message: 'outline has been replaced by the fill attribute.',
source
});
});

it('should fail when solid is used', () => {
let source = `
@Component({
template: \`
<ion-button solid></ion-button>\`
~~~~~
})
class Bar{}
`;

assertAnnotated({
ruleName,
message: 'solid has been replaced by the fill attribute.',
source
});
});

it('should fail when full is used', () => {
let source = `
@Component({
template: \`
<ion-button full></ion-button>\`
~~~~
})
class Bar{}
`;

assertAnnotated({
ruleName,
message: 'full has been replaced by the expand attribute.',
source
});
});

it('should fail when block is used', () => {
let source = `
@Component({
template: \`
<ion-button block></ion-button>\`
~~~~~
})
class Bar{}
`;

assertAnnotated({
ruleName,
message: 'block has been replaced by the expand attribute.',
source
});
});
});
});

0 comments on commit 7063c57

Please sign in to comment.