Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add export-template command to cli #10331

Merged
merged 10 commits into from
May 31, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
add tests
  • Loading branch information
markkaylor committed May 31, 2021
commit e652a53d79aefa955c7d43107f6cdee361a01c44
7 changes: 3 additions & 4 deletions packages/strapi/bin/strapi.js
Original file line number Diff line number Diff line change
Expand Up @@ -230,11 230,10 @@ program
.option('-p, --password <password>', 'New password for the user')
.action(getLocalScript('admin-reset'));

// `$ strapi export-template <name>`
// `$ strapi export:template <name>`
program
.command('export-template')
.arguments('<name>')
.command('export:template <directory>')
alexandrebodin marked this conversation as resolved.
Show resolved Hide resolved
.description('Export project as Strapi template')
.action(getLocalScript('exportTemplate'));
.action(getLocalScript('export-template'));

program.parseAsync(process.argv);
92 changes: 92 additions & 0 deletions packages/strapi/lib/commands/__tests__/export-template.test.js
Original file line number Diff line number Diff line change
@@ -0,0 1,92 @@
'use strict';
jest.mock('fs-extra', () => ({
ensureDir: jest.fn(() => Promise.resolve()),
copy: jest.fn(() => Promise.resolve()),
pathExists: jest.fn(() => Promise.resolve()),
}));

const { resolve, join } = require('path');
const fse = require('fs-extra');
const inquirer = require('inquirer');

const exportTemplate = require('../export-template');

describe('export:template command', () => {
beforeEach(() => {
jest.spyOn(console, 'log').mockImplementation(() => {});
jest.clearAllMocks();
});

it('creates a new template directory', async () => {
fse.pathExists.mockReturnValue(false);
const directory = '../test-dir';
const templatePath = resolve(directory);
const contentPath = join(templatePath, 'template');

await exportTemplate(directory);

expect(fse.pathExists).toHaveBeenCalledWith(contentPath);
expect(fse.ensureDir).toHaveBeenCalledWith(contentPath);
});

it.each(['api', 'components', 'config/functions/bootstrap.js', 'data'])(
'copies folder %s',
async item => {
const directory = '../test-dir';
const templatePath = resolve(directory);
const contentPath = join(templatePath, 'template');

await exportTemplate(directory);

expect(fse.copy).toHaveBeenCalledWith(join(process.cwd(), item), join(contentPath, item));
}
);

describe('handles prompt input', () => {
it('updates directory if confirmed', async () => {
fse.pathExists.mockReturnValue(true);
const mockInquiry = jest
.spyOn(inquirer, 'prompt')
.mockImplementationOnce(() => ({ confirm: true }));
const directory = '../test-dir';
const templatePath = resolve(directory);
const contentPath = join(templatePath, 'template');

await exportTemplate(directory);

expect(fse.pathExists).toHaveBeenCalledWith(contentPath);
expect(mockInquiry).toHaveBeenLastCalledWith(
expect.objectContaining({ message: expect.any(String), name: 'confirm', type: 'confirm' })
);
expect(fse.ensureDir).toHaveBeenCalled();
expect(fse.copy).toHaveBeenCalled();
});

it('exits if not confirmed', async () => {
fse.pathExists.mockReturnValue(true);
jest.spyOn(console, 'error').mockImplementation(() => {});
const mockInquiry = jest
.spyOn(inquirer, 'prompt')
.mockImplementationOnce(() => ({ confirm: false }));

const mockExit = jest.spyOn(process, 'exit').mockImplementation(() => {
throw new Error('exit');
});
const directory = '../test-dir';
const templatePath = resolve(directory);
const contentPath = join(templatePath, 'template');

await exportTemplate(directory).catch(err => {
expect(err).toEqual(new Error('exit'));
});

expect(fse.pathExists).toHaveBeenCalledWith(contentPath);
expect(mockInquiry).toHaveBeenLastCalledWith(
expect.objectContaining({ message: expect.any(String), name: 'confirm', type: 'confirm' })
);
expect(mockExit).toHaveBeenCalledWith(0);
expect(fse.ensureDir).not.toHaveBeenCalled();
expect(fse.copy).not.toHaveBeenCalled();
});
});
});
65 changes: 65 additions & 0 deletions packages/strapi/lib/commands/export-template.js
Original file line number Diff line number Diff line change
@@ -0,0 1,65 @@
'use strict';

const { resolve, join, basename } = require('path');
const fse = require('fs-extra');
const chalk = require('chalk');
const inquirer = require('inquirer');

// All directories that a template could need
const TEMPLATE_CONTENT = ['api', 'components', 'config/functions/bootstrap.js', 'data'];

async function createTemplate(templatePath) {
// Get path to template directory: strapi-template-<name>/template
const contentPath = join(templatePath, 'template');
let successMessage = 'create';

// Check if the correct template directory structure exists
const exists = await fse.pathExists(contentPath);
const templateBase = basename(templatePath);

if (exists) {
// Confirm the user wants to update the existing template
const inquiry = await inquirer.prompt({
type: 'confirm',
name: 'confirm',
message: `${chalk.yellow(templateBase)} already exists. Do you want to replace it?`,
});

if (!inquiry.confirm) {
process.exit(0);
}

successMessage = 'update';
}

// Create/update the template
await fse.ensureDir(contentPath);
console.log(`${chalk.cyan(successMessage)}: ${templatePath}`);
}

async function copyContent(templatePath) {
const contentPath = join(templatePath, 'template');

TEMPLATE_CONTENT.forEach(async item => {
try {
await fse.copy(join(process.cwd(), item), join(contentPath, item));
const templateBase = basename(templatePath);
const currentProjectBase = basename(process.cwd());
console.log(
`${chalk.green(
'success'
)}: copy ${currentProjectBase}/${item} => ${templateBase}/template/${item}`
);
} catch (error) {
console.error(`${chalk.red('error')}: ${error.message}`);
}
});
}

module.exports = async function exportTemplate(directory) {
const dir = directory.startsWith('.') ? directory : `../${directory}`;
const templatePath = resolve(dir);

await createTemplate(templatePath);
await copyContent(templatePath);
};
71 changes: 0 additions & 71 deletions packages/strapi/lib/commands/exportTemplate.js

This file was deleted.