Skip to content

Commit

Permalink
fix(transloco): fixed file matching on Windows OS (#797)
Browse files Browse the repository at this point in the history
  • Loading branch information
hakimio authored Sep 16, 2024
1 parent e327f3b commit 71aade9
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 63 deletions.
22 changes: 16 additions & 6 deletions libs/transloco-schematics/src/migrate/ngx-translate-migration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,17 +100,20 @@ export function run(path) {
const serviceCallRgx = ({ map, func }) =>
new RegExp(
`(?:(?:\\s*|this\\.)${sanitizedName})(?:\\s*\\t*\\r*\\n*)*\\.(?:\\s*\\t*\\r*\\n*)*(${getTarget(
map
map,
)})[\\r\\t\\n\\s]*${func ? '\\(' : '(?!\\()'}`,
'g'
'g',
);
const getTarget = (t) => Object.keys(t).join('|');
return [
{ func: true, map: functionsMap },
{ func: false, map: propsMap },
].reduce((acc, curr) => {
return acc.replace(serviceCallRgx(curr), (str) =>
str.replace(new RegExp(getTarget(curr.map)), (func) => curr.map[func])
str.replace(
new RegExp(getTarget(curr.map)),
(func) => curr.map[func],
),
);
}, match);
},
Expand Down Expand Up @@ -158,14 +161,21 @@ export function run(path) {
async function migrate(matchersArr, filesType) {
console.log(`\nMigrating ${filesType} files 📜`);
let spinner;
const isWindows = process.platform === 'win32';

for (let i = 0; i < matchersArr.length; i++) {
const { step, matchers } = matchersArr[i];
const msg = `Step ${i + 1}/${matchersArr.length}: Migrating ${step}`;
spinner = ora().start(msg);
const noFilesFound = [];
for (const matcher of matchers) {
try {
await replaceInFile(matcher);
await replaceInFile({
...matcher,
glob: {
windowsPathsNoEscape: isWindows,
},
});
} catch (e) {
if (e.message.includes('No files match the pattern')) {
noFilesFound.push(e.message);
Expand All @@ -176,7 +186,7 @@ export function run(path) {
}
spinner.succeed(msg);
noFilesFound.forEach((pattern) =>
console.log('\x1b[33m%s\x1b[0m', `⚠️ ${pattern}`)
console.log('\x1b[33m%s\x1b[0m', `⚠️ ${pattern}`),
);
}
}
Expand All @@ -187,7 +197,7 @@ export function run(path) {
console.log('\n 🌵 Done! 🌵');
console.log('Welcome to a better translation experience 🌐');
console.log(
'\nFor more information about this script please visit 👉 https://jsverse.github.io/transloco/docs/migration/ngx\n'
'\nFor more information about this script please visit 👉 https://jsverse.github.io/transloco/docs/migration/ngx\n',
);
});
}
134 changes: 77 additions & 57 deletions libs/transloco-schematics/src/tests/ngx-translate-migration.spec.ts
Original file line number Diff line number Diff line change
@@ -1,50 +1,57 @@
// noinspection AngularUndefinedBinding

import * as nodePath from 'node:path';
import {readFile} from 'node:fs/promises';
import { readFile } from 'node:fs/promises';

import {replaceInFile, ReplaceInFileConfig} from 'replace-in-file';
import {glob} from 'glob';
import { replaceInFile, ReplaceInFileConfig } from 'replace-in-file';
import { glob } from 'glob';

import {PIPE_IN_BINDING_REGEX, PIPE_REGEX, run} from '../migrate/ngx-translate-migration';
import {
PIPE_IN_BINDING_REGEX,
PIPE_REGEX,
run,
} from '../migrate/ngx-translate-migration';

jest.mock('replace-in-file');

describe('ngx-translate migration', () => {

describe('Positive regex tests', () => {

describe('Pipe in binding', () => {
test.each([
{
testCase: `<component [header]="'hello.world' | translate">`,
match: [`]="'hello.world' | translate"`]
match: [`]="'hello.world' | translate"`],
},
{
testCase: `<component [header]="'hello.world' | translate | anotherPipe">`,
match: [`]="'hello.world' | translate | anotherPipe"`]
match: [`]="'hello.world' | translate | anotherPipe"`],
},
{
testCase: `<component [header]="'hello' | translate:params | anotherPipe">`,
match: [`]="'hello' | translate:params | anotherPipe"`]
match: [`]="'hello' | translate:params | anotherPipe"`],
},
{
testCase: `<component [title]="titleMap[reportType] | translate">`,
match: [`]="titleMap[reportType] | translate"`]
match: [`]="titleMap[reportType] | translate"`],
},
{
testCase: `<component [matTooltip]="('foo.bar' | translate) + ': ' + (value | number: '1.0-2')">`,
match: [`]="('foo.bar' | translate) + ': ' + (value | number: '1.0-2')"`]
match: [
`]="('foo.bar' | translate) + ': ' + (value | number: '1.0-2')"`,
],
},
{
testCase: `<compnent [title]="'Hello, ' + ('mom' | translate) | fooBar">`,
match: [`]="'Hello, ' + ('mom' | translate) | fooBar"`]
match: [`]="'Hello, ' + ('mom' | translate) | fooBar"`],
},
{
testCase: `<edge-wizard-step [label]="'Restore Options' | translate" [validatingMessage]="'Processing archive...'|translate"`,
match: [`]="'Restore Options' | translate"`, `]="'Processing archive...'|translate"`]
}
])('Case: $testCase; Match: $match', ({testCase, match}) => {
match: [
`]="'Restore Options' | translate"`,
`]="'Processing archive...'|translate"`,
],
},
])('Case: $testCase; Match: $match', ({ testCase, match }) => {
const regex = new RegExp(PIPE_IN_BINDING_REGEX, 'gm');
const result = testCase.match(regex);

Expand All @@ -56,33 +63,35 @@ describe('ngx-translate migration', () => {
test.each([
{
testCase: `<component>{{ "hello.world" | translate }}</component>`,
match: [`{{ "hello.world" | translate }}`]
match: [`{{ "hello.world" | translate }}`],
},
{
testCase: `<component>{{ "hello.world" | translate | anotherPipe | oneMore }}</component>`,
match: [`{{ "hello.world" | translate | anotherPipe | oneMore }}`]
match: [`{{ "hello.world" | translate | anotherPipe | oneMore }}`],
},
{
testCase: `<component>{{ "hello" | translate: { name: 'John' } }}</component>`,
match: [`{{ "hello" | translate: { name: 'John' } }}`]
match: [`{{ "hello" | translate: { name: 'John' } }}`],
},
{
testCase: `<component>{{ titleMap[reportType] | translate }}</component>`,
match: [`{{ titleMap[reportType] | translate }}`]
match: [`{{ titleMap[reportType] | translate }}`],
},
{
testCase: `<component>{{ ('foo.bar' | translate) + ': ' + (value | number: '1.0-2') }}</component>`,
match: [`{{ ('foo.bar' | translate) + ': ' + (value | number: '1.0-2') }}`]
match: [
`{{ ('foo.bar' | translate) + ': ' + (value | number: '1.0-2') }}`,
],
},
{
testCase: `<compnent>{{ 'Hello, ' + ('mom' | translate) | fooBar }}</compnent>`,
match: [`{{ 'Hello, ' + ('mom' | translate) | fooBar }}`]
match: [`{{ 'Hello, ' + ('mom' | translate) | fooBar }}`],
},
{
testCase: `{{"1" | translate}} {{errorCounter}} {{"2" | translate}}`,
match: [`{{"1" | translate}}`, `{{"2" | translate}}`]
}
])('Case: $testCase; Match: $match', ({testCase, match}) => {
match: [`{{"1" | translate}}`, `{{"2" | translate}}`],
},
])('Case: $testCase; Match: $match', ({ testCase, match }) => {
const regex = new RegExp(PIPE_REGEX, 'gm');
const result = testCase.match(regex);

Expand All @@ -92,106 +101,117 @@ describe('ngx-translate migration', () => {
});

describe('Negative regex tests', () => {

describe('Pipe in binding', () => {
test.each([
{
testCase: `<component [header]="'hello.world' | transloco">`
testCase: `<component [header]="'hello.world' | transloco">`,
},
{
testCase: `<component [header]="'hello.world' | somePipe | anotherPipe">`
testCase: `<component [header]="'hello.world' | somePipe | anotherPipe">`,
},
{
testCase: `<component [header]="'hello' | transloco:params | anotherPipe">`
testCase: `<component [header]="'hello' | transloco:params | anotherPipe">`,
},
{
testCase: `<component [title]="titleMap[reportType] | fooBar">`
testCase: `<component [title]="titleMap[reportType] | fooBar">`,
},
{
testCase: `<component [matTooltip]="('foo.bar' | transloco) + ': ' + (value | number: '1.0-2')">`
testCase: `<component [matTooltip]="('foo.bar' | transloco) + ': ' + (value | number: '1.0-2')">`,
},
{
testCase: `<compnent [title]="'Hello World ' + ('mom' | transloco) | fooBar">`
testCase: `<compnent [title]="'Hello World ' + ('mom' | transloco) | fooBar">`,
},
{
testCase: `<a [title]="'admin.1' | lowercase
| translate"
</a>`
}
])('Case: $testCase', ({testCase}) => {
</a>`,
},
])('Case: $testCase', ({ testCase }) => {
const regex = new RegExp(PIPE_IN_BINDING_REGEX, 'gm');
const result = testCase.match(regex);

expect(result).toBeNull();
});
});

describe('Pipe', () => {
test.each([
{
testCase: `<component>{{ "hello.world" | transloco }}</component>`
testCase: `<component>{{ "hello.world" | transloco }}</component>`,
},
{
testCase: `<component>{{ "hello.world" | transloco | anotherPipe | oneMore }}</component>`
testCase: `<component>{{ "hello.world" | transloco | anotherPipe | oneMore }}</component>`,
},
{
testCase: `<component>{{ "hello" | transloco: { name: 'John' } }}</component>`
testCase: `<component>{{ "hello" | transloco: { name: 'John' } }}</component>`,
},
{
testCase: `<component>{{ titleMap[reportType] | somePipe }}</component>`
testCase: `<component>{{ titleMap[reportType] | somePipe }}</component>`,
},
{
testCase: `<component>{{ ('foo.bar' | transloco) + ': ' + (value | number: '1.0-2') }}</component>`
testCase: `<component>{{ ('foo.bar' | transloco) + ': ' + (value | number: '1.0-2') }}</component>`,
},
{
testCase: `<compnent>{{ 'Hello, ' + ('mom' | transloco) | fooBar }}</compnent>`
}
])('Case: $testCase', ({testCase}) => {
testCase: `<compnent>{{ 'Hello, ' + ('mom' | transloco) | fooBar }}</compnent>`,
},
])('Case: $testCase', ({ testCase }) => {
const regex = new RegExp(PIPE_REGEX, 'gm');
const result = testCase.match(regex);

expect(result).toBeNull();
});
});

});

describe('HTML template', () => {

it('should replace html template content', async () => {
const replacements: Record<string, string> = {},
isWindows = process.platform === 'win32';

(replaceInFile as unknown as jest.Mock).mockImplementation(
async (config: ReplaceInFileConfig): Promise<void> => {
const path = config.files as string,
regex = config.from as RegExp,
replacer = config.to as (match: string) => string;
const files = await glob(path, {windowsPathsNoEscape: isWindows});

const files = await glob(path, { windowsPathsNoEscape: isWindows });

for (const fullPath of files) {
const filename = nodePath.parse(fullPath).base,
content = replacements[filename] ?? await readFile(fullPath, {encoding: 'utf-8'});

content =
replacements[filename] ??
(await readFile(fullPath, { encoding: 'utf-8' }));

replacements[filename] = content.replace(regex, replacer);
}
}
},
);

const ngxTranslateTemplatePath = './src/tests/templates/pipes/ngx-translate';
const ngxTranslateTemplatePath =
'./src/tests/templates/pipes/ngx-translate';

await run(ngxTranslateTemplatePath);

expect(replaceInFile).toHaveBeenLastCalledWith(
expect.objectContaining({
glob: {
windowsPathsNoEscape: isWindows,
},
}),
);

const filenames = Object.keys(replacements);

for(const filename of filenames) {
const resultPath = nodePath.join(__dirname, './templates/pipes/transloco', filename),
resultContent = await readFile(resultPath, {encoding: 'utf-8'});
for (const filename of filenames) {
const resultPath = nodePath.join(
__dirname,
'./templates/pipes/transloco',
filename,
),
resultContent = await readFile(resultPath, { encoding: 'utf-8' });

expect(replacements[filename]).toBe(resultContent);
}
});

});
});

0 comments on commit 71aade9

Please sign in to comment.