1
+ import { execSync } from 'child_process'
2
+ import { existsSync , readFileSync } from 'fs'
3
+ import { join } from 'path'
4
+ import { describe , expect , it , beforeAll } from 'vitest'
5
+
6
+ const DIST_DIR = join ( process . cwd ( ) , 'dist' )
7
+ const CJS_FILE = join ( DIST_DIR , 'index.cjs' )
8
+ const ESM_FILE = join ( DIST_DIR , 'index.js' )
9
+ const DTS_FILE = join ( DIST_DIR , 'index.d.ts' )
10
+
11
+ describe ( 'Build Output Verification' , ( ) => {
12
+ beforeAll ( ( ) => {
13
+ // Ensure build exists
14
+ if ( ! existsSync ( DIST_DIR ) ) {
15
+ execSync ( 'pnpm build' , { stdio : 'inherit' } )
16
+ }
17
+ } )
18
+
19
+ it ( 'should generate all required build files' , ( ) => {
20
+ expect ( existsSync ( CJS_FILE ) ) . toBe ( true )
21
+ expect ( existsSync ( ESM_FILE ) ) . toBe ( true )
22
+ expect ( existsSync ( DTS_FILE ) ) . toBe ( true )
23
+ } )
24
+
25
+ it ( 'should generate valid CommonJS format' , ( ) => {
26
+ const cjsContent = readFileSync ( CJS_FILE , 'utf8' )
27
+
28
+ // Should start with 'use strict'
29
+ expect ( cjsContent ) . toMatch ( / ^ ' u s e s t r i c t ' / )
30
+
31
+ // Should use require() for dependencies
32
+ expect ( cjsContent ) . toMatch ( / r e q u i r e \( [ ' " ] / )
33
+
34
+ // Should not contain ES6 import statements
35
+ expect ( cjsContent ) . not . toMatch ( / ^ i m p o r t \s + / )
36
+ } )
37
+
38
+ it ( 'should generate valid ES module format' , ( ) => {
39
+ const esmContent = readFileSync ( ESM_FILE , 'utf8' )
40
+
41
+ // Should use import statements
42
+ expect ( esmContent ) . toMatch ( / ^ i m p o r t \s + / )
43
+
44
+ // Should not contain require() calls
45
+ expect ( esmContent ) . not . toMatch ( / r e q u i r e \( [ ' " ] / )
46
+ } )
47
+
48
+ it ( 'should generate TypeScript definitions' , ( ) => {
49
+ const dtsContent = readFileSync ( DTS_FILE , 'utf8' )
50
+
51
+ // Should contain export declarations
52
+ expect ( dtsContent ) . toMatch ( / e x p o r t \s + / )
53
+
54
+ // Should contain key function types
55
+ expect ( dtsContent ) . toMatch ( / p a r s e / )
56
+ expect ( dtsContent ) . toMatch ( / r e n d e r / )
57
+ } )
58
+
59
+ it ( 'should load CJS build correctly' , async ( ) => {
60
+ // Use dynamic require to avoid bundler issues
61
+ const cjsModule = await import ( CJS_FILE )
62
+
63
+ expect ( typeof cjsModule . parse ) . toBe ( 'function' )
64
+ expect ( typeof cjsModule . render ) . toBe ( 'function' )
65
+ expect ( typeof cjsModule . createChain ) . toBe ( 'function' )
66
+ expect ( cjsModule . CompileError ) . toBeDefined ( )
67
+
68
+ // Should have all expected exports
69
+ const exports = Object . keys ( cjsModule )
70
+ expect ( exports ) . toContain ( 'parse' )
71
+ expect ( exports ) . toContain ( 'render' )
72
+ expect ( exports ) . toContain ( 'CompileError' )
73
+ expect ( exports ) . toContain ( 'ContentType' )
74
+ expect ( exports ) . toContain ( 'MessageRole' )
75
+ } )
76
+
77
+ it ( 'should load ESM build correctly' , async ( ) => {
78
+ const esmModule = await import ( ESM_FILE )
79
+
80
+ expect ( typeof esmModule . parse ) . toBe ( 'function' )
81
+ expect ( typeof esmModule . render ) . toBe ( 'function' )
82
+ expect ( typeof esmModule . createChain ) . toBe ( 'function' )
83
+ expect ( esmModule . CompileError ) . toBeDefined ( )
84
+
85
+ // Should have all expected exports
86
+ const exports = Object . keys ( esmModule )
87
+ expect ( exports ) . toContain ( 'parse' )
88
+ expect ( exports ) . toContain ( 'render' )
89
+ expect ( exports ) . toContain ( 'CompileError' )
90
+ expect ( exports ) . toContain ( 'ContentType' )
91
+ expect ( exports ) . toContain ( 'MessageRole' )
92
+ } )
93
+
94
+ it ( 'should have functional parse and render in CJS build' , async ( ) => {
95
+ const { parse, render } = await import ( CJS_FILE )
96
+
97
+ const template = 'Hello {{name}}!'
98
+ const parsed = parse ( template )
99
+
100
+ expect ( parsed ) . toBeDefined ( )
101
+ expect ( parsed . type ) . toBe ( 'Fragment' )
102
+
103
+ const rendered = await render ( {
104
+ prompt : template ,
105
+ parameters : { name : 'World' }
106
+ } )
107
+
108
+ expect ( rendered ) . toBeDefined ( )
109
+ expect ( rendered . messages ) . toBeDefined ( )
110
+ expect ( rendered . config ) . toBeDefined ( )
111
+ expect ( Array . isArray ( rendered . messages ) ) . toBe ( true )
112
+ } )
113
+
114
+ it ( 'should have functional parse and render in ESM build' , async ( ) => {
115
+ const { parse, render } = await import ( ESM_FILE )
116
+
117
+ const template = 'Hello {{name}}!'
118
+ const parsed = parse ( template )
119
+
120
+ expect ( parsed ) . toBeDefined ( )
121
+ expect ( parsed . type ) . toBe ( 'Fragment' )
122
+
123
+ const rendered = await render ( {
124
+ prompt : template ,
125
+ parameters : { name : 'World' }
126
+ } )
127
+
128
+ expect ( rendered ) . toBeDefined ( )
129
+ expect ( rendered . messages ) . toBeDefined ( )
130
+ expect ( rendered . config ) . toBeDefined ( )
131
+ expect ( Array . isArray ( rendered . messages ) ) . toBe ( true )
132
+ } )
133
+
134
+ it ( 'should have identical exports between CJS and ESM builds' , async ( ) => {
135
+ const cjsModule = await import ( CJS_FILE )
136
+ const esmModule = await import ( ESM_FILE )
137
+
138
+ // Filter out 'default' export which is expected to differ between CJS and ESM
139
+ const cjsExports = Object . keys ( cjsModule ) . filter ( key => key !== 'default' ) . sort ( )
140
+ const esmExports = Object . keys ( esmModule ) . filter ( key => key !== 'default' ) . sort ( )
141
+
142
+ expect ( cjsExports ) . toEqual ( esmExports )
143
+ expect ( cjsExports . length ) . toBeGreaterThan ( 10 ) // Ensure we have substantial exports
144
+ } )
145
+ } )
0 commit comments