@@ -59,4 +59,148 @@ export default {
5959 spmPackages ,
6060 ) ;
6161 } ) ;
62+
63+ const tsConfig = `export default {
64+ id: 'org.nativescript.myapp',
65+ appPath: 'src',
66+ version: 3,
67+ } as any;` ;
68+
69+ const roundTrip = ( content : string , path : string , value : any ) =>
70+ new ConfigTransformer (
71+ new ConfigTransformer ( content ) . setValue ( path , value ) ,
72+ ) . getValue ( path ) ;
73+
74+ it ( "reads and updates string literals" , ( ) => {
75+ assert . strictEqual (
76+ new ConfigTransformer ( tsConfig ) . getValue ( "id" ) ,
77+ "org.nativescript.myapp" ,
78+ ) ;
79+ assert . strictEqual ( roundTrip ( tsConfig , "appPath" , "app" ) , "app" ) ;
80+ } ) ;
81+
82+ it ( "reads and updates numeric literals" , ( ) => {
83+ assert . strictEqual ( new ConfigTransformer ( tsConfig ) . getValue ( "version" ) , 3 ) ;
84+ assert . strictEqual ( roundTrip ( tsConfig , "version" , 4 ) , 4 ) ;
85+ } ) ;
86+
87+ it ( "replaces the initializer when the new value changes type" , ( ) => {
88+ assert . strictEqual ( roundTrip ( tsConfig , "version" , "four" ) , "four" ) ;
89+ assert . strictEqual ( roundTrip ( tsConfig , "appPath" , 7 ) , 7 ) ;
90+ } ) ;
91+
92+ it ( "reads and updates CommonJS configs" , ( ) => {
93+ const content = `module.exports = {
94+ id: 'org.nativescript.myapp',
95+ appPath: 'src',
96+ };` ;
97+
98+ assert . strictEqual (
99+ new ConfigTransformer ( content ) . getValue ( "id" ) ,
100+ "org.nativescript.myapp" ,
101+ ) ;
102+ assert . strictEqual ( roundTrip ( content , "appPath" , "app" ) , "app" ) ;
103+ } ) ;
104+
105+ // the object may be wrapped in any combination of assertions and parentheses
106+ const wrappers : [ string , string ] [ ] = [
107+ [ "no assertion" , `{ id: 'org.nativescript.myapp' }` ] ,
108+ [
109+ "as NativeScriptConfig" ,
110+ `{ id: 'org.nativescript.myapp' } as NativeScriptConfig` ,
111+ ] ,
112+ [ "as any" , `{ id: 'org.nativescript.myapp' } as any` ] ,
113+ [ "as const" , `{ id: 'org.nativescript.myapp' } as const` ] ,
114+ [
115+ "satisfies" ,
116+ `{ id: 'org.nativescript.myapp' } satisfies NativeScriptConfig` ,
117+ ] ,
118+ [ "angle-bracket assertion" , `<any>{ id: 'org.nativescript.myapp' }` ] ,
119+ [ "parenthesized" , `({ id: 'org.nativescript.myapp' })` ] ,
120+ [
121+ "nested parens and assertion" ,
122+ `(({ id: 'org.nativescript.myapp' } as any))` ,
123+ ] ,
124+ ] ;
125+
126+ for ( const [ label , expression ] of wrappers ) {
127+ it ( `reads and updates a default export wrapped in ${ label } ` , ( ) => {
128+ const content = `export default ${ expression } ;` ;
129+
130+ assert . strictEqual (
131+ new ConfigTransformer ( content ) . getValue ( "id" ) ,
132+ "org.nativescript.myapp" ,
133+ ) ;
134+ assert . strictEqual ( roundTrip ( content , "id" , "org.other" ) , "org.other" ) ;
135+ } ) ;
136+ }
137+
138+ it ( "reads and updates a parenthesized CommonJS export" , ( ) => {
139+ const content = `module.exports = ({
140+ id: 'org.nativescript.myapp',
141+ });` ;
142+
143+ assert . strictEqual (
144+ new ConfigTransformer ( content ) . getValue ( "id" ) ,
145+ "org.nativescript.myapp" ,
146+ ) ;
147+ assert . strictEqual ( roundTrip ( content , "id" , "org.other" ) , "org.other" ) ;
148+ } ) ;
149+
150+ it ( "creates intermediate objects for a new dot-notation path" , ( ) => {
151+ assert . strictEqual (
152+ roundTrip ( tsConfig , "android.markingMode" , "none" ) ,
153+ "none" ,
154+ ) ;
155+ } ) ;
156+
157+ it ( "adds keys that are absent from the config" , ( ) => {
158+ assert . strictEqual (
159+ roundTrip ( tsConfig , "appResourcesPath" , "App_Resources" ) ,
160+ "App_Resources" ,
161+ ) ;
162+ assert . deepStrictEqual (
163+ roundTrip ( tsConfig , "ios" , { discardUncaughtJsExceptions : true } ) ,
164+ {
165+ discardUncaughtJsExceptions : true ,
166+ } ,
167+ ) ;
168+ } ) ;
169+
170+ it ( "resolves a value declared as a separate variable" , ( ) => {
171+ const content = `const appId = 'org.nativescript.myapp';
172+
173+ export default {
174+ id: appId,
175+ } as any;` ;
176+
177+ assert . strictEqual (
178+ new ConfigTransformer ( content ) . getValue ( "id" ) ,
179+ "org.nativescript.myapp" ,
180+ ) ;
181+ // the assignment is indirect, so the update lands on the declaration
182+ const updated = new ConfigTransformer ( content ) . setValue ( "id" , "org.other" ) ;
183+ assert . include ( updated , "const appId = 'org.other'" ) ;
184+ assert . strictEqual (
185+ new ConfigTransformer ( updated ) . getValue ( "id" ) ,
186+ "org.other" ,
187+ ) ;
188+ } ) ;
189+
190+ it ( "returns undefined for a key that is not present" , ( ) => {
191+ assert . isUndefined (
192+ new ConfigTransformer ( tsConfig ) . getValue ( "doesNotExist" ) ,
193+ ) ;
194+ } ) ;
195+
196+ it ( "throws when the default export is not an object" , ( ) => {
197+ assert . throws (
198+ ( ) => new ConfigTransformer ( `export default 42;` ) . getValue ( "id" ) ,
199+ "default export must be an object!" ,
200+ ) ;
201+ assert . throws (
202+ ( ) => new ConfigTransformer ( `module.exports = 42;` ) . getValue ( "id" ) ,
203+ "default export must be an object!" ,
204+ ) ;
205+ } ) ;
62206} ) ;
0 commit comments