Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
65 changes: 63 additions & 2 deletions src/__tests__/unit/init-file-generator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,68 @@ describe('init file generation', () => {
);

const adminIndexFile = getFile(files, 'admin/src/index.js');
expect(adminIndexFile.contents).toContain('to: `plugins/${PLUGIN_ID}`');
expect(adminIndexFile.contents).not.toContain('to: `plugins/${PluginIcon}`');
expect(adminIndexFile.contents).toMatch(/to:\s*`plugins\/\$\{PLUGIN_ID\}`/);
expect(adminIndexFile.contents).not.toMatch(/to:\s*`plugins\/\$\{PluginIcon\}`/);
});

it('should generate TS admin template with valid plugin export shape', async () => {
const { generateFiles } = await import('../../cli/commands/utils/init/file-generator');

const logger = {
info: jest.fn(),
debug: jest.fn(),
warn: jest.fn(),
error: jest.fn(),
log: jest.fn(),
};

const files = await generateFiles(
[
{ name: 'pkgName', answer: 'my-plugin' },
{ name: 'pluginId', answer: 'my-plugin' },
{ name: 'client-code', answer: true },
{ name: 'server-code', answer: false },
{ name: 'typescript', answer: true },
],
'my-plugin',
logger as any
);

const adminIndexFile = getFile(files, 'admin/src/index.ts');
expect(adminIndexFile.contents).toContain("const plugin: StrapiApp['appPlugins'][string] = {");
expect(adminIndexFile.contents).toContain('};\n\nexport default plugin;');
});

it('should generate JS admin template with docs-aligned App loader and translated trad keys', async () => {
const { generateFiles } = await import('../../cli/commands/utils/init/file-generator');

const logger = {
info: jest.fn(),
debug: jest.fn(),
warn: jest.fn(),
error: jest.fn(),
log: jest.fn(),
};

const files = await generateFiles(
[
{ name: 'pkgName', answer: 'my-plugin' },
{ name: 'pluginId', answer: 'my-plugin' },
{ name: 'client-code', answer: true },
{ name: 'server-code', answer: false },
{ name: 'typescript', answer: false },
],
'my-plugin',
logger as any
);

const adminIndexFile = getFile(files, 'admin/src/index.js');
expect(adminIndexFile.contents).toContain("const { App } = await import('./pages/App');");
expect(adminIndexFile.contents).not.toContain("const App = await import('./pages/App');");
expect(adminIndexFile.contents).toContain('newData[getTranslation(key)] = data[key];');

const appPageFile = getFile(files, 'admin/src/pages/App.jsx');
expect(appPageFile.contents).toContain('export { App };');
expect(appPageFile.contents).not.toContain('export default App;');
});
});
98 changes: 60 additions & 38 deletions src/cli/commands/plugin/init/files/admin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,45 +55,60 @@ const TYPESCRIPT: TemplateFile[] = [
import { PLUGIN_ID } from './pluginId';
import { Initializer } from './components/Initializer';
import { PluginIcon } from './components/PluginIcon';

// Types
import type { StrapiApp } from '@strapi/strapi/admin';

export default {
register(app: any) {
app.addMenuLink({
to: \`plugins/\${PLUGIN_ID}\`,
icon: PluginIcon,
intlLabel: {
id: \`\${PLUGIN_ID}.plugin.name\`,
defaultMessage: PLUGIN_ID,
},
Component: async () => {
const { App } = await import('./pages/App');

return App;
},
});

app.registerPlugin({
id: PLUGIN_ID,
initializer: Initializer,
isReady: false,
name: PLUGIN_ID,
});
},

async registerTrads({ locales }: { locales: string[] }) {
return Promise.all(
locales.map(async (locale) => {
try {
const { default: data } = await import(\`./translations/\${locale}.json\`);

return { data, locale };
} catch {
return { data: {}, locale };
const plugin: StrapiApp['appPlugins'][string] = {
register(app) {
app.addMenuLink({
to: \`plugins/\${PLUGIN_ID}\`,
icon: PluginIcon,
intlLabel: {
id: \`\${PLUGIN_ID}.plugin.name\`,
defaultMessage: PLUGIN_ID,
},
Component: async () => {
const { App } = await import('./pages/App');

return App;
},
permissions: [],
});

app.registerPlugin({
id: PLUGIN_ID,
initializer: Initializer,
isReady: false,
name: PLUGIN_ID,
});
},

registerTrads({ locales }) {
return Promise.all(
locales.map(async (locale) => {
try {
const { default: data } = (await import(\`./translations/\${locale}.json\`)) as {
default: Record<string, string>;
};

const newData: Record<string, string> = {};
const keys = Object.keys(data);

for (const key of keys) {
newData[getTranslation(key)] = data[key];
}
})
);
},

return { data: newData, locale };
} catch {
return { data: {}, locale };
}
})
);
},
};

export default plugin;
`,
},
{
Expand Down Expand Up @@ -198,8 +213,15 @@ const JAVASCRIPT: TemplateFile[] = [
locales.map(async (locale) => {
try {
const { default: data } = await import(\`./translations/\${locale}.json\`);

return { data, locale };

const newData = {};
const keys = Object.keys(data);

for (const key of keys) {
newData[getTranslation(key)] = data[key];
}

return { data: newData, locale };
} catch {
return { data: {}, locale };
}
Expand Down
Loading