@grafana/create-plugin 6.1.1 → 6.2.0-canary.2233.18586197736.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,335 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import { Context } from '../../migrations/context.js';
4
+ import migrate from './add-i18n.js';
5
+
6
+ describe('add-i18n', () => {
7
+ it('should be idempotent', async () => {
8
+ const context = new Context('/virtual');
9
+
10
+ // Set up a minimal plugin structure
11
+ context.addFile(
12
+ 'src/plugin.json',
13
+ JSON.stringify({
14
+ id: 'test-plugin',
15
+ type: 'panel',
16
+ name: 'Test Plugin',
17
+ dependencies: {
18
+ grafanaDependency: '>=11.0.0',
19
+ },
20
+ })
21
+ );
22
+ context.addFile('docker-compose.yaml', 'services:\n grafana:\n environment:\n FOO: bar');
23
+ context.addFile('package.json', JSON.stringify({ dependencies: {}, devDependencies: {} }));
24
+ context.addFile(
25
+ 'eslint.config.mjs',
26
+ 'import { defineConfig } from "eslint/config";\nexport default defineConfig([]);'
27
+ );
28
+ context.addFile(
29
+ 'src/module.ts',
30
+ 'import { PanelPlugin } from "@grafana/data";\nexport const plugin = new PanelPlugin();'
31
+ );
32
+
33
+ const migrateWithOptions = (ctx: Context) => migrate(ctx, { locales: ['en-US'] });
34
+ await expect(migrateWithOptions).toBeIdempotent(context);
35
+ });
36
+
37
+ it('should add i18n support with a single locale', () => {
38
+ const context = new Context('/virtual');
39
+
40
+ // Set up a minimal plugin structure
41
+ context.addFile(
42
+ 'src/plugin.json',
43
+ JSON.stringify({
44
+ id: 'test-plugin',
45
+ type: 'panel',
46
+ name: 'Test Plugin',
47
+ dependencies: {
48
+ grafanaDependency: '>=11.0.0',
49
+ },
50
+ })
51
+ );
52
+ context.addFile(
53
+ 'docker-compose.yaml',
54
+ `services:
55
+ grafana:
56
+ environment:
57
+ FOO: bar`
58
+ );
59
+ context.addFile('package.json', JSON.stringify({ dependencies: {}, devDependencies: {}, scripts: {} }));
60
+ context.addFile(
61
+ 'eslint.config.mjs',
62
+ 'import { defineConfig } from "eslint/config";\nexport default defineConfig([]);'
63
+ );
64
+ context.addFile(
65
+ 'src/module.ts',
66
+ 'import { PanelPlugin } from "@grafana/data";\nexport const plugin = new PanelPlugin();'
67
+ );
68
+
69
+ const result = migrate(context, { locales: ['en-US'] });
70
+
71
+ // Check plugin.json was updated
72
+ const pluginJson = JSON.parse(result.getFile('src/plugin.json') || '{}');
73
+ expect(pluginJson.languages).toEqual(['en-US']);
74
+ expect(pluginJson.dependencies.grafanaDependency).toBe('>=12.1.0');
75
+
76
+ // Check locale file was created
77
+ expect(result.doesFileExist('src/locales/en-US/test-plugin.json')).toBe(true);
78
+ const localeContent = result.getFile('src/locales/en-US/test-plugin.json');
79
+ expect(JSON.parse(localeContent || '{}')).toEqual({});
80
+
81
+ // Check package.json was updated with dependencies
82
+ const packageJson = JSON.parse(result.getFile('package.json') || '{}');
83
+ expect(packageJson.dependencies['@grafana/i18n']).toBeDefined();
84
+ expect(packageJson.devDependencies['i18next-cli']).toBeDefined();
85
+ expect(packageJson.scripts['i18n-extract']).toBe('i18next-cli extract --sync-primary');
86
+
87
+ // Check docker-compose.yaml was updated
88
+ const dockerCompose = result.getFile('docker-compose.yaml');
89
+ expect(dockerCompose).toContain('localizationForPlugins');
90
+
91
+ // Check module.ts was updated
92
+ const moduleTs = result.getFile('src/module.ts');
93
+ expect(moduleTs).toContain('@grafana/i18n');
94
+
95
+ // Check i18next.config.ts was created
96
+ expect(result.doesFileExist('i18next.config.ts')).toBe(true);
97
+ const i18nextConfig = result.getFile('i18next.config.ts');
98
+ expect(i18nextConfig).toContain('defineConfig');
99
+ expect(i18nextConfig).toContain('pluginJson.id');
100
+ });
101
+
102
+ it('should add i18n support with multiple locales', () => {
103
+ const context = new Context('/virtual');
104
+
105
+ context.addFile(
106
+ 'src/plugin.json',
107
+ JSON.stringify({
108
+ id: 'test-plugin',
109
+ type: 'panel',
110
+ name: 'Test Plugin',
111
+ dependencies: {
112
+ grafanaDependency: '>=11.0.0',
113
+ },
114
+ })
115
+ );
116
+ context.addFile(
117
+ 'docker-compose.yaml',
118
+ `services:
119
+ grafana:
120
+ environment:
121
+ FOO: bar`
122
+ );
123
+ context.addFile('package.json', JSON.stringify({ dependencies: {}, devDependencies: {}, scripts: {} }));
124
+ context.addFile(
125
+ 'eslint.config.mjs',
126
+ 'import { defineConfig } from "eslint/config";\nexport default defineConfig([]);'
127
+ );
128
+ context.addFile(
129
+ 'src/module.ts',
130
+ 'import { PanelPlugin } from "@grafana/data";\nexport const plugin = new PanelPlugin();'
131
+ );
132
+
133
+ const result = migrate(context, { locales: ['en-US', 'es-ES', 'sv-SE'] });
134
+
135
+ // Check plugin.json has all locales
136
+ const pluginJson = JSON.parse(result.getFile('src/plugin.json') || '{}');
137
+ expect(pluginJson.languages).toEqual(['en-US', 'es-ES', 'sv-SE']);
138
+
139
+ // Check all locale files were created
140
+ expect(result.doesFileExist('src/locales/en-US/test-plugin.json')).toBe(true);
141
+ expect(result.doesFileExist('src/locales/es-ES/test-plugin.json')).toBe(true);
142
+ expect(result.doesFileExist('src/locales/sv-SE/test-plugin.json')).toBe(true);
143
+ });
144
+
145
+ it('should skip if i18n is already configured', () => {
146
+ const context = new Context('/virtual');
147
+
148
+ // Set up a plugin with i18n already configured
149
+ context.addFile(
150
+ 'src/plugin.json',
151
+ JSON.stringify({
152
+ id: 'test-plugin',
153
+ type: 'panel',
154
+ name: 'Test Plugin',
155
+ languages: ['en-US'], // Already configured
156
+ dependencies: {
157
+ grafanaDependency: '>=12.1.0',
158
+ },
159
+ })
160
+ );
161
+ context.addFile(
162
+ 'docker-compose.yaml',
163
+ `services:
164
+ grafana:
165
+ environment:
166
+ FOO: bar`
167
+ );
168
+ context.addFile('package.json', JSON.stringify({ dependencies: {}, devDependencies: {}, scripts: {} }));
169
+ context.addFile(
170
+ 'eslint.config.mjs',
171
+ 'import { defineConfig } from "eslint/config";\nexport default defineConfig([]);'
172
+ );
173
+ context.addFile(
174
+ 'src/module.ts',
175
+ 'import { PanelPlugin } from "@grafana/data";\nimport { i18n } from "@grafana/i18n";\nexport const plugin = new PanelPlugin();'
176
+ );
177
+
178
+ // Flush the context to simulate these files existing on "disk"
179
+ const initialChanges = Object.keys(context.listChanges()).length;
180
+
181
+ const result = migrate(context, { locales: ['es-ES'] });
182
+
183
+ // Should not add any NEW changes beyond the initial setup
184
+ const finalChanges = Object.keys(result.listChanges()).length;
185
+ expect(finalChanges).toBe(initialChanges);
186
+ });
187
+
188
+ it('should handle existing feature toggles in docker-compose.yaml', () => {
189
+ const context = new Context('/virtual');
190
+
191
+ context.addFile(
192
+ 'src/plugin.json',
193
+ JSON.stringify({
194
+ id: 'test-plugin',
195
+ type: 'panel',
196
+ name: 'Test Plugin',
197
+ dependencies: {
198
+ grafanaDependency: '>=11.0.0',
199
+ },
200
+ })
201
+ );
202
+ context.addFile(
203
+ 'docker-compose.yaml',
204
+ `services:
205
+ grafana:
206
+ environment:
207
+ GF_FEATURE_TOGGLES_ENABLE: someOtherFeature`
208
+ );
209
+ context.addFile('package.json', JSON.stringify({ dependencies: {}, devDependencies: {}, scripts: {} }));
210
+ context.addFile(
211
+ 'eslint.config.mjs',
212
+ 'import { defineConfig } from "eslint/config";\nexport default defineConfig([]);'
213
+ );
214
+ context.addFile(
215
+ 'src/module.ts',
216
+ 'import { PanelPlugin } from "@grafana/data";\nexport const plugin = new PanelPlugin();'
217
+ );
218
+
219
+ const result = migrate(context, { locales: ['en-US'] });
220
+
221
+ const dockerCompose = result.getFile('docker-compose.yaml');
222
+ expect(dockerCompose).toContain('someOtherFeature,localizationForPlugins');
223
+ });
224
+
225
+ it('should work with module.tsx instead of module.ts', () => {
226
+ const context = new Context('/virtual');
227
+
228
+ context.addFile(
229
+ 'src/plugin.json',
230
+ JSON.stringify({
231
+ id: 'test-plugin',
232
+ type: 'panel',
233
+ name: 'Test Plugin',
234
+ dependencies: {
235
+ grafanaDependency: '>=11.0.0',
236
+ },
237
+ })
238
+ );
239
+ context.addFile(
240
+ 'docker-compose.yaml',
241
+ `services:
242
+ grafana:
243
+ environment:
244
+ FOO: bar`
245
+ );
246
+ context.addFile('package.json', JSON.stringify({ dependencies: {}, devDependencies: {}, scripts: {} }));
247
+ context.addFile(
248
+ 'eslint.config.mjs',
249
+ 'import { defineConfig } from "eslint/config";\nexport default defineConfig([]);'
250
+ );
251
+ context.addFile(
252
+ 'src/module.tsx',
253
+ 'import { PanelPlugin } from "@grafana/data";\nexport const plugin = new PanelPlugin();'
254
+ );
255
+
256
+ const result = migrate(context, { locales: ['en-US'] });
257
+
258
+ const moduleTsx = result.getFile('src/module.tsx');
259
+ expect(moduleTsx).toContain('@grafana/i18n');
260
+ });
261
+
262
+ it('should not update grafanaDependency if it is already >= 12.1.0', () => {
263
+ const context = new Context('/virtual');
264
+
265
+ context.addFile(
266
+ 'src/plugin.json',
267
+ JSON.stringify({
268
+ id: 'test-plugin',
269
+ type: 'panel',
270
+ name: 'Test Plugin',
271
+ dependencies: {
272
+ grafanaDependency: '>=13.0.0',
273
+ },
274
+ })
275
+ );
276
+ context.addFile(
277
+ 'docker-compose.yaml',
278
+ `services:
279
+ grafana:
280
+ environment:
281
+ FOO: bar`
282
+ );
283
+ context.addFile('package.json', JSON.stringify({ dependencies: {}, devDependencies: {}, scripts: {} }));
284
+ context.addFile(
285
+ 'eslint.config.mjs',
286
+ 'import { defineConfig } from "eslint/config";\nexport default defineConfig([]);'
287
+ );
288
+ context.addFile(
289
+ 'src/module.ts',
290
+ 'import { PanelPlugin } from "@grafana/data";\nexport const plugin = new PanelPlugin();'
291
+ );
292
+
293
+ const result = migrate(context, { locales: ['en-US'] });
294
+
295
+ const pluginJson = JSON.parse(result.getFile('src/plugin.json') || '{}');
296
+ expect(pluginJson.dependencies.grafanaDependency).toBe('>=13.0.0');
297
+ });
298
+
299
+ it('should handle plugins without existing scripts in package.json', () => {
300
+ const context = new Context('/virtual');
301
+
302
+ context.addFile(
303
+ 'src/plugin.json',
304
+ JSON.stringify({
305
+ id: 'test-plugin',
306
+ type: 'panel',
307
+ name: 'Test Plugin',
308
+ dependencies: {
309
+ grafanaDependency: '>=11.0.0',
310
+ },
311
+ })
312
+ );
313
+ context.addFile(
314
+ 'docker-compose.yaml',
315
+ `services:
316
+ grafana:
317
+ environment:
318
+ FOO: bar`
319
+ );
320
+ context.addFile('package.json', JSON.stringify({ dependencies: {}, devDependencies: {} })); // No scripts field
321
+ context.addFile(
322
+ 'eslint.config.mjs',
323
+ 'import { defineConfig } from "eslint/config";\nexport default defineConfig([]);'
324
+ );
325
+ context.addFile(
326
+ 'src/module.ts',
327
+ 'import { PanelPlugin } from "@grafana/data";\nexport const plugin = new PanelPlugin();'
328
+ );
329
+
330
+ const result = migrate(context, { locales: ['en-US'] });
331
+
332
+ const packageJson = JSON.parse(result.getFile('package.json') || '{}');
333
+ expect(packageJson.scripts['i18n-extract']).toBe('i18next-cli extract --sync-primary');
334
+ });
335
+ });