UNPKG

@tywalk/pcf-helper

Version:

Command line helper for building and publishing PCF controls to Dataverse.

157 lines (156 loc) 7.26 kB
"use strict"; 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/); })); });