@@ -10,15 +10,15 @@ class TestFramework {
1010 }
1111
1212 describe ( name , fn ) {
13- const suite = { name, tests : [ ] }
13+ const suite = { name, tests : [ ] , beforeEachFns : [ ] , afterEachFns : [ ] }
1414 this . suites . push ( suite )
1515 this . currentSuite = suite
1616 fn ( )
1717 this . currentSuite = null
1818 }
1919
2020 test ( name , fn ) {
21- const test = { name, fn, suite : this . currentSuite ?. name || 'Global' }
21+ const test = { name, fn, suite : this . currentSuite ?. name || 'Global' , suiteObj : this . currentSuite }
2222 this . tests . push ( test )
2323 if ( this . currentSuite ) {
2424 this . currentSuite . tests . push ( test )
@@ -29,12 +29,39 @@ class TestFramework {
2929 this . test ( name , fn )
3030 }
3131
32+ beforeEach ( fn ) {
33+ if ( this . currentSuite ) {
34+ this . currentSuite . beforeEachFns . push ( fn )
35+ }
36+ }
37+
38+ afterEach ( fn ) {
39+ if ( this . currentSuite ) {
40+ this . currentSuite . afterEachFns . push ( fn )
41+ }
42+ }
43+
3244 async run ( ) {
3345 console . log ( '🧪 Running Git-Smart Test Suite\n' )
3446
3547 for ( const test of this . tests ) {
3648 try {
49+ // Run beforeEach hooks
50+ if ( test . suiteObj && test . suiteObj . beforeEachFns ) {
51+ for ( const beforeEachFn of test . suiteObj . beforeEachFns ) {
52+ await beforeEachFn ( )
53+ }
54+ }
55+
3756 await test . fn ( )
57+
58+ // Run afterEach hooks
59+ if ( test . suiteObj && test . suiteObj . afterEachFns ) {
60+ for ( const afterEachFn of test . suiteObj . afterEachFns ) {
61+ await afterEachFn ( )
62+ }
63+ }
64+
3865 this . passed ++
3966 console . log ( `✅ ${ test . suite } : ${ test . name } ` )
4067 } catch ( error ) {
@@ -168,6 +195,7 @@ function expect(actual) {
168195class MockHelper {
169196 static mockExecSync ( returnValue = '' , shouldThrow = false ) {
170197 const originalExecSync = require ( 'child_process' ) . execSync
198+ const originalSpawnSync = require ( 'child_process' ) . spawnSync
171199
172200 const mock = ( command , options ) => {
173201 // Mock specific git commands for testing
@@ -184,7 +212,7 @@ class MockHelper {
184212 if ( shouldThrow ) throw new Error ( 'Git command failed' )
185213 return returnValue
186214 }
187- if ( command . includes ( 'git diff --cached' ) ) {
215+ if ( command . includes ( 'git diff --cached' ) && ! command . includes ( '--stat' ) ) {
188216 if ( shouldThrow ) throw new Error ( 'Git command failed' )
189217 return returnValue
190218 }
@@ -204,11 +232,49 @@ class MockHelper {
204232 return returnValue
205233 }
206234
235+ // Mock spawnSync for git commit
236+ const mockSpawnSync = ( command , args , options ) => {
237+ if ( command === 'git' && args && args [ 0 ] === 'commit' ) {
238+ if ( shouldThrow ) {
239+ return {
240+ status : 1 ,
241+ error : new Error ( 'Git command failed' ) ,
242+ stderr : 'Mock commit error' ,
243+ stdout : ''
244+ }
245+ }
246+ return {
247+ status : 0 ,
248+ error : null ,
249+ stderr : '' ,
250+ stdout : 'Mock commit success'
251+ }
252+ }
253+
254+ // Default mock behavior
255+ if ( shouldThrow ) {
256+ return {
257+ status : 1 ,
258+ error : new Error ( 'Mock error' ) ,
259+ stderr : 'Mock error' ,
260+ stdout : ''
261+ }
262+ }
263+ return {
264+ status : 0 ,
265+ error : null ,
266+ stderr : '' ,
267+ stdout : returnValue || ''
268+ }
269+ }
270+
207271 mock . restore = ( ) => {
208272 require ( 'child_process' ) . execSync = originalExecSync
273+ require ( 'child_process' ) . spawnSync = originalSpawnSync
209274 }
210275
211276 require ( 'child_process' ) . execSync = mock
277+ require ( 'child_process' ) . spawnSync = mockSpawnSync
212278 return mock
213279 }
214280
@@ -218,13 +284,23 @@ class MockHelper {
218284
219285 for ( let i = 0 ; i < count ; i ++ ) {
220286 commits . push ( {
221- hash : `abc${ i } 23 ${ i } ` ,
287+ hash : `abc${ i . toString ( ) . padStart ( 3 , '0' ) } ` ,
222288 message : `${ types [ i % types . length ] } : sample commit ${ i + 1 } `
223289 } )
224290 }
225291
226292 return commits
227293 }
294+
295+ static createMockGitOutput ( type = 'commits' ) {
296+ const outputs = {
297+ commits : 'abc123 feat: add authentication\ndef456 fix: resolve login bug\nghi789 docs: update README' ,
298+ stagedFiles : 'M\tsrc/auth.js\nA\tsrc/utils.js\nD\told-file.js' ,
299+ diff : 'diff --git a/src/auth.js b/src/auth.js\nindex 1234567..abcdefg 100644\n--- a/src/auth.js\n+++ b/src/auth.js\n@@ -1,3 +1,6 @@\n function login(user) {\n+ if (!user.email) {\n+ throw new Error(\'Email required\')\n+ }\n return authenticate(user)\n }' ,
300+ stats : '2 files changed, 5 insertions(+), 1 deletion(-)'
301+ }
302+ return outputs [ type ] || ''
303+ }
228304
229305 static createMockDiff ( type = 'feat' ) {
230306 const diffs = {
@@ -315,6 +391,8 @@ const testFramework = new TestFramework()
315391global . describe = testFramework . describe . bind ( testFramework )
316392global . test = testFramework . test . bind ( testFramework )
317393global . it = testFramework . it . bind ( testFramework )
394+ global . beforeEach = testFramework . beforeEach . bind ( testFramework )
395+ global . afterEach = testFramework . afterEach . bind ( testFramework )
318396global . expect = expect
319397global . MockHelper = MockHelper
320398
0 commit comments