From 82b3abc290685321d82267d011d165225125b18c Mon Sep 17 00:00:00 2001 From: nathan Date: Fri, 10 Dec 2021 11:15:02 -0700 Subject: [PATCH] Etemplate: Some more tests for readonly --- api/js/etemplate/Et2Date/test/Et2Date.test.ts | 74 ++++++------- .../Et2InputWidget/Et2InputWidget.ts | 2 + .../Et2InputWidget/test/InputBasicTests.ts | 101 ++++++++++++++++++ 3 files changed, 133 insertions(+), 44 deletions(-) create mode 100644 api/js/etemplate/Et2InputWidget/test/InputBasicTests.ts diff --git a/api/js/etemplate/Et2Date/test/Et2Date.test.ts b/api/js/etemplate/Et2Date/test/Et2Date.test.ts index 7ab15e8191..92bb110c2a 100644 --- a/api/js/etemplate/Et2Date/test/Et2Date.test.ts +++ b/api/js/etemplate/Et2Date/test/Et2Date.test.ts @@ -5,34 +5,38 @@ import {assert, elementUpdated, fixture} from '@open-wc/testing'; import {Et2Date} from "../Et2Date"; import {html} from "lit-element"; import * as sinon from 'sinon'; +import {inputBasicTests} from "../../Et2InputWidget/test/InputBasicTests"; + +let element : Et2Date; + +async function before() +{ + // Create an element to test with, and wait until it's ready + // @ts-ignore + element = await fixture(html` + + `); + + // Stub egw() + sinon.stub(element, "egw").returns({ + tooltipUnbind: () => {}, + // Image always give check mark. Use data URL to avoid having to serve an actual image + image: i => "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAxNS4wLjAsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+DQo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkViZW5lXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4Ig0KCSB3aWR0aD0iMzJweCIgaGVpZ2h0PSIzMnB4IiB2aWV3Qm94PSIwIDAgMzIgMzIiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDMyIDMyIiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBmaWxsPSIjNjk2OTY5IiBkPSJNNi45NDMsMjguNDUzDQoJYzAuOTA2LDAuNzY1LDIuMDk3LDEuMTI3LDMuMjg2LDEuMTA5YzAuNDMsMC4wMTQsMC44NTItMC4wNjgsMS4yNjUtMC4yMDdjMC42NzktMC4xOCwxLjMyOC0wLjQ1LDEuODY2LTAuOTAyTDI5LjQwMywxNC45DQoJYzEuNzcyLTEuNDk4LDEuNzcyLTMuOTI1LDAtNS40MjJjLTEuNzcyLTEuNDk3LTQuNjQ2LTEuNDk3LTYuNDE4LDBMMTAuMTE5LDIwLjM0OWwtMi4zODktMi40MjRjLTEuNDQtMS40NTctMy43NzItMS40NTctNS4yMTIsMA0KCWMtMS40MzgsMS40Ni0xLjQzOCwzLjgyNSwwLDUuMjgxQzIuNTE4LDIzLjIwNiw1LjQ3NCwyNi45NDcsNi45NDMsMjguNDUzeiIvPg0KPC9zdmc+DQo=" + }); + + // Stub global egw for preference + // @ts-ignore + window.egw = { + preference: () => 'Y-m-d' + }; + + return element; +}; describe("Date widget", () => { - // Reference to component under test - let element : Et2Date; - // Setup run before each test - beforeEach(async() => - { - // Create an element to test with, and wait until it's ready - // @ts-ignore - element = await fixture(html` - - `); - - // Stub egw() - sinon.stub(element, "egw").returns({ - tooltipUnbind: () => {}, - // Image always give check mark. Use data URL to avoid having to serve an actual image - image: i => "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAxNS4wLjAsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+DQo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkViZW5lXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4Ig0KCSB3aWR0aD0iMzJweCIgaGVpZ2h0PSIzMnB4IiB2aWV3Qm94PSIwIDAgMzIgMzIiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDMyIDMyIiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBmaWxsPSIjNjk2OTY5IiBkPSJNNi45NDMsMjguNDUzDQoJYzAuOTA2LDAuNzY1LDIuMDk3LDEuMTI3LDMuMjg2LDEuMTA5YzAuNDMsMC4wMTQsMC44NTItMC4wNjgsMS4yNjUtMC4yMDdjMC42NzktMC4xOCwxLjMyOC0wLjQ1LDEuODY2LTAuOTAyTDI5LjQwMywxNC45DQoJYzEuNzcyLTEuNDk4LDEuNzcyLTMuOTI1LDAtNS40MjJjLTEuNzcyLTEuNDk3LTQuNjQ2LTEuNDk3LTYuNDE4LDBMMTAuMTE5LDIwLjM0OWwtMi4zODktMi40MjRjLTEuNDQtMS40NTctMy43NzItMS40NTctNS4yMTIsMA0KCWMtMS40MzgsMS40Ni0xLjQzOCwzLjgyNSwwLDUuMjgxQzIuNTE4LDIzLjIwNiw1LjQ3NCwyNi45NDcsNi45NDMsMjguNDUzeiIvPg0KPC9zdmc+DQo=" - }); - - // Stub global egw for preference - // @ts-ignore - window.egw = { - preference: () => 'Y-m-d' - }; - }); + beforeEach(before); // Make sure it works it('is defined', () => @@ -47,25 +51,6 @@ describe("Date widget", () => assert.equal(element.querySelector("[slot='label']").textContent, "Label set"); }) - it('Readonly does not return a value', async() => - { - element.readOnly = true; - let test_time_string = '2008-09-22T12:00:00.000Z'; - - element.set_value(test_time_string); - - - // wait for asychronous changes to the DOM - await elementUpdated(element); - // Read-only widget returns null - assert.equal(element.getValue(), null); - }); - - it('No value shows no value', () => - { - assert.equal(element.querySelector("input").textContent, ""); - assert.equal(element.get_value(), null); - }); it("'0' shows no value", async() => { @@ -122,4 +107,5 @@ describe("Date widget", () => tz_offset_stub.restore(); }); } -}); \ No newline at end of file +}); +inputBasicTests(before, "2008-09-22T00:00:00.000Z", "input"); \ No newline at end of file diff --git a/api/js/etemplate/Et2InputWidget/Et2InputWidget.ts b/api/js/etemplate/Et2InputWidget/Et2InputWidget.ts index ad3f5f71a0..8750ba3bed 100644 --- a/api/js/etemplate/Et2InputWidget/Et2InputWidget.ts +++ b/api/js/etemplate/Et2InputWidget/Et2InputWidget.ts @@ -25,6 +25,8 @@ export declare class Et2InputWidgetInterface public getValue() : any; + public set_readonly(boolean) : void; + public isDirty() : boolean; public resetDirty() : void; diff --git a/api/js/etemplate/Et2InputWidget/test/InputBasicTests.ts b/api/js/etemplate/Et2InputWidget/test/InputBasicTests.ts new file mode 100644 index 0000000000..58088ff235 --- /dev/null +++ b/api/js/etemplate/Et2InputWidget/test/InputBasicTests.ts @@ -0,0 +1,101 @@ +import {Et2InputWidgetInterface} from "../Et2InputWidget"; +import {assert, elementUpdated} from "@open-wc/testing"; + + +/** + * Some basic, common tests that any decent input widget should pass + * + * Have your widget creation in a separate function, and pass it in along with a "good" value. + * Checking "bad" values and error conditions are widget-specific, so you have to handle those in your own tests. + * This is just a starting point, and to make sure that if a widget doesn't pass these, there's something + * wrong. + * + * @example + * async function before() + * { + * // Create an element to test with, and wait until it's ready + * // @ts-ignore + * element = await fixture(html` + * + * `); + * } + * inputBasicTests(before, "2008-09-22T00:00:00.000Z", "input"); + * + * @param {Function} beforeEach function to create / setup the widget + * @param {string} test_value A "good" value + * @param {string} value_selector Passed to document.querySelector() to check that the value is displayed + */ + +// Widget used in each test +let element : Et2InputWidgetInterface; + +export function inputBasicTests(before : Function, test_value : string, value_selector : string) +{ + describe("Readonly tests", () => + { + beforeEach(async() => + { + element = await before(); + }); + + it('Does not return a value (via attribute)', async() => + { + element.readOnly = true; + + element.set_value(test_value); + + // wait for asychronous changes to the DOM + await elementUpdated(element); + // Read-only widget returns null + assert.equal(element.getValue(), null); + }); + + it('Does not return a value (via method)', async() => + { + (element).set_readonly(true); + + element.set_value(test_value); + + // wait for asychronous changes to the DOM + await elementUpdated(element); + // Read-only widget returns null + assert.equal(element.getValue(), null); + }); + + it('Does not return a value if it goes readonly after having a value', async() => + { + element.set_value(test_value); + + element.set_readonly(true); + + // wait for asychronous changes to the DOM + await elementUpdated(element); + // Read-only widget returns null + assert.equal(element.getValue(), null); + }); + }); + + describe("In/Out value tests", () => + { + beforeEach(async() => + { + element = await before(); + }); + it('No value shows no value', () => + { + assert.equal((element).querySelector(value_selector).textContent, ""); + assert.equal(element.get_value(), null); + }); + + it('Value out matches value in', async() => + { + element.set_value(test_value); + + // wait for asychronous changes to the DOM + await elementUpdated(element); + + // widget returns what we gave it + assert.equal(element.get_value(), test_value); + }); + }) +} \ No newline at end of file