Skip to content

Commit

Permalink
chore: add toggle migration (#5835)
Browse files Browse the repository at this point in the history
  • Loading branch information
vladimirpotekhin authored Nov 2, 2023
1 parent 6303efd commit da739b5
Show file tree
Hide file tree
Showing 12 changed files with 257 additions and 7 deletions.
5 changes: 5 additions & 0 deletions projects/cdk/schematics/ng-update/interfaces/html-comment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface HtmlComment {
readonly tag: string;
readonly withAttrs: string[];
readonly comment: string;
}
1 change: 1 addition & 0 deletions projects/cdk/schematics/ng-update/interfaces/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './asset';
export * from './html-comment';
export * from './migration-warning';
export * from './removable-input';
export * from './removed-module';
Expand Down
6 changes: 6 additions & 0 deletions projects/cdk/schematics/ng-update/utils/templates/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export * from './remove-inputs';
export * from './replace-attr-values';
export * from './replace-attrs';
export * from './replace-tag';
export * from './replace-tags';
export * from './template-comments';
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import {UpdateRecorder} from '@angular-devkit/schematics';
import {DevkitFileSystem} from 'ng-morph';

import {TODO_MARK} from '../../../utils/insert-todo';
import {findElementsWithAttributeOnTag} from '../../../utils/templates/elements';
import {
getTemplateFromTemplateResource,
getTemplateOffset,
} from '../../../utils/templates/template-resource';
import {TemplateResource} from '../../interfaces';
import {HtmlComment} from '../../interfaces';

export function addHTMLCommentTags({
resource,
recorder,
fileSystem,
data,
}: {
fileSystem: DevkitFileSystem;
recorder: UpdateRecorder;
data: readonly HtmlComment[];
resource: TemplateResource;
}): void {
const template = getTemplateFromTemplateResource(resource, fileSystem);
const templateOffset = getTemplateOffset(resource);

data.forEach(({comment, tag, withAttrs}) => {
const elementStartOffsets = [
...findElementsWithAttributeOnTag(template, withAttrs, [tag]),
...findElementsWithAttributeOnTag(
template,
withAttrs.map(attr => `[${attr}]`),
[tag],
),
].map(
({sourceCodeLocation}) =>
(sourceCodeLocation?.startOffset || 0) + templateOffset,
);

elementStartOffsets.forEach(offset => {
recorder.insertRight(offset, `<!-- ${TODO_MARK} ${comment} -->\n`);
});
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import {HtmlComment} from '../../../interfaces';

export const HTML_COMMENTS: HtmlComment[] = [
{
tag: `tui-toggle`,
withAttrs: [`singleColor`, `showLoader`],
comment: `toggle [singleColor] and [showLoader] inputs have been removed due to design changes`,
},
];
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ export const IDENTIFIERS_TO_REPLACE: ReplacementIdentifier[] = [
from: {name: `TuiRadioModule`, moduleSpecifier: `@taiga-ui/experimental`},
to: {name: `TuiRadioModule`, moduleSpecifier: `@taiga-ui/kit`},
},
{
from: {name: `TuiToggleModule`, moduleSpecifier: `@taiga-ui/experimental`},
to: {name: `TuiToggleModule`, moduleSpecifier: `@taiga-ui/kit`},
},
{
from: {name: `TuiTextAreaModule`, moduleSpecifier: `@taiga-ui/kit`},
to: {name: `TuiTextareaModule`, moduleSpecifier: `@taiga-ui/kit`},
Expand Down
5 changes: 5 additions & 0 deletions projects/cdk/schematics/ng-update/v4/steps/constants/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from './attrs-to-replace';
export * from './html-comments';
export * from './identifiers-to-replace';
export * from './inputs-to-remove';
export * from './tags-to-replace';
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ import {RemovableInput} from '../../../interfaces';

export const INPUTS_TO_REMOVE: RemovableInput[] = [
{inputName: `active`, tags: [`tui-card`, `tui-thumbnail-card`]},
{inputName: `showLoader`, tags: [`tui-toggle`]},
{inputName: `singleColor`, tags: [`tui-toggle`]},
];
27 changes: 20 additions & 7 deletions projects/cdk/schematics/ng-update/v4/steps/migrate-templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,24 @@ import {setupProgressLogger} from '../../../utils/progress';
import {getComponentTemplates} from '../../../utils/templates/get-component-templates';
import {getPathFromTemplateResource} from '../../../utils/templates/template-resource';
import {TemplateResource} from '../../interfaces/template-resource';
import {removeInputs} from '../../utils/templates/remove-inputs';
import {replaceAttrs} from '../../utils/templates/replace-attrs';
import {replaceTags} from '../../utils/templates/replace-tags';
import {ATTRS_TO_REPLACE} from './constants/attrs-to-replace';
import {INPUTS_TO_REMOVE} from './constants/inputs-to-remove';
import {TAGS_TO_REPLACE} from './constants/tags-to-replace';
import {migrateBadgeValue, migrateCheckbox, migrateRadio} from './templates';
import {
addHTMLCommentTags,
removeInputs,
replaceAttrs,
replaceTags,
} from '../../utils/templates';
import {
ATTRS_TO_REPLACE,
HTML_COMMENTS,
INPUTS_TO_REMOVE,
TAGS_TO_REPLACE,
} from './constants';
import {
migrateBadgeValue,
migrateCheckbox,
migrateRadio,
migrateToggle,
} from './templates';

export function migrateTemplates(fileSystem: DevkitFileSystem, options: TuiSchema): void {
!options[`skip-logs`] &&
Expand All @@ -28,12 +39,14 @@ export function migrateTemplates(fileSystem: DevkitFileSystem, options: TuiSchem
const componentWithTemplatesPaths = getComponentTemplates(ALL_TS_FILES);

const actions = [
getAction({action: addHTMLCommentTags, requiredData: HTML_COMMENTS}),
getAction({action: replaceTags, requiredData: TAGS_TO_REPLACE}),
getAction({action: replaceAttrs, requiredData: ATTRS_TO_REPLACE}),
getAction({action: removeInputs, requiredData: INPUTS_TO_REMOVE}),
migrateBadgeValue,
migrateCheckbox,
migrateRadio,
migrateToggle,
] as const;

const progressLog = setupProgressLogger({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './migrate-checkbox';
export * from './migrate-radio';
export * from './migrate-toggle';
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import {UpdateRecorder} from '@angular-devkit/schematics';
import {DevkitFileSystem} from 'ng-morph';

import {findElementsByTagName} from '../../../../../utils/templates/elements';
import {
getTemplateFromTemplateResource,
getTemplateOffset,
} from '../../../../../utils/templates/template-resource';
import {TemplateResource} from '../../../../interfaces';
import {closeStartTag, removeClosingTag, replaceOpenTag, replaceSizeAttr} from './common';

export function migrateToggle({
resource,
recorder,
fileSystem,
}: {
fileSystem: DevkitFileSystem;
recorder: UpdateRecorder;
resource: TemplateResource;
}): void {
const template = getTemplateFromTemplateResource(resource, fileSystem);
const templateOffset = getTemplateOffset(resource);

const elements = findElementsByTagName(template, `tui-toggle`);

elements.forEach(({attrs, sourceCodeLocation}) => {
if (!sourceCodeLocation) {
return;
}

replaceSizeAttr(attrs, sourceCodeLocation, recorder, templateOffset);
replaceOpenTag(sourceCodeLocation, recorder, templateOffset, {
tag: `tui-toggle`,
directive: `tuiToggle`,
type: `checkbox`,
});
closeStartTag(sourceCodeLocation, recorder, templateOffset);
removeClosingTag(sourceCodeLocation, recorder, templateOffset);
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/* eslint-disable rxjs/no-topromise */
import {HostTree} from '@angular-devkit/schematics';
import {SchematicTestRunner, UnitTestTree} from '@angular-devkit/schematics/testing';
import {TuiSchema} from '@taiga-ui/cdk/schematics/ng-add/schema';
import {
createProject,
createSourceFile,
resetActiveProject,
saveActiveProject,
setActiveProject,
} from 'ng-morph';
import {join} from 'path';

import {createAngularJson} from '../../../utils/create-angular-json';

const collectionPath = join(__dirname, `../../../migration.json`);

const COMPONENT_BEFORE = `
import { TuiToggleModule } from "@taiga-ui/experimental";
@Component({
standalone: true,
templateUrl: './test.template.html',
imports: [TuiToggleModule]
})
export class TestComponent {
}`;

const COMPONENT_AFTER = `import { TuiToggleModule } from "@taiga-ui/kit";
@Component({
standalone: true,
templateUrl: './test.template.html',
imports: [TuiToggleModule]
})
export class TestComponent {
}`;

const TEMPLATE_BEFORE = `
<tui-toggle
formControlName="test"
class="toggle"
[showIcons]="true"
></tui-toggle>
<tui-toggle
[showIcons]="true"
[singleColor]="true"
></tui-toggle>
`;

const TEMPLATE_AFTER = `
<input
tuiToggle
type="checkbox"
formControlName="test"
class="toggle"
[showIcons]="true"
/>
<!-- TODO: (Taiga UI migration) toggle [singleColor] and [showLoader] inputs have been removed due to design changes -->
<input
tuiToggle
type="checkbox"
[showIcons]="true"
${``}
/>
`;

describe(`ng-update`, () => {
let host: UnitTestTree;
let runner: SchematicTestRunner;

beforeEach(() => {
host = new UnitTestTree(new HostTree());
runner = new SchematicTestRunner(`schematics`, collectionPath);

setActiveProject(createProject(host));

createMainFiles();

saveActiveProject();
});

it(`should migrate toggle in template`, async () => {
const tree = await runner
.runSchematicAsync(
`updateToV4`,
{'skip-logs': process.env[`TUI_CI`] === `true`} as Partial<TuiSchema>,
host,
)
.toPromise();

expect(tree.readContent(`test/app/test.template.html`)).toEqual(TEMPLATE_AFTER);
});

it(`should migrate toggle references in ts files`, async () => {
const tree = await runner
.runSchematicAsync(
`updateToV4`,
{'skip-logs': process.env[`TUI_CI`] === `true`} as Partial<TuiSchema>,
host,
)
.toPromise();

expect(tree.readContent(`test/app/test.component.ts`)).toEqual(COMPONENT_AFTER);
});

afterEach(() => resetActiveProject());
});

function createMainFiles(): void {
createSourceFile(`test/app/test.component.ts`, COMPONENT_BEFORE);

createSourceFile(`test/app/test.template.html`, TEMPLATE_BEFORE);

createAngularJson();
createSourceFile(
`package.json`,
`{"dependencies": {"@angular/core": "~13.0.0", "@taiga-ui/addon-commerce": "~3.42.0"}}`,
);
}

0 comments on commit da739b5

Please sign in to comment.