UNPKG

@sprouted/create-vibes

Version:
238 lines (208 loc) 6.68 kB
import { CreateAppCommand, CreateAppOptions } from './create-app' import { TemplateEngine } from '../template-engine/engine' import inquirer from 'inquirer' import * as fs from 'fs/promises' jest.mock('../template-engine/engine') jest.mock('inquirer') jest.mock('fs/promises') describe('CreateAppCommand', () => { let command: CreateAppCommand let mockEngine: jest.Mocked<TemplateEngine> beforeEach(() => { mockEngine = { generateFromTemplate: jest.fn().mockResolvedValue(undefined) } as any command = new CreateAppCommand(mockEngine) jest.spyOn(console, 'log').mockImplementation() ;(fs.mkdir as jest.Mock).mockResolvedValue(undefined) }) afterEach(() => { jest.clearAllMocks() }) it('should create a web app with provided options', async () => { const options: CreateAppOptions = { type: 'web', name: 'my-app', framework: 'vite-react', includeRouter: true, includeTailwind: false } await command.execute(options) expect(fs.mkdir).toHaveBeenCalledWith( expect.stringContaining('apps'), { recursive: true } ) expect(mockEngine.generateFromTemplate).toHaveBeenCalledWith( expect.stringContaining('templates/typescript/apps/web'), { appName: 'my-app', framework: 'vite-react', includeRouter: true, includeTailwind: false }, { outputPath: expect.stringContaining('apps/my-app'), dryRun: false } ) expect(console.log).toHaveBeenCalledWith('✨ Created web app: my-app') }) it('should create a mobile app with provided options', async () => { const options: CreateAppOptions = { type: 'mobile', name: 'my-mobile-app', displayName: 'My Mobile App', includeNavigator: true, includeAuth: false, includeApiClient: true } await command.execute(options) expect(mockEngine.generateFromTemplate).toHaveBeenCalledWith( expect.stringContaining('templates/typescript/apps/mobile'), { appName: 'my-mobile-app', displayName: 'My Mobile App', includeNavigator: true, includeAuth: false, includeApiClient: true, framework: undefined, includeRouter: undefined, includeTailwind: undefined }, { outputPath: expect.stringContaining('apps/my-mobile-app'), dryRun: false } ) expect(console.log).toHaveBeenCalledWith('✨ Created mobile app: my-mobile-app') }) it('should create an API app with provided options', async () => { const options: CreateAppOptions = { type: 'api', name: 'my-api', port: 3001, includeDatabase: true, includeAuth: true, includeValidation: true, includeSwagger: false, includeGraphQL: false } await command.execute(options) expect(mockEngine.generateFromTemplate).toHaveBeenCalledWith( expect.stringContaining('templates/typescript/apps/api'), { appName: 'my-api', port: 3001, includeDatabase: true, includeAuth: true, includeValidation: true, includeSwagger: false, includeGraphQL: false, displayName: undefined, framework: undefined, includeRouter: undefined, includeTailwind: undefined, includeNavigator: undefined, includeApiClient: undefined }, { outputPath: expect.stringContaining('apps/my-api'), dryRun: false } ) expect(console.log).toHaveBeenCalledWith('✨ Created api app: my-api') }) it('should create a desktop app with provided options', async () => { const options: CreateAppOptions = { type: 'desktop', name: 'my-desktop', displayName: 'My Desktop App', appId: 'com.vibes.my-desktop', includeAutoUpdater: true, includeSystemTray: false, includeMenuBar: true, includeIpc: true, includeDarkMode: true } await command.execute(options) expect(mockEngine.generateFromTemplate).toHaveBeenCalledWith( expect.stringContaining('templates/typescript/apps/desktop'), { appName: 'my-desktop', displayName: 'My Desktop App', appId: 'com.vibes.my-desktop', includeAutoUpdater: true, includeSystemTray: false, includeMenuBar: true, includeIpc: true, includeDarkMode: true, framework: undefined, includeRouter: undefined, includeTailwind: undefined, includeNavigator: undefined, includeAuth: undefined, includeApiClient: undefined, port: undefined, includeDatabase: undefined, includeValidation: undefined, includeSwagger: undefined, includeGraphQL: undefined }, { outputPath: expect.stringContaining('apps/my-desktop'), dryRun: false } ) expect(console.log).toHaveBeenCalledWith('✨ Created desktop app: my-desktop') }) it('should prompt for missing options', async () => { const options: CreateAppOptions = { type: 'web' } ;(inquirer.prompt as jest.Mock).mockResolvedValue({ name: 'prompted-app', framework: 'nextjs', includeRouter: false, includeTailwind: true }) await command.execute(options) expect(inquirer.prompt).toHaveBeenCalledWith( expect.arrayContaining([ expect.objectContaining({ name: 'name' }), expect.objectContaining({ name: 'framework' }), expect.objectContaining({ name: 'includeRouter' }), expect.objectContaining({ name: 'includeTailwind' }) ]) ) expect(mockEngine.generateFromTemplate).toHaveBeenCalledWith( expect.any(String), { appName: 'prompted-app', framework: 'nextjs', includeRouter: false, includeTailwind: true }, expect.any(Object) ) }) it('should validate app name', async () => { const options: CreateAppOptions = { type: 'web' } ;(inquirer.prompt as jest.Mock).mockImplementation((questions) => { const nameQuestion = questions.find((q: any) => q.name === 'name') expect(nameQuestion.validate('Invalid Name!')).toBe( 'App name must be lowercase alphanumeric with dashes' ) expect(nameQuestion.validate('')).toBe('App name is required') expect(nameQuestion.validate('valid-name')).toBe(true) return Promise.resolve({ name: 'valid-name', framework: 'vite-react', includeRouter: true, includeTailwind: false }) }) await command.execute(options) }) })