sunpeak 0.20.6 → 0.20.7
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.
|
@@ -61,12 +61,14 @@ export const defaultDeps = {
|
|
|
61
61
|
* - JS/TS projects: root-level config + test files
|
|
62
62
|
* - sunpeak projects: migrate to defineConfig()
|
|
63
63
|
*
|
|
64
|
-
* Scaffolds
|
|
64
|
+
* Scaffolds 4 test types:
|
|
65
65
|
* 1. E2E tests — Playwright-based inspector tests (mcp fixture)
|
|
66
66
|
* 2. Visual regression — Screenshot comparison via result.screenshot()
|
|
67
67
|
* 3. Live tests — Test against real ChatGPT/Claude hosts
|
|
68
68
|
* 4. Evals — Multi-model tool calling reliability tests
|
|
69
|
-
*
|
|
69
|
+
*
|
|
70
|
+
* Unit tests are not scaffolded here — they're part of the sunpeak app
|
|
71
|
+
* framework (`sunpeak new`) where tool handlers can be imported directly.
|
|
70
72
|
*/
|
|
71
73
|
export async function testInit(args = [], deps = defaultDeps) {
|
|
72
74
|
const d = { ...defaultDeps, ...deps };
|
|
@@ -532,56 +534,6 @@ export default defineLiveConfig({${serverOption}
|
|
|
532
534
|
d.log.success(`Created ${liveDir}/ with live test config and example.`);
|
|
533
535
|
}
|
|
534
536
|
|
|
535
|
-
/**
|
|
536
|
-
* Scaffold a unit test example for JS/TS projects.
|
|
537
|
-
* @param {string} filePath - Full path to the unit test file
|
|
538
|
-
* @param {object} d - Dependencies
|
|
539
|
-
*/
|
|
540
|
-
function scaffoldUnitTest(filePath, d) {
|
|
541
|
-
if (d.existsSync(filePath)) {
|
|
542
|
-
d.log.info('Unit test already exists. Skipping.');
|
|
543
|
-
return;
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
d.mkdirSync(dirname(filePath), { recursive: true });
|
|
547
|
-
|
|
548
|
-
d.writeFileSync(
|
|
549
|
-
filePath,
|
|
550
|
-
`import { describe, it, expect } from 'vitest';
|
|
551
|
-
|
|
552
|
-
/**
|
|
553
|
-
* Unit tests for your MCP tool handlers.
|
|
554
|
-
*
|
|
555
|
-
* Import your tool handler directly and test its input/output
|
|
556
|
-
* without starting the MCP server or inspector.
|
|
557
|
-
*
|
|
558
|
-
* Run with: npx sunpeak test --unit
|
|
559
|
-
*
|
|
560
|
-
* To set up vitest, add it to your devDependencies:
|
|
561
|
-
* npm install -D vitest
|
|
562
|
-
*
|
|
563
|
-
* Uncomment and customize the tests below for your tools.
|
|
564
|
-
*/
|
|
565
|
-
|
|
566
|
-
// import handler, { tool, schema } from '../../src/tools/your-tool';
|
|
567
|
-
// const extra = {} as Parameters<typeof handler>[1];
|
|
568
|
-
|
|
569
|
-
// describe('your tool', () => {
|
|
570
|
-
// it('returns expected output', async () => {
|
|
571
|
-
// const result = await handler({ key: 'value' }, extra);
|
|
572
|
-
// expect(result.structuredContent).toBeDefined();
|
|
573
|
-
// });
|
|
574
|
-
//
|
|
575
|
-
// it('exports correct tool config', () => {
|
|
576
|
-
// expect(tool.title).toBe('Your Tool');
|
|
577
|
-
// expect(tool.annotations?.readOnlyHint).toBe(true);
|
|
578
|
-
// });
|
|
579
|
-
// });
|
|
580
|
-
`
|
|
581
|
-
);
|
|
582
|
-
d.log.success(`Created ${filePath}`);
|
|
583
|
-
}
|
|
584
|
-
|
|
585
537
|
async function initExternalProject(cliServer, d) {
|
|
586
538
|
d.log.info('Detected non-JS project. Creating self-contained test directory.');
|
|
587
539
|
|
|
@@ -715,6 +667,22 @@ async function initJsProject(cliServer, d) {
|
|
|
715
667
|
const server = await getServerConfig(cliServer, d);
|
|
716
668
|
const cwd = d.cwd();
|
|
717
669
|
|
|
670
|
+
// Ensure "type": "module" — sunpeak exports are ESM-only and Playwright's
|
|
671
|
+
// CJS resolver won't find them without it.
|
|
672
|
+
const pkgPath = join(cwd, 'package.json');
|
|
673
|
+
if (d.existsSync(pkgPath)) {
|
|
674
|
+
try {
|
|
675
|
+
const pkg = JSON.parse(d.readFileSync(pkgPath, 'utf-8'));
|
|
676
|
+
if (pkg.type !== 'module') {
|
|
677
|
+
pkg.type = 'module';
|
|
678
|
+
d.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
|
|
679
|
+
d.log.success('Set "type": "module" in package.json (required for sunpeak imports)');
|
|
680
|
+
}
|
|
681
|
+
} catch {
|
|
682
|
+
d.log.warn('Could not read package.json. Make sure "type": "module" is set.');
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
|
|
718
686
|
// Create playwright.config.ts
|
|
719
687
|
const configPath = join(cwd, 'playwright.config.ts');
|
|
720
688
|
if (d.existsSync(configPath)) {
|
|
@@ -775,19 +743,15 @@ test('server exposes tools', async ({ mcp }) => {
|
|
|
775
743
|
// 4. Eval boilerplate
|
|
776
744
|
scaffoldEvals(join(cwd, 'tests', 'evals'), { server, d });
|
|
777
745
|
|
|
778
|
-
// 5. Unit test
|
|
779
|
-
scaffoldUnitTest(join(cwd, 'tests', 'unit', 'example.test.ts'), d);
|
|
780
|
-
|
|
781
746
|
if (server.type === 'later') {
|
|
782
747
|
d.log.warn('Server not configured. Edit playwright.config.ts before running tests.');
|
|
783
748
|
}
|
|
784
749
|
const pkgMgr = d.detectPackageManager();
|
|
785
750
|
d.log.step('Next steps:');
|
|
786
|
-
d.log.message(` ${pkgMgr} add -D sunpeak @playwright/test
|
|
751
|
+
d.log.message(` ${pkgMgr} add -D sunpeak @playwright/test`);
|
|
787
752
|
d.log.message(` ${pkgMgr} exec playwright install chromium`);
|
|
788
753
|
d.log.message('');
|
|
789
754
|
d.log.message(' npx sunpeak test # E2E tests');
|
|
790
|
-
d.log.message(' npx sunpeak test --unit # Unit tests (vitest)');
|
|
791
755
|
d.log.message(' npx sunpeak test --visual # Visual regression');
|
|
792
756
|
d.log.message(' npx sunpeak test --live # Live tests against real hosts');
|
|
793
757
|
d.log.message(' npx sunpeak test --eval # Multi-model evals');
|
|
@@ -833,14 +797,10 @@ export default defineConfig();
|
|
|
833
797
|
// 3. Eval boilerplate
|
|
834
798
|
scaffoldEvals(join(cwd, 'tests', 'evals'), { isSunpeak: true, d });
|
|
835
799
|
|
|
836
|
-
// 4. Unit test
|
|
837
|
-
scaffoldUnitTest(join(cwd, 'tests', 'unit', 'example.test.ts'), d);
|
|
838
|
-
|
|
839
800
|
d.log.step('Scaffolded test types:');
|
|
840
801
|
d.log.message(' tests/e2e/visual.test.ts — Visual regression (npx sunpeak test --visual)');
|
|
841
802
|
d.log.message(' tests/live/ — Live host tests (npx sunpeak test --live)');
|
|
842
803
|
d.log.message(' tests/evals/ — Multi-model evals (npx sunpeak test --eval)');
|
|
843
|
-
d.log.message(' tests/unit/example.test.ts — Unit tests (npx sunpeak test --unit)');
|
|
844
804
|
d.log.message('');
|
|
845
805
|
d.log.message(' Migrate existing e2e tests:');
|
|
846
806
|
d.log.message(' Replace: import { test, expect } from "@playwright/test"');
|
package/bin/commands/test.mjs
CHANGED
|
@@ -59,8 +59,17 @@ export async function runTest(args) {
|
|
|
59
59
|
const results = [];
|
|
60
60
|
|
|
61
61
|
if (runUnit) {
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
// Only run unit tests if vitest is available (app framework projects have it,
|
|
63
|
+
// standalone testing framework projects don't).
|
|
64
|
+
const hasVitest = existsSync(join(process.cwd(), 'node_modules', '.bin', 'vitest'));
|
|
65
|
+
if (hasVitest) {
|
|
66
|
+
const code = await runChild('pnpm', ['exec', 'vitest', 'run', ...filteredArgs]);
|
|
67
|
+
results.push({ suite: 'unit', code });
|
|
68
|
+
} else if (isUnit) {
|
|
69
|
+
// Only warn if the user explicitly asked for --unit
|
|
70
|
+
console.error('vitest is not installed. Install it with: npm add -D vitest');
|
|
71
|
+
results.push({ suite: 'unit', code: 1 });
|
|
72
|
+
}
|
|
64
73
|
}
|
|
65
74
|
|
|
66
75
|
if (runE2e) {
|
package/package.json
CHANGED