Skip to content

Commit

Permalink
test(localize): ensure tests pass on Windows (#40952)
Browse files Browse the repository at this point in the history
These tests were relying upon unix-like paths, which
caused them to fail on Windows.

Note that the `filegroup` Bazel rule tends not to work well
on Windows, so this has been replaced with `copy_to_bin`
instead.

PR Close #40952
  • Loading branch information
petebacondarwin authored and zarend committed Feb 24, 2021
1 parent 5ae28a4 commit 51a7977
Show file tree
Hide file tree
Showing 25 changed files with 207 additions and 130 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export function makeEs5ExtractPlugin(
// If we get a BabelParseError here then something went wrong with Babel itself
// since there must be something wrong with the structure of the AST generated
// by Babel parsing a TaggedTemplateExpression.
throw buildCodeFrameError(callPath, e);
throw buildCodeFrameError(fs, callPath, e);
} else {
throw e;
}
Expand Down
28 changes: 22 additions & 6 deletions packages/localize/src/tools/src/source_file_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {AbsoluteFsPath, getFileSystem, PathManipulation} from '@angular/compiler-cli/src/ngtsc/file_system';
import {absoluteFrom, AbsoluteFsPath, getFileSystem, PathManipulation} from '@angular/compiler-cli/src/ngtsc/file_system';
import {ɵisMissingTranslationError, ɵmakeTemplateObject, ɵParsedTranslation, ɵSourceLocation, ɵtranslate} from '@angular/localize';
import {NodePath} from '@babel/traverse';
import * as t from '@babel/types';
Expand Down Expand Up @@ -400,8 +400,19 @@ export function isBabelParseError(e: any): e is BabelParseError {
return e.type === 'BabelParseError';
}

export function buildCodeFrameError(path: NodePath, e: BabelParseError): string {
const filename = path.hub.file.opts.filename || '(unknown file)';
export function buildCodeFrameError(
fs: PathManipulation, path: NodePath, e: BabelParseError): string {
let filename = path.hub.file.opts.filename;
if (filename) {
filename = fs.resolve(filename);
let cwd = path.hub.file.opts.cwd;
if (cwd) {
cwd = fs.resolve(cwd);
filename = fs.relative(cwd, filename);
}
} else {
filename = '(unknown file)';
}
const message = path.hub.file.buildCodeFrameError(e.node, e.message).message;
return `${filename}: ${message}`;
}
Expand Down Expand Up @@ -434,9 +445,14 @@ export function serializeLocationPosition(location: ɵSourceLocation): string {

function getFileFromPath(fs: PathManipulation, path: NodePath|undefined): AbsoluteFsPath|null {
const opts = path?.hub.file.opts;
return opts?.filename ?
fs.resolve(opts.generatorOpts.sourceRoot ?? opts.cwd, fs.relative(opts.cwd, opts.filename)) :
null;
const filename = opts?.filename;
if (!filename) {
return null;
}
const relativePath = fs.relative(opts.cwd, filename);
const root = opts.generatorOpts.sourceRoot ?? opts.cwd;
const absPath = fs.resolve(root, relativePath);
return absPath;
}

function getLineAndColumn(loc: {line: number, column: number}): {line: number, column: number} {
Expand Down
2 changes: 1 addition & 1 deletion packages/localize/src/tools/src/translate/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ if (require.main === module) {
const sourceRootPath = options.r;
const sourceFilePaths = glob.sync(options.s, {cwd: sourceRootPath, nodir: true});
const translationFilePaths: (string|string[])[] = convertArraysFromArgs(options.t);
const outputPathFn = getOutputPathFn(fs.resolve(options.o));
const outputPathFn = getOutputPathFn(fs, fs.resolve(options.o));
const diagnostics = new Diagnostics();
const missingTranslation = options.m as DiagnosticHandlingStrategy;
const duplicateTranslation = options.d as DiagnosticHandlingStrategy;
Expand Down
9 changes: 4 additions & 5 deletions packages/localize/src/tools/src/translate/output_path.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {AbsoluteFsPath} from '@angular/compiler-cli/src/ngtsc/file_system';
import {join} from 'path';
import {AbsoluteFsPath, PathManipulation} from '@angular/compiler-cli/src/ngtsc/file_system';

/**
* A function that will return an absolute path to where a file is to be written, given a locale and
Expand All @@ -23,8 +22,8 @@ export interface OutputPathFn {
* The special `{{LOCALE}}` marker will be replaced with the locale code of the current translation.
* @param outputFolder An absolute path to the folder containing this set of translations.
*/
export function getOutputPathFn(outputFolder: AbsoluteFsPath): OutputPathFn {
export function getOutputPathFn(fs: PathManipulation, outputFolder: AbsoluteFsPath): OutputPathFn {
const [pre, post] = outputFolder.split('{{LOCALE}}');
return post === undefined ? (_locale, relativePath) => join(pre, relativePath) :
(locale, relativePath) => join(pre + locale + post, relativePath);
return post === undefined ? (_locale, relativePath) => fs.join(pre, relativePath) :
(locale, relativePath) => fs.join(pre + locale + post, relativePath);
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export function makeEs2015TranslatePlugin(
// If we get a BabelParseError here then something went wrong with Babel itself
// since there must be something wrong with the structure of the AST generated
// by Babel parsing a TaggedTemplateExpression.
throw buildCodeFrameError(path, e);
throw buildCodeFrameError(fs, path, e);
} else {
throw e;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export function makeEs5TranslatePlugin(
}
} catch (e) {
if (isBabelParseError(e)) {
diagnostics.error(buildCodeFrameError(callPath, e));
diagnostics.error(buildCodeFrameError(fs, callPath, e));
} else {
throw e;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export class SourceFileTranslationHandler implements TranslationHandler {
makeEs2015TranslatePlugin(diagnostics, translationBundle.translations, options, this.fs),
makeEs5TranslatePlugin(diagnostics, translationBundle.translations, options, this.fs),
],
cwd: sourceRoot,
filename,
});
if (translated && translated.code) {
Expand Down
1 change: 1 addition & 0 deletions packages/localize/src/tools/test/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ ts_library(
"//packages/compiler-cli/src/ngtsc/logging/testing",
"//packages/localize",
"//packages/localize/src/tools",
"//packages/localize/src/tools/test/helpers",
"//packages/localize/src/utils",
"@npm//@babel/core",
"@npm//@babel/generator",
Expand Down
84 changes: 20 additions & 64 deletions packages/localize/src/tools/test/extract/extractor_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {absoluteFrom, getFileSystem, relativeFrom} from '@angular/compiler-cli/src/ngtsc/file_system';
import {runInEachFileSystem} from '@angular/compiler-cli/src/ngtsc/file_system/testing';
import {absoluteFrom, getFileSystem} from '@angular/compiler-cli/src/ngtsc/file_system';
import {MockLogger} from '@angular/compiler-cli/src/ngtsc/logging/testing';

import {MessageExtractor} from '../../src/extract/extraction';
import {runInNativeFileSystem} from '../helpers';

runInEachFileSystem(() => {
runInNativeFileSystem(() => {
describe('extractMessages', () => {
it('should extract a message for each $localize template tag', () => {
const fs = getFileSystem();
Expand All @@ -20,7 +20,7 @@ runInEachFileSystem(() => {
const filename = 'relative/path.js';
const file = fs.resolve(basePath, filename);
const extractor = new MessageExtractor(fs, logger, {basePath});
fs.ensureDir(absoluteFrom('/root/path/relative'));
fs.ensureDir(fs.dirname(file));
fs.writeFile(file, [
'$localize`:meaning|description:a${1}b${2}c`;',
'$localize(__makeTemplateObject(["a", ":custom-placeholder:b", "c"], ["a", ":custom-placeholder:b", "c"]), 1, 2);',
Expand All @@ -40,38 +40,28 @@ runInEachFileSystem(() => {
{
start: {line: 0, column: 10},
end: {line: 0, column: 32},
file: absoluteFrom('/root/path/relative/path.js'),
file,
text: ':meaning|description:a',
},
{
start: {line: 0, column: 36},
end: {line: 0, column: 37},
file: absoluteFrom('/root/path/relative/path.js'),
file,
text: 'b',
},
{
start: {line: 0, column: 41},
end: {line: 0, column: 42},
file: absoluteFrom('/root/path/relative/path.js'),
file,
text: 'c',
}
],
text: 'a{$PH}b{$PH_1}c',
placeholderNames: ['PH', 'PH_1'],
substitutions: jasmine.any(Object),
substitutionLocations: {
PH: {
start: {line: 0, column: 34},
end: {line: 0, column: 35},
file: absoluteFrom('/root/path/relative/path.js'),
text: '1'
},
PH_1: {
start: {line: 0, column: 39},
end: {line: 0, column: 40},
file: absoluteFrom('/root/path/relative/path.js'),
text: '2'
}
PH: {start: {line: 0, column: 34}, end: {line: 0, column: 35}, file, text: '1'},
PH_1: {start: {line: 0, column: 39}, end: {line: 0, column: 40}, file, text: '2'}
},
legacyIds: [],
location: {
Expand All @@ -92,38 +82,29 @@ runInEachFileSystem(() => {
{
start: {line: 1, column: 69},
end: {line: 1, column: 72},
file: absoluteFrom('/root/path/relative/path.js'),
file,
text: '"a"',
},
{
start: {line: 1, column: 74},
end: {line: 1, column: 97},
file: absoluteFrom('/root/path/relative/path.js'),
file,
text: '":custom-placeholder:b"',
},
{
start: {line: 1, column: 99},
end: {line: 1, column: 102},
file: absoluteFrom('/root/path/relative/path.js'),
file,
text: '"c"',
}
],
text: 'a{$custom-placeholder}b{$PH_1}c',
placeholderNames: ['custom-placeholder', 'PH_1'],
substitutions: jasmine.any(Object),
substitutionLocations: {
'custom-placeholder': {
start: {line: 1, column: 106},
end: {line: 1, column: 107},
file: absoluteFrom('/root/path/relative/path.js'),
text: '1'
},
PH_1: {
start: {line: 1, column: 109},
end: {line: 1, column: 110},
file: absoluteFrom('/root/path/relative/path.js'),
text: '2'
}
'custom-placeholder':
{start: {line: 1, column: 106}, end: {line: 1, column: 107}, file, text: '1'},
PH_1: {start: {line: 1, column: 109}, end: {line: 1, column: 110}, file, text: '2'}
},
legacyIds: [],
location: {
Expand All @@ -145,38 +126,13 @@ runInEachFileSystem(() => {
placeholderNames: ['PH', 'PH_1'],
substitutions: jasmine.any(Object),
substitutionLocations: {
PH: {
start: {line: 2, column: 26},
end: {line: 2, column: 27},
file: absoluteFrom('/root/path/relative/path.js'),
text: '1'
},
PH_1: {
start: {line: 2, column: 31},
end: {line: 2, column: 32},
file: absoluteFrom('/root/path/relative/path.js'),
text: '2'
}
PH: {start: {line: 2, column: 26}, end: {line: 2, column: 27}, file, text: '1'},
PH_1: {start: {line: 2, column: 31}, end: {line: 2, column: 32}, file, text: '2'}
},
messagePartLocations: [
{
start: {line: 2, column: 10},
end: {line: 2, column: 24},
file: absoluteFrom('/root/path/relative/path.js'),
text: ':@@custom-id:a'
},
{
start: {line: 2, column: 28},
end: {line: 2, column: 29},
file: absoluteFrom('/root/path/relative/path.js'),
text: 'b'
},
{
start: {line: 2, column: 33},
end: {line: 2, column: 34},
file: absoluteFrom('/root/path/relative/path.js'),
text: 'c'
}
{start: {line: 2, column: 10}, end: {line: 2, column: 24}, file, text: ':@@custom-id:a'},
{start: {line: 2, column: 28}, end: {line: 2, column: 29}, file, text: 'b'},
{start: {line: 2, column: 33}, end: {line: 2, column: 34}, file, text: 'c'}
],
legacyIds: [],
location: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ ts_library(
"//packages/compiler-cli/src/ngtsc/testing",
"//packages/localize/src/tools",
"//packages/localize/src/tools/test:test_lib",
"//packages/localize/src/tools/test/helpers",
],
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@
*/
import {absoluteFrom, AbsoluteFsPath, FileSystem, getFileSystem, setFileSystem} from '@angular/compiler-cli/src/ngtsc/file_system';
import {InvalidFileSystem} from '@angular/compiler-cli/src/ngtsc/file_system/src/invalid_file_system';
import {runInEachFileSystem} from '@angular/compiler-cli/src/ngtsc/file_system/testing';
import {MockLogger} from '@angular/compiler-cli/src/ngtsc/logging/testing';
import {loadTestDirectory} from '@angular/compiler-cli/src/ngtsc/testing';

import {extractTranslations} from '../../../src/extract/main';
import {FormatOptions} from '../../../src/extract/translation_files/format_options';
import {runInNativeFileSystem} from '../../helpers';
import {toAttributes} from '../translation_files/utils';

runInEachFileSystem(() => {
runInNativeFileSystem(() => {
let fs: FileSystem;
let logger: MockLogger;
let rootPath: AbsoluteFsPath;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package(default_visibility = ["//packages/localize/src/tools/test/extract/integration:__pkg__"])

load("@npm//typescript:index.bzl", "tsc")
load("@build_bazel_rules_nodejs//:index.bzl", "copy_to_bin")

tsc(
name = "compile_es5",
Expand Down Expand Up @@ -44,7 +45,8 @@ tsc(
data = glob(["src/*.ts"]),
)

filegroup(
# Use copy_to_bin since filegroup doesn't seem to work on Windows.
copy_to_bin(
name = "test_files",
srcs = glob([
"**/*.js",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,42 @@
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {getFileSystem} from '@angular/compiler-cli/src/ngtsc/file_system';
import {runInEachFileSystem} from '@angular/compiler-cli/src/ngtsc/file_system/testing';
import {FileSystem, getFileSystem, PathSegment, relativeFrom} from '@angular/compiler-cli/src/ngtsc/file_system';
import {ɵParsedMessage} from '@angular/localize/private';
import {transformSync} from '@babel/core';

import {makeEs5ExtractPlugin} from '../../../src/extract/source_files/es5_extract_plugin';
import {runInNativeFileSystem} from '../../helpers';

runInNativeFileSystem(() => {
let fs: FileSystem;
let testPath: PathSegment;

beforeEach(() => {
fs = getFileSystem();
testPath = relativeFrom('app/dist/test.js');
});

runInEachFileSystem(() => {
describe('makeEs5ExtractPlugin()', () => {
it('should error with code-frame information if the first argument to `$localize` is not an array',
() => {
const input = '$localize(null, [])';
expect(() => transformCode(input))
.toThrowError(
'Cannot create property \'message\' on string \'/app/dist/test.js: Unexpected messageParts for `$localize` (expected an array of strings).\n' +
`Cannot create property 'message' on string '${testPath}: ` +
'Unexpected messageParts for `$localize` (expected an array of strings).\n' +
'> 1 | $localize(null, [])\n' +
' | ^^^^\'');
});

function transformCode(input: string): ɵParsedMessage[] {
const messages: ɵParsedMessage[] = [];
const cwd = fs.resolve('/');
const filename = fs.resolve(cwd, testPath);
transformSync(input, {
plugins: [makeEs5ExtractPlugin(getFileSystem(), messages)],
filename: '/app/dist/test.js'
filename,
cwd,
})!.code!;
return messages;
}
Expand Down
14 changes: 14 additions & 0 deletions packages/localize/src/tools/test/helpers/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
load("//tools:defaults.bzl", "ts_library")

ts_library(
name = "helpers",
testonly = True,
srcs = glob(
["**/*.ts"],
),
visibility = ["//packages/localize/src/tools/test:__subpackages__"],
deps = [
"//packages/compiler-cli/src/ngtsc/file_system",
"//packages/compiler-cli/src/ngtsc/file_system/testing",
],
)

0 comments on commit 51a7977

Please sign in to comment.