UNPKG

@tywalk/pcf-helper

Version:

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

317 lines (316 loc) 15.8 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const session_pcf_1 = require("../tasks/session-pcf"); const fs = __importStar(require("fs")); const path = __importStar(require("path")); const color_logger_1 = __importDefault(require("@tywalk/color-logger")); jest.mock('fs'); jest.mock('path'); jest.mock('@tywalk/color-logger', () => ({ __esModule: true, default: { log: jest.fn(), warn: jest.fn(), error: jest.fn(), debug: jest.fn() } })); const mockFs = fs; const mockPath = path; describe('session-pcf loadConfig', () => { beforeEach(() => { jest.clearAllMocks(); delete process.env.REMOTE_ENVIRONMENT_URL; delete process.env.REMOTE_SCRIPT_TO_INTERCEPT; delete process.env.REMOTE_STYLESHEET_TO_INTERCEPT; delete process.env.LOCAL_CSS_PATH; delete process.env.LOCAL_BUNDLE_PATH; delete process.env.START_WATCH; mockPath.join.mockImplementation((...args) => args.join('/')); jest.spyOn(process, 'cwd').mockReturnValue('/test/cwd'); }); afterEach(() => { jest.restoreAllMocks(); }); describe('config file loading', () => { it('should load config from default session.config.json', () => { const config = { remoteEnvironmentUrl: 'https://example.crm.dynamics.com', remoteScriptToIntercept: '/static/bundle.js', remoteStylesheetToIntercept: '/static/style.css', localBundlePath: '/local/bundle.js', localCssPath: '/local/style.css' }; mockFs.existsSync.mockReturnValue(true); mockFs.readFileSync.mockReturnValue(JSON.stringify(config)); const result = (0, session_pcf_1.loadConfig)(); expect(result.remoteEnvironmentUrl).toBe('https://example.crm.dynamics.com'); expect(mockFs.existsSync).toHaveBeenCalled(); expect(mockFs.readFileSync).toHaveBeenCalled(); }); it('should load config from custom config file path', () => { const config = { remoteEnvironmentUrl: 'https://custom.crm.dynamics.com', remoteScriptToIntercept: 'custom-bundle.js', localBundlePath: '/custom/bundle.js', localCssPath: '/custom/style.css' }; mockFs.existsSync.mockReturnValue(true); mockFs.readFileSync.mockReturnValue(JSON.stringify(config)); const result = (0, session_pcf_1.loadConfig)('custom.config.json'); expect(result.remoteEnvironmentUrl).toBe('https://custom.crm.dynamics.com'); }); it('should return empty object if config file does not exist', () => { mockFs.existsSync.mockReturnValue(false); const result = (0, session_pcf_1.loadConfig)(); expect(result).toEqual({}); }); it('should log error if config file is invalid JSON', () => { mockFs.existsSync.mockReturnValue(true); mockFs.readFileSync.mockReturnValue('{ invalid json }'); const result = (0, session_pcf_1.loadConfig)(); expect(color_logger_1.default.error).toHaveBeenCalledWith(expect.stringContaining('Failed to parse config file')); expect(result).toEqual({}); }); it('should log warning if config file not found and no env vars', () => { mockFs.existsSync.mockReturnValue(false); (0, session_pcf_1.loadConfig)(); expect(color_logger_1.default.warn).not.toHaveBeenCalled(); // Returns empty, no warning since it checks for env vars }); it('should log config when file is loaded successfully', () => { const config = { remoteEnvironmentUrl: 'https://example.crm.dynamics.com' }; mockFs.existsSync.mockReturnValue(true); mockFs.readFileSync.mockReturnValue(JSON.stringify(config)); (0, session_pcf_1.loadConfig)(); expect(color_logger_1.default.log).toHaveBeenCalledWith(expect.stringContaining('Loaded config file')); }); }); describe('environment variable overrides', () => { it('should use REMOTE_ENVIRONMENT_URL env var if set', () => { process.env.REMOTE_ENVIRONMENT_URL = 'https://env.crm.dynamics.com'; mockFs.existsSync.mockReturnValue(false); const result = (0, session_pcf_1.loadConfig)(); expect(result.remoteEnvironmentUrl).toBe('https://env.crm.dynamics.com'); }); it('should use REMOTE_SCRIPT_TO_INTERCEPT env var if set', () => { process.env.REMOTE_ENVIRONMENT_URL = 'https://env.crm.dynamics.com'; process.env.REMOTE_SCRIPT_TO_INTERCEPT = 'https://example.com/env-bundle.js'; mockFs.existsSync.mockReturnValue(false); const result = (0, session_pcf_1.loadConfig)(); expect(result.remoteScriptToIntercept).toBe('https://example.com/env-bundle.js'); }); it('should use LOCAL_CSS_PATH env var if set', () => { process.env.REMOTE_ENVIRONMENT_URL = 'https://env.crm.dynamics.com'; process.env.LOCAL_CSS_PATH = '/env/style.css'; mockFs.existsSync.mockReturnValue(false); const result = (0, session_pcf_1.loadConfig)(); expect(result.localCssPath).toBe('/env/style.css'); }); it('should use LOCAL_BUNDLE_PATH env var if set', () => { process.env.REMOTE_ENVIRONMENT_URL = 'https://env.crm.dynamics.com'; process.env.LOCAL_BUNDLE_PATH = '/env/bundle.js'; mockFs.existsSync.mockReturnValue(false); const result = (0, session_pcf_1.loadConfig)(); expect(result.localBundlePath).toBe('/env/bundle.js'); }); it('should prefer env var over config file value', () => { const config = { remoteEnvironmentUrl: 'https://config.crm.dynamics.com' }; mockFs.existsSync.mockReturnValue(true); mockFs.readFileSync.mockReturnValue(JSON.stringify(config)); process.env.REMOTE_ENVIRONMENT_URL = 'https://env.crm.dynamics.com'; const result = (0, session_pcf_1.loadConfig)(); expect(result.remoteEnvironmentUrl).toBe('https://env.crm.dynamics.com'); }); }); describe('URL normalization and path construction', () => { it('should construct full URL from base URL and relative script path', () => { const config = { remoteEnvironmentUrl: 'https://example.crm.dynamics.com', remoteScriptToIntercept: 'webresources/bundle.js' }; mockFs.existsSync.mockReturnValue(true); mockFs.readFileSync.mockReturnValue(JSON.stringify(config)); const result = (0, session_pcf_1.loadConfig)(); expect(result.remoteScriptToIntercept).toBe('https://example.crm.dynamics.com/webresources/bundle.js'); }); it('should handle script path that already starts with /', () => { const config = { remoteEnvironmentUrl: 'https://example.crm.dynamics.com', remoteScriptToIntercept: '/webresources/bundle.js' }; mockFs.existsSync.mockReturnValue(true); mockFs.readFileSync.mockReturnValue(JSON.stringify(config)); const result = (0, session_pcf_1.loadConfig)(); expect(result.remoteScriptToIntercept).toBe('https://example.crm.dynamics.com/webresources/bundle.js'); }); it('should not add duplicate slashes when base URL has trailing slash', () => { const config = { remoteEnvironmentUrl: 'https://example.crm.dynamics.com/', remoteScriptToIntercept: '/webresources/bundle.js' }; mockFs.existsSync.mockReturnValue(true); mockFs.readFileSync.mockReturnValue(JSON.stringify(config)); const result = (0, session_pcf_1.loadConfig)(); expect(result.remoteScriptToIntercept).toBe('https://example.crm.dynamics.com/webresources/bundle.js'); expect(result.remoteScriptToIntercept).not.toContain('//webresources'); }); it('should keep full URLs unchanged', () => { const config = { remoteEnvironmentUrl: 'https://example.crm.dynamics.com', remoteScriptToIntercept: 'https://cdn.example.com/bundle.js' }; mockFs.existsSync.mockReturnValue(true); mockFs.readFileSync.mockReturnValue(JSON.stringify(config)); const result = (0, session_pcf_1.loadConfig)(); expect(result.remoteScriptToIntercept).toBe('https://cdn.example.com/bundle.js'); }); it('should handle stylesheet path normalization', () => { const config = { remoteEnvironmentUrl: 'https://example.crm.dynamics.com', remoteStylesheetToIntercept: 'webresources/style.css' }; mockFs.existsSync.mockReturnValue(true); mockFs.readFileSync.mockReturnValue(JSON.stringify(config)); const result = (0, session_pcf_1.loadConfig)(); expect(result.remoteStylesheetToIntercept).toBe('https://example.crm.dynamics.com/webresources/style.css'); }); it('should not attempt URL construction if base URL is missing', () => { const config = { remoteScriptToIntercept: 'webresources/bundle.js' }; mockFs.existsSync.mockReturnValue(true); mockFs.readFileSync.mockReturnValue(JSON.stringify(config)); const result = (0, session_pcf_1.loadConfig)(); // Should remain as is since no base URL expect(result.remoteScriptToIntercept).toBe('webresources/bundle.js'); }); it('should not attempt URL construction if script is empty', () => { const config = { remoteEnvironmentUrl: 'https://example.crm.dynamics.com', remoteScriptToIntercept: '' }; mockFs.existsSync.mockReturnValue(true); mockFs.readFileSync.mockReturnValue(JSON.stringify(config)); const result = (0, session_pcf_1.loadConfig)(); // Should remain empty expect(result.remoteScriptToIntercept).toBe(''); }); }); describe('watch flag handling', () => { it('should set startWatch to true if config has it', () => { const config = { remoteEnvironmentUrl: 'https://example.crm.dynamics.com', startWatch: true }; mockFs.existsSync.mockReturnValue(true); mockFs.readFileSync.mockReturnValue(JSON.stringify(config)); const result = (0, session_pcf_1.loadConfig)(); expect(result.startWatch).toBe(true); }); it('should set startWatch to false if config has it false', () => { const config = { remoteEnvironmentUrl: 'https://example.crm.dynamics.com', startWatch: false }; mockFs.existsSync.mockReturnValue(true); mockFs.readFileSync.mockReturnValue(JSON.stringify(config)); const result = (0, session_pcf_1.loadConfig)(); expect(result.startWatch).toBe(false); }); it('should check START_WATCH env var', () => { process.env.REMOTE_ENVIRONMENT_URL = 'https://env.crm.dynamics.com'; process.env.START_WATCH = 'true'; mockFs.existsSync.mockReturnValue(false); const result = (0, session_pcf_1.loadConfig)(); expect(result.startWatch).toBe(true); }); it('should set startWatch to false if START_WATCH env var is not true', () => { process.env.REMOTE_ENVIRONMENT_URL = 'https://env.crm.dynamics.com'; process.env.START_WATCH = 'false'; mockFs.existsSync.mockReturnValue(false); const result = (0, session_pcf_1.loadConfig)(); expect(result.startWatch).toBe(false); }); it('should default startWatch to false', () => { process.env.REMOTE_ENVIRONMENT_URL = 'https://env.crm.dynamics.com'; mockFs.existsSync.mockReturnValue(false); const result = (0, session_pcf_1.loadConfig)(); expect(result.startWatch).toBe(false); }); }); describe('edge cases', () => { it('should handle config with only some fields present', () => { const config = { remoteEnvironmentUrl: 'https://example.crm.dynamics.com' }; mockFs.existsSync.mockReturnValue(true); mockFs.readFileSync.mockReturnValue(JSON.stringify(config)); const result = (0, session_pcf_1.loadConfig)(); expect(result.remoteEnvironmentUrl).toBe('https://example.crm.dynamics.com'); expect(result.remoteScriptToIntercept).toBeUndefined(); }); it('should handle empty config file', () => { mockFs.existsSync.mockReturnValue(true); mockFs.readFileSync.mockReturnValue('{}'); const result = (0, session_pcf_1.loadConfig)(); expect(result).toEqual({ remoteEnvironmentUrl: undefined, remoteScriptToIntercept: undefined, remoteStylesheetToIntercept: undefined, localCssPath: undefined, localBundlePath: undefined, startWatch: false, watchRetry: true }); }); it('should handle config file with extra fields', () => { const config = { remoteEnvironmentUrl: 'https://example.crm.dynamics.com', extraField: 'should be ignored' }; mockFs.existsSync.mockReturnValue(true); mockFs.readFileSync.mockReturnValue(JSON.stringify(config)); const result = (0, session_pcf_1.loadConfig)(); expect(result.remoteEnvironmentUrl).toBe('https://example.crm.dynamics.com'); expect(result.watchRetry).toBe(true); }); }); });