From 62ff3fd736429eb9f3e4038694e4d192944489f8 Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Mon, 12 Aug 2024 14:44:15 +0200 Subject: [PATCH] add test, update docs --- packages/playwright/src/util.ts | 12 +++++++-- tests/playwright-test/resolver.spec.ts | 36 ++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/packages/playwright/src/util.ts b/packages/playwright/src/util.ts index d317e65955f2c..367bb721d9bbd 100644 --- a/packages/playwright/src/util.ts +++ b/packages/playwright/src/util.ts @@ -319,8 +319,16 @@ export function resolveImportSpecifierExtension(resolved: string, isPathMapping: break; // Do not try '' when a more specific extension like '.jsx' matched. } - // Following TypeScript's path mapping logic, index files and package.json are not resolved in ESM. - // TypeScript does not interpret package.json for path mappings: https://www.typescriptlang.org/docs/handbook/modules/reference.html#paths-should-not-point-to-monorepo-packages-or-node_modules-packages + // After TypeScript path mapping, here's how directories with a `package.json` are resolved: + // - `package.json#exports` is not respected + // - `package.json#main` is respected only in CJS mode + // - `index.js` default is respected only in CJS mode + // + // More info: + // - https://www.typescriptlang.org/docs/handbook/modules/reference.html#paths-should-not-point-to-monorepo-packages-or-node_modules-packages + // - https://www.typescriptlang.org/docs/handbook/modules/reference.html#directory-modules-index-file-resolution + // - https://nodejs.org/dist/latest-v20.x/docs/api/modules.html#folders-as-modules + const shouldNotResolveDirectory = isPathMapping && isESM; if (!shouldNotResolveDirectory && dirExists(resolved)) { diff --git a/tests/playwright-test/resolver.spec.ts b/tests/playwright-test/resolver.spec.ts index fdc7a816a1aa9..b87e22babbe45 100644 --- a/tests/playwright-test/resolver.spec.ts +++ b/tests/playwright-test/resolver.spec.ts @@ -606,6 +606,42 @@ test('should import packages with non-index main script through path resolver', expect(result.output).toContain(`foo=42`); }); +test('should not honor `package.json#main` field in ESM mode', async ({ runInlineTest }) => { + const result = await runInlineTest({ + 'app/pkg/main.ts': ` + export const foo = 42; + `, + 'app/pkg/package.json': ` + { "main": "main.ts" } + `, + 'package.json': ` + { "name": "example-project", "type": "module" } + `, + 'playwright.config.ts': ` + export default {}; + `, + 'tsconfig.json': `{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "app/*": ["app/*"], + }, + }, + }`, + 'example.spec.ts': ` + import { foo } from 'app/pkg'; + import { test, expect } from '@playwright/test'; + test('test', ({}) => { + console.log('foo=' + foo); + }); + `, + }); + + expect(result.exitCode).toBe(1); + expect(result.output).toContain(`Cannot find package 'app'`); +}); + + test('does not honor `exports` field after type mapping', async ({ runInlineTest }) => { const result = await runInlineTest({ 'app/pkg/main.ts': `