UNPKG

spanwright

Version:

CLI tool to generate Cloud Spanner E2E testing framework projects with Go database tools and Playwright browser automation

575 lines 33.6 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); const vitest_1 = require("vitest"); const readline = __importStar(require("readline")); const configuration_1 = require("../configuration"); const constants_1 = require("../constants"); const errors_1 = require("../errors"); const validation_1 = require("../validation"); // Mock the validation module vitest_1.vi.mock('../validation', () => ({ validateDatabaseCount: vitest_1.vi.fn(), validateSchemaPath: vitest_1.vi.fn(), sanitizeInput: vitest_1.vi.fn((input) => input.trim()), })); // Mock readline module vitest_1.vi.mock('readline', () => ({ createInterface: vitest_1.vi.fn(), })); (0, vitest_1.describe)('Configuration Module', () => { let mockConsoleLog; (0, vitest_1.beforeEach)(() => { vitest_1.vi.clearAllMocks(); // Mock console methods after clearing mockConsoleLog = vitest_1.vi.spyOn(console, 'log').mockImplementation(() => { }); // Reset environment variables delete process.env[constants_1.ENV_VARS.DB_COUNT]; delete process.env[constants_1.ENV_VARS.PRIMARY_DB_NAME]; delete process.env[constants_1.ENV_VARS.PRIMARY_SCHEMA_PATH]; delete process.env[constants_1.ENV_VARS.SECONDARY_DB_NAME]; delete process.env[constants_1.ENV_VARS.SECONDARY_SCHEMA_PATH]; }); (0, vitest_1.afterEach)(() => { vitest_1.vi.restoreAllMocks(); }); (0, vitest_1.describe)('getConfiguration', () => { (0, vitest_1.it)('should call getNonInteractiveConfiguration when isNonInteractive is true', async () => { // Setup environment variables for non-interactive mode process.env[constants_1.ENV_VARS.DB_COUNT] = '1'; process.env[constants_1.ENV_VARS.PRIMARY_DB_NAME] = 'test-db'; process.env[constants_1.ENV_VARS.PRIMARY_SCHEMA_PATH] = '/path/to/schema'; // Mock validation to pass vitest_1.vi.mocked(validation_1.validateDatabaseCount).mockImplementation(() => { }); const result = await (0, configuration_1.getConfiguration)(true); (0, vitest_1.expect)(result).toEqual({ count: '1', primaryDbName: 'test-db', primarySchemaPath: '/path/to/schema', secondaryDbName: undefined, secondarySchemaPath: undefined, }); (0, vitest_1.expect)(validation_1.validateDatabaseCount).toHaveBeenCalledWith('1'); (0, vitest_1.expect)(mockConsoleLog).toHaveBeenCalledWith('🤖 Non-interactive mode: Creating project with 1 database(s)'); }); (0, vitest_1.it)('should call getInteractiveConfiguration when isNonInteractive is false', async () => { // Mock readline interface const mockQuestion = vitest_1.vi.fn(); const mockClose = vitest_1.vi.fn(); const mockReadlineInterface = { question: mockQuestion, close: mockClose, }; vitest_1.vi.mocked(readline.createInterface).mockReturnValue(mockReadlineInterface); // Mock user inputs mockQuestion .mockImplementationOnce((query, callback) => { callback('1'); }) .mockImplementationOnce((query, callback) => { callback('test-db'); }) .mockImplementationOnce((query, callback) => { callback('/path/to/schema'); }); // Mock validation to pass vitest_1.vi.mocked(validation_1.validateDatabaseCount).mockImplementation(() => { }); vitest_1.vi.mocked(validation_1.validateSchemaPath).mockImplementation(() => { }); const result = await (0, configuration_1.getConfiguration)(false); (0, vitest_1.expect)(result).toEqual({ count: '1', primaryDbName: 'test-db', primarySchemaPath: '/path/to/schema', }); (0, vitest_1.expect)(mockClose).toHaveBeenCalled(); }); }); (0, vitest_1.describe)('getNonInteractiveConfiguration', () => { (0, vitest_1.it)('should use environment variables when provided', async () => { process.env[constants_1.ENV_VARS.DB_COUNT] = '2'; process.env[constants_1.ENV_VARS.PRIMARY_DB_NAME] = 'custom-primary'; process.env[constants_1.ENV_VARS.PRIMARY_SCHEMA_PATH] = '/custom/primary/schema'; process.env[constants_1.ENV_VARS.SECONDARY_DB_NAME] = 'custom-secondary'; process.env[constants_1.ENV_VARS.SECONDARY_SCHEMA_PATH] = '/custom/secondary/schema'; vitest_1.vi.mocked(validation_1.validateDatabaseCount).mockImplementation(() => { }); const result = await (0, configuration_1.getConfiguration)(true); (0, vitest_1.expect)(result).toEqual({ count: '2', primaryDbName: 'custom-primary', primarySchemaPath: '/custom/primary/schema', secondaryDbName: 'custom-secondary', secondarySchemaPath: '/custom/secondary/schema', }); (0, vitest_1.expect)(mockConsoleLog).toHaveBeenCalledWith('🤖 Non-interactive mode: Creating project with 2 database(s)'); (0, vitest_1.expect)(mockConsoleLog).toHaveBeenCalledWith(' Primary DB: custom-primary (/custom/primary/schema)'); (0, vitest_1.expect)(mockConsoleLog).toHaveBeenCalledWith(' Secondary DB: custom-secondary (/custom/secondary/schema)'); }); (0, vitest_1.it)('should use default values when environment variables are not set', async () => { vitest_1.vi.mocked(validation_1.validateDatabaseCount).mockImplementation(() => { }); const result = await (0, configuration_1.getConfiguration)(true); (0, vitest_1.expect)(result).toEqual({ count: constants_1.DEFAULTS.DB_COUNT, primaryDbName: constants_1.DEFAULTS.PRIMARY_DB_NAME, primarySchemaPath: constants_1.DEFAULTS.PRIMARY_SCHEMA_PATH, secondaryDbName: undefined, secondarySchemaPath: undefined, }); (0, vitest_1.expect)(mockConsoleLog).toHaveBeenCalledWith(`🤖 Non-interactive mode: Creating project with ${constants_1.DEFAULTS.DB_COUNT} database(s)`); (0, vitest_1.expect)(mockConsoleLog).toHaveBeenCalledWith(` Primary DB: ${constants_1.DEFAULTS.PRIMARY_DB_NAME} (${constants_1.DEFAULTS.PRIMARY_SCHEMA_PATH})`); }); (0, vitest_1.it)('should handle single database configuration', async () => { process.env[constants_1.ENV_VARS.DB_COUNT] = '1'; vitest_1.vi.mocked(validation_1.validateDatabaseCount).mockImplementation(() => { }); const result = await (0, configuration_1.getConfiguration)(true); (0, vitest_1.expect)(result.count).toBe('1'); (0, vitest_1.expect)(result.secondaryDbName).toBeUndefined(); (0, vitest_1.expect)(result.secondarySchemaPath).toBeUndefined(); (0, vitest_1.expect)(mockConsoleLog).not.toHaveBeenCalledWith(vitest_1.expect.stringContaining('Secondary DB:')); }); (0, vitest_1.it)('should handle dual database configuration', async () => { process.env[constants_1.ENV_VARS.DB_COUNT] = '2'; vitest_1.vi.mocked(validation_1.validateDatabaseCount).mockImplementation(() => { }); const result = await (0, configuration_1.getConfiguration)(true); (0, vitest_1.expect)(result.count).toBe('2'); (0, vitest_1.expect)(result.secondaryDbName).toBe(constants_1.DEFAULTS.SECONDARY_DB_NAME); (0, vitest_1.expect)(result.secondarySchemaPath).toBe(constants_1.DEFAULTS.SECONDARY_SCHEMA_PATH); (0, vitest_1.expect)(mockConsoleLog).toHaveBeenCalledWith(vitest_1.expect.stringContaining('Secondary DB:')); }); (0, vitest_1.it)('should throw ConfigurationError for invalid database count', async () => { process.env[constants_1.ENV_VARS.DB_COUNT] = '3'; vitest_1.vi.mocked(validation_1.validateDatabaseCount).mockImplementation(() => { throw new Error('Invalid count'); }); await (0, vitest_1.expect)((0, configuration_1.getConfiguration)(true)).rejects.toThrow(errors_1.ConfigurationError); await (0, vitest_1.expect)((0, configuration_1.getConfiguration)(true)).rejects.toThrow(constants_1.MESSAGES.ERRORS.ENV_DB_COUNT_INVALID); }); (0, vitest_1.it)('should validate database count', async () => { process.env[constants_1.ENV_VARS.DB_COUNT] = '1'; vitest_1.vi.mocked(validation_1.validateDatabaseCount).mockImplementation(() => { }); await (0, configuration_1.getConfiguration)(true); (0, vitest_1.expect)(validation_1.validateDatabaseCount).toHaveBeenCalledWith('1'); }); }); (0, vitest_1.describe)('getInteractiveConfiguration', () => { let mockQuestion; let mockClose; let mockReadlineInterface; (0, vitest_1.beforeEach)(() => { mockQuestion = vitest_1.vi.fn(); mockClose = vitest_1.vi.fn(); mockReadlineInterface = { question: mockQuestion, close: mockClose, }; vitest_1.vi.mocked(readline.createInterface).mockReturnValue(mockReadlineInterface); }); (0, vitest_1.it)('should handle single database configuration', async () => { mockQuestion .mockImplementationOnce((query, callback) => { callback('1'); }) .mockImplementationOnce((query, callback) => { callback('my-primary-db'); }) .mockImplementationOnce((query, callback) => { callback('/path/to/primary/schema'); }); vitest_1.vi.mocked(validation_1.validateDatabaseCount).mockImplementation(() => { }); vitest_1.vi.mocked(validation_1.validateSchemaPath).mockImplementation(() => { }); const result = await (0, configuration_1.getConfiguration)(false); (0, vitest_1.expect)(result).toEqual({ count: '1', primaryDbName: 'my-primary-db', primarySchemaPath: '/path/to/primary/schema', }); (0, vitest_1.expect)(mockQuestion).toHaveBeenCalledTimes(3); (0, vitest_1.expect)(mockClose).toHaveBeenCalled(); }); (0, vitest_1.it)('should handle dual database configuration', async () => { mockQuestion .mockImplementationOnce((query, callback) => { callback('2'); }) .mockImplementationOnce((query, callback) => { callback('my-primary-db'); }) .mockImplementationOnce((query, callback) => { callback('/path/to/primary/schema'); }) .mockImplementationOnce((query, callback) => { callback('my-secondary-db'); }) .mockImplementationOnce((query, callback) => { callback('/path/to/secondary/schema'); }); vitest_1.vi.mocked(validation_1.validateDatabaseCount).mockImplementation(() => { }); vitest_1.vi.mocked(validation_1.validateSchemaPath).mockImplementation(() => { }); const result = await (0, configuration_1.getConfiguration)(false); (0, vitest_1.expect)(result).toEqual({ count: '2', primaryDbName: 'my-primary-db', primarySchemaPath: '/path/to/primary/schema', secondaryDbName: 'my-secondary-db', secondarySchemaPath: '/path/to/secondary/schema', }); (0, vitest_1.expect)(mockQuestion).toHaveBeenCalledTimes(5); (0, vitest_1.expect)(mockClose).toHaveBeenCalled(); }); (0, vitest_1.it)('should use default values for empty database names', async () => { mockQuestion .mockImplementationOnce((query, callback) => { callback('2'); }) .mockImplementationOnce((query, callback) => { callback(''); // Empty primary db name }) .mockImplementationOnce((query, callback) => { callback('/path/to/primary/schema'); }) .mockImplementationOnce((query, callback) => { callback(''); // Empty secondary db name }) .mockImplementationOnce((query, callback) => { callback('/path/to/secondary/schema'); }); vitest_1.vi.mocked(validation_1.validateDatabaseCount).mockImplementation(() => { }); vitest_1.vi.mocked(validation_1.validateSchemaPath).mockImplementation(() => { }); const result = await (0, configuration_1.getConfiguration)(false); (0, vitest_1.expect)(result.primaryDbName).toBe(constants_1.DEFAULTS.PRIMARY_DB_NAME); (0, vitest_1.expect)(result.secondaryDbName).toBe(constants_1.DEFAULTS.SECONDARY_DB_NAME); }); (0, vitest_1.it)('should throw ValidationError for invalid database count', async () => { mockQuestion.mockImplementationOnce((query, callback) => { callback('3'); }); vitest_1.vi.mocked(validation_1.validateDatabaseCount).mockImplementation(() => { throw new errors_1.ValidationError('Invalid count', 'dbCount'); }); await (0, vitest_1.expect)((0, configuration_1.getConfiguration)(false)).rejects.toThrow(errors_1.ValidationError); (0, vitest_1.expect)(mockClose).toHaveBeenCalled(); }, 10000); (0, vitest_1.it)('should re-throw non-ValidationError exceptions', async () => { mockQuestion .mockImplementationOnce((query, callback) => { callback('1'); }) .mockImplementationOnce((query, callback) => { callback('my-db'); }) .mockImplementationOnce((query, callback) => { callback('/some/path'); }); vitest_1.vi.mocked(validation_1.validateDatabaseCount).mockImplementation(() => { }); vitest_1.vi.mocked(validation_1.validateSchemaPath).mockImplementation(() => { throw new Error('Unexpected error'); }); await (0, vitest_1.expect)((0, configuration_1.getConfiguration)(false)).rejects.toThrow('Unexpected error'); (0, vitest_1.expect)(mockClose).toHaveBeenCalled(); }); (0, vitest_1.it)('should sanitize all user inputs', async () => { mockQuestion .mockImplementationOnce((query, callback) => { callback(' 1 '); }) .mockImplementationOnce((query, callback) => { callback(' my-db '); }) .mockImplementationOnce((query, callback) => { callback(' /path/to/schema '); }); vitest_1.vi.mocked(validation_1.validateDatabaseCount).mockImplementation(() => { }); vitest_1.vi.mocked(validation_1.validateSchemaPath).mockImplementation(() => { }); vitest_1.vi.mocked(validation_1.sanitizeInput).mockImplementation((input) => input.trim()); await (0, configuration_1.getConfiguration)(false); (0, vitest_1.expect)(validation_1.sanitizeInput).toHaveBeenCalledWith(' 1 '); (0, vitest_1.expect)(validation_1.sanitizeInput).toHaveBeenCalledWith(' my-db '); (0, vitest_1.expect)(validation_1.sanitizeInput).toHaveBeenCalledWith(' /path/to/schema '); }); (0, vitest_1.it)('should always close readline interface even on error', async () => { mockQuestion.mockImplementationOnce((query, callback) => { callback('1'); }); vitest_1.vi.mocked(validation_1.validateDatabaseCount).mockImplementation(() => { throw new Error('Validation failed'); }); await (0, vitest_1.expect)((0, configuration_1.getConfiguration)(false)).rejects.toThrow(); (0, vitest_1.expect)(mockClose).toHaveBeenCalled(); }); }); (0, vitest_1.describe)('generateEnvironmentContent', () => { (0, vitest_1.it)('should generate environment content for single database configuration', () => { const config = { count: '1', primaryDbName: 'test-primary', primarySchemaPath: '/path/to/primary/schema', }; const result = (0, configuration_1.generateEnvironmentContent)(config); (0, vitest_1.expect)(result).toContain('DB_COUNT=1'); (0, vitest_1.expect)(result).toContain('PRIMARY_DB_ID=test-primary'); (0, vitest_1.expect)(result).toContain('PRIMARY_DATABASE_ID=test-primary'); (0, vitest_1.expect)(result).toContain('PRIMARY_DB_SCHEMA_PATH=/path/to/primary/schema'); (0, vitest_1.expect)(result).toContain('PRIMARY_SCHEMA_PATH=/path/to/primary/schema'); // Should not contain secondary database configuration (0, vitest_1.expect)(result).not.toContain('SECONDARY_DB_ID'); (0, vitest_1.expect)(result).not.toContain('SECONDARY_DATABASE_ID'); (0, vitest_1.expect)(result).not.toContain('SECONDARY_DB_SCHEMA_PATH'); (0, vitest_1.expect)(result).not.toContain('SECONDARY_SCHEMA_PATH'); // Should contain default project settings (0, vitest_1.expect)(result).toContain(`PROJECT_ID=${constants_1.DEFAULTS.PROJECT_ID}`); (0, vitest_1.expect)(result).toContain(`INSTANCE_ID=${constants_1.DEFAULTS.INSTANCE_ID}`); // Should contain default Docker settings (0, vitest_1.expect)(result).toContain(`DOCKER_IMAGE=${constants_1.DEFAULTS.DOCKER_IMAGE}`); (0, vitest_1.expect)(result).toContain(`DOCKER_CONTAINER_NAME=${constants_1.DEFAULTS.CONTAINER_NAME}`); (0, vitest_1.expect)(result).toContain(`DOCKER_SPANNER_PORT=${constants_1.DEFAULTS.SPANNER_PORT}`); (0, vitest_1.expect)(result).toContain(`DOCKER_ADMIN_PORT=${constants_1.DEFAULTS.ADMIN_PORT}`); (0, vitest_1.expect)(result).toContain(`DOCKER_STARTUP_WAIT=${constants_1.DEFAULTS.STARTUP_WAIT}`); }); (0, vitest_1.it)('should generate environment content for dual database configuration', () => { const config = { count: '2', primaryDbName: 'test-primary', primarySchemaPath: '/path/to/primary/schema', secondaryDbName: 'test-secondary', secondarySchemaPath: '/path/to/secondary/schema', }; const result = (0, configuration_1.generateEnvironmentContent)(config); (0, vitest_1.expect)(result).toContain('DB_COUNT=2'); (0, vitest_1.expect)(result).toContain('PRIMARY_DB_ID=test-primary'); (0, vitest_1.expect)(result).toContain('PRIMARY_DATABASE_ID=test-primary'); (0, vitest_1.expect)(result).toContain('PRIMARY_DB_SCHEMA_PATH=/path/to/primary/schema'); (0, vitest_1.expect)(result).toContain('PRIMARY_SCHEMA_PATH=/path/to/primary/schema'); // Should contain secondary database configuration (0, vitest_1.expect)(result).toContain('SECONDARY_DB_ID=test-secondary'); (0, vitest_1.expect)(result).toContain('SECONDARY_DATABASE_ID=test-secondary'); (0, vitest_1.expect)(result).toContain('SECONDARY_DB_SCHEMA_PATH=/path/to/secondary/schema'); (0, vitest_1.expect)(result).toContain('SECONDARY_SCHEMA_PATH=/path/to/secondary/schema'); // Should contain default project settings (0, vitest_1.expect)(result).toContain(`PROJECT_ID=${constants_1.DEFAULTS.PROJECT_ID}`); (0, vitest_1.expect)(result).toContain(`INSTANCE_ID=${constants_1.DEFAULTS.INSTANCE_ID}`); // Should contain default Docker settings (0, vitest_1.expect)(result).toContain(`DOCKER_IMAGE=${constants_1.DEFAULTS.DOCKER_IMAGE}`); (0, vitest_1.expect)(result).toContain(`DOCKER_CONTAINER_NAME=${constants_1.DEFAULTS.CONTAINER_NAME}`); (0, vitest_1.expect)(result).toContain(`DOCKER_SPANNER_PORT=${constants_1.DEFAULTS.SPANNER_PORT}`); (0, vitest_1.expect)(result).toContain(`DOCKER_ADMIN_PORT=${constants_1.DEFAULTS.ADMIN_PORT}`); (0, vitest_1.expect)(result).toContain(`DOCKER_STARTUP_WAIT=${constants_1.DEFAULTS.STARTUP_WAIT}`); }); (0, vitest_1.it)('should not include secondary database configuration when count is 2 but secondary values are missing', () => { const config = { count: '2', primaryDbName: 'test-primary', primarySchemaPath: '/path/to/primary/schema', // Missing secondaryDbName and secondarySchemaPath }; const result = (0, configuration_1.generateEnvironmentContent)(config); (0, vitest_1.expect)(result).toContain('DB_COUNT=2'); (0, vitest_1.expect)(result).toContain('PRIMARY_DB_ID=test-primary'); // Should not contain secondary database configuration (0, vitest_1.expect)(result).not.toContain('SECONDARY_DB_ID'); (0, vitest_1.expect)(result).not.toContain('SECONDARY_DATABASE_ID'); (0, vitest_1.expect)(result).not.toContain('SECONDARY_DB_SCHEMA_PATH'); (0, vitest_1.expect)(result).not.toContain('SECONDARY_SCHEMA_PATH'); }); (0, vitest_1.it)('should not include secondary database configuration when count is 2 but secondaryDbName is missing', () => { const config = { count: '2', primaryDbName: 'test-primary', primarySchemaPath: '/path/to/primary/schema', secondarySchemaPath: '/path/to/secondary/schema', // Missing secondaryDbName }; const result = (0, configuration_1.generateEnvironmentContent)(config); (0, vitest_1.expect)(result).toContain('DB_COUNT=2'); (0, vitest_1.expect)(result).not.toContain('SECONDARY_DB_ID'); (0, vitest_1.expect)(result).not.toContain('SECONDARY_DATABASE_ID'); (0, vitest_1.expect)(result).not.toContain('SECONDARY_DB_SCHEMA_PATH'); (0, vitest_1.expect)(result).not.toContain('SECONDARY_SCHEMA_PATH'); }); (0, vitest_1.it)('should not include secondary database configuration when count is 2 but secondarySchemaPath is missing', () => { const config = { count: '2', primaryDbName: 'test-primary', primarySchemaPath: '/path/to/primary/schema', secondaryDbName: 'test-secondary', // Missing secondarySchemaPath }; const result = (0, configuration_1.generateEnvironmentContent)(config); (0, vitest_1.expect)(result).toContain('DB_COUNT=2'); (0, vitest_1.expect)(result).not.toContain('SECONDARY_DB_ID'); (0, vitest_1.expect)(result).not.toContain('SECONDARY_DATABASE_ID'); (0, vitest_1.expect)(result).not.toContain('SECONDARY_DB_SCHEMA_PATH'); (0, vitest_1.expect)(result).not.toContain('SECONDARY_SCHEMA_PATH'); }); (0, vitest_1.it)('should include header comments', () => { const config = { count: '1', primaryDbName: 'test-db', primarySchemaPath: '/path/to/schema', }; const result = (0, configuration_1.generateEnvironmentContent)(config); (0, vitest_1.expect)(result).toContain('# ================================================'); (0, vitest_1.expect)(result).toContain('# Spanner E2E Testing Framework Configuration'); (0, vitest_1.expect)(result).toContain('# Copy this file to .env and adjust the settings'); (0, vitest_1.expect)(result).toContain('# ================================================'); (0, vitest_1.expect)(result).toContain('# 🔧 Database Settings'); (0, vitest_1.expect)(result).toContain('# 📊 Project Settings (usually no need to change)'); (0, vitest_1.expect)(result).toContain('# 🐳 Docker Settings (usually no need to change)'); }); (0, vitest_1.it)('should handle special characters in database names and paths', () => { const config = { count: '2', primaryDbName: 'test-db_with-special.chars', primarySchemaPath: '/path/to/schema with spaces', secondaryDbName: 'secondary-db_with-special.chars', secondarySchemaPath: '/path/to/secondary schema with spaces', }; const result = (0, configuration_1.generateEnvironmentContent)(config); (0, vitest_1.expect)(result).toContain('PRIMARY_DB_ID=test-db_with-special.chars'); (0, vitest_1.expect)(result).toContain('PRIMARY_DB_SCHEMA_PATH=/path/to/schema with spaces'); (0, vitest_1.expect)(result).toContain('SECONDARY_DB_ID=secondary-db_with-special.chars'); (0, vitest_1.expect)(result).toContain('SECONDARY_DB_SCHEMA_PATH=/path/to/secondary schema with spaces'); }); (0, vitest_1.it)('should maintain consistent formatting', () => { const config = { count: '1', primaryDbName: 'test-db', primarySchemaPath: '/path/to/schema', }; const result = (0, configuration_1.generateEnvironmentContent)(config); // Check that each section is properly separated const sections = result.split('\n\n'); (0, vitest_1.expect)(sections.length).toBeGreaterThan(1); // Check that variables are properly formatted (KEY=VALUE) const lines = result.split('\n'); const variableLines = lines.filter(line => line.includes('=') && !line.startsWith('#')); variableLines.forEach(line => { (0, vitest_1.expect)(line).toMatch(/^[A-Z_]+=.+$/); }); }); }); (0, vitest_1.describe)('PromptInterface', () => { (0, vitest_1.it)('should create readline interface on construction', async () => { const mockReadlineInterface = { question: vitest_1.vi.fn((query, callback) => { callback('1'); }), close: vitest_1.vi.fn(), }; vitest_1.vi.mocked(readline.createInterface).mockReturnValue(mockReadlineInterface); vitest_1.vi.mocked(validation_1.validateDatabaseCount).mockImplementation(() => { }); vitest_1.vi.mocked(validation_1.validateSchemaPath).mockImplementation(() => { }); // Trigger the creation of PromptInterface through interactive configuration await (0, configuration_1.getConfiguration)(false); (0, vitest_1.expect)(readline.createInterface).toHaveBeenCalledWith({ input: process.stdin, output: process.stdout, }); }); (0, vitest_1.it)('should handle question method correctly', async () => { const mockQuestion = vitest_1.vi.fn(); const mockClose = vitest_1.vi.fn(); const mockReadlineInterface = { question: mockQuestion, close: mockClose, }; vitest_1.vi.mocked(readline.createInterface).mockReturnValue(mockReadlineInterface); mockQuestion.mockImplementationOnce((query, callback) => { (0, vitest_1.expect)(query).toBe('Select number of databases (1 or 2): '); callback('1'); }); mockQuestion.mockImplementationOnce((query, callback) => { (0, vitest_1.expect)(query).toBe('Primary DB name (default: primary-db): '); callback('test-db'); }); mockQuestion.mockImplementationOnce((query, callback) => { (0, vitest_1.expect)(query).toBe('Primary DB schema path: '); callback('/path/to/schema'); }); vitest_1.vi.mocked(validation_1.validateDatabaseCount).mockImplementation(() => { }); vitest_1.vi.mocked(validation_1.validateSchemaPath).mockImplementation(() => { }); await (0, configuration_1.getConfiguration)(false); (0, vitest_1.expect)(mockQuestion).toHaveBeenCalledTimes(3); (0, vitest_1.expect)(mockClose).toHaveBeenCalled(); }); (0, vitest_1.it)('should close readline interface properly', async () => { const mockQuestion = vitest_1.vi.fn(); const mockClose = vitest_1.vi.fn(); const mockReadlineInterface = { question: mockQuestion, close: mockClose, }; vitest_1.vi.mocked(readline.createInterface).mockReturnValue(mockReadlineInterface); mockQuestion.mockImplementationOnce((query, callback) => { callback('1'); }); vitest_1.vi.mocked(validation_1.validateDatabaseCount).mockImplementation(() => { throw new Error('Validation error'); }); await (0, vitest_1.expect)((0, configuration_1.getConfiguration)(false)).rejects.toThrow(); (0, vitest_1.expect)(mockClose).toHaveBeenCalled(); }); }); (0, vitest_1.describe)('Edge Cases and Error Handling', () => { (0, vitest_1.it)('should handle empty string environment variables', async () => { process.env[constants_1.ENV_VARS.DB_COUNT] = ''; process.env[constants_1.ENV_VARS.PRIMARY_DB_NAME] = ''; process.env[constants_1.ENV_VARS.PRIMARY_SCHEMA_PATH] = ''; vitest_1.vi.mocked(validation_1.validateDatabaseCount).mockImplementation(() => { }); const result = await (0, configuration_1.getConfiguration)(true); (0, vitest_1.expect)(result.count).toBe(constants_1.DEFAULTS.DB_COUNT); (0, vitest_1.expect)(result.primaryDbName).toBe(constants_1.DEFAULTS.PRIMARY_DB_NAME); (0, vitest_1.expect)(result.primarySchemaPath).toBe(constants_1.DEFAULTS.PRIMARY_SCHEMA_PATH); }); (0, vitest_1.it)('should handle undefined environment variables gracefully', async () => { // Ensure all environment variables are undefined Object.values(constants_1.ENV_VARS).forEach(envVar => { delete process.env[envVar]; }); vitest_1.vi.mocked(validation_1.validateDatabaseCount).mockImplementation(() => { }); const result = await (0, configuration_1.getConfiguration)(true); (0, vitest_1.expect)(result.count).toBe(constants_1.DEFAULTS.DB_COUNT); (0, vitest_1.expect)(result.primaryDbName).toBe(constants_1.DEFAULTS.PRIMARY_DB_NAME); (0, vitest_1.expect)(result.primarySchemaPath).toBe(constants_1.DEFAULTS.PRIMARY_SCHEMA_PATH); }); (0, vitest_1.it)('should preserve original process.env after configuration', async () => { process.env[constants_1.ENV_VARS.DB_COUNT] = '1'; process.env[constants_1.ENV_VARS.PRIMARY_DB_NAME] = 'test-db'; vitest_1.vi.mocked(validation_1.validateDatabaseCount).mockImplementation(() => { }); await (0, configuration_1.getConfiguration)(true); (0, vitest_1.expect)(process.env[constants_1.ENV_VARS.DB_COUNT]).toBe('1'); (0, vitest_1.expect)(process.env[constants_1.ENV_VARS.PRIMARY_DB_NAME]).toBe('test-db'); }); }); }); //# sourceMappingURL=configuration.test.js.map