Skip to content
Draft
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"presets": ["@babel/preset-env"]
}
92 changes: 92 additions & 0 deletions __tests__/createController.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import chalk from 'chalk';
import { Command } from 'commander';
import fs from 'fs-extra';
import path from 'path';
import createController from '../commands/createController';

jest.mock('fs-extra');

Check failure on line 7 in __tests__/createController.test.js

View workflow job for this annotation

GitHub Actions / ESLint & Prettier

'jest' is not defined
jest.mock('chalk', () => ({

Check failure on line 8 in __tests__/createController.test.js

View workflow job for this annotation

GitHub Actions / ESLint & Prettier

'jest' is not defined
green: jest.fn((text) => text),

Check failure on line 9 in __tests__/createController.test.js

View workflow job for this annotation

GitHub Actions / ESLint & Prettier

'jest' is not defined
red: jest.fn((text) => text),

Check failure on line 10 in __tests__/createController.test.js

View workflow job for this annotation

GitHub Actions / ESLint & Prettier

'jest' is not defined
cyan: jest.fn((text) => text),

Check failure on line 11 in __tests__/createController.test.js

View workflow job for this annotation

GitHub Actions / ESLint & Prettier

'jest' is not defined
white: jest.fn((text) => text),

Check failure on line 12 in __tests__/createController.test.js

View workflow job for this annotation

GitHub Actions / ESLint & Prettier

'jest' is not defined
}));

describe('add-controller command', () => {

Check failure on line 15 in __tests__/createController.test.js

View workflow job for this annotation

GitHub Actions / ESLint & Prettier

'describe' is not defined
let consoleLogSpy;
let consoleErrorSpy;
let program;
const testDir = path.join(__dirname, '../backend/controllers');
const fileName = 'Test';
const controllerFilePath = path.join(testDir, `${fileName.toLowerCase()}.js`);

beforeAll(() => {

Check failure on line 23 in __tests__/createController.test.js

View workflow job for this annotation

GitHub Actions / ESLint & Prettier

'beforeAll' is not defined
// Ensure test directories are created before tests run
fs.ensureDirSync(testDir);
});

beforeEach(() => {

Check failure on line 28 in __tests__/createController.test.js

View workflow job for this annotation

GitHub Actions / ESLint & Prettier

'beforeEach' is not defined
consoleLogSpy = jest.spyOn(console, 'log').mockImplementation(() => {});

Check failure on line 29 in __tests__/createController.test.js

View workflow job for this annotation

GitHub Actions / ESLint & Prettier

'jest' is not defined
consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
fs.existsSync.mockReset();
fs.mkdirSync.mockReset();
fs.writeFileSync.mockReset();

program = new Command();
createController(program);
});

afterEach(() => {
jest.clearAllMocks();
});

afterAll(() => {
// Clean up test directories after tests complete
fs.removeSync(testDir);
});

it('should create a controller file in controllers directory if it does not exist', () => {
fs.existsSync.mockReturnValue(false);
fs.mkdirSync.mockImplementation(() => {});
fs.writeFileSync.mockImplementation(() => {});

program.parse(['add-controller', fileName], { from: 'user' });

// Check if the directory was created
expect(fs.mkdirSync).toHaveBeenCalledWith(
expect.stringContaining('controllers'),
{ recursive: true }
);

// Check if the controller file was created
expect(fs.writeFileSync).toHaveBeenCalledWith(
expect.stringContaining(controllerFilePath),
expect.any(String)
);

// Verify log output
expect(consoleLogSpy).toHaveBeenCalledWith(
expect.stringContaining('✅ Created controllers directory')
);
expect(consoleLogSpy).toHaveBeenCalledWith(
expect.stringContaining(
`✅ ${fileName} created at controllers/${fileName.toLowerCase()}.js`
)
);
});

it('should log an error if controller file creation fails', () => {
fs.existsSync.mockReturnValue(true);

const errorMessage = 'File system error';
fs.writeFileSync.mockImplementation(() => {
throw new Error(errorMessage);
});

program.parse(['add-controller', fileName], { from: 'user' });

expect(consoleErrorSpy).toHaveBeenCalledWith(
chalk.red(`❌ Failed to write controller file: ${errorMessage}`)
);
});
});
92 changes: 92 additions & 0 deletions __tests__/createRoute.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import chalk from 'chalk';
import { Command } from 'commander';
import fs from 'fs-extra';
import path from 'path';
import createRoute from '../commands/createRoute';

jest.mock('fs-extra');
jest.mock('chalk', () => ({
green: jest.fn((text) => text),
red: jest.fn((text) => text),
cyan: jest.fn((text) => text),
white: jest.fn((text) => text),
}));

describe('add-route command', () => {
let consoleLogSpy;
let consoleErrorSpy;
let program;
const testDir = path.join(__dirname, '../backend/routes');
const fileName = 'Test';
const controllerFilePath = path.join(testDir, `${fileName.toLowerCase()}.js`);

beforeAll(() => {
// Ensure test directories are created before tests run
fs.ensureDirSync(testDir);
});

beforeEach(() => {
consoleLogSpy = jest.spyOn(console, 'log').mockImplementation(() => {});
consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
fs.existsSync.mockReset();
fs.mkdirSync.mockReset();
fs.writeFileSync.mockReset();

program = new Command();
createRoute(program);
});

afterEach(() => {
jest.clearAllMocks();
});

afterAll(() => {
// Clean up test directories after tests complete
fs.removeSync(testDir);
});

it('should create a route file in routes directory if it does not exist', () => {
fs.existsSync.mockReturnValue(false);
fs.mkdirSync.mockImplementation(() => {});
fs.writeFileSync.mockImplementation(() => {});

program.parse(['add-route', fileName], { from: 'user' });

// Check if the directory was created
expect(fs.mkdirSync).toHaveBeenCalledWith(
expect.stringContaining('routes'),
{ recursive: true }
);

// Check if the route file was created
expect(fs.writeFileSync).toHaveBeenCalledWith(
expect.stringContaining(controllerFilePath),
expect.any(String)
);

// Verify log output
expect(consoleLogSpy).toHaveBeenCalledWith(
expect.stringContaining('✅ Created routes directory')
);
expect(consoleLogSpy).toHaveBeenCalledWith(
expect.stringContaining(
`✅ ${fileName} created at routes/${fileName.toLowerCase()}.js`
)
);
});

it('should log an error if route file creation fails', () => {
fs.existsSync.mockReturnValue(true);

const errorMessage = 'File system error';
fs.writeFileSync.mockImplementation(() => {
throw new Error(errorMessage);
});

program.parse(['add-route', fileName], { from: 'user' });

expect(consoleErrorSpy).toHaveBeenCalledWith(
chalk.red(`❌ Failed to write route file: ${errorMessage}`)
);
});
});
92 changes: 92 additions & 0 deletions __tests__/createService.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import chalk from 'chalk';
import { Command } from 'commander';
import fs from 'fs-extra';
import path from 'path';
import createService from '../commands/cerateService';

jest.mock('fs-extra');
jest.mock('chalk', () => ({
green: jest.fn((text) => text),
red: jest.fn((text) => text),
cyan: jest.fn((text) => text),
white: jest.fn((text) => text),
}));

describe('add-service command', () => {
let consoleLogSpy;
let consoleErrorSpy;
let program;
const testDir = path.join(__dirname, '../backend/services');
const fileName = 'Test';
const controllerFilePath = path.join(testDir, `${fileName.toLowerCase()}.js`);

beforeAll(() => {
// Ensure test directories are created before tests run
fs.ensureDirSync(testDir);
});

beforeEach(() => {
consoleLogSpy = jest.spyOn(console, 'log').mockImplementation(() => {});
consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
fs.existsSync.mockReset();
fs.mkdirSync.mockReset();
fs.writeFileSync.mockReset();

program = new Command();
createService(program);
});

afterEach(() => {
jest.clearAllMocks();
});

afterAll(() => {
// Clean up test directories after tests complete
fs.removeSync(testDir);
});

it('should create a service file in services directory if it does not exist', () => {
fs.existsSync.mockReturnValue(false);
fs.mkdirSync.mockImplementation(() => {});
fs.writeFileSync.mockImplementation(() => {});

program.parse(['add-service', fileName], { from: 'user' });

// Check if the directory was created
expect(fs.mkdirSync).toHaveBeenCalledWith(
expect.stringContaining('services'),
{ recursive: true }
);

// Check if the service file was created
expect(fs.writeFileSync).toHaveBeenCalledWith(
expect.stringContaining(controllerFilePath),
expect.any(String)
);

// Verify log output
expect(consoleLogSpy).toHaveBeenCalledWith(
expect.stringContaining('✅ Created services directory')
);
expect(consoleLogSpy).toHaveBeenCalledWith(
expect.stringContaining(
`✅ ${fileName} created at services/${fileName.toLowerCase()}.js`
)
);
});

it('should log an error if service file creation fails', () => {
fs.existsSync.mockReturnValue(true);

const errorMessage = 'File system error';
fs.writeFileSync.mockImplementation(() => {
throw new Error(errorMessage);
});

program.parse(['add-service', fileName], { from: 'user' });

expect(consoleErrorSpy).toHaveBeenCalledWith(
chalk.red(`❌ Failed to write service file: ${errorMessage}`)
);
});
});
76 changes: 76 additions & 0 deletions commands/cerateService.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import chalk from 'chalk';
import fs from 'fs-extra';
import path from 'path';
import { capitalize } from '../utils/capitalize';

export default function createService(program) {
program
.command('add-service <FileName>')
.description('Generate a service')
.action((fileName) => {
const currentDir = process.cwd();
const isInBackend = path.basename(currentDir) === 'backend';

// service dir
const serviceDir = isInBackend
? path.join(currentDir, 'services')
: path.join(currentDir, 'backend', 'services');

// Create the services directory if it doesn't exist
if (!fs.existsSync(serviceDir)) {
try {
fs.mkdirSync(serviceDir, { recursive: true });
console.log(chalk.green('✅ Created services directory'));
} catch (error) {
console.error(
chalk.red(
`❌ Failed to create services directory: ${error.message}`
)
);
return;
}
}

// Service template
const serviceContent = `
// Service for ${capitalize(fileName)}
import ${capitalize(fileName)} from '../models/${capitalize(fileName)}.js';

class ${capitalize(fileName)}Service {
// ${capitalize(fileName)} Services..
}

export default ${capitalize(fileName)}Service;
`;

// Write the service file to the services directory
try {
const serviceFilePath = path.join(
serviceDir,
`${fileName.toLowerCase()}.js`
);
fs.writeFileSync(serviceFilePath, serviceContent);
console.log(
chalk.green(
`✅ ${capitalize(fileName)} created at services/${fileName.toLowerCase()}.js`
)
);
} catch (error) {
console.error(
chalk.red(`❌ Failed to write service file: ${error.message}`)
);
return;
}

// Final success message
console.log(chalk.cyan('\n📝 Next steps:'));
console.log(
chalk.white(
`1. Review your service in services/${fileName.toLowerCase()}.js`
)
);
console.log(
chalk.white('2. Import and use your service in your app as needed')
);
});
}
Loading
Loading