@caperjs/core 0.7.0 → 0.7.2
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.
- package/build/assetpack.mjs +35 -3
- package/build/defaults.mjs +39 -1
- package/build/index.mjs +13 -2
- package/build/internal/outputMarker.mjs +52 -0
- package/cli/doctor.mjs +205 -2
- package/cli/doctor.test.mjs +522 -1
- package/cli/native.mjs +808 -0
- package/cli/native.test.mjs +1039 -0
- package/cli.mjs +4 -0
- package/extras/css/fullscreen.css +8 -0
- package/extras/llms.txt +18 -0
- package/extras/skills/caper/SKILL.md +1 -0
- package/lib/{CaptionsPlugin-Boj-gm3A.js → CaptionsPlugin-COrofpHN.js} +2 -2
- package/lib/{CaptionsPlugin-Boj-gm3A.js.map → CaptionsPlugin-COrofpHN.js.map} +1 -1
- package/lib/{DataAdapter-Cra9dJ6W.js → DataAdapter-T-22-_D1.js} +2 -2
- package/lib/{DataAdapter-Cra9dJ6W.js.map → DataAdapter-T-22-_D1.js.map} +1 -1
- package/lib/{DebugRenderer-19S58S4h.js → DebugRenderer-ZN692Pbg.js} +4 -4
- package/lib/{DebugRenderer-19S58S4h.js.map → DebugRenderer-ZN692Pbg.js.map} +1 -1
- package/lib/{DevToolsPlugin-BTSkRsdS.js → DevToolsPlugin-CQXFoj1T.js} +3 -3
- package/lib/{DevToolsPlugin-BTSkRsdS.js.map → DevToolsPlugin-CQXFoj1T.js.map} +1 -1
- package/lib/{GSAPPlugin-BcL7vjyw.js → GSAPPlugin-CNkncyXS.js} +2 -2
- package/lib/{GSAPPlugin-BcL7vjyw.js.map → GSAPPlugin-CNkncyXS.js.map} +1 -1
- package/lib/{LayoutPlugin-BDhSngz_.js → LayoutPlugin-BuJgr9bd.js} +26 -26
- package/lib/{LayoutPlugin-BDhSngz_.js.map → LayoutPlugin-BuJgr9bd.js.map} +1 -1
- package/lib/{ScreenDebugPlugin-C6pxs_3O.js → ScreenDebugPlugin-kz9Mr6j1.js} +2 -2
- package/lib/{ScreenDebugPlugin-C6pxs_3O.js.map → ScreenDebugPlugin-kz9Mr6j1.js.map} +1 -1
- package/lib/{SpinePlugin-CrQhaK6r.js → SpinePlugin-DDzD-Qxd.js} +1099 -877
- package/lib/SpinePlugin-DDzD-Qxd.js.map +1 -0
- package/lib/{StatsPlugin-Cu625dmk.js → StatsPlugin-tyFGzVjy.js} +2 -2
- package/lib/{StatsPlugin-Cu625dmk.js.map → StatsPlugin-tyFGzVjy.js.map} +1 -1
- package/lib/{VoiceOverPlugin-D4rfHFyJ.js → VoiceOverPlugin-rTNz_9eb.js} +2 -2
- package/lib/{VoiceOverPlugin-D4rfHFyJ.js.map → VoiceOverPlugin-rTNz_9eb.js.map} +1 -1
- package/lib/caper.mjs +51 -51
- package/lib/caper.mjs.map +1 -1
- package/lib/{const-BQ2iMCtc.js → const-Cj14a5U2.js} +5 -3
- package/lib/const-Cj14a5U2.js.map +1 -0
- package/lib/plugins/FullScreenPlugin.d.ts +65 -0
- package/lib/plugins/FullScreenPlugin.d.ts.map +1 -1
- package/lib/plugins/spine/SpinePlugin.d.ts.map +1 -1
- package/lib/plugins/spine/SpinePlugin.test.d.ts +2 -0
- package/lib/plugins/spine/SpinePlugin.test.d.ts.map +1 -0
- package/lib/{registries-BmDw_GV1.js → registries-DmNGVLAi.js} +489 -446
- package/lib/registries-DmNGVLAi.js.map +1 -0
- package/lib/ui/Button.d.ts.map +1 -1
- package/lib/utils/platform.d.ts +5 -0
- package/lib/utils/platform.d.ts.map +1 -1
- package/lib/utils/platform.test.d.ts +2 -0
- package/lib/utils/platform.test.d.ts.map +1 -0
- package/lib/utils/types.d.ts +1 -1
- package/lib/utils/types.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/plugins/FullScreenPlugin.test.ts +138 -0
- package/src/plugins/FullScreenPlugin.ts +132 -0
- package/src/plugins/spine/SpinePlugin.test.ts +31 -0
- package/src/plugins/spine/SpinePlugin.ts +9 -2
- package/src/ui/Button.test.ts +22 -0
- package/src/ui/Button.ts +7 -0
- package/src/utils/platform.test.ts +20 -0
- package/src/utils/platform.ts +6 -0
- package/src/utils/types.ts +5 -1
- package/src/version.ts +2 -2
- package/lib/SpinePlugin-CrQhaK6r.js.map +0 -1
- package/lib/const-BQ2iMCtc.js.map +0 -1
- package/lib/registries-BmDw_GV1.js.map +0 -1
package/cli/doctor.test.mjs
CHANGED
|
@@ -4,7 +4,8 @@ import os from 'node:os';
|
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
|
|
6
6
|
import { agentInit } from './agent.mjs';
|
|
7
|
-
import { runChecks } from './doctor.mjs';
|
|
7
|
+
import { parseRustcVersion, runChecks } from './doctor.mjs';
|
|
8
|
+
import { TAURI_PLUGIN_PERMISSIONS } from './native.mjs';
|
|
8
9
|
|
|
9
10
|
const START_MARKER = '<!-- caper:agent-start -->';
|
|
10
11
|
const END_MARKER = '<!-- caper:agent-end -->';
|
|
@@ -294,3 +295,523 @@ ${END_MARKER}`;
|
|
|
294
295
|
expect(link.label).toContain('linked from');
|
|
295
296
|
});
|
|
296
297
|
});
|
|
298
|
+
|
|
299
|
+
describe('parseRustcVersion', () => {
|
|
300
|
+
it('parses a normal rustc --version line', () => {
|
|
301
|
+
expect(parseRustcVersion('rustc 1.98.1 (48a229cea 2026-09-01)')).toBe('1.98.1');
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
it('returns null for garbage input', () => {
|
|
305
|
+
expect(parseRustcVersion('command not found')).toBeNull();
|
|
306
|
+
expect(parseRustcVersion('')).toBeNull();
|
|
307
|
+
expect(parseRustcVersion(undefined)).toBeNull();
|
|
308
|
+
});
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
function writeTauriConf(cwd, overrides = {}) {
|
|
312
|
+
fs.mkdirSync(path.join(cwd, 'src-tauri'), { recursive: true });
|
|
313
|
+
fs.writeFileSync(
|
|
314
|
+
path.join(cwd, 'src-tauri/tauri.conf.json'),
|
|
315
|
+
JSON.stringify(
|
|
316
|
+
{
|
|
317
|
+
identifier: 'dev.caper.my-game',
|
|
318
|
+
build: {
|
|
319
|
+
frontendDist: '../dist',
|
|
320
|
+
devUrl: 'http://localhost:3123',
|
|
321
|
+
beforeDevCommand: 'pnpm vite --port 3123',
|
|
322
|
+
beforeBuildCommand: 'pnpm run build',
|
|
323
|
+
},
|
|
324
|
+
app: { windows: [{ title: 'My Game', width: 1280, height: 720 }], security: { csp: null } },
|
|
325
|
+
...overrides,
|
|
326
|
+
},
|
|
327
|
+
null,
|
|
328
|
+
2,
|
|
329
|
+
),
|
|
330
|
+
'utf-8',
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
function writeTauriCli(cwd, version) {
|
|
335
|
+
const dir = path.join(cwd, 'node_modules/@tauri-apps/cli');
|
|
336
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
337
|
+
fs.writeFileSync(path.join(dir, 'package.json'), JSON.stringify({ name: '@tauri-apps/cli', version }), 'utf-8');
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
function makeRun(responses) {
|
|
341
|
+
return (cmd, args) => {
|
|
342
|
+
const key = `${cmd} ${args.join(' ')}`;
|
|
343
|
+
if (key in responses) {
|
|
344
|
+
const value = responses[key];
|
|
345
|
+
if (value instanceof Error) throw value;
|
|
346
|
+
return value;
|
|
347
|
+
}
|
|
348
|
+
throw new Error(`unstubbed command in test: ${key}`);
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
describe('runChecks native rows', () => {
|
|
353
|
+
it('are absent when src-tauri does not exist', async () => {
|
|
354
|
+
const cwd = makeTempDir();
|
|
355
|
+
|
|
356
|
+
const checks = await runChecks(cwd, { online: false });
|
|
357
|
+
|
|
358
|
+
expect(find(checks, 'native-rust')).toBeUndefined();
|
|
359
|
+
expect(find(checks, 'native-tauri-cli')).toBeUndefined();
|
|
360
|
+
expect(find(checks, 'native-identifier')).toBeUndefined();
|
|
361
|
+
expect(find(checks, 'native-dev-port')).toBeUndefined();
|
|
362
|
+
expect(find(checks, 'native-xcode-clt')).toBeUndefined();
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
it('report rustc ok when the version is new enough', async () => {
|
|
366
|
+
const cwd = makeTempDir();
|
|
367
|
+
writeTauriConf(cwd);
|
|
368
|
+
writeTauriCli(cwd, '2.11.4');
|
|
369
|
+
|
|
370
|
+
const checks = await runChecks(cwd, {
|
|
371
|
+
online: false,
|
|
372
|
+
run: makeRun({ 'rustc --version': 'rustc 1.98.1 (48a229cea 2026-09-01)' }),
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
const rust = find(checks, 'native-rust');
|
|
376
|
+
expect(rust.status).toBe('ok');
|
|
377
|
+
expect(rust.label).toContain('1.98.1');
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
it('fails rustc when the version is below 1.88.0', async () => {
|
|
381
|
+
const cwd = makeTempDir();
|
|
382
|
+
writeTauriConf(cwd);
|
|
383
|
+
writeTauriCli(cwd, '2.11.4');
|
|
384
|
+
|
|
385
|
+
const checks = await runChecks(cwd, {
|
|
386
|
+
online: false,
|
|
387
|
+
run: makeRun({ 'rustc --version': 'rustc 1.87.0 (abc 2025-01-01)' }),
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
const rust = find(checks, 'native-rust');
|
|
391
|
+
expect(rust.status).toBe('fail');
|
|
392
|
+
expect(rust.hint).toMatch(/rustup/);
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
it('fails rustc when it is not installed', async () => {
|
|
396
|
+
const cwd = makeTempDir();
|
|
397
|
+
writeTauriConf(cwd);
|
|
398
|
+
writeTauriCli(cwd, '2.11.4');
|
|
399
|
+
|
|
400
|
+
const checks = await runChecks(cwd, {
|
|
401
|
+
online: false,
|
|
402
|
+
run: makeRun({ 'rustc --version': new Error('command not found') }),
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
const rust = find(checks, 'native-rust');
|
|
406
|
+
expect(rust.status).toBe('fail');
|
|
407
|
+
expect(rust.hint).toMatch(/rustup\.rs/);
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
it('reports native-tauri-cli ok when @tauri-apps/cli major 2 is resolvable', async () => {
|
|
411
|
+
const cwd = makeTempDir();
|
|
412
|
+
writeTauriConf(cwd);
|
|
413
|
+
writeTauriCli(cwd, '2.11.4');
|
|
414
|
+
|
|
415
|
+
const checks = await runChecks(cwd, { online: false, run: makeRun({ 'rustc --version': 'rustc 1.98.1 ()' }) });
|
|
416
|
+
|
|
417
|
+
expect(find(checks, 'native-tauri-cli').status).toBe('ok');
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
it('fails native-tauri-cli when @tauri-apps/cli is missing', async () => {
|
|
421
|
+
const cwd = makeTempDir();
|
|
422
|
+
writeTauriConf(cwd);
|
|
423
|
+
|
|
424
|
+
const checks = await runChecks(cwd, { online: false, run: makeRun({ 'rustc --version': 'rustc 1.98.1 ()' }) });
|
|
425
|
+
|
|
426
|
+
const tauriCli = find(checks, 'native-tauri-cli');
|
|
427
|
+
expect(tauriCli.status).toBe('fail');
|
|
428
|
+
expect(tauriCli.hint).toMatch(/caper native init/);
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
it('warns native-tauri-cli on a non-2 major version', async () => {
|
|
432
|
+
const cwd = makeTempDir();
|
|
433
|
+
writeTauriConf(cwd);
|
|
434
|
+
writeTauriCli(cwd, '1.6.0');
|
|
435
|
+
|
|
436
|
+
const checks = await runChecks(cwd, { online: false, run: makeRun({ 'rustc --version': 'rustc 1.98.1 ()' }) });
|
|
437
|
+
|
|
438
|
+
expect(find(checks, 'native-tauri-cli').status).toBe('warn');
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
it('fails native-identifier on the tauri placeholder', async () => {
|
|
442
|
+
const cwd = makeTempDir();
|
|
443
|
+
writeTauriConf(cwd, { identifier: 'com.tauri.dev' });
|
|
444
|
+
writeTauriCli(cwd, '2.11.4');
|
|
445
|
+
|
|
446
|
+
const checks = await runChecks(cwd, { online: false, run: makeRun({ 'rustc --version': 'rustc 1.98.1 ()' }) });
|
|
447
|
+
|
|
448
|
+
expect(find(checks, 'native-identifier').status).toBe('fail');
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
it('warns native-identifier on the dev.caper.* default', async () => {
|
|
452
|
+
const cwd = makeTempDir();
|
|
453
|
+
writeTauriConf(cwd, { identifier: 'dev.caper.my-game' });
|
|
454
|
+
writeTauriCli(cwd, '2.11.4');
|
|
455
|
+
|
|
456
|
+
const checks = await runChecks(cwd, { online: false, run: makeRun({ 'rustc --version': 'rustc 1.98.1 ()' }) });
|
|
457
|
+
|
|
458
|
+
const identifier = find(checks, 'native-identifier');
|
|
459
|
+
expect(identifier.status).toBe('warn');
|
|
460
|
+
expect(identifier.hint).toMatch(/before shipping/);
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
it('passes native-identifier for a real identifier', async () => {
|
|
464
|
+
const cwd = makeTempDir();
|
|
465
|
+
writeTauriConf(cwd, { identifier: 'dev.caperjs.kitchensink' });
|
|
466
|
+
writeTauriCli(cwd, '2.11.4');
|
|
467
|
+
|
|
468
|
+
const checks = await runChecks(cwd, { online: false, run: makeRun({ 'rustc --version': 'rustc 1.98.1 ()' }) });
|
|
469
|
+
|
|
470
|
+
expect(find(checks, 'native-identifier').status).toBe('ok');
|
|
471
|
+
});
|
|
472
|
+
|
|
473
|
+
it('fails native-identifier when tauri.conf.json is unreadable', async () => {
|
|
474
|
+
const cwd = makeTempDir();
|
|
475
|
+
fs.mkdirSync(path.join(cwd, 'src-tauri'), { recursive: true });
|
|
476
|
+
fs.writeFileSync(path.join(cwd, 'src-tauri/tauri.conf.json'), '{ not json', 'utf-8');
|
|
477
|
+
writeTauriCli(cwd, '2.11.4');
|
|
478
|
+
|
|
479
|
+
const checks = await runChecks(cwd, { online: false, run: makeRun({ 'rustc --version': 'rustc 1.98.1 ()' }) });
|
|
480
|
+
|
|
481
|
+
expect(find(checks, 'native-identifier').status).toBe('fail');
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
it('warns native-dev-port when beforeDevCommand port differs from devUrl', async () => {
|
|
485
|
+
const cwd = makeTempDir();
|
|
486
|
+
writeTauriConf(cwd, {
|
|
487
|
+
build: {
|
|
488
|
+
frontendDist: '../dist',
|
|
489
|
+
devUrl: 'http://localhost:3123',
|
|
490
|
+
beforeDevCommand: 'pnpm vite --port 3200',
|
|
491
|
+
beforeBuildCommand: 'pnpm run build',
|
|
492
|
+
},
|
|
493
|
+
});
|
|
494
|
+
writeTauriCli(cwd, '2.11.4');
|
|
495
|
+
|
|
496
|
+
const checks = await runChecks(cwd, { online: false, run: makeRun({ 'rustc --version': 'rustc 1.98.1 ()' }) });
|
|
497
|
+
|
|
498
|
+
expect(find(checks, 'native-dev-port').status).toBe('warn');
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
it('warns native-dev-port when devUrl is the shared default port 3000', async () => {
|
|
502
|
+
const cwd = makeTempDir();
|
|
503
|
+
writeTauriConf(cwd, {
|
|
504
|
+
build: {
|
|
505
|
+
frontendDist: '../dist',
|
|
506
|
+
devUrl: 'http://localhost:3000',
|
|
507
|
+
beforeDevCommand: 'pnpm vite',
|
|
508
|
+
beforeBuildCommand: 'pnpm run build',
|
|
509
|
+
},
|
|
510
|
+
});
|
|
511
|
+
writeTauriCli(cwd, '2.11.4');
|
|
512
|
+
|
|
513
|
+
const checks = await runChecks(cwd, { online: false, run: makeRun({ 'rustc --version': 'rustc 1.98.1 ()' }) });
|
|
514
|
+
|
|
515
|
+
const devPort = find(checks, 'native-dev-port');
|
|
516
|
+
expect(devPort.status).toBe('warn');
|
|
517
|
+
expect(devPort.hint).toMatch(/collides/);
|
|
518
|
+
});
|
|
519
|
+
|
|
520
|
+
it('passes native-dev-port for a consistent non-3000 port', async () => {
|
|
521
|
+
const cwd = makeTempDir();
|
|
522
|
+
writeTauriConf(cwd, {
|
|
523
|
+
build: {
|
|
524
|
+
frontendDist: '../dist',
|
|
525
|
+
devUrl: 'http://localhost:3123',
|
|
526
|
+
beforeDevCommand: 'pnpm vite --port 3123',
|
|
527
|
+
beforeBuildCommand: 'pnpm run build',
|
|
528
|
+
},
|
|
529
|
+
});
|
|
530
|
+
writeTauriCli(cwd, '2.11.4');
|
|
531
|
+
|
|
532
|
+
const checks = await runChecks(cwd, { online: false, run: makeRun({ 'rustc --version': 'rustc 1.98.1 ()' }) });
|
|
533
|
+
|
|
534
|
+
expect(find(checks, 'native-dev-port').status).toBe('ok');
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
it('reports native-xcode-clt ok on darwin when xcode-select succeeds', async () => {
|
|
538
|
+
const cwd = makeTempDir();
|
|
539
|
+
writeTauriConf(cwd);
|
|
540
|
+
writeTauriCli(cwd, '2.11.4');
|
|
541
|
+
|
|
542
|
+
const checks = await runChecks(cwd, {
|
|
543
|
+
online: false,
|
|
544
|
+
platform: 'darwin',
|
|
545
|
+
run: makeRun({ 'rustc --version': 'rustc 1.98.1 ()', 'xcode-select -p': '/Library/Developer/CommandLineTools' }),
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
expect(find(checks, 'native-xcode-clt').status).toBe('ok');
|
|
549
|
+
});
|
|
550
|
+
|
|
551
|
+
it('fails native-xcode-clt on darwin when xcode-select fails', async () => {
|
|
552
|
+
const cwd = makeTempDir();
|
|
553
|
+
writeTauriConf(cwd);
|
|
554
|
+
writeTauriCli(cwd, '2.11.4');
|
|
555
|
+
|
|
556
|
+
const checks = await runChecks(cwd, {
|
|
557
|
+
online: false,
|
|
558
|
+
platform: 'darwin',
|
|
559
|
+
run: makeRun({ 'rustc --version': 'rustc 1.98.1 ()', 'xcode-select -p': new Error('not installed') }),
|
|
560
|
+
});
|
|
561
|
+
|
|
562
|
+
expect(find(checks, 'native-xcode-clt').status).toBe('fail');
|
|
563
|
+
});
|
|
564
|
+
|
|
565
|
+
it('omits native-xcode-clt on non-darwin platforms', async () => {
|
|
566
|
+
const cwd = makeTempDir();
|
|
567
|
+
writeTauriConf(cwd);
|
|
568
|
+
writeTauriCli(cwd, '2.11.4');
|
|
569
|
+
|
|
570
|
+
const checks = await runChecks(cwd, {
|
|
571
|
+
online: false,
|
|
572
|
+
platform: 'linux',
|
|
573
|
+
run: makeRun({ 'rustc --version': 'rustc 1.98.1 ()' }),
|
|
574
|
+
});
|
|
575
|
+
|
|
576
|
+
expect(find(checks, 'native-xcode-clt')).toBeUndefined();
|
|
577
|
+
});
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
function writePluginAppPkg(cwd) {
|
|
581
|
+
fs.writeFileSync(path.join(cwd, 'package.json'), JSON.stringify({ dependencies: { '@caperjs/plugin-tauri': '^1' } }), 'utf-8');
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
function writeCargoToml(cwd, { withStorePlugin = true } = {}) {
|
|
585
|
+
fs.writeFileSync(
|
|
586
|
+
path.join(cwd, 'src-tauri/Cargo.toml'),
|
|
587
|
+
withStorePlugin ? '[dependencies]\ntauri-plugin-store = "2"\n' : '[dependencies]\ntauri = "2"\n',
|
|
588
|
+
'utf-8',
|
|
589
|
+
);
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
function writeCapabilities(cwd, permissions = ['core:default', ...TAURI_PLUGIN_PERMISSIONS]) {
|
|
593
|
+
fs.mkdirSync(path.join(cwd, 'src-tauri/capabilities'), { recursive: true });
|
|
594
|
+
fs.writeFileSync(
|
|
595
|
+
path.join(cwd, 'src-tauri/capabilities/default.json'),
|
|
596
|
+
JSON.stringify({ $schema: '../gen/schemas/desktop-schema.json', identifier: 'default', windows: ['main'], permissions }),
|
|
597
|
+
'utf-8',
|
|
598
|
+
);
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
describe('runChecks native-plugin row', () => {
|
|
602
|
+
it('is absent when src-tauri exists but the app does not depend on @caperjs/plugin-tauri', async () => {
|
|
603
|
+
const cwd = makeTempDir();
|
|
604
|
+
writeTauriConf(cwd);
|
|
605
|
+
writeTauriCli(cwd, '2.11.4');
|
|
606
|
+
|
|
607
|
+
const checks = await runChecks(cwd, { online: false, run: makeRun({ 'rustc --version': 'rustc 1.98.1 ()' }) });
|
|
608
|
+
|
|
609
|
+
expect(find(checks, 'native-plugin')).toBeUndefined();
|
|
610
|
+
});
|
|
611
|
+
|
|
612
|
+
it('is absent when the app depends on the plugin but src-tauri does not exist', async () => {
|
|
613
|
+
const cwd = makeTempDir();
|
|
614
|
+
writePluginAppPkg(cwd);
|
|
615
|
+
|
|
616
|
+
const checks = await runChecks(cwd, { online: false });
|
|
617
|
+
|
|
618
|
+
expect(find(checks, 'native-plugin')).toBeUndefined();
|
|
619
|
+
});
|
|
620
|
+
|
|
621
|
+
it('fails when Cargo.toml is unreadable', async () => {
|
|
622
|
+
const cwd = makeTempDir();
|
|
623
|
+
writeTauriConf(cwd);
|
|
624
|
+
writeTauriCli(cwd, '2.11.4');
|
|
625
|
+
writePluginAppPkg(cwd);
|
|
626
|
+
|
|
627
|
+
const checks = await runChecks(cwd, { online: false, run: makeRun({ 'rustc --version': 'rustc 1.98.1 ()' }) });
|
|
628
|
+
const row = find(checks, 'native-plugin');
|
|
629
|
+
|
|
630
|
+
expect(row.status).toBe('fail');
|
|
631
|
+
expect(row.label).toContain('Cargo.toml');
|
|
632
|
+
expect(row.hint).toMatch(/caper native plugin/);
|
|
633
|
+
});
|
|
634
|
+
|
|
635
|
+
it('fails when Cargo.toml is missing tauri-plugin-store', async () => {
|
|
636
|
+
const cwd = makeTempDir();
|
|
637
|
+
writeTauriConf(cwd);
|
|
638
|
+
writeTauriCli(cwd, '2.11.4');
|
|
639
|
+
writePluginAppPkg(cwd);
|
|
640
|
+
writeCargoToml(cwd, { withStorePlugin: false });
|
|
641
|
+
|
|
642
|
+
const checks = await runChecks(cwd, { online: false, run: makeRun({ 'rustc --version': 'rustc 1.98.1 ()' }) });
|
|
643
|
+
const row = find(checks, 'native-plugin');
|
|
644
|
+
|
|
645
|
+
expect(row.status).toBe('fail');
|
|
646
|
+
expect(row.hint).toMatch(/caper native plugin/);
|
|
647
|
+
});
|
|
648
|
+
|
|
649
|
+
it('warns when window permissions are missing from capabilities/default.json', async () => {
|
|
650
|
+
const cwd = makeTempDir();
|
|
651
|
+
writeTauriConf(cwd);
|
|
652
|
+
writeTauriCli(cwd, '2.11.4');
|
|
653
|
+
writePluginAppPkg(cwd);
|
|
654
|
+
writeCargoToml(cwd);
|
|
655
|
+
writeCapabilities(cwd, ['core:default']);
|
|
656
|
+
|
|
657
|
+
const checks = await runChecks(cwd, { online: false, run: makeRun({ 'rustc --version': 'rustc 1.98.1 ()' }) });
|
|
658
|
+
const row = find(checks, 'native-plugin');
|
|
659
|
+
|
|
660
|
+
expect(row.status).toBe('warn');
|
|
661
|
+
expect(row.label).toContain('core:window:allow-set-fullscreen');
|
|
662
|
+
});
|
|
663
|
+
|
|
664
|
+
it('fails when capabilities/default.json is unreadable', async () => {
|
|
665
|
+
const cwd = makeTempDir();
|
|
666
|
+
writeTauriConf(cwd);
|
|
667
|
+
writeTauriCli(cwd, '2.11.4');
|
|
668
|
+
writePluginAppPkg(cwd);
|
|
669
|
+
writeCargoToml(cwd);
|
|
670
|
+
// no capabilities/default.json written
|
|
671
|
+
|
|
672
|
+
const checks = await runChecks(cwd, { online: false, run: makeRun({ 'rustc --version': 'rustc 1.98.1 ()' }) });
|
|
673
|
+
const row = find(checks, 'native-plugin');
|
|
674
|
+
|
|
675
|
+
expect(row.status).toBe('fail');
|
|
676
|
+
expect(row.hint).toMatch(/caper native plugin/);
|
|
677
|
+
});
|
|
678
|
+
|
|
679
|
+
it('is ok when Cargo.toml has the store plugin and all window permissions are present', async () => {
|
|
680
|
+
const cwd = makeTempDir();
|
|
681
|
+
writeTauriConf(cwd);
|
|
682
|
+
writeTauriCli(cwd, '2.11.4');
|
|
683
|
+
writePluginAppPkg(cwd);
|
|
684
|
+
writeCargoToml(cwd);
|
|
685
|
+
writeCapabilities(cwd);
|
|
686
|
+
|
|
687
|
+
const checks = await runChecks(cwd, { online: false, run: makeRun({ 'rustc --version': 'rustc 1.98.1 ()' }) });
|
|
688
|
+
|
|
689
|
+
expect(find(checks, 'native-plugin').status).toBe('ok');
|
|
690
|
+
});
|
|
691
|
+
});
|
|
692
|
+
|
|
693
|
+
describe('runChecks native-android rows', () => {
|
|
694
|
+
const STOCK_ACTIVITY = 'package x.y.z\n\nclass MainActivity : TauriActivity()\n';
|
|
695
|
+
|
|
696
|
+
function scaffoldAndroid(cwd, { buildRs = 'fn main() { tauri_build::build() }\n', activity = STOCK_ACTIVITY } = {}) {
|
|
697
|
+
writeTauriConf(cwd);
|
|
698
|
+
writeTauriCli(cwd, '2.11.4');
|
|
699
|
+
fs.writeFileSync(path.join(cwd, 'src-tauri/build.rs'), buildRs, 'utf-8');
|
|
700
|
+
const javaDir = path.join(cwd, 'src-tauri/gen/android/app/src/main/java/x/y/z');
|
|
701
|
+
fs.mkdirSync(javaDir, { recursive: true });
|
|
702
|
+
fs.writeFileSync(path.join(javaDir, 'MainActivity.kt'), activity, 'utf-8');
|
|
703
|
+
const bin = path.join(cwd, 'bin');
|
|
704
|
+
fs.mkdirSync(bin);
|
|
705
|
+
fs.writeFileSync(path.join(bin, 'rustup'), '', 'utf-8');
|
|
706
|
+
const ndk = path.join(cwd, 'ndk');
|
|
707
|
+
const java = path.join(cwd, 'java');
|
|
708
|
+
fs.mkdirSync(ndk);
|
|
709
|
+
fs.mkdirSync(java);
|
|
710
|
+
return { bin, ndk, java };
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
const allTargets = 'aarch64-linux-android\narmv7-linux-androideabi\ni686-linux-android\nx86_64-linux-android\n';
|
|
714
|
+
|
|
715
|
+
function check(cwd, env, responses = { 'rustup target list --installed': allTargets }) {
|
|
716
|
+
return runChecks(cwd, {
|
|
717
|
+
online: false,
|
|
718
|
+
platform: 'linux',
|
|
719
|
+
env,
|
|
720
|
+
homedir: path.join(cwd, 'home'),
|
|
721
|
+
run: makeRun({ 'rustc --version': 'rustc 1.98.1 ()', ...responses }),
|
|
722
|
+
});
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
it('are absent when src-tauri/gen/android does not exist', async () => {
|
|
726
|
+
const cwd = makeTempDir();
|
|
727
|
+
writeTauriConf(cwd);
|
|
728
|
+
writeTauriCli(cwd, '2.11.4');
|
|
729
|
+
|
|
730
|
+
const checks = await check(cwd, {});
|
|
731
|
+
|
|
732
|
+
for (const id of ['native-android-rust', 'native-android-ndk', 'native-android-java', 'native-android-16kb', 'native-android-bars']) {
|
|
733
|
+
expect(find(checks, id)).toBeUndefined();
|
|
734
|
+
}
|
|
735
|
+
});
|
|
736
|
+
|
|
737
|
+
it('are all ok on a fully set-up app', async () => {
|
|
738
|
+
const cwd = makeTempDir();
|
|
739
|
+
const { bin, ndk, java } = scaffoldAndroid(cwd, {
|
|
740
|
+
buildRs: 'fn main() { println!("cargo:rustc-link-arg=-Wl,-z,max-page-size=16384"); }\n',
|
|
741
|
+
activity: 'controller.hide(WindowInsetsCompat.Type.systemBars())',
|
|
742
|
+
});
|
|
743
|
+
|
|
744
|
+
const checks = await check(cwd, { PATH: bin, NDK_HOME: ndk, JAVA_HOME: java });
|
|
745
|
+
|
|
746
|
+
for (const id of ['native-android-rust', 'native-android-ndk', 'native-android-java', 'native-android-16kb', 'native-android-bars']) {
|
|
747
|
+
expect(find(checks, id).status).toBe('ok');
|
|
748
|
+
}
|
|
749
|
+
});
|
|
750
|
+
|
|
751
|
+
it('fails native-android-rust when a target is missing', async () => {
|
|
752
|
+
const cwd = makeTempDir();
|
|
753
|
+
const { bin, ndk, java } = scaffoldAndroid(cwd);
|
|
754
|
+
|
|
755
|
+
const checks = await check(cwd, { PATH: bin, NDK_HOME: ndk, JAVA_HOME: java }, { 'rustup target list --installed': 'aarch64-linux-android\n' });
|
|
756
|
+
|
|
757
|
+
const row = find(checks, 'native-android-rust');
|
|
758
|
+
expect(row.status).toBe('fail');
|
|
759
|
+
expect(row.label).toMatch(/armv7-linux-androideabi/);
|
|
760
|
+
expect(row.hint).toMatch(/caper native android/);
|
|
761
|
+
});
|
|
762
|
+
|
|
763
|
+
it('fails native-android-rust when rustup cannot be found', async () => {
|
|
764
|
+
const cwd = makeTempDir();
|
|
765
|
+
const { ndk, java } = scaffoldAndroid(cwd);
|
|
766
|
+
|
|
767
|
+
const checks = await check(cwd, { PATH: path.join(cwd, 'nowhere'), NDK_HOME: ndk, JAVA_HOME: java }, {});
|
|
768
|
+
|
|
769
|
+
expect(find(checks, 'native-android-rust').status).toBe('fail');
|
|
770
|
+
});
|
|
771
|
+
|
|
772
|
+
it('warns native-android-ndk / -java when unset but resolvable, with an export hint', async () => {
|
|
773
|
+
const cwd = makeTempDir();
|
|
774
|
+
const { bin, java } = scaffoldAndroid(cwd);
|
|
775
|
+
const sdk = path.join(cwd, 'sdk');
|
|
776
|
+
fs.mkdirSync(path.join(sdk, 'ndk/27.0.12077973'), { recursive: true });
|
|
777
|
+
fs.mkdirSync(path.join(sdk, 'ndk/27.1.12297006'), { recursive: true });
|
|
778
|
+
|
|
779
|
+
const checks = await check(cwd, { PATH: bin, ANDROID_HOME: sdk, JAVA_HOME: java });
|
|
780
|
+
|
|
781
|
+
const ndk = find(checks, 'native-android-ndk');
|
|
782
|
+
expect(ndk.status).toBe('warn');
|
|
783
|
+
expect(ndk.hint).toBe(`export NDK_HOME=${path.join(sdk, 'ndk/27.1.12297006')}`);
|
|
784
|
+
expect(find(checks, 'native-android-java').status).toBe('ok');
|
|
785
|
+
});
|
|
786
|
+
|
|
787
|
+
it('fails native-android-ndk / -java when neither set nor resolvable', async () => {
|
|
788
|
+
const cwd = makeTempDir();
|
|
789
|
+
const { bin } = scaffoldAndroid(cwd);
|
|
790
|
+
|
|
791
|
+
const checks = await check(cwd, { PATH: bin });
|
|
792
|
+
|
|
793
|
+
expect(find(checks, 'native-android-ndk').status).toBe('fail');
|
|
794
|
+
expect(find(checks, 'native-android-java').status).toBe('fail');
|
|
795
|
+
});
|
|
796
|
+
|
|
797
|
+
it('fails native-android-java when JAVA_HOME points at a missing directory', async () => {
|
|
798
|
+
const cwd = makeTempDir();
|
|
799
|
+
const { bin, ndk } = scaffoldAndroid(cwd);
|
|
800
|
+
|
|
801
|
+
const checks = await check(cwd, { PATH: bin, NDK_HOME: ndk, JAVA_HOME: path.join(cwd, 'gone') });
|
|
802
|
+
|
|
803
|
+
expect(find(checks, 'native-android-java').status).toBe('fail');
|
|
804
|
+
});
|
|
805
|
+
|
|
806
|
+
it('fails native-android-16kb and warns native-android-bars on the stock files', async () => {
|
|
807
|
+
const cwd = makeTempDir();
|
|
808
|
+
const { bin, ndk, java } = scaffoldAndroid(cwd);
|
|
809
|
+
|
|
810
|
+
const checks = await check(cwd, { PATH: bin, NDK_HOME: ndk, JAVA_HOME: java });
|
|
811
|
+
|
|
812
|
+
const pageSize = find(checks, 'native-android-16kb');
|
|
813
|
+
expect(pageSize.status).toBe('fail');
|
|
814
|
+
expect(pageSize.hint).toMatch(/caper native android/);
|
|
815
|
+
expect(find(checks, 'native-android-bars').status).toBe('warn');
|
|
816
|
+
});
|
|
817
|
+
});
|