1+ import { join } from 'path' ;
2+ import { writeFileSync , mkdirSync , rmSync } from 'fs' ;
3+ import {
4+ parseConfigFile ,
5+ parseConfigContent ,
6+ getConfigValue ,
7+ getConfigSection ,
8+ hasConfigSection
9+ } from '../src' ;
10+ import { ConfigFile } from '../src/types' ;
11+
12+ describe ( 'Config Parser' , ( ) => {
13+ const testDir = join ( __dirname , 'test-configs' ) ;
14+
15+ beforeAll ( ( ) => {
16+ mkdirSync ( testDir , { recursive : true } ) ;
17+ } ) ;
18+
19+ afterAll ( ( ) => {
20+ rmSync ( testDir , { recursive : true , force : true } ) ;
21+ } ) ;
22+
23+ describe ( 'parseConfigFile' , ( ) => {
24+ it ( 'should parse a simple config file' , ( ) => {
25+ const configContent = `[core]
26+ engine = pg
27+ plan_file = sqitch.plan
28+ top_dir = .
29+
30+ [engine "pg"]
31+ target = db:pg://localhost/mydb
32+ registry = sqitch
33+ client = psql` ;
34+
35+ const configPath = join ( testDir , 'simple.conf' ) ;
36+ writeFileSync ( configPath , configContent ) ;
37+
38+ const result = parseConfigFile ( configPath ) ;
39+
40+ expect ( result . errors ) . toHaveLength ( 0 ) ;
41+ expect ( result . data ) . toBeDefined ( ) ;
42+ expect ( result . data ) . toHaveProperty ( 'core' ) ;
43+ expect ( result . data ) . toHaveProperty ( 'engine "pg"' ) ;
44+ expect ( result . data ! . core . engine ) . toBe ( 'pg' ) ;
45+ expect ( result . data ! [ 'engine "pg"' ] . target ) . toBe ( 'db:pg://localhost/mydb' ) ;
46+ } ) ;
47+
48+ it ( 'should handle comments and empty lines' , ( ) => {
49+ const configContent = `# This is a comment
50+ [core]
51+ # Another comment
52+ engine = pg
53+
54+ plan_file = sqitch.plan
55+
56+ # Section comment
57+ [deploy]
58+ verify = true` ;
59+
60+ const configPath = join ( testDir , 'with-comments.conf' ) ;
61+ writeFileSync ( configPath , configContent ) ;
62+
63+ const result = parseConfigFile ( configPath ) ;
64+
65+ expect ( result . errors ) . toHaveLength ( 0 ) ;
66+ expect ( result . data ! . core . engine ) . toBe ( 'pg' ) ;
67+ expect ( result . data ! . deploy . verify ) . toBe ( 'true' ) ;
68+ } ) ;
69+
70+ it ( 'should report errors for multi-line values' , ( ) => {
71+ const configContent = `[core]
72+ engine = pg
73+
74+ [notes]
75+ add = This is a long \\
76+ multi-line \\
77+ value that continues` ;
78+
79+ const configPath = join ( testDir , 'multiline.conf' ) ;
80+ writeFileSync ( configPath , configContent ) ;
81+
82+ const result = parseConfigFile ( configPath ) ;
83+
84+ // Multi-line values are not supported
85+ expect ( result . errors ) . toHaveLength ( 2 ) ;
86+ expect ( result . errors [ 0 ] . message ) . toContain ( 'Invalid line format' ) ;
87+ } ) ;
88+
89+ it ( 'should report errors for invalid syntax' , ( ) => {
90+ const configContent = `[core]
91+ engine = pg
92+
93+ invalid line without equals
94+
95+ [deploy]
96+ verify = true` ;
97+
98+ const configPath = join ( testDir , 'invalid.conf' ) ;
99+ writeFileSync ( configPath , configContent ) ;
100+
101+ const result = parseConfigFile ( configPath ) ;
102+
103+ expect ( result . errors . length ) . toBeGreaterThan ( 0 ) ;
104+ expect ( result . errors [ 0 ] . line ) . toBe ( 4 ) ;
105+ } ) ;
106+ } ) ;
107+
108+ describe ( 'parseConfigContent' , ( ) => {
109+ it ( 'should parse config content directly' , ( ) => {
110+ const configContent = `[core]
111+ engine = pg
112+ plan_file = sqitch.plan` ;
113+
114+ const result = parseConfigContent ( configContent ) ;
115+
116+ expect ( result . errors ) . toHaveLength ( 0 ) ;
117+ expect ( result . data ! . core . engine ) . toBe ( 'pg' ) ;
118+ } ) ;
119+ } ) ;
120+
121+ describe ( 'getConfigValue' , ( ) => {
122+ const config : ConfigFile = {
123+ core : {
124+ engine : 'pg' ,
125+ plan_file : 'sqitch.plan'
126+ } ,
127+ 'engine "pg"' : {
128+ target : 'db:pg://localhost/mydb' ,
129+ registry : 'sqitch'
130+ }
131+ } ;
132+
133+ it ( 'should get values from simple sections' , ( ) => {
134+ expect ( getConfigValue ( config , 'core' , 'engine' ) ) . toBe ( 'pg' ) ;
135+ expect ( getConfigValue ( config , 'core' , 'plan_file' ) ) . toBe ( 'sqitch.plan' ) ;
136+ } ) ;
137+
138+ it ( 'should get values from quoted sections' , ( ) => {
139+ expect ( getConfigValue ( config , 'engine "pg"' , 'target' ) ) . toBe ( 'db:pg://localhost/mydb' ) ;
140+ expect ( getConfigValue ( config , 'engine "pg"' , 'registry' ) ) . toBe ( 'sqitch' ) ;
141+ } ) ;
142+
143+ it ( 'should return undefined for non-existent values' , ( ) => {
144+ expect ( getConfigValue ( config , 'core' , 'nonexistent' ) ) . toBeUndefined ( ) ;
145+ expect ( getConfigValue ( config , 'nonexistent' , 'key' ) ) . toBeUndefined ( ) ;
146+ } ) ;
147+ } ) ;
148+
149+ describe ( 'getConfigSection' , ( ) => {
150+ const config : ConfigFile = {
151+ core : {
152+ engine : 'pg' ,
153+ plan_file : 'sqitch.plan'
154+ } ,
155+ deploy : {
156+ verify : 'true' ,
157+ mode : 'strict'
158+ }
159+ } ;
160+
161+ it ( 'should get entire sections' , ( ) => {
162+ const coreSection = getConfigSection ( config , 'core' ) ;
163+ expect ( coreSection ) . toEqual ( {
164+ engine : 'pg' ,
165+ plan_file : 'sqitch.plan'
166+ } ) ;
167+ } ) ;
168+
169+ it ( 'should return undefined for non-existent sections' , ( ) => {
170+ expect ( getConfigSection ( config , 'nonexistent' ) ) . toBeUndefined ( ) ;
171+ } ) ;
172+ } ) ;
173+
174+ describe ( 'hasConfigSection' , ( ) => {
175+ const config : ConfigFile = {
176+ core : { engine : 'pg' } ,
177+ deploy : { verify : 'true' }
178+ } ;
179+
180+ it ( 'should check if sections exist' , ( ) => {
181+ expect ( hasConfigSection ( config , 'core' ) ) . toBe ( true ) ;
182+ expect ( hasConfigSection ( config , 'deploy' ) ) . toBe ( true ) ;
183+ expect ( hasConfigSection ( config , 'nonexistent' ) ) . toBe ( false ) ;
184+ } ) ;
185+ } ) ;
186+
187+ describe ( 'Complex config scenarios' , ( ) => {
188+ it ( 'should handle all sqitch config options' , ( ) => {
189+ const configContent = `[core]
190+ engine = pg
191+ plan_file = sqitch.plan
192+ top_dir = .
193+ deploy_dir = deploy
194+ revert_dir = revert
195+ verify_dir = verify
196+ extension = sql
197+
198+ [engine "pg"]
199+ target = db:pg://localhost/mydb
200+ registry = sqitch
201+ client = psql
202+
203+ [deploy]
204+ verify = true
205+ mode = tag
206+
207+ [revert]
208+ prompt_accept = true
209+
210+ [target "production"]
211+ uri = db:pg://prod.example.com/mydb
212+
213+ [user]
214+ name = Developer
215+ 216+
217+ const result = parseConfigContent ( configContent ) ;
218+
219+ expect ( result . errors ) . toHaveLength ( 0 ) ;
220+ expect ( Object . keys ( result . data ! ) ) . toHaveLength ( 6 ) ;
221+ expect ( result . data ! . core . engine ) . toBe ( 'pg' ) ;
222+ expect ( result . data ! [ 'engine "pg"' ] . client ) . toBe ( 'psql' ) ;
223+ expect ( result . data ! . deploy . verify ) . toBe ( 'true' ) ;
224+ expect ( result . data ! . revert . prompt_accept ) . toBe ( 'true' ) ;
225+ expect ( result . data ! [ 'target "production"' ] . uri ) . toBe ( 'db:pg://prod.example.com/mydb' ) ;
226+ expect ( result . data ! . user . email ) . toBe ( '[email protected] ' ) ; 227+ } ) ;
228+ } ) ;
229+ } ) ;
0 commit comments