From 2a009b38b9d140880c7c88733994789138e5712c Mon Sep 17 00:00:00 2001 From: ace-n-msft <acenassri@microsoft.com> Date: Fri, 27 Dec 2024 16:13:55 -0800 Subject: [PATCH] Feat: allow configuration via JS files --- spec/e2e/pbivizConfigSpec.js | 66 ++++++++++++++++++++++++++++++++++++ spec/e2e/testUtils.js | 14 ++++++++ src/utils.ts | 22 +++++++++--- 3 files changed, 97 insertions(+), 5 deletions(-) create mode 100644 spec/e2e/pbivizConfigSpec.js diff --git a/spec/e2e/pbivizConfigSpec.js b/spec/e2e/pbivizConfigSpec.js new file mode 100644 index 00000000..a414c3e6 --- /dev/null +++ b/spec/e2e/pbivizConfigSpec.js @@ -0,0 +1,66 @@ +/* + * Power BI Visual CLI + * + * Copyright (c) Microsoft Corporation + * All rights reserved. + * MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the ""Software""), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +"use strict"; + +import { createRequire } from 'module'; +import fs from 'fs-extra'; +import path from 'path'; +import FileSystem from '../helpers/FileSystem.js'; +import { writeMetadataAsJsFile } from "./testUtils.js"; + +const require = createRequire(import.meta.url); +const tempPath = path.join(FileSystem.getTempPath(), path.basename(import.meta.url)); +const startPath = process.cwd(); + +describe("E2E - pbiviz JS config", () => { + + const visualName = 'myjsvisualname'; + const visualPath = path.join(tempPath, visualName); + + beforeEach(() => { + process.chdir(startPath); + FileSystem.resetDirectory(tempPath); + process.chdir(tempPath); + FileSystem.runPbiviz('new', visualName); + process.chdir(visualPath); + + writeMetadataAsJsFile(visualPath); + }); + + afterAll(() => { + process.chdir(startPath); + FileSystem.deleteDirectory(tempPath); + }); + + it("Should output visual info from a JS file", () => { + const output = FileSystem.runPbiviz('info').toString(); + const visualConfig = require(path.join(visualPath, 'pbiviz.js')).visual; + expect(output).toContain(visualName); + expect(output).toContain(visualConfig.guid); + }); +}); + diff --git a/spec/e2e/testUtils.js b/spec/e2e/testUtils.js index 8141974c..b3865513 100644 --- a/spec/e2e/testUtils.js +++ b/spec/e2e/testUtils.js @@ -58,3 +58,17 @@ export const writeMetadata = (visualPath) => { pbiviz.author.email = "pbicvsupport"; fs.writeJSONSync(pbivizJSONFile, pbiviz); }; + +export const writeMetadataAsJsFile = (visualPath) => { + const pbivizJSONFile = path.join(visualPath, '/pbiviz.json'); + const pbivizJSFile = path.join(visualPath, '/pbiviz.js'); + + const pbiviz = fs.readJSONSync(pbivizJSONFile); + pbiviz.visual.description = "description"; + pbiviz.visual.supportUrl = "supportUrl"; + pbiviz.author.name = "Microsoft"; + pbiviz.author.email = "pbicvsupport"; + + const pbivizJSContents = `module.exports = JSON.parse(\`${JSON.stringify(pbiviz)}\`)`; + fs.writeFileSync(pbivizJSFile, pbivizJSContents); +}; diff --git a/src/utils.ts b/src/utils.ts index b85b882c..9bee4e57 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -26,14 +26,26 @@ export function getRootPath(): string { return path.join(pathToDirectory, "..", ".."); } -function readFileFromRoot(filePath: string) { - return fs.readFileSync(path.join(getRootPath(), filePath), "utf8") +function getJsPath(filePath: string) { + return filePath.replace(/\.json$/, '.js'); } -export function readJsonFromRoot(filePath: string) { - return JSON.parse(readFileFromRoot(filePath)); +function safelyRequire(filePath: string) { + return fs.existsSync(filePath) && require(filePath); +} + +function safelyParse(filePath: string) { + return fs.existsSync(filePath) && JSON.parse(fs.readFileSync(filePath, "utf-8")); +} + +export function readJsonFromRoot(jsonFilename: string) { + const jsonPath = path.join(getRootPath(), jsonFilename); + const jsPath = getJsPath(jsonPath); + return safelyRequire(jsPath) || safelyParse(jsonPath); } export function readJsonFromVisual(filePath: string, visualPath?: string) { - return JSON.parse(fs.readFileSync(path.join(visualPath ?? process.cwd(), filePath), "utf8")); + const jsonPath = path.join(visualPath ?? process.cwd(), filePath); + const jsPath = getJsPath(jsonPath); + return safelyRequire(jsPath) || safelyParse(jsonPath); } \ No newline at end of file