Skip to content

fix: re-export the named userEvent from the built entries - #12

Merged
owjs3901 merged 1 commit into
mainfrom
owjs3901/fix-user-event-export
Sep 23, 2026
Merged

owjs3901 merged 1 commit into
mainfrom
owjs3901/fix-user-event-export

Conversation

@owjs3901

Copy link
Copy Markdown
Contributor

문제

1.0.4에서 userEvent export가 깨졌습니다. 의도치 않은 breaking change입니다.

  • 증상: import { userEvent } from 'bun-test-env-dom' → userEvent.type is not a function
  • 실측: Object.keys(userEvent)가 default,userEvent,PointerEventsCheckLevel로 나옵니다. user-event API가 아니라 모듈 namespace 전체가 export되고 있습니다.
  • 영향: util-support에서 테스트 134개 중 116개가 실패해 1.0.3으로 고정해 둔 상태입니다(dev-five-git/util-support#158).

원인

#8에서 ESM 번들을 없애고 dist/index.mjs를 export * from './index.cjs'로 바꿨습니다. 그런데 bun build --target node --format cjs가 export { default as userEvent } from '@testing-library/user-event'를 다음처럼 컴파일합니다.

S = __toESM(require("@testing-library/user-event"), 1)  // 1 = Node 방식 interop
userEvent: () => S.default

Node 방식 interop은 __esModule을 무시하고 module.exports 전체를 default로 취급합니다. 그래서 userEvent가 모듈 namespace가 됐습니다. 1.0.3은 ESM 번들에서 import { default as F } from '@testing-library/user-event'를 썼기 때문에 정상이었습니다. 타입 선언은 그대로였기 때문에 tsc와 build는 통과했습니다.

수정

  • src/index.ts: default 대신 이름으로 export된 userEvent를 다시 export합니다. user-event 14는 CJS와 타입 모두에서 userEvent라는 이름을 제공하므로, interop 방식과 상관없이 올바른 값이 나옵니다. 빌드 결과는 userEvent: () => S.userEvent입니다.
  • dist-preload.test.ts: 빌드된 각 진입 파일(dist/index.cjs, dist/index.mjs)을 preload한 새 프로세스에서, 그 진입 파일이 export한 userEvent로 실제로 타이핑하는 테스트를 추가했습니다.
    • 수정 전(1.0.4 소스): 두 진입 파일 모두 TypeError: userEvent.type is not a function으로 실패
    • 수정 후: 2 pass / 0 fail
  • changepack: Patch (1.0.5)

검증

  • bun lint: 통과
  • bun test: 28 pass, coverage 100%
  • bun run build: dist/index.d.ts는 export { userEvent } from '@testing-library/user-event'로 생성됩니다

1.0.4 builds only the CJS bundle and makes index.mjs re-export it. bun build --target node compiles export { default as userEvent } to __toESM(require('@testing-library/user-event'), 1).default, and that Node-style interop ignores __esModule, so userEvent became user-event's whole module namespace ({ default, userEvent, PointerEventsCheckLevel }) and userEvent.type was undefined for every consumer.

Re-export the named userEvent binding instead, which does not depend on interop. The dist preload fixture now also types through the userEvent imported from each built entry; it fails on 1.0.4 with 'userEvent.type is not a function' and passes with this change.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
@owjs3901
owjs3901 merged commit f5cc4b3 into main Sep 23, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant