@operato/input 10.29.61 → 10.29.63
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/dist/src/ox-input-data.d.ts +0 -1
- package/dist/src/ox-input-data.js +3 -5
- package/dist/src/ox-input-data.js.map +1 -1
- package/dist/test/ox-input-data.test.d.ts +1 -0
- package/dist/test/ox-input-data.test.js +42 -0
- package/dist/test/ox-input-data.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -2
- package/test/ox-input-data.test.ts +58 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,24 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
### [10.29.63](https://github.com/hatiolab/operato/compare/v10.29.62...v10.29.63) (2026-10-31)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### :bug: Bug Fix
|
|
10
|
+
|
|
11
|
+
* **input:** read ox-input-data objects as JSON5 data, not as code ([5fa2c3f](https://github.com/hatiolab/operato/commit/5fa2c3fed144af2c1a4357f956cf66ab1c08fdbc))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### [10.29.62](https://github.com/hatiolab/operato/compare/v10.29.61...v10.29.62) (2026-10-30)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### :bug: Bug Fix
|
|
19
|
+
|
|
20
|
+
* **input:** declare ses, which ox-input-data imports ([e373dfa](https://github.com/hatiolab/operato/commit/e373dfaecd132b0a0966fce9854f904671562dac))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
6
24
|
### [10.29.61](https://github.com/hatiolab/operato/compare/v10.29.60...v10.29.61) (2026-10-30)
|
|
7
25
|
|
|
8
26
|
**Note:** Version bump only for package @operato/input
|
|
@@ -6,7 +6,7 @@ import { live } from 'lit/directives/live.js';
|
|
|
6
6
|
import { OxFormField } from './ox-form-field.js';
|
|
7
7
|
import { InputStyles } from './input-styles.js';
|
|
8
8
|
import { isEqual } from 'lodash-es';
|
|
9
|
-
import '
|
|
9
|
+
import JSON5 from 'json5';
|
|
10
10
|
/**
|
|
11
11
|
WEB Component for code-mirror based data editor.
|
|
12
12
|
|
|
@@ -185,8 +185,7 @@ let OxInputData = class OxInputData extends OxFormField {
|
|
|
185
185
|
}
|
|
186
186
|
break;
|
|
187
187
|
case 'object':
|
|
188
|
-
|
|
189
|
-
value = compartment.evaluate(`(${value})`);
|
|
188
|
+
value = JSON5.parse(value);
|
|
190
189
|
break;
|
|
191
190
|
}
|
|
192
191
|
}
|
|
@@ -216,8 +215,7 @@ let OxInputData = class OxInputData extends OxFormField {
|
|
|
216
215
|
}
|
|
217
216
|
break;
|
|
218
217
|
case 'object':
|
|
219
|
-
|
|
220
|
-
value = compartment.evaluate(`(${value})`);
|
|
218
|
+
value = JSON5.parse(value);
|
|
221
219
|
break;
|
|
222
220
|
}
|
|
223
221
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ox-input-data.js","sourceRoot":"","sources":["../../src/ox-input-data.ts"],"names":[],"mappings":"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","sourcesContent":["import './ox-input-code.js'\n\nimport { css, html } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { live } from 'lit/directives/live.js'\n\nimport { OxFormField } from './ox-form-field.js'\nimport { InputStyles } from './input-styles.js'\nimport { OxInputCode } from './ox-input-code.js'\nimport { isEqual } from 'lodash-es'\nimport 'ses'\n\n/**\nWEB Component for code-mirror based data editor.\n\nExample:\n\n <ox-input-data value=${text}>\n </ox-input-data>\n*/\n@customElement('ox-input-data')\nexport class OxInputData extends OxFormField {\n static styles = [\n InputStyles,\n css`\n :host {\n display: flex;\n flex-direction: column;\n position: relative;\n }\n\n /*\n * The type is a row of three quiet segments with the clear action at the far right - not\n * a framed accent box. The radios stay for the form; their labels are what you press.\n */\n div.datatype {\n display: flex;\n align-items: center;\n gap: 2px;\n margin-bottom: 6px;\n min-height: 24px;\n font-size: 0.74rem;\n color: var(--md-sys-color-on-surface-variant);\n }\n\n div.datatype input[type='radio'] {\n position: absolute;\n opacity: 0;\n width: 0;\n height: 0;\n margin: 0;\n pointer-events: none;\n }\n\n div.datatype label {\n display: flex;\n align-items: center;\n height: 24px;\n padding: 0 8px;\n margin: 0;\n border-radius: 4px;\n text-transform: capitalize;\n cursor: pointer;\n user-select: none;\n }\n\n div.datatype label:hover {\n color: var(--md-sys-color-on-surface);\n background-color: var(--md-sys-color-surface-container-high);\n }\n\n div.datatype input[type='radio']:checked + label {\n color: var(--md-sys-color-on-secondary-container);\n background-color: var(--md-sys-color-secondary-container);\n }\n\n div.datatype input[type='radio']:disabled + label {\n opacity: 0.4;\n cursor: default;\n }\n\n div.datatype md-icon {\n margin-left: auto;\n --md-icon-size: 18px;\n color: var(--md-sys-color-on-surface-variant);\n cursor: pointer;\n }\n\n div.datatype md-icon:hover {\n color: var(--md-sys-color-error);\n }\n\n /* The editor is a field like the others: a quiet tint, a hairline, an accent ring on focus. */\n ox-input-code {\n flex: 1;\n max-width: 260px;\n overflow: auto;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n background: var(--property-input-background, var(--md-sys-color-surface-container-high));\n }\n\n ox-input-code:focus-within {\n border-color: var(--md-sys-color-primary);\n }\n\n ox-input-code[full-width] {\n max-width: 100%;\n }\n `\n ]\n\n @property({ type: Boolean, attribute: 'full-width' }) fullWidth: boolean = false\n\n render() {\n const valueType = typeof this.value\n\n return html`\n <div class=\"datatype\">\n <input\n id=\"string\"\n type=\"radio\"\n name=\"data-type\"\n data-value=\"string\"\n .checked=${live(valueType == 'string')}\n @click=${() => this._setDataType('string')}\n ?disabled=${this.disabled}\n />\n <label for=\"string\">string</label>\n\n <input\n id=\"number\"\n type=\"radio\"\n name=\"data-type\"\n data-value=\"number\"\n .checked=${live(valueType == 'number')}\n @click=${() => this._setDataType('number')}\n ?disabled=${this.disabled}\n />\n <label for=\"number\">number</label>\n\n <input\n id=\"object\"\n type=\"radio\"\n name=\"data-type\"\n data-value=\"object\"\n .checked=${live(valueType == 'object')}\n @click=${() => this._setDataType('object')}\n ?disabled=${this.disabled}\n />\n <label for=\"object\">object</label>\n\n <md-icon @click=${() => this._clearData()} title=\"delete\">delete_forever</md-icon>\n </div>\n\n <ox-input-code\n .value=${this._getStringData(this.value)}\n language=\"text\"\n editor\n ?full-width=${this.fullWidth}\n ?disabled=${this.disabled}\n @change=${(e: CustomEvent) => {\n e.stopPropagation()\n this._setDataTypeAndValue(valueType, (e.target as any).value)\n }}\n >\n </ox-input-code>\n `\n }\n\n firstUpdated() {\n this.renderRoot.addEventListener('change', e => {\n e.stopPropagation()\n\n const target = e.target as OxInputCode\n if (target.hasAttribute('editor')) {\n if (this.value === undefined && target.value == '') {\n return\n }\n this.value = target.value\n }\n })\n }\n\n _setDataTypeAndValue(type: string | undefined | null, value: any) {\n /* value must be a string */\n try {\n switch (type) {\n case 'number':\n if (!isNaN(Number(value))) {\n value = Number(value)\n }\n break\n case 'object':\n const compartment = new Compartment()\n value = compartment.evaluate(`(${value})`)\n break\n }\n } catch (e) {\n console.error('Error parsing value:', e)\n }\n\n if (isEqual(this.value, value)) {\n return\n }\n\n this.value = value\n\n this.requestUpdate()\n this._onAfterValueChange()\n }\n\n _setDataType(type: string | undefined | null) {\n if (typeof this.value == type) {\n return\n }\n\n var value = this.value\n\n try {\n switch (type) {\n case 'string':\n value = this._getStringData(value)\n break\n case 'number':\n if (!isNaN(value)) {\n value = Number(value)\n }\n break\n case 'object':\n const compartment = new Compartment()\n value = compartment.evaluate(`(${value})`)\n break\n }\n } catch (e) {\n console.error('Error setting data type:', e)\n }\n\n if (isEqual(this.value, value)) {\n this.requestUpdate()\n return\n }\n\n this.value = value\n\n this.requestUpdate()\n this._onAfterValueChange()\n }\n\n _clearData() {\n this.value = undefined\n this._onAfterValueChange()\n }\n\n _getStringData(data: any) {\n const type = typeof data\n\n switch (type) {\n case 'object':\n return JSON.stringify(data, null, 1)\n case 'undefined':\n return ''\n default:\n return String(data) || ''\n }\n }\n\n async _onAfterValueChange() {\n this.dispatchEvent(\n new CustomEvent('change', {\n bubbles: true,\n composed: true\n })\n )\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ox-input-data.js","sourceRoot":"","sources":["../../src/ox-input-data.ts"],"names":[],"mappings":"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","sourcesContent":["import './ox-input-code.js'\n\nimport { css, html } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { live } from 'lit/directives/live.js'\n\nimport { OxFormField } from './ox-form-field.js'\nimport { InputStyles } from './input-styles.js'\nimport { OxInputCode } from './ox-input-code.js'\nimport { isEqual } from 'lodash-es'\nimport JSON5 from 'json5'\n\n/**\nWEB Component for code-mirror based data editor.\n\nExample:\n\n <ox-input-data value=${text}>\n </ox-input-data>\n*/\n@customElement('ox-input-data')\nexport class OxInputData extends OxFormField {\n static styles = [\n InputStyles,\n css`\n :host {\n display: flex;\n flex-direction: column;\n position: relative;\n }\n\n /*\n * The type is a row of three quiet segments with the clear action at the far right - not\n * a framed accent box. The radios stay for the form; their labels are what you press.\n */\n div.datatype {\n display: flex;\n align-items: center;\n gap: 2px;\n margin-bottom: 6px;\n min-height: 24px;\n font-size: 0.74rem;\n color: var(--md-sys-color-on-surface-variant);\n }\n\n div.datatype input[type='radio'] {\n position: absolute;\n opacity: 0;\n width: 0;\n height: 0;\n margin: 0;\n pointer-events: none;\n }\n\n div.datatype label {\n display: flex;\n align-items: center;\n height: 24px;\n padding: 0 8px;\n margin: 0;\n border-radius: 4px;\n text-transform: capitalize;\n cursor: pointer;\n user-select: none;\n }\n\n div.datatype label:hover {\n color: var(--md-sys-color-on-surface);\n background-color: var(--md-sys-color-surface-container-high);\n }\n\n div.datatype input[type='radio']:checked + label {\n color: var(--md-sys-color-on-secondary-container);\n background-color: var(--md-sys-color-secondary-container);\n }\n\n div.datatype input[type='radio']:disabled + label {\n opacity: 0.4;\n cursor: default;\n }\n\n div.datatype md-icon {\n margin-left: auto;\n --md-icon-size: 18px;\n color: var(--md-sys-color-on-surface-variant);\n cursor: pointer;\n }\n\n div.datatype md-icon:hover {\n color: var(--md-sys-color-error);\n }\n\n /* The editor is a field like the others: a quiet tint, a hairline, an accent ring on focus. */\n ox-input-code {\n flex: 1;\n max-width: 260px;\n overflow: auto;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n background: var(--property-input-background, var(--md-sys-color-surface-container-high));\n }\n\n ox-input-code:focus-within {\n border-color: var(--md-sys-color-primary);\n }\n\n ox-input-code[full-width] {\n max-width: 100%;\n }\n `\n ]\n\n @property({ type: Boolean, attribute: 'full-width' }) fullWidth: boolean = false\n\n render() {\n const valueType = typeof this.value\n\n return html`\n <div class=\"datatype\">\n <input\n id=\"string\"\n type=\"radio\"\n name=\"data-type\"\n data-value=\"string\"\n .checked=${live(valueType == 'string')}\n @click=${() => this._setDataType('string')}\n ?disabled=${this.disabled}\n />\n <label for=\"string\">string</label>\n\n <input\n id=\"number\"\n type=\"radio\"\n name=\"data-type\"\n data-value=\"number\"\n .checked=${live(valueType == 'number')}\n @click=${() => this._setDataType('number')}\n ?disabled=${this.disabled}\n />\n <label for=\"number\">number</label>\n\n <input\n id=\"object\"\n type=\"radio\"\n name=\"data-type\"\n data-value=\"object\"\n .checked=${live(valueType == 'object')}\n @click=${() => this._setDataType('object')}\n ?disabled=${this.disabled}\n />\n <label for=\"object\">object</label>\n\n <md-icon @click=${() => this._clearData()} title=\"delete\">delete_forever</md-icon>\n </div>\n\n <ox-input-code\n .value=${this._getStringData(this.value)}\n language=\"text\"\n editor\n ?full-width=${this.fullWidth}\n ?disabled=${this.disabled}\n @change=${(e: CustomEvent) => {\n e.stopPropagation()\n this._setDataTypeAndValue(valueType, (e.target as any).value)\n }}\n >\n </ox-input-code>\n `\n }\n\n firstUpdated() {\n this.renderRoot.addEventListener('change', e => {\n e.stopPropagation()\n\n const target = e.target as OxInputCode\n if (target.hasAttribute('editor')) {\n if (this.value === undefined && target.value == '') {\n return\n }\n this.value = target.value\n }\n })\n }\n\n _setDataTypeAndValue(type: string | undefined | null, value: any) {\n /* value must be a string */\n try {\n switch (type) {\n case 'number':\n if (!isNaN(Number(value))) {\n value = Number(value)\n }\n break\n case 'object':\n value = JSON5.parse(value)\n break\n }\n } catch (e) {\n console.error('Error parsing value:', e)\n }\n\n if (isEqual(this.value, value)) {\n return\n }\n\n this.value = value\n\n this.requestUpdate()\n this._onAfterValueChange()\n }\n\n _setDataType(type: string | undefined | null) {\n if (typeof this.value == type) {\n return\n }\n\n var value = this.value\n\n try {\n switch (type) {\n case 'string':\n value = this._getStringData(value)\n break\n case 'number':\n if (!isNaN(value)) {\n value = Number(value)\n }\n break\n case 'object':\n value = JSON5.parse(value)\n break\n }\n } catch (e) {\n console.error('Error setting data type:', e)\n }\n\n if (isEqual(this.value, value)) {\n this.requestUpdate()\n return\n }\n\n this.value = value\n\n this.requestUpdate()\n this._onAfterValueChange()\n }\n\n _clearData() {\n this.value = undefined\n this._onAfterValueChange()\n }\n\n _getStringData(data: any) {\n const type = typeof data\n\n switch (type) {\n case 'object':\n return JSON.stringify(data, null, 1)\n case 'undefined':\n return ''\n default:\n return String(data) || ''\n }\n }\n\n async _onAfterValueChange() {\n this.dispatchEvent(\n new CustomEvent('change', {\n bubbles: true,\n composed: true\n })\n )\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import '../src/ox-input-data.js';
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { html } from 'lit';
|
|
2
|
+
import { fixture, expect } from '@open-wc/testing';
|
|
3
|
+
import '../src/ox-input-data.js';
|
|
4
|
+
/**
|
|
5
|
+
* ox-input-data 의 object 해석 계약.
|
|
6
|
+
*
|
|
7
|
+
* object 로 고른 글은 JSON5 데이터로 읽는다 — 코드로 실행하지 않는다.
|
|
8
|
+
* 따옴표 없는 키·작은따옴표·끝 쉼표·주석은 받고, 식은 계산하지 않아 글 그대로 남는다.
|
|
9
|
+
*/
|
|
10
|
+
async function makeInput() {
|
|
11
|
+
return (await fixture(html `<ox-input-data></ox-input-data>`));
|
|
12
|
+
}
|
|
13
|
+
describe('ox-input-data — object 는 데이터로 읽는다', () => {
|
|
14
|
+
it('JSON5 표기를 객체로 읽는다', async () => {
|
|
15
|
+
const el = await makeInput();
|
|
16
|
+
el._setDataTypeAndValue('object', `{ a: 1, 'b': [1, 2,], /* note */ c: { d: "x" }, }`);
|
|
17
|
+
expect(el.value).to.deep.equal({ a: 1, b: [1, 2], c: { d: 'x' } });
|
|
18
|
+
});
|
|
19
|
+
it('JSON 으로 저장된 값은 그대로 읽는다', async () => {
|
|
20
|
+
const el = await makeInput();
|
|
21
|
+
const saved = JSON.stringify({ a: 1, b: [true, null], c: 'x' }, null, 1);
|
|
22
|
+
el._setDataTypeAndValue('object', saved);
|
|
23
|
+
expect(el.value).to.deep.equal({ a: 1, b: [true, null], c: 'x' });
|
|
24
|
+
});
|
|
25
|
+
it('식은 실행하지 않는다 — 글이 그대로 남는다', async () => {
|
|
26
|
+
const el = await makeInput();
|
|
27
|
+
const text = `{ a: (globalThis.__oxInputDataRan = 1) }`;
|
|
28
|
+
el._setDataTypeAndValue('object', text);
|
|
29
|
+
expect(globalThis.__oxInputDataRan).to.equal(undefined);
|
|
30
|
+
expect(el.value).to.equal(text);
|
|
31
|
+
});
|
|
32
|
+
it('string 값을 object 로 바꾸면 그 글을 읽는다', async () => {
|
|
33
|
+
const el = await makeInput();
|
|
34
|
+
el.value = `{ n: 2 }`;
|
|
35
|
+
el._setDataType('object');
|
|
36
|
+
expect(el.value).to.deep.equal({ n: 2 });
|
|
37
|
+
});
|
|
38
|
+
it('불러도 전역에 Compartment 를 심지 않는다', () => {
|
|
39
|
+
expect(globalThis.Compartment).to.equal(undefined);
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
//# sourceMappingURL=ox-input-data.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ox-input-data.test.js","sourceRoot":"","sources":["../../test/ox-input-data.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAA;AAC1B,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAElD,OAAO,yBAAyB,CAAA;AAGhC;;;;;GAKG;AAEH,KAAK,UAAU,SAAS;IACtB,OAAO,CAAC,MAAM,OAAO,CAAC,IAAI,CAAA,iCAAiC,CAAC,CAAgB,CAAA;AAC9E,CAAC;AAED,QAAQ,CAAC,mCAAmC,EAAE,GAAG,EAAE;IACjD,EAAE,CAAC,mBAAmB,EAAE,KAAK,IAAI,EAAE;QACjC,MAAM,EAAE,GAAG,MAAM,SAAS,EAAE,CAAA;QAE5B,EAAE,CAAC,oBAAoB,CAAC,QAAQ,EAAE,mDAAmD,CAAC,CAAA;QAEtF,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,CAAA;IACpE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,wBAAwB,EAAE,KAAK,IAAI,EAAE;QACtC,MAAM,EAAE,GAAG,MAAM,SAAS,EAAE,CAAA;QAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;QAExE,EAAE,CAAC,oBAAoB,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAA;QAExC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAA;IACnE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,0BAA0B,EAAE,KAAK,IAAI,EAAE;QACxC,MAAM,EAAE,GAAG,MAAM,SAAS,EAAE,CAAA;QAC5B,MAAM,IAAI,GAAG,0CAA0C,CAAA;QAEvD,EAAE,CAAC,oBAAoB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;QAEvC,MAAM,CAAE,UAAkB,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;QAChE,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IACjC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;QAC/C,MAAM,EAAE,GAAG,MAAM,SAAS,EAAE,CAAA;QAC5B,EAAE,CAAC,KAAK,GAAG,UAAU,CAAA;QAErB,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAA;QAEzB,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;IAC1C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,CAAE,UAAkB,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;IAC7D,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA","sourcesContent":["import { html } from 'lit'\nimport { fixture, expect } from '@open-wc/testing'\n\nimport '../src/ox-input-data.js'\nimport { OxInputData } from '../src/ox-input-data.js'\n\n/**\n * ox-input-data 의 object 해석 계약.\n *\n * object 로 고른 글은 JSON5 데이터로 읽는다 — 코드로 실행하지 않는다.\n * 따옴표 없는 키·작은따옴표·끝 쉼표·주석은 받고, 식은 계산하지 않아 글 그대로 남는다.\n */\n\nasync function makeInput() {\n return (await fixture(html`<ox-input-data></ox-input-data>`)) as OxInputData\n}\n\ndescribe('ox-input-data — object 는 데이터로 읽는다', () => {\n it('JSON5 표기를 객체로 읽는다', async () => {\n const el = await makeInput()\n\n el._setDataTypeAndValue('object', `{ a: 1, 'b': [1, 2,], /* note */ c: { d: \"x\" }, }`)\n\n expect(el.value).to.deep.equal({ a: 1, b: [1, 2], c: { d: 'x' } })\n })\n\n it('JSON 으로 저장된 값은 그대로 읽는다', async () => {\n const el = await makeInput()\n const saved = JSON.stringify({ a: 1, b: [true, null], c: 'x' }, null, 1)\n\n el._setDataTypeAndValue('object', saved)\n\n expect(el.value).to.deep.equal({ a: 1, b: [true, null], c: 'x' })\n })\n\n it('식은 실행하지 않는다 — 글이 그대로 남는다', async () => {\n const el = await makeInput()\n const text = `{ a: (globalThis.__oxInputDataRan = 1) }`\n\n el._setDataTypeAndValue('object', text)\n\n expect((globalThis as any).__oxInputDataRan).to.equal(undefined)\n expect(el.value).to.equal(text)\n })\n\n it('string 값을 object 로 바꾸면 그 글을 읽는다', async () => {\n const el = await makeInput()\n el.value = `{ n: 2 }`\n\n el._setDataType('object')\n\n expect(el.value).to.deep.equal({ n: 2 })\n })\n\n it('불러도 전역에 Compartment 를 심지 않는다', () => {\n expect((globalThis as any).Compartment).to.equal(undefined)\n })\n})\n"]}
|