@@ -8,20 +8,57 @@ const sb3fix = require('../src/sb3fix');
88
99const inputDirectory = path . join ( __dirname , 'samples' ) ;
1010const outputDirectory = path . join ( __dirname , 'expected-output' ) ;
11+
12+ /** @type {Array<import('../src/sb3fix').Platform> } */
13+ const nonScratchPlatforms = Object . keys ( sb3fix . platforms ) . filter ( i => i !== 'scratch' ) ;
14+
1115const testcases = fs . readdirSync ( inputDirectory )
1216 . filter ( i => i . endsWith ( '.sb3' ) || i . endsWith ( '.sprite3' ) )
13- . sort ( )
14- . map ( i => ( {
15- name : i ,
16- inputPath : path . join ( inputDirectory , i ) ,
17- outputProjectPath : path . join ( outputDirectory , i ) ,
18- outputLogPath : path . join ( outputDirectory , i . replace ( / \. (?: s b | s p r i t e ) 3 $ / , '.txt' ) ) ,
19- } ) ) ;
20-
21- const runTestcase = async ( testcase ) => {
17+ . sort ( ) ;
18+
19+ /**
20+ * @typedef Result
21+ * @property {Uint8Array } result
22+ * @property {string } log
23+ */
24+
25+ /**
26+ * @param {string } testcase
27+ * @param {import('../src/sb3fix').Platform } platform
28+ * @returns {string }
29+ */
30+ const getOutputProjectPath = ( testcase , platform ) => {
31+ if ( platform === 'scratch' ) {
32+ return path . join ( outputDirectory , testcase ) ;
33+ }
34+ return path . join ( outputDirectory , platform , testcase ) ;
35+ } ;
36+
37+ /**
38+ *
39+ * @param {string } testcase
40+ * @param {import('../src/sb3fix').Platform } platform
41+ * @returns {string }
42+ */
43+ const getOutputLogPath = ( testcase , platform ) => {
44+ const name = testcase . replace ( / \. (?: s b | s p r i t e ) 3 $ / , '.txt' ) ;
45+ if ( platform === 'scratch' ) {
46+ return path . join ( outputDirectory , name ) ;
47+ }
48+ return path . join ( outputDirectory , platform , name ) ;
49+ } ;
50+
51+ /**
52+ * @param {string } testcase
53+ * @param {import('../src/sb3fix').Platform } platform
54+ * @returns {Promise<Result> }
55+ */
56+ const runTestcase = async ( testcase , platform ) => {
2257 const logs = [ ] ;
23- const data = await fsPromises . readFile ( testcase . inputPath ) ;
58+ const inputPath = path . join ( inputDirectory , testcase ) ;
59+ const data = await fsPromises . readFile ( inputPath ) ;
2460 const result = await sb3fix . fixZip ( data , {
61+ platform,
2562 logCallback : ( message ) => {
2663 logs . push ( message ) ;
2764 }
@@ -32,35 +69,129 @@ const runTestcase = async (testcase) => {
3269 } ;
3370} ;
3471
72+ /**
73+ * @param {Uint8Array } a
74+ * @param {Uint8Array } b
75+ * @returns {boolean }
76+ */
77+ const areArraysShallowEqual = ( a , b ) => {
78+ if ( a . length !== b . length ) {
79+ return false ;
80+ }
81+ for ( let i = 0 ; i < a . length ; i ++ ) {
82+ if ( a [ i ] !== b [ i ] ) {
83+ return false ;
84+ }
85+ }
86+ return true ;
87+ } ;
88+
89+ /**
90+ * @param {Result } resultA
91+ * @param {Result } resultB
92+ * @returns {boolean }
93+ */
94+ const isIdenticalResult = ( resultA , resultB ) => (
95+ resultA . log === resultB . log &&
96+ areArraysShallowEqual ( resultA . result , resultB . result )
97+ ) ;
98+
99+ /**
100+ * @param {Result } resultA
101+ * @param {Result } resultB
102+ */
103+ const assertIdenticalResults = ( resultA , resultB ) => {
104+ assert . strictEqual ( resultA . log , resultB . log , 'log' ) ;
105+ assert . deepStrictEqual ( resultA . result , resultB . result , 'project' ) ;
106+ } ;
107+
35108const validate = async ( ) => {
36109 for ( const testcase of testcases ) {
37- await nodeTest ( testcase , async ( t ) => {
38- const expectedFixedProject = new Uint8Array ( await fsPromises . readFile ( testcase . outputProjectPath ) ) ;
39- const expectedLog = await fsPromises . readFile ( testcase . outputLogPath , 'utf-8' ) ;
40- const result = await runTestcase ( testcase ) ;
110+ await nodeTest ( testcase , async ( ) => {
111+ /** @type {Result|null } */
112+ let expectedScratchResult = null ;
41113
42- assert . equal ( result . log , expectedLog , 'log' ) ;
43- assert . deepStrictEqual ( result . result , expectedFixedProject , 'project' ) ;
114+ await nodeTest ( "scratch" , async ( ) => {
115+ expectedScratchResult = await readResult ( testcase , 'scratch' ) ;
116+ assert . notStrictEqual ( expectedScratchResult , null , 'scratch expected result exists' ) ;
117+
118+ const actualResult = await runTestcase ( testcase , 'scratch' ) ;
119+ assertIdenticalResults ( expectedScratchResult , actualResult ) ;
120+ } ) ;
121+
122+ for ( const platform of nonScratchPlatforms ) {
123+ await nodeTest ( platform , async ( ) => {
124+ const expectedResult = await readResult ( testcase , platform ) || expectedScratchResult ;
125+ const actualResult = await runTestcase ( testcase , platform ) ;
126+ assertIdenticalResults ( expectedResult , actualResult ) ;
127+ } ) ;
128+ }
44129 } ) ;
45130 }
46131} ;
47132
133+ /**
134+ * @param {string } testcase
135+ * @param {import('../src/sb3fix').Platform } platform
136+ * @returns {Promise<Result|null> }
137+ */
138+ const readResult = async ( testcase , platform ) => {
139+ const outputProjectPath = getOutputProjectPath ( testcase , platform ) ;
140+ const outputLogPath = getOutputLogPath ( testcase , platform ) ;
141+
142+ try {
143+ const result = new Uint8Array ( await fsPromises . readFile ( outputProjectPath ) ) ;
144+ const log = await fsPromises . readFile ( outputLogPath , 'utf8' ) ;
145+ return {
146+ result,
147+ log
148+ } ;
149+ } catch ( e ) {
150+ if ( e . code === 'ENOENT' ) {
151+ return null ;
152+ }
153+ throw e ;
154+ }
155+ } ;
156+
157+ /**
158+ * @param {string } testcase
159+ * @param {import('../src/sb3fix').Platform } platform
160+ * @param {Result } result
161+ */
162+ const writeResult = async ( testcase , platform , result ) => {
163+ const outputProjectPath = getOutputProjectPath ( testcase , platform ) ;
164+ const outputLogPath = getOutputLogPath ( testcase , platform ) ;
165+
166+ const directory = path . dirname ( outputProjectPath ) ;
167+ await fsPromises . mkdir ( directory , {
168+ recursive : true
169+ } ) ;
170+
171+ await fsPromises . writeFile ( outputProjectPath , result . result ) ;
172+ await fsPromises . writeFile ( outputLogPath , result . log ) ;
173+ } ;
174+
48175const update = async ( ) => {
49176 console . time ( 'Updated snapshots' ) ;
50177
51178 await fsPromises . rm ( outputDirectory , {
52179 force : true ,
53180 recursive : true
54181 } ) ;
55- await fsPromises . mkdir ( outputDirectory , {
56- recursive : true
57- } ) ;
58182
59183 for ( const testcase of testcases ) {
60- console . log ( `${ testcase . name } ...` ) ;
61- const result = await runTestcase ( testcase ) ;
62- await fsPromises . writeFile ( testcase . outputProjectPath , result . result ) ;
63- await fsPromises . writeFile ( testcase . outputLogPath , result . log ) ;
184+ console . log ( `${ testcase } ...` ) ;
185+
186+ const scratchResult = await runTestcase ( testcase , 'scratch' ) ;
187+ await writeResult ( testcase , 'scratch' , scratchResult ) ;
188+
189+ for ( const platform of nonScratchPlatforms ) {
190+ const nonScratchResult = await runTestcase ( testcase , platform ) ;
191+ if ( ! isIdenticalResult ( scratchResult , nonScratchResult ) ) {
192+ await writeResult ( testcase , platform , nonScratchResult ) ;
193+ }
194+ }
64195 }
65196
66197 console . timeEnd ( 'Updated snapshots' ) ;
0 commit comments