core.test.jsā¢11.8 kB
/**
* Core Methods Unit Tests
* Comprehensive test suite for all core functionality
*/
import { jest } from '@jest/globals';
import { AutomationScriptGenerator } from '../index.js';
import fs from 'fs-extra';
import path from 'path';
describe('AutomationScriptGenerator', () => {
let generator;
let testDir;
beforeEach(async () => {
generator = new AutomationScriptGenerator();
testDir = path.join(process.cwd(), 'test-temp');
await fs.ensureDir(testDir);
});
afterEach(async () => {
if (await fs.pathExists(testDir)) {
await fs.remove(testDir);
}
});
describe('File Pattern Matching', () => {
beforeEach(async () => {
// Create test files
await fs.ensureDir(path.join(testDir, 'features'));
await fs.ensureDir(path.join(testDir, 'step-definitions'));
await fs.ensureDir(path.join(testDir, 'pageobjects'));
await fs.ensureDir(path.join(testDir, 'utils'));
await fs.writeFile(path.join(testDir, 'features', 'login.feature'), 'Feature: Login');
await fs.writeFile(path.join(testDir, 'step-definitions', 'login.steps.js'), 'export const step = () => {};');
await fs.writeFile(path.join(testDir, 'pageobjects', 'login.page.js'), 'export class LoginPage {}');
await fs.writeFile(path.join(testDir, 'utils', 'helpers.js'), 'export const helper = () => {};');
});
test('should find feature files', async () => {
const files = await generator.findFilesByPattern(testDir, 'features');
expect(files).toHaveLength(1);
expect(files[0]).toMatch(/login\.feature$/);
});
test('should find step files', async () => {
const files = await generator.findFilesByPattern(testDir, 'steps');
expect(files).toHaveLength(1);
expect(files[0]).toMatch(/login\.steps\.js$/);
});
test('should find page files', async () => {
const files = await generator.findFilesByPattern(testDir, 'pages');
expect(files).toHaveLength(1);
expect(files[0]).toMatch(/login\.page\.js$/);
});
test('should find utility files', async () => {
const files = await generator.findFilesByPattern(testDir, 'utils');
expect(files).toHaveLength(1);
expect(files[0]).toMatch(/helpers\.js$/);
});
test('should handle non-existent directories gracefully', async () => {
const files = await generator.findFilesByPattern('/non-existent', 'features');
expect(files).toEqual([]);
});
});
describe('Pattern Extraction', () => {
test('should extract feature patterns correctly', () => {
const content = `
Feature: User Login
@login @smoke
Scenario: Successful login
Given I am on the login page
When I enter valid credentials
Then I should be logged in
`;
const patterns = generator.extractFeaturePatterns(content);
expect(patterns.scenarios).toContain('Successful login');
expect(patterns.tags).toContain('@login');
expect(patterns.tags).toContain('@smoke');
expect(patterns.steps).toContain('Given I am on the login page');
});
test('should extract step patterns correctly', () => {
const content = `
import { Given, When, Then } from '@wdio/cucumber-framework';
Given('I am on the login page', async () => {
await browser.url('/login');
});
function loginUser() {
return 'logged in';
}
`;
const patterns = generator.extractStepPatterns(content);
expect(patterns.stepDefinitions).toContain('Given');
expect(patterns.exports).toContain('loginUser');
});
test('should extract page object patterns correctly', () => {
const content = `
class LoginPage {
get usernameInput() { return $('#username'); }
get passwordInput() { return $('#password'); }
async login(username, password) {
await this.usernameInput.setValue(username);
}
}
`;
const patterns = generator.extractPagePatterns(content);
expect(patterns.className).toBe('LoginPage');
expect(patterns.methods).toContain('login');
expect(patterns.selectors).toHaveProperty('#username');
});
});
describe('Utility Function Extraction', () => {
test('should extract function declarations', () => {
const content = `
export function helper() {}
async function asyncHelper() {}
const arrowFunc = () => {};
const asyncArrow = async () => {};
`;
const functions = generator.extractUtilFunctions(content);
expect(functions).toHaveLength(4);
expect(functions.find(f => f.name === 'helper')).toBeDefined();
expect(functions.find(f => f.name === 'asyncHelper')).toMatchObject({
name: 'asyncHelper',
isAsync: true
});
});
test('should extract exported functions', () => {
const content = `
export { func1, func2 as renamed };
export default defaultFunc;
export const directExport = () => {};
`;
const exports = generator.extractExportedFunctions(content);
expect(exports).toContain('func1');
expect(exports).toContain('func2');
expect(exports).toContain('defaultFunc');
expect(exports).toContain('directExport');
});
});
describe('Naming Convention Detection', () => {
test('should detect kebab-case', () => {
const pattern = generator.detectNamingPattern(
['my-file', 'another-file', 'test-case'],
['kebab-case', 'camelCase']
);
expect(pattern).toBe('kebab-case');
});
test('should detect camelCase', () => {
const pattern = generator.detectNamingPattern(
['myFile', 'anotherFile', 'testCase'],
['kebab-case', 'camelCase']
);
expect(pattern).toBe('camelCase');
});
test('should detect PascalCase', () => {
const pattern = generator.detectNamingPattern(
['MyClass', 'AnotherClass', 'TestCase'],
['PascalCase', 'camelCase']
);
expect(pattern).toBe('PascalCase');
});
});
describe('Smart File Analysis', () => {
beforeEach(async () => {
await fs.ensureDir(path.join(testDir, 'features'));
await fs.writeFile(path.join(testDir, 'features', 'existing-login.feature'), `
Feature: User Authentication
Scenario: Login with credentials
Given I am on the login page
`);
});
test('should find similar features', async () => {
const similar = await generator.findSimilarFeatures(
testDir,
'User Login Process',
'Given I am on the login page'
);
expect(similar).toHaveLength(1);
expect(similar[0].similarity).toBeGreaterThan(0.6);
});
test('should calculate feature similarity correctly', () => {
const similarity = generator.calculateFeatureSimilarity(
'User Login',
'Given I am on the login page',
'Feature: User Authentication\nGiven I am on the login page'
);
expect(similarity).toBeGreaterThan(0.5);
});
});
describe('Step Implementation Generation', () => {
test('should generate Given step implementation', () => {
const implementation = generator.generateStepImplementation(
'Given I am on the login page',
'I am on the login page',
'Given'
);
expect(implementation).toContain('browser.url');
expect(implementation).toContain('waitUntil');
});
test('should generate When step implementation', () => {
const selectors = { usernameInput: '#username' };
const implementation = generator.generateStepImplementation(
'When I enter username',
'I enter username',
'When',
selectors
);
expect(implementation).toContain('setValue');
expect(implementation).toContain('#username');
});
test('should generate Then step implementation', () => {
const implementation = generator.generateStepImplementation(
'Then I should see welcome message',
'I should see welcome message',
'Then'
);
expect(implementation).toContain('expect');
expect(implementation).toContain('toBeDisplayed');
});
});
describe('Code Review', () => {
test('should identify missing documentation', async () => {
const content = `
function undocumentedFunction() {
return 'test';
}
`;
const review = await generator.performCodeReview(
content,
['docs'],
null,
'test.js'
);
expect(review.issues.length).toBeGreaterThan(0);
expect(review.issues[0]).toMatch(/JSDoc/);
});
test('should identify POM violations', async () => {
const content = `
const selector = '#element';
function clickElement() {
$(selector).click();
}
`;
const review = await generator.performCodeReview(
content,
['pom'],
null,
'page.js'
);
expect(review.issues.length).toBeGreaterThan(0);
expect(review.issues[0]).toMatch(/class/);
});
});
describe('Configuration Management', () => {
test('should validate schema correctly', () => {
const validArgs = {
scenario_title: 'Test Scenario',
gherkin_syntax: 'Given test step',
selectors: { button: '#btn' },
output_directory: './output'
};
expect(() => {
generator.validateArgs('process_test_scenario', validArgs);
}).not.toThrow();
});
test('should reject invalid schema', () => {
const invalidArgs = {
scenario_title: '', // Empty title should fail
selectors: { button: '#btn' },
output_directory: './output'
};
expect(() => {
generator.validateArgs('process_test_scenario', invalidArgs);
}).toThrow();
});
});
describe('Error Handling', () => {
test('should handle file read errors gracefully', async () => {
const patterns = await generator.scanForPatterns('/non-existent-path', 'features');
expect(patterns).toEqual([]);
});
test('should handle invalid content gracefully', () => {
const patterns = generator.extractFeaturePatterns('invalid content');
expect(patterns.scenarios).toEqual([]);
expect(patterns.tags).toEqual([]);
expect(patterns.steps).toEqual([]);
});
test('should handle missing selectors in step generation', () => {
const implementation = generator.generateStepImplementation(
'When I click unknown element',
'I click unknown element',
'When',
{}
);
expect(implementation).toContain('$(".element")'); // Fallback selector
});
});
});