@@ -3,7 +3,7 @@ import { cleanTree } from './clean-tree';
33import { readFileSync } from 'fs' ;
44import * as path from 'path' ;
55import { expect } from '@jest/globals' ;
6-
6+ import { diff } from 'jest-diff' ;
77const parser13 = new Parser ( 13 as any ) ;
88const parser14 = new Parser ( 14 as any ) ;
99const parser15 = new Parser ( 15 as any ) ;
@@ -55,53 +55,6 @@ export function getTransformerForVersion(versionPrevious: number, versionNext: n
5555 return new ASTTransformer ( ) ;
5656}
5757
58- /**
59- * Helper function to find the first difference between two objects
60- */
61- function findFirstDifference ( obj1 : any , obj2 : any , path : string = '' ) : { path : string ; expected : any ; actual : any } | null {
62- // Handle primitive values
63- if ( obj1 === obj2 ) return null ;
64- if ( typeof obj1 !== 'object' || typeof obj2 !== 'object' || obj1 === null || obj2 === null ) {
65- return { path, expected : obj1 , actual : obj2 } ;
66- }
67-
68- // Handle arrays
69- if ( Array . isArray ( obj1 ) && Array . isArray ( obj2 ) ) {
70- if ( obj1 . length !== obj2 . length ) {
71- return { path : `${ path } .length` , expected : obj1 . length , actual : obj2 . length } ;
72- }
73- for ( let i = 0 ; i < obj1 . length ; i ++ ) {
74- const diff = findFirstDifference ( obj1 [ i ] , obj2 [ i ] , `${ path } [${ i } ]` ) ;
75- if ( diff ) return diff ;
76- }
77- return null ;
78- }
79-
80- // Handle objects
81- const keys1 = Object . keys ( obj1 ) . sort ( ) ;
82- const keys2 = Object . keys ( obj2 ) . sort ( ) ;
83-
84- // Check for missing/extra keys
85- if ( keys1 . length !== keys2 . length || keys1 . some ( ( k , i ) => k !== keys2 [ i ] ) ) {
86- const missingInObj2 = keys1 . filter ( k => ! keys2 . includes ( k ) ) ;
87- const extraInObj2 = keys2 . filter ( k => ! keys1 . includes ( k ) ) ;
88- if ( missingInObj2 . length > 0 ) {
89- return { path : `${ path } .${ missingInObj2 [ 0 ] } ` , expected : obj1 [ missingInObj2 [ 0 ] ] , actual : undefined } ;
90- }
91- if ( extraInObj2 . length > 0 ) {
92- return { path : `${ path } .${ extraInObj2 [ 0 ] } ` , expected : undefined , actual : obj2 [ extraInObj2 [ 0 ] ] } ;
93- }
94- }
95-
96- // Check values
97- for ( const key of keys1 ) {
98- const diff = findFirstDifference ( obj1 [ key ] , obj2 [ key ] , path ? `${ path } .${ key } ` : key ) ;
99- if ( diff ) return diff ;
100- }
101-
102- return null ;
103- }
104-
10558/**
10659 * Perform the parse-transform-parse equality test
10760 */
@@ -111,7 +64,8 @@ export async function expectTransformedAstToEqualParsedAst(
11164 parserNext : any ,
11265 transformer : ASTTransformer ,
11366 versionPrevious : number ,
114- versionNext : number
67+ versionNext : number ,
68+ relativePath ?: string
11569) : Promise < void > {
11670 const parsedPrevious = await parserPrevious . parse ( sql ) ;
11771 const parsedNext = await parserNext . parse ( sql ) ;
@@ -129,13 +83,13 @@ export async function expectTransformedAstToEqualParsedAst(
12983 return { ...stmtWrapper , stmt : transformedStmt } ;
13084 } catch ( error : any ) {
13185 const errorMessage = [
132- `\n❌ TRANSFORMATION ERROR` ,
133- ` Previous Version: ${ versionPrevious } ` ,
134- ` Next Version: ${ versionNext } ` ,
135- ` Statement Index: ${ index } ` ,
136- ` Statement Type: ${ Object . keys ( stmtWrapper . stmt ) [ 0 ] } ` ,
137- ` Error: ${ error . message } ` ,
138- `\n Original Statement:` ,
86+ `\n❌ TRANSFORMATION ERROR ${ relativePath ? `( ${ relativePath } )` : '' } ` ,
87+ ` ⚠️ Previous Version: ${ versionPrevious } ` ,
88+ ` ⚠️ Next Version: ${ versionNext } ` ,
89+ ` ⚠️ Statement Index: ${ index } ` ,
90+ ` ⚠️ Statement Type: ${ Object . keys ( stmtWrapper . stmt ) [ 0 ] } ` ,
91+ ` ⚠️ Error: ${ error . message } ` ,
92+ `\n ⚠️ Original Statement:` ,
13993 JSON . stringify ( stmtWrapper . stmt , null , 2 )
14094 ] . join ( '\n' ) ;
14195
@@ -161,22 +115,19 @@ export async function expectTransformedAstToEqualParsedAst(
161115 expect ( nextAst ) . toEqual ( previousTransformedAst ) ;
162116 } catch ( error : any ) {
163117 // Try to find the first difference
164- const diff = findFirstDifference ( nextAst , previousTransformedAst ) ;
118+ const d = diff ( nextAst , previousTransformedAst ) ;
165119
166120 const errorMessage = [
167- `\n❌ TRANSFORMATION MISMATCH` ,
168- ` Previous Version: ${ versionPrevious } ` ,
169- ` Next Version: ${ versionNext } ` ,
170- ` SQL: ${ sql } ` ,
171- `\n Expected (parsed with v${ versionNext } ):` ,
121+ `\n❌ TRANSFORMATION MISMATCH ${ relativePath ? `( ${ relativePath } )` : '' } ` ,
122+ ` ⚠️ Previous Version: ${ versionPrevious } ` ,
123+ ` ⚠️ Next Version: ${ versionNext } ` ,
124+ ` ⚠️ SQL: ${ sql } ` ,
125+ `\n ⚠️ Expected (parsed with v${ versionNext } ):` ,
172126 JSON . stringify ( nextAst , null , 2 ) ,
173- `\n Actual (transformed from v${ versionPrevious } ):` ,
174- JSON . stringify ( previousTransformedAst , null , 2 ) ,
175- diff ? `\n First difference at path: ${ diff . path } ` : '' ,
176- diff ? ` Expected: ${ JSON . stringify ( diff . expected ) } ` : '' ,
177- diff ? ` Actual: ${ JSON . stringify ( diff . actual ) } ` : ''
127+ `\n ⚠️ Actual (transformed from v${ versionPrevious } ):` ,
128+ JSON . stringify ( previousTransformedAst , null , 2 )
178129 ] . filter ( line => line !== '' ) . join ( '\n' ) ;
179-
130+ console . log ( relativePath + ':\n' + d ) ;
180131 console . error ( errorMessage ) ;
181132 throw error ;
182133 }
@@ -229,7 +180,7 @@ export class FixtureTestUtils {
229180
230181 async expectParseTransformParseToBeEqual ( relativePath : string , sql : string ) {
231182 // Use the modular helper function instead of duplicating logic
232- await expectTransformedAstToEqualParsedAst ( sql , this . parserPrevious , this . parserNext , this . transformer , this . versionPrevious , this . versionNext ) ;
183+ await expectTransformedAstToEqualParsedAst ( sql , this . parserPrevious , this . parserNext , this . transformer , this . versionPrevious , this . versionNext , relativePath ) ;
233184 }
234185
235186 async runFixtureTests ( filters : string [ ] ) {
0 commit comments