/* * Copyright © 2021 Bonitasoft S.A. * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ import {CustomWidgetBuilder} from "../src/CustomWidgetBuilder"; import {FwkType, HtmlTemplatesGenerator} from "../src/HtmlTemplatesGenerator"; import * as os from "os"; import {sep} from "path"; import {PropertiesInfo} from "../src/PropertiesInfo"; import {PropertyType} from "../src/PropertyType"; import {Bond} from "../src/Bond"; const fs = require('fs'); describe('HtmlTemplateGenerator', () => { let builder: CustomWidgetBuilder; let tempDir: string; const wcBundle = "test/resources/uid-input/lib/uid-input.es5.min.js"; beforeAll(() => { builder = new CustomWidgetBuilder(); tempDir = fs.mkdtempSync(`${os.tmpdir()}${sep}`); }); afterAll(() => { fs.rmSync(tempDir, {recursive: true}); }); test('should generate correct html templates when a simple web component is given as input', async () => { handleSimpleWC("WcExample.ts"); }); test('should generate correct html templates when a complex web component is given as input', async () => { let jsonProperties = JSON.parse(fs.readFileSync("test/resources/my-input/myInput.json")); let tmplGenerator = new HtmlTemplatesGenerator(jsonProperties); tmplGenerator.generate(tempDir); // AngularJS template let templateAngularJs = getFileContent(`myInput.${HtmlTemplatesGenerator.AngularJsFileExtension}`); expect(getStringOccurrences(templateAngularJs, "")).toBe(4); expect(getStringOccurrences(templateAngularJs, "ng-if")).toBe(4); let expectedPropsAngularJs = ["ng-required=\"properties.required\"", "ng-readonly=\"properties.readOnly\"", "ng-if=\"!properties.disabled && properties.labelHidden\"\n\tlabel-hidden", "ng-if=\"!properties.disabled && !properties.labelHidden\"\n\tng-required", "label-position=\"{{properties.labelPosition}}\""]; checkStringContains(templateAngularJs, expectedPropsAngularJs); // Angular template let templateAngular = getFileContent(`myInput.${HtmlTemplatesGenerator.AngularFileExtension}`); expect(getStringOccurrences(templateAngular, "\\*ngIf")).toBe(4); let expectedPropsAngular = ["[required]=\"properties.required\"", "[readonly]=\"properties.readOnly\"", "*ngIf=\"!properties.disabled && properties.labelHidden\"\n\tlabel-hidden", "*ngIf=\"!properties.disabled && !properties.labelHidden\"\n\t[required]", "labelPosition=\"{{properties.labelPosition}}\"", "[(value)]=\"properties.value\""]; checkStringContains(templateAngular, expectedPropsAngular); }); test('should generate correct html templates when a JavaScript web component is given as input', async () => { handleSimpleWC("WcExample2.js"); }); test('should generate correct html templates when a standard web component is given as input', async () => { // Standard web component (i.e. extending HTMLElement) let tmplGenerator = new HtmlTemplatesGenerator(builder.getPropertiesInfoFromWebComponent("test/resources/app-drawer.js")); tmplGenerator.generate(tempDir); // AngularJS template let templateAngularJs = getFileContent(`appDrawer.${HtmlTemplatesGenerator.AngularJsFileExtension}`); let expectedPropsAngularJs = ["open=\"{{properties.open}}\"", "disabled=\"{{properties.disabled}}\""]; checkStringContains(templateAngularJs, expectedPropsAngularJs); // Angular template let templateAngular = getFileContent(`appDrawer.${HtmlTemplatesGenerator.AngularFileExtension}`); let expectedPropsAngular = ["[open]=\"properties.open\"", "[disabled]=\"properties.disabled\""]; checkStringContains(templateAngular, expectedPropsAngular); }); function handleSimpleWC(wcFilename: string) { let wcNameLowercase = getWcFileLowercase(wcFilename); let tmplGenerator = new HtmlTemplatesGenerator(builder.getPropertiesInfoFromWebComponent(`test/resources/${wcFilename}`)); tmplGenerator.generate(tempDir); // AngularJS template let templateAngularJs = getFileContent(`${wcNameLowercase}.${HtmlTemplatesGenerator.AngularJsFileExtension}`); expect(templateAngularJs.includes(HtmlTemplatesGenerator.ifDirectiveAngularJS)).toBeFalsy(); let expectedPropsAngularJs = ["title=\"{{properties.title}}\"", "counter=\"{{properties.counter}}\""]; checkStringContains(templateAngularJs, expectedPropsAngularJs); // Angular template let templateAngular = getFileContent(`${wcNameLowercase}.${HtmlTemplatesGenerator.AngularFileExtension}`); expect(templateAngular.includes(HtmlTemplatesGenerator.ifDirectiveAngular)).toBeFalsy(); let expectedPropsAngular = ["[title]=\"properties.title\"", "[counter]=\"properties.counter\""]; checkStringContains(templateAngular, expectedPropsAngular); } test('should generate html attributes name in camelCase', function (){ let propertiesInfos: PropertiesInfo = { "id": "myInput", "name": "MyInput", "type": "widget", "template": "@myInput.tpl.html", "description": "Field where the user can enter information", "order": "1", "custom": true, "modelVersion": "3.0", "icon": "", "jsBundle":"", "htmlBundle":"", "properties": [ { "label" : "Interpret HTML", "name" : "allowHTML", "help" : "If you choose 'no', HTML code will be escaped instead of being interpreted", "type" : PropertyType.Boolean, "defaultValue" : false, "bond": Bond.Constant }, { "label": "Label position", "name": "labelPosition", "type": PropertyType.Choice, "choiceValues": [ "left", "top" ], "defaultValue": "top", "bond": Bond.Constant, "showFor": "properties.labelHidden.value === false" } ], "assets":[] }; let html = new HtmlTemplatesGenerator(propertiesInfos); expect(html['generateProperties'](FwkType.Angular)).toContain("labelPosition=\"{{properties.labelPosition}}\""); let booleanProperties = html['generateIfBoolean'](FwkType.Angular); expect(booleanProperties.length).toEqual(2); expect(booleanProperties[1]).toBe('*ngIf="properties.allowHTML"\n' + '\tallow-html\n' + '\t'); }); function checkStringContains(str: string, items: Array) { for (let item of items) { expect(str.includes(item)).toBeTruthy(); } } function getStringOccurrences(str: string, item: string) { let regexp = new RegExp(item, 'g'); return (str.match(regexp) || []).length; } function getFileContent(fileName: string): string { let filePath = `${tempDir}/${fileName}`; expect(fs.existsSync(filePath)).toBeTruthy(); return fs.readFileSync(filePath, 'utf8'); } function getJsonFile(wcFile: string) { let jsonFile = wcFile.substring(0, wcFile.indexOf('.')) + ".json"; // First letter lowercase return jsonFile.charAt(0).toLowerCase() + jsonFile.slice(1); } function getWcFileLowercase(wcFile: string) { wcFile = wcFile.substring(0, wcFile.indexOf(".")); // First letter lowercase return wcFile.charAt(0).toLowerCase() + wcFile.slice(1); } });