Skip to content

Commit

Permalink
feat(testing): add support for transforming path aliases in spec tests
Browse files Browse the repository at this point in the history
This adds support for transforming path aliases in spec tests, using the
transformer which was added in #4042. Adding such support also revealed
a bug with the existing path transformer, notably that it did not
produce a valid path for sibling modules. See the diff for a comment
explaining the details.
  • Loading branch information
alicewriteswrongs committed Feb 22, 2023
1 parent 7430191 commit dd792d3
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 14 deletions.
35 changes: 26 additions & 9 deletions src/compiler/sys/typescript/typescript-sys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { patchTypeScriptResolveModule } from './typescript-resolve-module';
export const patchTsSystemFileSystem = (
config: d.Config,
compilerSys: d.CompilerSystem,
inMemoryFs: InMemoryFileSystem,
inMemoryFs: InMemoryFileSystem | null,
tsSys: ts.System
): ts.System => {
const realpath = (path: string) => {
Expand Down Expand Up @@ -55,8 +55,13 @@ export const patchTsSystemFileSystem = (
};

tsSys.directoryExists = (p) => {
const s = inMemoryFs.statSync(p);
return s.isDirectory;
if (inMemoryFs) {
const s = inMemoryFs.statSync(p);
return s.isDirectory;
} else {
const s = compilerSys.statSync(p);
return s.isDirectory;
}
};

tsSys.exit = compilerSys.exit;
Expand All @@ -68,8 +73,13 @@ export const patchTsSystemFileSystem = (
filePath = getTypescriptPathFromUrl(config, tsSys.getExecutingFilePath(), p);
}

const s = inMemoryFs.statSync(filePath);
return !!(s && s.isFile);
if (inMemoryFs) {
const s = inMemoryFs.statSync(filePath);
return !!(s && s.isFile);
} else {
const s = compilerSys.statSync(filePath);
return !!(s && s.isFile);
}
};

tsSys.getCurrentDirectory = compilerSys.getCurrentDirectory;
Expand All @@ -79,8 +89,13 @@ export const patchTsSystemFileSystem = (
tsSys.getDirectories = (p) => {
const items = compilerSys.readDirSync(p);
return items.filter((itemPath) => {
const s = inMemoryFs.statSync(itemPath);
return !!(s && s.exists && s.isDirectory);
if (inMemoryFs) {
const s = inMemoryFs.statSync(itemPath);
return !!(s && s.exists && s.isDirectory);
} else {
const s = compilerSys.statSync(itemPath);
return !!(s && s.isDirectory);
}
});
};

Expand Down Expand Up @@ -108,7 +123,9 @@ export const patchTsSystemFileSystem = (
filePath = getTypescriptPathFromUrl(config, tsSys.getExecutingFilePath(), p);
}

let content = inMemoryFs.readFileSync(filePath, { useCache: isUrl });
let content = inMemoryFs
? inMemoryFs.readFileSync(filePath, { useCache: isUrl })
: compilerSys.readFileSync(filePath);

if (typeof content !== 'string' && isUrl) {
if (IS_WEB_WORKER_ENV) {
Expand All @@ -124,7 +141,7 @@ export const patchTsSystemFileSystem = (
return content;
};

tsSys.writeFile = (p, data) => inMemoryFs.writeFile(p, data);
tsSys.writeFile = (p, data) => (inMemoryFs ? inMemoryFs.writeFile(p, data) : compilerSys.writeFile(p, data));

return tsSys;
};
Expand Down
32 changes: 31 additions & 1 deletion src/compiler/transformers/rewrite-aliased-paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,37 @@ function rewriteAliasedImport(
node,
retrieveTsModifiers(node),
node.importClause,
transformCtx.factory.createStringLiteral(importPath),
transformCtx.factory.createStringLiteral(
// if the importeee is a sibling file of the importer then `relative`
// will produce a something confusing result. We use `dirname` to get the
// directory of the importer, so for example, assume we have two files
// `foo/bar.ts` and `foo/baz.ts` like so:
//
// ```
// foo
// ├── bar.ts
// └── baz.ts
// ```
//
// then if `baz.ts` imports a symbol from `bar.ts` we'll call
// `relative(fromdir, to)` like so:
//
// ```ts
// relative(dirname("foo/baz.ts"), "foo/bar.ts")
// // equivalently
// relative("foo", "foo/bar.ts")
// ```
//
// you'd think that in this case `relative` would return `'./bar.ts'` as
// a correct relative path to `bar.ts` from the `foo` directory, but
// actually in this case it returns just `bar.ts`. So since when updating
// import paths we're only concerned with `paths` aliases that should be
// transformed to relative imports anyway, we check to see if the new
// `importPath` starts with `'.'`, and add `'./'` if it doesn't, since
// otherwise nodejs will interpret `bar` as a module name, not a relative
// path.
importPath.startsWith('.') ? importPath : './' + importPath
),
node.assertClause
);
}
36 changes: 32 additions & 4 deletions src/compiler/transformers/test/rewrite-aliased-paths.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ import { transpileModule } from './transpile';
* transpiles the provided code.
*
* @param component the string of a component
* @param inputFileName an optional filename to use for the input file
* @returns the tranpiled module
*/
async function pathTransformTranspile(component: string) {
async function pathTransformTranspile(component: string, inputFileName = 'module.tsx') {
const compilerContext: CompilerCtx = mockCompilerCtx();
const config = mockValidatedConfig();

Expand All @@ -37,8 +38,6 @@ async function pathTransformTranspile(component: string) {
await compilerContext.fs.writeFile(path.join(config.rootDir, 'name/space.ts'), 'export const foo = x => x');
await compilerContext.fs.writeFile(path.join(config.rootDir, 'name/space/subdir.ts'), 'export const bar = x => x;');

const inputFileName = normalizePath(path.join(config.rootDir, 'module.tsx'));

return transpileModule(
component,
null,
Expand All @@ -47,7 +46,7 @@ async function pathTransformTranspile(component: string) {
[],
[rewriteAliasedDTSImportPaths],
mockPathsConfig,
inputFileName
normalizePath(path.join(config.rootDir, inputFileName))
);
}

Expand Down Expand Up @@ -144,4 +143,33 @@ describe('rewrite alias module paths transform', () => {
'import { Foo } from "./name/space/subdir";import { Bar } from "./name/space";export declare function fooUtil(foo: Foo): Bar;'
);
});

it('should correctly rewrite sibling paths', async () => {
const t = await pathTransformTranspile(
`
import { foo } from "@namespace";
export class CmpA {
render() {
return <some-cmp>{ foo("bar") }</some-cmp>
}
}
`,
'name/component.tsx'
);

// with the import filename passed to `pathTransformTranspile` the file
// layout during this test looks like this:
//
// ```
// name
// ├── space.ts
// └── component.tsx
// ```
//
// we need to test that the relative path from `name/component.tsx` to
// `name/space.ts` is resolved correctly as `'./space'`.
expect(t.outputText).toBe(
'import { foo } from "./space";export class CmpA { render() { return h("some-cmp", null, foo("bar")); }}'
);
});
});
2 changes: 2 additions & 0 deletions src/declarations/stencil-private.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2299,6 +2299,8 @@ export interface E2EProcessEnv {
__STENCIL_PUPPETEER_MODULE__?: string;
__STENCIL_PUPPETEER_VERSION__?: number;
__STENCIL_DEFAULT_TIMEOUT__?: string;

__STENCIL_TRANSPILE_PATHS__?: boolean;
}

export interface AnyHTMLElement extends HTMLElement {
Expand Down
1 change: 1 addition & 0 deletions src/testing/jest/jest-runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export async function runJest(config: d.ValidatedConfig, env: d.E2EProcessEnv) {
const emulateConfigs = getEmulateConfigs(config.testing, config.flags);
env.__STENCIL_EMULATE_CONFIGS__ = JSON.stringify(emulateConfigs);
env.__STENCIL_ENV__ = JSON.stringify(config.env);
env.__STENCIL_TRANSPILE_PATHS__ = !!config.transformAliasedImportPaths;

if (config.flags.ci || config.flags.e2e) {
env.__STENCIL_DEFAULT_TIMEOUT__ = '30000';
Expand Down
1 change: 1 addition & 0 deletions src/testing/test-transpile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export function transpile(input: string, opts: TranspileOptions = {}): Transpile
style: null,
styleImportData: 'queryparams',
target: 'es2015', // default to es2015
transformAliasedImportPaths: !!process.env.__STENCIL_TRANSPILE_PATHS__,
};

try {
Expand Down

0 comments on commit dd792d3

Please sign in to comment.