|
1 |
| -import {patchAppConfigurationFile, patchAppHiddenConfigFile} from './patch-app-configuration-file.js' |
| 1 | +import { |
| 2 | + patchAppHiddenConfigFile, |
| 3 | + setAppConfigValue, |
| 4 | + unsetAppConfigValue, |
| 5 | + setManyAppConfigValues, |
| 6 | +} from './patch-app-configuration-file.js' |
2 | 7 | import {getAppVersionedSchema} from '../../models/app/app.js'
|
3 | 8 | import {loadLocalExtensionsSpecifications} from '../../models/extensions/load-specifications.js'
|
4 | 9 | import {readFile, writeFileSync, inTemporaryDirectory} from '@shopify/cli-kit/node/fs'
|
@@ -33,150 +38,6 @@ function writeDefaulToml(tmpDir: string) {
|
33 | 38 | return configPath
|
34 | 39 | }
|
35 | 40 |
|
36 |
| -describe('patchAppConfigurationFile', () => { |
37 |
| - test('updates existing configuration with new values and adds new top-levelfields, replaces arrays', async () => { |
38 |
| - await inTemporaryDirectory(async (tmpDir) => { |
39 |
| - const configPath = writeDefaulToml(tmpDir) |
40 |
| - const patch = { |
41 |
| - name: 'Updated App Name', |
42 |
| - application_url: 'https://example.com', |
43 |
| - access_scopes: { |
44 |
| - use_legacy_install_flow: false, |
45 |
| - }, |
46 |
| - auth: { |
47 |
| - redirect_urls: ['https://example.com/redirect3', 'https://example.com/redirect4'], |
48 |
| - }, |
49 |
| - } |
50 |
| - |
51 |
| - await patchAppConfigurationFile({path: configPath, patch, schema}) |
52 |
| - |
53 |
| - const updatedTomlFile = await readFile(configPath) |
54 |
| - expect(updatedTomlFile) |
55 |
| - .toEqual(`# Learn more about configuring your app at https://shopify.dev/docs/apps/tools/cli/configuration |
56 |
| -
|
57 |
| -client_id = "12345" |
58 |
| -name = "Updated App Name" |
59 |
| -application_url = "https://example.com" |
60 |
| -embedded = true |
61 |
| -
|
62 |
| -[access_scopes] |
63 |
| -# Learn more at https://shopify.dev/docs/apps/tools/cli/configuration#access_scopes |
64 |
| -use_legacy_install_flow = false |
65 |
| -
|
66 |
| -[auth] |
67 |
| -redirect_urls = [ |
68 |
| - "https://example.com/redirect3", |
69 |
| - "https://example.com/redirect4" |
70 |
| -] |
71 |
| -
|
72 |
| -[webhooks] |
73 |
| -api_version = "2023-04" |
74 |
| -`) |
75 |
| - }) |
76 |
| - }) |
77 |
| - |
78 |
| - test('Adds new table to the toml file', async () => { |
79 |
| - await inTemporaryDirectory(async (tmpDir) => { |
80 |
| - const configPath = writeDefaulToml(tmpDir) |
81 |
| - const patch = { |
82 |
| - application_url: 'https://example.com', |
83 |
| - build: { |
84 |
| - dev_store_url: 'example.myshopify.com', |
85 |
| - }, |
86 |
| - } |
87 |
| - |
88 |
| - await patchAppConfigurationFile({path: configPath, patch, schema}) |
89 |
| - |
90 |
| - const updatedTomlFile = await readFile(configPath) |
91 |
| - expect(updatedTomlFile) |
92 |
| - .toEqual(`# Learn more about configuring your app at https://shopify.dev/docs/apps/tools/cli/configuration |
93 |
| -
|
94 |
| -client_id = "12345" |
95 |
| -name = "app1" |
96 |
| -application_url = "https://example.com" |
97 |
| -embedded = true |
98 |
| -
|
99 |
| -[access_scopes] |
100 |
| -# Learn more at https://shopify.dev/docs/apps/tools/cli/configuration#access_scopes |
101 |
| -use_legacy_install_flow = true |
102 |
| -
|
103 |
| -[auth] |
104 |
| -redirect_urls = [ |
105 |
| - "https://example.com/redirect", |
106 |
| - "https://example.com/redirect2" |
107 |
| -] |
108 |
| -
|
109 |
| -[webhooks] |
110 |
| -api_version = "2023-04" |
111 |
| -
|
112 |
| -[build] |
113 |
| -dev_store_url = "example.myshopify.com" |
114 |
| -`) |
115 |
| - }) |
116 |
| - }) |
117 |
| - |
118 |
| - test('Adds a new field to a toml table, merging with exsisting values', async () => { |
119 |
| - await inTemporaryDirectory(async (tmpDir) => { |
120 |
| - const configPath = writeDefaulToml(tmpDir) |
121 |
| - const patch = { |
122 |
| - application_url: 'https://example.com', |
123 |
| - access_scopes: { |
124 |
| - scopes: 'read_products', |
125 |
| - }, |
126 |
| - } |
127 |
| - |
128 |
| - await patchAppConfigurationFile({path: configPath, patch, schema}) |
129 |
| - |
130 |
| - const updatedTomlFile = await readFile(configPath) |
131 |
| - expect(updatedTomlFile) |
132 |
| - .toEqual(`# Learn more about configuring your app at https://shopify.dev/docs/apps/tools/cli/configuration |
133 |
| -
|
134 |
| -client_id = "12345" |
135 |
| -name = "app1" |
136 |
| -application_url = "https://example.com" |
137 |
| -embedded = true |
138 |
| -
|
139 |
| -[access_scopes] |
140 |
| -# Learn more at https://shopify.dev/docs/apps/tools/cli/configuration#access_scopes |
141 |
| -use_legacy_install_flow = true |
142 |
| -scopes = "read_products" |
143 |
| -
|
144 |
| -[auth] |
145 |
| -redirect_urls = [ |
146 |
| - "https://example.com/redirect", |
147 |
| - "https://example.com/redirect2" |
148 |
| -] |
149 |
| -
|
150 |
| -[webhooks] |
151 |
| -api_version = "2023-04" |
152 |
| -`) |
153 |
| - }) |
154 |
| - }) |
155 |
| - |
156 |
| - test('does not validate the toml if no schema is provided', async () => { |
157 |
| - await inTemporaryDirectory(async (tmpDir) => { |
158 |
| - const configPath = joinPath(tmpDir, 'shopify.app.toml') |
159 |
| - writeFileSync( |
160 |
| - configPath, |
161 |
| - ` |
162 |
| -random_toml_field = "random_value" |
163 |
| -`, |
164 |
| - ) |
165 |
| - const patch = {name: 123} |
166 |
| - |
167 |
| - await patchAppConfigurationFile({path: configPath, patch, schema: undefined}) |
168 |
| - |
169 |
| - const updatedTomlFile = await readFile(configPath) |
170 |
| - expect(updatedTomlFile) |
171 |
| - .toEqual(`# Learn more about configuring your app at https://shopify.dev/docs/apps/tools/cli/configuration |
172 |
| -
|
173 |
| -random_toml_field = "random_value" |
174 |
| -name = 123 |
175 |
| -`) |
176 |
| - }) |
177 |
| - }) |
178 |
| -}) |
179 |
| - |
180 | 41 | describe('patchAppHiddenConfigFile', () => {
|
181 | 42 | test('creates a new hidden config file when it does not exist', async () => {
|
182 | 43 | await inTemporaryDirectory(async (tmpDir) => {
|
@@ -257,3 +118,176 @@ describe('patchAppHiddenConfigFile', () => {
|
257 | 118 | })
|
258 | 119 | })
|
259 | 120 | })
|
| 121 | + |
| 122 | +describe('setAppConfigValue', () => { |
| 123 | + test('sets a top-level value in the configuration', async () => { |
| 124 | + await inTemporaryDirectory(async (tmpDir) => { |
| 125 | + const configPath = writeDefaulToml(tmpDir) |
| 126 | + |
| 127 | + await setAppConfigValue(configPath, 'name', 'Updated App Name', schema) |
| 128 | + |
| 129 | + const updatedTomlFile = await readFile(configPath) |
| 130 | + expect(updatedTomlFile).toContain('name = "Updated App Name"') |
| 131 | + }) |
| 132 | + }) |
| 133 | + |
| 134 | + test('sets a nested value in the configuration', async () => { |
| 135 | + await inTemporaryDirectory(async (tmpDir) => { |
| 136 | + const configPath = writeDefaulToml(tmpDir) |
| 137 | + |
| 138 | + await setAppConfigValue(configPath, 'build.dev_store_url', 'example.myshopify.com', schema) |
| 139 | + |
| 140 | + const updatedTomlFile = await readFile(configPath) |
| 141 | + expect(updatedTomlFile).toContain('[build]') |
| 142 | + expect(updatedTomlFile).toContain('dev_store_url = "example.myshopify.com"') |
| 143 | + }) |
| 144 | + }) |
| 145 | + |
| 146 | + test('sets a deeply nested value in the configuration', async () => { |
| 147 | + await inTemporaryDirectory(async (tmpDir) => { |
| 148 | + const configPath = writeDefaulToml(tmpDir) |
| 149 | + |
| 150 | + await setAppConfigValue(configPath, 'build.auth.settings', true, schema) |
| 151 | + |
| 152 | + const updatedTomlFile = await readFile(configPath) |
| 153 | + expect(updatedTomlFile).toContain('[build.auth]') |
| 154 | + expect(updatedTomlFile).toContain('settings = true') |
| 155 | + }) |
| 156 | + }) |
| 157 | +}) |
| 158 | + |
| 159 | +describe('unsetAppConfigValue', () => { |
| 160 | + test('unsets a top-level value in the configuration', async () => { |
| 161 | + await inTemporaryDirectory(async (tmpDir) => { |
| 162 | + const configPath = writeDefaulToml(tmpDir) |
| 163 | + |
| 164 | + await unsetAppConfigValue(configPath, 'name', schema) |
| 165 | + |
| 166 | + const updatedTomlFile = await readFile(configPath) |
| 167 | + expect(updatedTomlFile).not.toContain('name = "app1"') |
| 168 | + }) |
| 169 | + }) |
| 170 | + |
| 171 | + test('unsets a nested value in existing table in the configuration', async () => { |
| 172 | + await inTemporaryDirectory(async (tmpDir) => { |
| 173 | + const configPath = writeDefaulToml(tmpDir) |
| 174 | + |
| 175 | + // Add a value first |
| 176 | + await setAppConfigValue(configPath, 'build.dev_store_url', 'example.myshopify.com', schema) |
| 177 | + |
| 178 | + // Now unset it |
| 179 | + await unsetAppConfigValue(configPath, 'build.dev_store_url', schema) |
| 180 | + |
| 181 | + const updatedTomlFile = await readFile(configPath) |
| 182 | + expect(updatedTomlFile).toContain('[build]') |
| 183 | + expect(updatedTomlFile).not.toContain('dev_store_url = "example.myshopify.com"') |
| 184 | + }) |
| 185 | + }) |
| 186 | +}) |
| 187 | + |
| 188 | +describe('setManyAppConfigValues', () => { |
| 189 | + test('sets multiple top-level values in the configuration', async () => { |
| 190 | + await inTemporaryDirectory(async (tmpDir) => { |
| 191 | + const configPath = writeDefaulToml(tmpDir) |
| 192 | + |
| 193 | + await setManyAppConfigValues( |
| 194 | + configPath, |
| 195 | + [ |
| 196 | + {keyPath: 'name', value: 'Updated App Name'}, |
| 197 | + {keyPath: 'client_id', value: '67890'}, |
| 198 | + ], |
| 199 | + schema, |
| 200 | + ) |
| 201 | + |
| 202 | + const updatedTomlFile = await readFile(configPath) |
| 203 | + expect(updatedTomlFile).toContain('name = "Updated App Name"') |
| 204 | + expect(updatedTomlFile).toContain('client_id = "67890"') |
| 205 | + }) |
| 206 | + }) |
| 207 | + |
| 208 | + test('sets a mix of top-level and nested values in the configuration', async () => { |
| 209 | + await inTemporaryDirectory(async (tmpDir) => { |
| 210 | + const configPath = writeDefaulToml(tmpDir) |
| 211 | + |
| 212 | + await setManyAppConfigValues( |
| 213 | + configPath, |
| 214 | + [ |
| 215 | + {keyPath: 'name', value: 'Updated App Name'}, |
| 216 | + {keyPath: 'build.dev_store_url', value: 'example.myshopify.com'}, |
| 217 | + ], |
| 218 | + schema, |
| 219 | + ) |
| 220 | + |
| 221 | + const updatedTomlFile = await readFile(configPath) |
| 222 | + expect(updatedTomlFile).toContain('name = "Updated App Name"') |
| 223 | + expect(updatedTomlFile).toContain('[build]') |
| 224 | + expect(updatedTomlFile).toContain('dev_store_url = "example.myshopify.com"') |
| 225 | + }) |
| 226 | + }) |
| 227 | + |
| 228 | + test('properly handles array values in the configuration', async () => { |
| 229 | + await inTemporaryDirectory(async (tmpDir) => { |
| 230 | + const configPath = writeDefaulToml(tmpDir) |
| 231 | + |
| 232 | + await setManyAppConfigValues( |
| 233 | + configPath, |
| 234 | + [{keyPath: 'auth.redirect_urls', value: ['https://example.com/redirect3', 'https://example.com/redirect4']}], |
| 235 | + schema, |
| 236 | + ) |
| 237 | + |
| 238 | + const updatedTomlFile = await readFile(configPath) |
| 239 | + expect(updatedTomlFile).toContain('[auth]') |
| 240 | + expect(updatedTomlFile).toContain('redirect_urls = [') |
| 241 | + expect(updatedTomlFile).toContain('"https://example.com/redirect3"') |
| 242 | + expect(updatedTomlFile).toContain('"https://example.com/redirect4"') |
| 243 | + expect(updatedTomlFile).not.toContain('"https://example.com/redirect"') |
| 244 | + expect(updatedTomlFile).not.toContain('"https://example.com/redirect2"') |
| 245 | + }) |
| 246 | + }) |
| 247 | + |
| 248 | + test('combines multiple nested keys into a single object structure', async () => { |
| 249 | + await inTemporaryDirectory(async (tmpDir) => { |
| 250 | + const configPath = writeDefaulToml(tmpDir) |
| 251 | + |
| 252 | + await setManyAppConfigValues( |
| 253 | + configPath, |
| 254 | + [ |
| 255 | + {keyPath: 'build.dev_store_url', value: 'example.myshopify.com'}, |
| 256 | + {keyPath: 'build.automatically_update_urls_on_dev', value: true}, |
| 257 | + ], |
| 258 | + schema, |
| 259 | + ) |
| 260 | + |
| 261 | + const updatedTomlFile = await readFile(configPath) |
| 262 | + expect(updatedTomlFile).toContain('[build]') |
| 263 | + expect(updatedTomlFile).toContain('dev_store_url = "example.myshopify.com"') |
| 264 | + expect(updatedTomlFile).toContain('automatically_update_urls_on_dev = true') |
| 265 | + }) |
| 266 | + }) |
| 267 | + |
| 268 | + test('updates existing configuration with new values and replaces arrays', async () => { |
| 269 | + await inTemporaryDirectory(async (tmpDir) => { |
| 270 | + const configPath = writeDefaulToml(tmpDir) |
| 271 | + |
| 272 | + await setManyAppConfigValues( |
| 273 | + configPath, |
| 274 | + [ |
| 275 | + {keyPath: 'name', value: 'Updated App Name'}, |
| 276 | + {keyPath: 'application_url', value: 'https://example.com'}, |
| 277 | + {keyPath: 'access_scopes.use_legacy_install_flow', value: false}, |
| 278 | + {keyPath: 'auth.redirect_urls', value: ['https://example.com/redirect3', 'https://example.com/redirect4']}, |
| 279 | + ], |
| 280 | + schema, |
| 281 | + ) |
| 282 | + |
| 283 | + const updatedTomlFile = await readFile(configPath) |
| 284 | + expect(updatedTomlFile).toContain('name = "Updated App Name"') |
| 285 | + expect(updatedTomlFile).toContain('application_url = "https://example.com"') |
| 286 | + expect(updatedTomlFile).toContain('use_legacy_install_flow = false') |
| 287 | + expect(updatedTomlFile).toContain('redirect_urls = [') |
| 288 | + expect(updatedTomlFile).toContain('"https://example.com/redirect3"') |
| 289 | + expect(updatedTomlFile).toContain('"https://example.com/redirect4"') |
| 290 | + expect(updatedTomlFile).not.toContain('"https://example.com/redirect"') |
| 291 | + }) |
| 292 | + }) |
| 293 | +}) |
0 commit comments