1- import { describe , it , vi , afterEach } from 'vitest' ;
2- import { FileModificationCalculator , ModificationType } from './file-modification-calculator' ;
3- import { ResourceConfig } from '../entities/resource-config' ;
4- import { ResourceInfo } from '../entities/resource-info' ;
5- import { FileType , InMemoryFile } from '../parser/entities' ;
1+ import * as fs from 'node:fs' ;
2+ import * as os from 'node:os' ;
3+ import * as path from 'node:path' ;
4+
5+ import { describe , it , vi , afterEach , expect } from 'vitest' ;
6+ import { FileModificationCalculator , ModificationType } from './file-modification-calculator.js' ;
7+ import { ResourceConfig } from '../entities/resource-config.js' ;
8+ import { ResourceInfo } from '../entities/resource-info.js' ;
9+ import { CodifyParser } from '../parser/index.js' ;
610
711vi . mock ( 'node:fs' , async ( ) => {
812 const { fs } = await import ( 'memfs' ) ;
@@ -14,39 +18,133 @@ vi.mock('node:fs/promises', async () => {
1418 return fs . promises ;
1519} )
1620
21+ const defaultPath = '/codify.json'
22+
1723
1824describe ( 'File modification calculator tests' , ( ) => {
1925
2026 it ( 'Can generate a diff and a new file' , async ( ) => {
21- const existingResource = new ResourceConfig ( {
22- type : 'resource1'
27+ const existingFile =
28+ `[
29+ {
30+ "type": "project",
31+ "plugins": {
32+ "default": "latest"
33+ }
34+ },
35+ { "type": "resource1", "param2": ["a", "b", "c"]}
36+ ]`
37+ generateTestFile ( existingFile ) ;
38+
39+ const project = await CodifyParser . parse ( defaultPath )
40+ project . resourceConfigs . forEach ( ( r ) => {
41+ r . attachResourceInfo ( generateResourceInfo ( r . type ) )
2342 } ) ;
24- existingResource . attachResourceInfo ( generateResourceInfo ( 'resource1' ) )
2543
26- const existingFileContents =
44+ const modifiedResource = new ResourceConfig ( {
45+ type : 'resource1' ,
46+ parameter1 : 'abc'
47+ } )
48+ modifiedResource . attachResourceInfo ( generateResourceInfo ( 'resource1' ) )
49+
50+ const calculator = new FileModificationCalculator ( project . resourceConfigs , project . sourceMaps . getSourceMap ( defaultPath ) . file , project . sourceMaps ) ;
51+ const result = await calculator . calculate ( [ {
52+ modification : ModificationType . INSERT_OR_UPDATE ,
53+ resource : modifiedResource ,
54+ } ] )
55+
56+ console . log ( result )
57+ console . log ( result . diff )
58+ } )
59+
60+ it ( 'Can delete a resource from an existing config (with proper commas)' , async ( ) => {
61+ const existingFile =
2762`[
2863 {
2964 "type": "project",
3065 "plugins": {
31- "default": "latest",
66+ "default": "latest"
3267 }
3368 },
34- { "type": "resource1" }
69+ {
70+ "type": "resource1",
71+ "param2": ["a", "b", "c"]
72+ }
3573]`
36- const existingFile = < InMemoryFile > { filePath : '/path/to/file.json' , fileType : FileType . JSON , contents : existingFileContents } ;
74+ generateTestFile ( existingFile ) ;
75+
76+ const project = await CodifyParser . parse ( defaultPath )
77+ project . resourceConfigs . forEach ( ( r ) => {
78+ r . attachResourceInfo ( generateResourceInfo ( r . type ) )
79+ } ) ;
3780
3881 const modifiedResource = new ResourceConfig ( {
3982 type : 'resource1' ,
4083 parameter1 : 'abc'
4184 } )
4285 modifiedResource . attachResourceInfo ( generateResourceInfo ( 'resource1' ) )
4386
44- const calculator = new FileModificationCalculator ( [ existingResource ] , existingFile )
87+ const calculator = new FileModificationCalculator ( project . resourceConfigs , project . sourceMaps . getSourceMap ( defaultPath ) . file , project . sourceMaps ) ;
4588 const result = await calculator . calculate ( [ {
46- modification : ModificationType . INSERT_OR_UPDATE ,
89+ modification : ModificationType . DELETE ,
4790 resource : modifiedResource ,
4891 } ] )
4992
93+ expect ( result . newFile ) . to . eq ( '[\n' +
94+ ' {\n' +
95+ ' "type": "project",\n' +
96+ ' "plugins": {\n' +
97+ ' "default": "latest"\n' +
98+ ' }\n' +
99+ ' }\n' +
100+ ' \n' +
101+ ']' )
102+ console . log ( result )
103+ console . log ( result . diff )
104+ } )
105+
106+ it ( 'Can delete a resource from an existing config 2 (with proper commas)' , async ( ) => {
107+ const existingFile =
108+ `[
109+ {
110+ "type": "resource1",
111+ "param2": ["a", "b", "c"]
112+ },
113+ {
114+ "type": "project",
115+ "plugins": {
116+ "default": "latest"
117+ }
118+ }
119+ ]`
120+ generateTestFile ( existingFile ) ;
121+
122+ const project = await CodifyParser . parse ( defaultPath )
123+ project . resourceConfigs . forEach ( ( r ) => {
124+ r . attachResourceInfo ( generateResourceInfo ( r . type ) )
125+ } ) ;
126+
127+ const modifiedResource = new ResourceConfig ( {
128+ type : 'resource1' ,
129+ parameter1 : 'abc'
130+ } )
131+ modifiedResource . attachResourceInfo ( generateResourceInfo ( 'resource1' ) )
132+
133+ const calculator = new FileModificationCalculator ( project . resourceConfigs , project . sourceMaps . getSourceMap ( defaultPath ) . file , project . sourceMaps ) ;
134+ const result = await calculator . calculate ( [ {
135+ modification : ModificationType . DELETE ,
136+ resource : modifiedResource ,
137+ } ] )
138+
139+ // expect(result.newFile).to.eq('[\n' +
140+ // ' {\n' +
141+ // ' "type": "project",\n' +
142+ // ' "plugins": {\n' +
143+ // ' "default": "latest"\n' +
144+ // ' }\n' +
145+ // ' }\n' +
146+ // ' \n' +
147+ // ']')
50148 console . log ( result )
51149 console . log ( result . diff )
52150 } )
@@ -63,3 +161,10 @@ function generateResourceInfo(type: string, requiredParameters?: string[]): Reso
63161 import : { requiredParameters }
64162 } )
65163}
164+
165+ /**
166+ * To generate the source maps and parsed resources it's easier to write it to the file-system and parse it for real
167+ */
168+ function generateTestFile ( contents : string , filePath = defaultPath ) : void {
169+ fs . writeFileSync ( filePath , contents , { encoding : 'utf8' } ) ;
170+ }
0 commit comments