|
| 1 | +import * as child_process from 'child_process'; |
1 | 2 | import * as os from 'os'; |
2 | 3 | import * as path from 'path'; |
3 | 4 | import * as cxapi from '@aws-cdk/cx-api'; |
4 | 5 | import * as fs from 'fs-extra'; |
5 | 6 | import { availableInitLanguages, availableInitTemplates, cliInit, currentlyRecommendedAwsCdkLibFlags, expandPlaceholders, printAvailableTemplates } from '../../lib/commands/init'; |
| 7 | +import type { JsPackageManager } from '../../lib/commands/init/package-manager'; |
6 | 8 | import { createSingleLanguageTemplate, createMultiLanguageTemplate, createMultiTemplateRepository } from '../_fixtures/init-templates/template-helpers'; |
7 | 9 | import { TestIoHost } from '../_helpers/io-host'; |
8 | 10 |
|
@@ -1352,6 +1354,143 @@ describe('constructs version', () => { |
1352 | 1354 | // cdk.json should not exist since template didn't have one |
1353 | 1355 | expect(await fs.pathExists(path.join(projectDir, 'cdk.json'))).toBeFalsy(); |
1354 | 1356 | }); |
| 1357 | + |
| 1358 | + describe('package-manager option', () => { |
| 1359 | + let spawnSpy: jest.SpyInstance; |
| 1360 | + |
| 1361 | + beforeEach(async () => { |
| 1362 | + // Mock child_process.spawn to track which package manager is called |
| 1363 | + spawnSpy = jest.spyOn(child_process, 'spawn').mockImplementation(() => ({ |
| 1364 | + stdout: { on: jest.fn() }, |
| 1365 | + }) as unknown as child_process.ChildProcess); |
| 1366 | + }); |
| 1367 | + |
| 1368 | + afterEach(() => { |
| 1369 | + spawnSpy.mockRestore(); |
| 1370 | + }); |
| 1371 | + |
| 1372 | + test.each([ |
| 1373 | + { language: 'typescript', packageManager: 'npm' }, |
| 1374 | + { language: 'typescript', packageManager: 'yarn' }, |
| 1375 | + { language: 'typescript', packageManager: 'pnpm' }, |
| 1376 | + { language: 'typescript', packageManager: 'bun' }, |
| 1377 | + { language: 'javascript', packageManager: 'npm' }, |
| 1378 | + { language: 'javascript', packageManager: 'yarn' }, |
| 1379 | + { language: 'javascript', packageManager: 'pnpm' }, |
| 1380 | + { language: 'javascript', packageManager: 'bun' }, |
| 1381 | + ])('uses $packageManager for $language project', async ({ language, packageManager }) => { |
| 1382 | + await withTempDir(async (workDir) => { |
| 1383 | + await cliInit({ |
| 1384 | + ioHelper, |
| 1385 | + type: 'app', |
| 1386 | + language, |
| 1387 | + packageManager: packageManager as JsPackageManager, |
| 1388 | + workDir, |
| 1389 | + }); |
| 1390 | + |
| 1391 | + const installCalls = spawnSpy.mock.calls.filter( |
| 1392 | + ([cmd, args]) => cmd === packageManager && args.includes('install'), |
| 1393 | + ); |
| 1394 | + expect(installCalls.length).toBeGreaterThan(0); |
| 1395 | + }); |
| 1396 | + }); |
| 1397 | + |
| 1398 | + cliTest('uses npm as default when package manager not specified', async (workDir) => { |
| 1399 | + await cliInit({ |
| 1400 | + ioHelper, |
| 1401 | + type: 'app', |
| 1402 | + language: 'typescript', |
| 1403 | + workDir, |
| 1404 | + }); |
| 1405 | + |
| 1406 | + const installCalls = spawnSpy.mock.calls.filter( |
| 1407 | + ([cmd, args]) => cmd === 'npm' && args.includes('install'), |
| 1408 | + ); |
| 1409 | + expect(installCalls.length).toBeGreaterThan(0); |
| 1410 | + }); |
| 1411 | + |
| 1412 | + cliTest('ignores package manager option for non-JavaScript languages', async (workDir) => { |
| 1413 | + await cliInit({ |
| 1414 | + ioHelper, |
| 1415 | + type: 'app', |
| 1416 | + language: 'python', |
| 1417 | + packageManager: 'yarn', |
| 1418 | + canUseNetwork: false, |
| 1419 | + generateOnly: true, |
| 1420 | + workDir, |
| 1421 | + }); |
| 1422 | + |
| 1423 | + expect(await fs.pathExists(path.join(workDir, 'requirements.txt'))).toBeTruthy(); |
| 1424 | + }); |
| 1425 | + }); |
| 1426 | + |
| 1427 | + describe('validate CLI init options', () => { |
| 1428 | + const cdkBin = path.join(__dirname, '..', '..', 'bin', 'cdk'); |
| 1429 | + const commonEnv = { ...process.env, CDK_DISABLE_VERSION_CHECK: '1', CI: 'true', FORCE_COLOR: '0' }; |
| 1430 | + |
| 1431 | + test.each([ |
| 1432 | + 'python', |
| 1433 | + 'java', |
| 1434 | + 'go', |
| 1435 | + 'csharp', |
| 1436 | + 'fsharp', |
| 1437 | + ])('warns when package-manager option is specified for non-JS language=%s', async (language) => { |
| 1438 | + await withTempDir(async (workDir) => { |
| 1439 | + const output = child_process.execSync( |
| 1440 | + `node ${cdkBin} init app --language ${language} --package-manager npm --generate-only`, |
| 1441 | + { |
| 1442 | + cwd: workDir, |
| 1443 | + env: commonEnv, |
| 1444 | + encoding: 'utf-8', |
| 1445 | + }, |
| 1446 | + ); |
| 1447 | + |
| 1448 | + expect(output).toContain('--package-manager option is only applicable for JavaScript and TypeScript projects'); |
| 1449 | + expect(output).toContain(`Applying project template app for ${language}`); |
| 1450 | + }); |
| 1451 | + }); |
| 1452 | + |
| 1453 | + test.each([ |
| 1454 | + 'python', |
| 1455 | + 'java', |
| 1456 | + 'go', |
| 1457 | + 'csharp', |
| 1458 | + 'fsharp', |
| 1459 | + ])('does not warn when package-manager option is omitted for non-JS language=%s', async (language) => { |
| 1460 | + await withTempDir(async (workDir) => { |
| 1461 | + const output = child_process.execSync( |
| 1462 | + `node ${cdkBin} init app --language ${language} --generate-only`, |
| 1463 | + { |
| 1464 | + cwd: workDir, |
| 1465 | + env: commonEnv, |
| 1466 | + encoding: 'utf-8', |
| 1467 | + }, |
| 1468 | + ); |
| 1469 | + |
| 1470 | + expect(output).not.toContain('--package-manager option is only applicable for JavaScript and TypeScript projects'); |
| 1471 | + expect(output).toContain(`Applying project template app for ${language}`); |
| 1472 | + }); |
| 1473 | + }); |
| 1474 | + |
| 1475 | + test.each([ |
| 1476 | + 'typescript', |
| 1477 | + 'javascript', |
| 1478 | + ])('does not warn when package-manager option is specified for language=%s', async (language) => { |
| 1479 | + await withTempDir(async (workDir) => { |
| 1480 | + const output = child_process.execSync( |
| 1481 | + `node ${cdkBin} init app --language ${language} --generate-only`, |
| 1482 | + { |
| 1483 | + cwd: workDir, |
| 1484 | + env: commonEnv, |
| 1485 | + encoding: 'utf-8', |
| 1486 | + }, |
| 1487 | + ); |
| 1488 | + |
| 1489 | + expect(output).not.toContain('--package-manager option is only applicable for JavaScript and TypeScript projects'); |
| 1490 | + expect(output).toContain(`Applying project template app for ${language}`); |
| 1491 | + }); |
| 1492 | + }); |
| 1493 | + }); |
1355 | 1494 | }); |
1356 | 1495 |
|
1357 | 1496 | test('when no version number is present (e.g., local development), the v2 templates are chosen by default', async () => { |
|
0 commit comments