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
4 changes: 4 additions & 0 deletions messages/ui-bundle.generate.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ Use the --template flag for generating the files to get started with a speciic U

<%= config.bin %> <%= command.id %> --name MyReactApp --template reactbasic

- Generate a Vue-based UI bundle:

<%= config.bin %> <%= command.id %> --name MyVueApp --template vuebasic

- Generate the React-based UI bundle in the "force-app/main/default/uiBundles" directory:

<%= config.bin %> <%= command.id %> --name MyUiBundle --template reactbasic --output-dir force-app/main/default/uiBundles
Expand Down
2 changes: 1 addition & 1 deletion src/commands/template/generate/ui-bundle/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export default class UiBundleGenerate extends SfCommand<CreateOutput> {
summary: messages.getMessage('flags.template.summary'),
description: messages.getMessage('flags.template.description'),
default: 'default',
options: ['default', 'reactbasic'],
options: ['default', 'reactbasic', 'vuebasic'],
}),
label: Flags.string({
char: 'l',
Expand Down
16 changes: 16 additions & 0 deletions test/commands/template/generate/ui-bundle/index.nut.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,22 @@ describe('template generate ui-bundle:', () => {
});
});

// TODO: unskip once @salesforce/templates ships the vuebasic template
describe.skip('Check UI bundle creation with vuebasic template', () => {
it('should create Vue UI bundle with all required files', () => {
const outputDir = path.join(projectDir, 'force-app', 'main', 'default', UI_BUNDLES_DIR);
execCmd(`template generate ui-bundle --name MyVueApp --template vuebasic --output-dir "${outputDir}"`, {
ensureExitCode: 0,
});
assert.file([
path.join(outputDir, 'MyVueApp', 'MyVueApp.uibundle-meta.xml'),
path.join(outputDir, 'MyVueApp', 'index.html'),
path.join(outputDir, 'MyVueApp', 'ui-bundle.json'),
path.join(outputDir, 'MyVueApp', 'package.json'),
]);
});
});

describe('Check that all invalid name errors are thrown', () => {
it('should throw a missing name error', () => {
const stderr = execCmd('template generate ui-bundle').shellOutput.stderr;
Expand Down
55 changes: 55 additions & 0 deletions test/commands/template/generate/ui-bundle/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright (c) 2025, salesforce.com, inc.
* All rights reserved.
* Licensed under the BSD 3-Clause license.
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/

import { expect } from 'chai';
import UiBundleGenerate from '../../../../../src/commands/template/generate/ui-bundle/index.js';

describe('template:generate:ui-bundle', () => {
it('should include vuebasic in --template flag options', () => {
const templateFlag = UiBundleGenerate.flags.template;
expect(templateFlag.options).to.include('vuebasic');
});

it('should include all expected --template flag options', () => {
const templateFlag = UiBundleGenerate.flags.template;
expect(templateFlag.options).to.deep.equal(['default', 'reactbasic', 'vuebasic']);
});

it('should default --template to default', () => {
const templateFlag = UiBundleGenerate.flags.template;
expect(templateFlag.default).to.equal('default');
});

it('should accept --template vuebasic without validation error', async () => {
try {
await UiBundleGenerate.run(['--name', 'TestBundle', '--template', 'vuebasic']);
} catch (err) {
const error = err as Error;
expect(error.message).to.not.include('Expected --template=vuebasic to be one of');
}
});

it('should reject invalid --template value', async () => {
try {
await UiBundleGenerate.run(['--name', 'TestBundle', '--template', 'invalidtemplate']);
expect.fail('Should have thrown an error');
} catch (err) {
const error = err as Error;
expect(error.message).to.include('Expected --template=invalidtemplate to be one of');
}
});

it('should require name flag', async () => {
try {
await UiBundleGenerate.run([]);
expect.fail('Should have thrown an error');
} catch (err) {
const error = err as Error;
expect(error.message).to.include('Missing required flag');
}
});
});