204 lines
6.2 KiB
JavaScript
204 lines
6.2 KiB
JavaScript
/**
|
|
* Question Skipping Unit Tests
|
|
* Tests for skipping questions during update installations
|
|
* File: test/unit/prompt-skipping.test.js
|
|
*/
|
|
|
|
const { PromptHandler } = require('../../tools/cli/lib/ui');
|
|
const { ManifestConfigLoader } = require('../../tools/cli/lib/config-loader');
|
|
|
|
describe('Question Skipping', () => {
|
|
let promptHandler;
|
|
let configLoader;
|
|
|
|
beforeEach(() => {
|
|
promptHandler = new PromptHandler();
|
|
configLoader = new ManifestConfigLoader();
|
|
});
|
|
|
|
describe('skipQuestion', () => {
|
|
// Test 4.1: Skip Question When Update with Config
|
|
it('should skip question and return config value when isUpdate=true and config exists', async () => {
|
|
const mockConfig = {
|
|
prd_sharding: true,
|
|
getConfig: jest.fn(() => true),
|
|
hasConfig: jest.fn(() => true),
|
|
};
|
|
|
|
const result = await promptHandler.askPrdSharding({ isUpdate: true, config: mockConfig });
|
|
|
|
expect(result).toBe(true);
|
|
expect(mockConfig.hasConfig).toHaveBeenCalledWith('prd_sharding');
|
|
});
|
|
|
|
// Test 4.2: Ask Question When Fresh Install
|
|
it('should ask question on fresh install (isUpdate=false)', async () => {
|
|
const mockInquirer = jest.spyOn(promptHandler, 'prompt').mockResolvedValueOnce({
|
|
prd_sharding: true,
|
|
});
|
|
|
|
const result = await promptHandler.askPrdSharding({
|
|
isUpdate: false,
|
|
config: {},
|
|
});
|
|
|
|
expect(mockInquirer).toHaveBeenCalled();
|
|
expect(result).toBe(true);
|
|
|
|
mockInquirer.mockRestore();
|
|
});
|
|
|
|
// Test 4.3: Ask Question When Config Missing
|
|
it('should ask question if config missing on update', async () => {
|
|
const mockConfig = {
|
|
hasConfig: jest.fn(() => false),
|
|
};
|
|
|
|
const mockInquirer = jest.spyOn(promptHandler, 'prompt').mockResolvedValueOnce({
|
|
architecture_sharding: false,
|
|
});
|
|
|
|
const result = await promptHandler.askArchitectureSharding({ isUpdate: true, config: mockConfig });
|
|
|
|
expect(mockInquirer).toHaveBeenCalled();
|
|
expect(result).toBe(false);
|
|
|
|
mockInquirer.mockRestore();
|
|
});
|
|
|
|
// Test 4.4: Log Skipped Questions
|
|
it('should log when question is skipped', async () => {
|
|
const consoleLogSpy = jest.spyOn(console, 'log').mockImplementation();
|
|
|
|
const mockConfig = {
|
|
getConfig: jest.fn(() => 'full'),
|
|
hasConfig: jest.fn(() => true),
|
|
};
|
|
|
|
await promptHandler.askInstallType({ isUpdate: true, config: mockConfig });
|
|
|
|
expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('Skipping question'));
|
|
|
|
consoleLogSpy.mockRestore();
|
|
});
|
|
|
|
// Test 4.5: Multiple Questions Skipped
|
|
it('should skip all applicable questions on update', async () => {
|
|
const mockConfig = {
|
|
getConfig: jest.fn((key, fallback) => {
|
|
const values = {
|
|
prd_sharding: true,
|
|
architecture_sharding: false,
|
|
doc_organization: 'by-module',
|
|
install_type: 'full',
|
|
};
|
|
return values[key] || fallback;
|
|
}),
|
|
hasConfig: jest.fn(() => true),
|
|
};
|
|
|
|
const results = await Promise.all([
|
|
promptHandler.askPrdSharding({ isUpdate: true, config: mockConfig }),
|
|
promptHandler.askArchitectureSharding({ isUpdate: true, config: mockConfig }),
|
|
promptHandler.askDocOrganization({ isUpdate: true, config: mockConfig }),
|
|
promptHandler.askInstallType({ isUpdate: true, config: mockConfig }),
|
|
]);
|
|
|
|
expect(results).toEqual([true, false, 'by-module', 'full']);
|
|
// Each should have checked hasConfig
|
|
expect(mockConfig.hasConfig.mock.calls.length).toBe(4);
|
|
});
|
|
});
|
|
|
|
describe('prompt behavior during updates', () => {
|
|
it('should not display UI when skipping question', async () => {
|
|
const mockConfig = {
|
|
getConfig: jest.fn(() => 'value'),
|
|
hasConfig: jest.fn(() => true),
|
|
};
|
|
|
|
const consoleLogSpy = jest.spyOn(console, 'log').mockImplementation();
|
|
|
|
await promptHandler.askConfigQuestion('test_key', {
|
|
isUpdate: true,
|
|
config: mockConfig,
|
|
});
|
|
|
|
// Should log skip message but not the question itself
|
|
expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('Skipping'));
|
|
|
|
consoleLogSpy.mockRestore();
|
|
});
|
|
|
|
it('should handle null/undefined defaults gracefully', async () => {
|
|
const mockConfig = {
|
|
getConfig: jest.fn(() => {}),
|
|
hasConfig: jest.fn(() => true),
|
|
};
|
|
|
|
const mockInquirer = jest.spyOn(promptHandler, 'prompt').mockResolvedValueOnce({
|
|
answer: 'user-provided',
|
|
});
|
|
|
|
const result = await promptHandler.askConfigQuestion('missing_key', {
|
|
isUpdate: true,
|
|
config: mockConfig,
|
|
});
|
|
|
|
expect(result).toBe('user-provided');
|
|
|
|
mockInquirer.mockRestore();
|
|
});
|
|
});
|
|
|
|
describe('isUpdate flag propagation', () => {
|
|
it('should pass isUpdate flag through prompt pipeline', () => {
|
|
const flags = {
|
|
isUpdate: true,
|
|
config: {},
|
|
};
|
|
|
|
expect(flags.isUpdate).toBe(true);
|
|
expect(flags.config).toBeDefined();
|
|
});
|
|
|
|
it('should distinguish fresh install from update', () => {
|
|
const freshInstallFlags = { isUpdate: false };
|
|
const updateFlags = { isUpdate: true };
|
|
|
|
expect(freshInstallFlags.isUpdate).toBe(false);
|
|
expect(updateFlags.isUpdate).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('backward compatibility', () => {
|
|
it('should handle missing isUpdate flag (default to fresh install)', async () => {
|
|
const mockInquirer = jest.spyOn(promptHandler, 'prompt').mockResolvedValueOnce({
|
|
answer: 'default-behavior',
|
|
});
|
|
|
|
// When isUpdate is not provided, should ask question
|
|
const result = await promptHandler.askConfigQuestion('key', {});
|
|
|
|
expect(mockInquirer).toHaveBeenCalled();
|
|
|
|
mockInquirer.mockRestore();
|
|
});
|
|
|
|
it('should handle missing config object', async () => {
|
|
const mockInquirer = jest.spyOn(promptHandler, 'prompt').mockResolvedValueOnce({
|
|
answer: 'fallback',
|
|
});
|
|
|
|
const result = await promptHandler.askConfigQuestion('key', {
|
|
isUpdate: true,
|
|
// config intentionally missing
|
|
});
|
|
|
|
expect(mockInquirer).toHaveBeenCalled();
|
|
|
|
mockInquirer.mockRestore();
|
|
});
|
|
});
|
|
});
|