chore: update e2e test templates

This commit is contained in:
Alexandre Bodin 2024-08-26 15:37:24 +02:00
parent f39f099ca8
commit 6d27139261
6 changed files with 141 additions and 215 deletions

View File

@ -21,8 +21,7 @@ To update the app template:
- Move into this folder and run `yarn develop`.
- Login using the credentials found in `e2e/constants.js`.
- Make any changes you need (i.e. create a content-type).
- Kill the server and run [[`yarn strapi templates:generate <path>`]](https://docs.strapi.io/dev-docs/cli#strapi-templatesgenerate).
- Replace the existing template in `e2e/app-template` with the newly generated one.
- Replace the existing template in `e2e/app-template` with the current folder content (only keep the files you need).
## Content Schemas

View File

@ -1,116 +0,0 @@
import { resolve, join } from 'path';
import fse from 'fs-extra';
import inquirer from 'inquirer';
import { action as exportTemplate } from '../generate';
jest.mock('fs-extra', () => ({
ensureDir: jest.fn(() => Promise.resolve()),
copy: jest.fn(() => Promise.resolve()),
pathExists: jest.fn(() => Promise.resolve()),
writeJSON: jest.fn(() => Promise.resolve()),
}));
describe('templates:generate 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 rootPath = resolve(directory);
const templatePath = join(rootPath, 'template');
await exportTemplate(directory);
expect(fse.pathExists).toHaveBeenCalledWith(templatePath);
expect(fse.ensureDir).toHaveBeenCalledWith(templatePath);
});
it.each(['src', 'data'])('copies folder %s', async (item) => {
// Mock the empty directory arg
fse.pathExists.mockReturnValueOnce(false);
// Mock the folder exists
fse.pathExists.mockReturnValue(true);
const directory = '../test-dir';
const rootPath = resolve(directory);
const templatePath = join(rootPath, 'template');
await exportTemplate(directory);
expect(fse.pathExists).toHaveBeenCalledWith(join(process.cwd(), item));
expect(fse.copy).toHaveBeenCalledWith(join(process.cwd(), item), join(templatePath, item));
});
it('creates a json config file', async () => {
fse.pathExists.mockReturnValue(false);
const directory = '../test-dir';
const rootPath = resolve(directory);
await exportTemplate(directory);
expect(fse.pathExists).toHaveBeenCalledWith(join(rootPath, 'template.json'));
expect(fse.writeJSON).toHaveBeenCalledWith(join(rootPath, 'template.json'), {});
});
describe('handles prompt input', () => {
it('replaces directory if confirmed', async () => {
fse.pathExists.mockReturnValue(true);
const mockInquiry = jest
.spyOn(inquirer, 'prompt')
.mockImplementationOnce(() => ({ confirm: true }));
const directory = '../test-dir';
const rootPath = resolve(directory);
const templatePath = join(rootPath, 'template');
await exportTemplate(directory);
expect(fse.pathExists).toHaveBeenCalledWith(templatePath);
expect(mockInquiry).toHaveBeenLastCalledWith(
expect.objectContaining({ message: expect.any(String), name: 'confirm', type: 'confirm' })
);
expect(fse.ensureDir).toHaveBeenCalled();
expect(fse.copy).toHaveBeenCalled();
});
it('does not replace existing config file', async () => {
fse.pathExists.mockReturnValue(true);
jest.spyOn(inquirer, 'prompt').mockImplementationOnce(() => ({ confirm: true }));
const directory = '../test-dir';
const rootPath = resolve(directory);
await exportTemplate(directory);
expect(fse.pathExists).toHaveBeenCalledWith(join(rootPath, 'template.json'));
expect(fse.writeJSON).not.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 rootPath = resolve(directory);
const templatePath = join(rootPath, 'template');
await exportTemplate(directory).catch((err) => {
expect(err).toEqual(new Error('exit'));
});
expect(fse.pathExists).toHaveBeenCalledWith(templatePath);
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();
});
});
});

View File

@ -1,108 +1,17 @@
import { createCommand } from 'commander';
import { resolve, join, basename } from 'path';
import fse from 'fs-extra';
import chalk from 'chalk';
import inquirer from 'inquirer';
import type { StrapiCommand } from '../../types';
import { runAction } from '../../utils/helpers';
// All directories that a template could need
const TEMPLATE_CONTENT = ['src', 'data'];
async function copyContent(templatePath: string, rootBase: string) {
for (const item of TEMPLATE_CONTENT) {
try {
const pathToCopy = join(process.cwd(), item);
if (!(await fse.pathExists(pathToCopy))) {
continue;
}
await fse.copy(pathToCopy, join(templatePath, item));
const currentProjectBase = basename(process.cwd());
console.log(
`${chalk.green(
'success'
)}: copy ${currentProjectBase}/${item} => ${rootBase}/template/${item}`
);
} catch (error) {
if (error instanceof Error) {
console.error(`${chalk.red('error')}: ${error.message}`);
}
}
}
}
/**
*
* @param {string} rootPath Absolute path to the root directory
*/
async function writeTemplateJson(rootPath: string) {
try {
await fse.writeJSON(join(rootPath, 'template.json'), {});
console.log(`${chalk.green('success')}: create JSON config file`);
} catch (error) {
if (error instanceof Error) {
console.error(`${chalk.red('error')}: ${error.message}`);
}
}
}
/**
*
* @param {string} rootPath Absolute path to the root directory
* @returns boolean
*/
async function templateConfigExists(rootPath: string) {
const configExists = await fse.pathExists(join(rootPath, 'template.json'));
console.log(`checking: ${join(rootPath, 'template.json')}. result ${configExists}`);
return configExists;
}
const action = async function generateTemplate(directory: string) {
const rootPath = resolve(directory);
// Get path to template directory: <rootPath>/template
const templatePath = join(rootPath, 'template');
// Check if the template directory exists
const exists = await fse.pathExists(templatePath);
const rootBase = basename(rootPath);
if (exists) {
// Confirm the user wants to replace the existing template
const inquiry = await inquirer.prompt({
type: 'confirm',
name: 'confirm',
message: `${chalk.yellow(rootBase)} already exists. Do you want to replace it?`,
});
if (!inquiry.confirm) {
process.exit(0);
}
}
// Create or replace root directory with <roothPath>/template
await fse.ensureDir(templatePath);
// Copy content to /template
await copyContent(templatePath, rootBase);
// Create config file if it doesn't exist
const configExists = await templateConfigExists(rootPath);
if (!configExists) {
await writeTemplateJson(rootPath);
}
console.log(`${chalk.green('success')}: generated template at ${chalk.yellow(rootPath)}`);
};
/**
*`$ strapi templates:generate <directory>`
*/
const command: StrapiCommand = () => {
return createCommand('templates:generate <directory>')
.description('Generate template from Strapi project')
.action(runAction('templates:generate', action));
.description('(deprecated) Generate template from Strapi project')
.action(() => {
console.warn('This command is deprecated and will be removed in the next major release.');
console.warn('You can now copy an existing app and use it as a template.');
});
};
export { action, command };
export { command };

133
tests/e2e/app-template/.gitignore vendored Normal file
View File

@ -0,0 +1,133 @@
############################
# OS X
############################
.DS_Store
.AppleDouble
.LSOverride
Icon
.Spotlight-V100
.Trashes
._*
############################
# Linux
############################
*~
############################
# Windows
############################
Thumbs.db
ehthumbs.db
Desktop.ini
$RECYCLE.BIN/
*.cab
*.msi
*.msm
*.msp
############################
# Packages
############################
*.7z
*.csv
*.dat
*.dmg
*.gz
*.iso
*.jar
*.rar
*.tar
*.zip
*.com
*.class
*.dll
*.exe
*.o
*.seed
*.so
*.swo
*.swp
*.swn
*.swm
*.out
*.pid
############################
# Logs and databases
############################
.tmp
*.log
*.sql
*.sqlite
*.sqlite3
############################
# Misc.
############################
*#
ssl
.idea
nbproject
public/uploads/*
!public/uploads/.gitkeep
.tsbuildinfo
.eslintcache
############################
# Node.js
############################
lib-cov
lcov.info
pids
logs
results
node_modules
.node_history
############################
# Package managers
############################
.yarn/*
!.yarn/cache
!.yarn/unplugged
!.yarn/patches
!.yarn/releases
!.yarn/sdks
!.yarn/versions
.pnp.*
yarn-error.log
############################
# Tests
############################
coverage
############################
# Strapi
############################
.env
license.txt
exports
.strapi
dist
build
.strapi-updater.json
.strapi-cloud.json
.yalc
.tmp

View File

@ -48,6 +48,7 @@ const generateTestApp = async ({ appPath, database, template, link = false }) =>
'styled-components': '^6.0.0',
},
template: template ? path.resolve(template) : template,
gitInit: false,
};
await createStrapi(scope);