@tywalk/pcf-helper
Version:
Command line helper for building and publishing PCF controls to Dataverse.
157 lines (156 loc) • 7.26 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = __importDefault(require("fs"));
const os_1 = __importDefault(require("os"));
const path_1 = __importDefault(require("path"));
const profileInitUtil_1 = require("../util/profileInitUtil");
jest.mock('@tywalk/color-logger', () => ({
__esModule: true,
default: {
log: jest.fn(),
warn: jest.fn(),
error: jest.fn(),
debug: jest.fn(),
},
}));
/**
* Build a mock prompt that returns a scripted list of answers in order.
* If the script runs out we return '' (user skipped).
*/
function mockPrompt(answers) {
let i = 0;
return (_q, currentValue) => __awaiter(this, void 0, void 0, function* () {
const answer = answers[i++];
if (answer === undefined)
return currentValue !== null && currentValue !== void 0 ? currentValue : '';
return answer;
});
}
describe('buildProfileFromOptions', () => {
it('non-interactive mode uses only passed flags, nothing else', () => __awaiter(void 0, void 0, void 0, function* () {
const profile = yield (0, profileInitUtil_1.buildProfileFromOptions)({
name: 'dev',
environment: 'DevOrg',
publisherName: 'Tyler W',
nonInteractive: true,
}, mockPrompt([]));
expect(profile).toEqual({
environment: 'DevOrg',
publisherName: 'Tyler W',
});
}));
it('interactive mode uses prompt answers, overriding passed defaults', () => __awaiter(void 0, void 0, void 0, function* () {
const profile = yield (0, profileInitUtil_1.buildProfileFromOptions)({
name: 'dev',
environment: 'DevOrg', // offered as default; user types 'OverrideOrg'
}, mockPrompt(['OverrideOrg', 'Tyler', 'tyw', './MySolution', '', '']));
expect(profile).toEqual({
environment: 'OverrideOrg',
publisherName: 'Tyler',
publisherPrefix: 'tyw',
path: './MySolution',
});
// Empty answers for template/framework must NOT appear in the profile.
expect(profile.template).toBeUndefined();
expect(profile.framework).toBeUndefined();
}));
it('interactive mode: hitting enter keeps the default value', () => __awaiter(void 0, void 0, void 0, function* () {
const profile = yield (0, profileInitUtil_1.buildProfileFromOptions)({
name: 'dev',
environment: 'DevOrg',
publisherName: 'Tyler W',
publisherPrefix: 'tyw',
},
// mockPrompt returns currentValue when the scripted answer is undefined.
mockPrompt([undefined, undefined, undefined, undefined, undefined, undefined]));
expect(profile).toEqual({
environment: 'DevOrg',
publisherName: 'Tyler W',
publisherPrefix: 'tyw',
});
}));
it('session fields only appear when at least one session flag was passed', () => __awaiter(void 0, void 0, void 0, function* () {
const without = yield (0, profileInitUtil_1.buildProfileFromOptions)({ name: 'dev', nonInteractive: true, environment: 'DevOrg' }, mockPrompt([]));
expect(without.session).toBeUndefined();
const withSession = yield (0, profileInitUtil_1.buildProfileFromOptions)({
name: 'dev',
nonInteractive: true,
environment: 'DevOrg',
sessionUrl: 'https://dev.example.com',
}, mockPrompt([]));
expect(withSession.session).toEqual({
remoteEnvironmentUrl: 'https://dev.example.com',
});
}));
});
describe('runProfileInit', () => {
let tmpRoot;
beforeEach(() => {
tmpRoot = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'pcf-helper-runProfileInit-'));
});
afterEach(() => {
try {
fs_1.default.rmSync(tmpRoot, { recursive: true, force: true });
}
catch (_a) {
// best-effort
}
});
it('writes a non-interactive profile end-to-end', () => __awaiter(void 0, void 0, void 0, function* () {
var _a;
const fakeHome = path_1.default.join(tmpRoot, 'fake-home');
const spy = jest.spyOn(os_1.default, 'homedir').mockReturnValue(fakeHome);
// Also redirect cwd so project-level writes land inside tmpRoot.
const cwdSpy = jest.spyOn(process, 'cwd').mockReturnValue(tmpRoot);
try {
const result = yield (0, profileInitUtil_1.runProfileInit)({
name: 'dev',
environment: 'DevOrg',
publisherName: 'Tyler W',
publisherPrefix: 'tyw',
path: './MySolution',
setDefault: true,
nonInteractive: true,
}, mockPrompt([]));
expect(result.createdFile).toBe(true);
expect(result.filePath).toBe(path_1.default.join(tmpRoot, 'pcf-helper.config.json'));
const onDisk = JSON.parse(fs_1.default.readFileSync(result.filePath, 'utf8'));
expect(onDisk.defaultProfile).toBe('dev');
expect((_a = onDisk.profiles) === null || _a === void 0 ? void 0 : _a.dev).toEqual({
environment: 'DevOrg',
publisherName: 'Tyler W',
publisherPrefix: 'tyw',
path: './MySolution',
});
}
finally {
spy.mockRestore();
cwdSpy.mockRestore();
}
}));
it('propagates the force-required error when name already exists', () => __awaiter(void 0, void 0, void 0, function* () {
const cwdSpy = jest.spyOn(process, 'cwd').mockReturnValue(tmpRoot);
try {
fs_1.default.writeFileSync(path_1.default.join(tmpRoot, 'pcf-helper.config.json'), JSON.stringify({ profiles: { dev: { environment: 'DevOrg' } } }, null, 2));
yield expect((0, profileInitUtil_1.runProfileInit)({ name: 'dev', environment: 'NewDevOrg', nonInteractive: true }, mockPrompt([]))).rejects.toThrow(/already exists/);
}
finally {
cwdSpy.mockRestore();
}
}));
it('throws helpful error when name is blank', () => __awaiter(void 0, void 0, void 0, function* () {
yield expect((0, profileInitUtil_1.runProfileInit)({ name: '', nonInteractive: true }, mockPrompt([]))).rejects.toThrow(/name is required/);
}));
});