pict-section-formeditor 1.0.0
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/LICENSE +21 -0
- package/README.md +118 -0
- package/docs/.nojekyll +0 -0
- package/docs/README.md +162 -0
- package/docs/_sidebar.md +23 -0
- package/docs/_topbar.md +5 -0
- package/docs/cover.md +12 -0
- package/docs/css/docuserve.css +73 -0
- package/docs/index.html +39 -0
- package/docs/retold-catalog.json +224 -0
- package/docs/retold-keyword-index.json +46846 -0
- package/example_applications/form_editor/.quackage.json +10 -0
- package/example_applications/form_editor/FormEditor-Example-Application.js +226 -0
- package/example_applications/form_editor/html/icon-chooser.html +375 -0
- package/example_applications/form_editor/html/index.html +54 -0
- package/example_applications/form_editor/package.json +50 -0
- package/package.json +55 -0
- package/sample_manifests/Complex-Table.json +974 -0
- package/sample_manifests/Distill-Example.json +200 -0
- package/sample_manifests/Gradebook-Assignment.json +38 -0
- package/sample_manifests/Gradebook-Student.json +40 -0
- package/sample_manifests/Manyfest-Editor.json +347 -0
- package/sample_manifests/Simple-Form.json +232 -0
- package/sample_manifests/Simple-Table.json +79 -0
- package/source/Pict-Section-FormEditor-DefaultConfiguration.js +3321 -0
- package/source/Pict-Section-FormEditor.js +35 -0
- package/source/providers/Pict-Provider-ChildPictManager-Application.js +40 -0
- package/source/providers/Pict-Provider-ChildPictManager.js +238 -0
- package/source/providers/Pict-Provider-FormEditorDocumentation.js +356 -0
- package/source/providers/Pict-Provider-FormEditorDragDrop.js +535 -0
- package/source/providers/Pict-Provider-FormEditorIconography.js +1002 -0
- package/source/providers/Pict-Provider-FormEditorManifestOps.js +1443 -0
- package/source/providers/Pict-Provider-FormEditorRendering.js +730 -0
- package/source/providers/Pict-Provider-FormEditorUtilities.js +862 -0
- package/source/providers/Pict-Provider-PreviewCSS.js +42 -0
- package/source/views/PictView-FormEditor-InlineEditing.js +309 -0
- package/source/views/PictView-FormEditor-InputTypePicker.js +532 -0
- package/source/views/PictView-FormEditor-PropertiesPanel.js +7730 -0
- package/source/views/PictView-FormEditor.js +681 -0
- package/test/Pict-Section-FormEditor_tests.js +4102 -0
- package/user-documentation/.pict_documentation_topics.json +695 -0
- package/user-documentation/Getting-Started.md +32 -0
- package/user-documentation/Groups.md +52 -0
- package/user-documentation/Inputs.md +98 -0
- package/user-documentation/Sections.md +36 -0
- package/user-documentation/Shortcuts.md +44 -0
- package/user-documentation/Solver-Expression-Walkthrough.md +176 -0
- package/user-documentation/Solver-Expressions-Advanced.md +344 -0
- package/user-documentation/Solver-Functions.md +213 -0
- package/user-documentation/Solvers.md +81 -0
- package/user-documentation/ToC.md +18 -0
- package/user-documentation/solverfunctions/abs.md +84 -0
- package/user-documentation/solverfunctions/aggregationhistogram.md +83 -0
- package/user-documentation/solverfunctions/aggregationhistogrambyobject.md +64 -0
- package/user-documentation/solverfunctions/arrayconcat.md +64 -0
- package/user-documentation/solverfunctions/avg.md +81 -0
- package/user-documentation/solverfunctions/bucketset.md +69 -0
- package/user-documentation/solverfunctions/ceil.md +70 -0
- package/user-documentation/solverfunctions/cleanvaluearray.md +66 -0
- package/user-documentation/solverfunctions/cleanvalueobject.md +68 -0
- package/user-documentation/solverfunctions/colorgroupbackground.md +60 -0
- package/user-documentation/solverfunctions/colorinputbackground.md +62 -0
- package/user-documentation/solverfunctions/colorinputbackgroundtabular.md +64 -0
- package/user-documentation/solverfunctions/colorsectionbackground.md +59 -0
- package/user-documentation/solverfunctions/compare.md +72 -0
- package/user-documentation/solverfunctions/concat.md +73 -0
- package/user-documentation/solverfunctions/concatraw.md +73 -0
- package/user-documentation/solverfunctions/cos.md +75 -0
- package/user-documentation/solverfunctions/count.md +73 -0
- package/user-documentation/solverfunctions/countset.md +65 -0
- package/user-documentation/solverfunctions/countsetelements.md +63 -0
- package/user-documentation/solverfunctions/createarrayfromabsolutevalues.md +63 -0
- package/user-documentation/solverfunctions/createvalueobjectbyhashes.md +69 -0
- package/user-documentation/solverfunctions/cumulativesummation.md +96 -0
- package/user-documentation/solverfunctions/dateadddays.md +79 -0
- package/user-documentation/solverfunctions/dateaddhours.md +74 -0
- package/user-documentation/solverfunctions/dateaddmilliseconds.md +65 -0
- package/user-documentation/solverfunctions/dateaddminutes.md +72 -0
- package/user-documentation/solverfunctions/dateaddmonths.md +74 -0
- package/user-documentation/solverfunctions/dateaddseconds.md +66 -0
- package/user-documentation/solverfunctions/dateaddweeks.md +73 -0
- package/user-documentation/solverfunctions/dateaddyears.md +74 -0
- package/user-documentation/solverfunctions/datedaydifference.md +84 -0
- package/user-documentation/solverfunctions/datefromparts.md +81 -0
- package/user-documentation/solverfunctions/datehourdifference.md +64 -0
- package/user-documentation/solverfunctions/datemathadd.md +72 -0
- package/user-documentation/solverfunctions/datemilliseconddifference.md +64 -0
- package/user-documentation/solverfunctions/dateminutedifference.md +64 -0
- package/user-documentation/solverfunctions/datemonthdifference.md +66 -0
- package/user-documentation/solverfunctions/dateseconddifference.md +64 -0
- package/user-documentation/solverfunctions/dateweekdifference.md +65 -0
- package/user-documentation/solverfunctions/dateyeardifference.md +64 -0
- package/user-documentation/solverfunctions/differencearrays.md +59 -0
- package/user-documentation/solverfunctions/disablesolverordinal.md +58 -0
- package/user-documentation/solverfunctions/distributionhistogram.md +96 -0
- package/user-documentation/solverfunctions/distributionhistogrambyobject.md +64 -0
- package/user-documentation/solverfunctions/enablesolverordinal.md +57 -0
- package/user-documentation/solverfunctions/entryinset.md +72 -0
- package/user-documentation/solverfunctions/euler.md +77 -0
- package/user-documentation/solverfunctions/exp.md +74 -0
- package/user-documentation/solverfunctions/findfirstvaluebyexactmatch.md +67 -0
- package/user-documentation/solverfunctions/findfirstvaluebystringincludes.md +67 -0
- package/user-documentation/solverfunctions/flatten.md +76 -0
- package/user-documentation/solverfunctions/floor.md +70 -0
- package/user-documentation/solverfunctions/gaussianelimination.md +75 -0
- package/user-documentation/solverfunctions/generatearrayofobjectsfromsets.md +70 -0
- package/user-documentation/solverfunctions/generatehtmlhexcolor.md +67 -0
- package/user-documentation/solverfunctions/getvalue.md +90 -0
- package/user-documentation/solverfunctions/getvaluearray.md +64 -0
- package/user-documentation/solverfunctions/getvalueobject.md +67 -0
- package/user-documentation/solverfunctions/hidesections.md +58 -0
- package/user-documentation/solverfunctions/if.md +109 -0
- package/user-documentation/solverfunctions/iterativeseries.md +107 -0
- package/user-documentation/solverfunctions/join.md +75 -0
- package/user-documentation/solverfunctions/joinraw.md +64 -0
- package/user-documentation/solverfunctions/largestinset.md +63 -0
- package/user-documentation/solverfunctions/leastsquares.md +66 -0
- package/user-documentation/solverfunctions/linest.md +58 -0
- package/user-documentation/solverfunctions/log.md +74 -0
- package/user-documentation/solverfunctions/logvalues.md +65 -0
- package/user-documentation/solverfunctions/match.md +71 -0
- package/user-documentation/solverfunctions/matrixinverse.md +67 -0
- package/user-documentation/solverfunctions/matrixmultiply.md +71 -0
- package/user-documentation/solverfunctions/matrixtranspose.md +72 -0
- package/user-documentation/solverfunctions/matrixvectormultiply.md +69 -0
- package/user-documentation/solverfunctions/max.md +73 -0
- package/user-documentation/solverfunctions/mean.md +63 -0
- package/user-documentation/solverfunctions/median.md +79 -0
- package/user-documentation/solverfunctions/min.md +73 -0
- package/user-documentation/solverfunctions/mode.md +66 -0
- package/user-documentation/solverfunctions/objectkeystoarray.md +66 -0
- package/user-documentation/solverfunctions/objectvaluessortbyexternalobjectarray.md +65 -0
- package/user-documentation/solverfunctions/objectvaluestoarray.md +67 -0
- package/user-documentation/solverfunctions/percent.md +75 -0
- package/user-documentation/solverfunctions/pi.md +77 -0
- package/user-documentation/solverfunctions/polynomialregression.md +69 -0
- package/user-documentation/solverfunctions/predict.md +71 -0
- package/user-documentation/solverfunctions/rad.md +85 -0
- package/user-documentation/solverfunctions/randomfloat.md +63 -0
- package/user-documentation/solverfunctions/randomfloatbetween.md +72 -0
- package/user-documentation/solverfunctions/randomfloatupto.md +65 -0
- package/user-documentation/solverfunctions/randominteger.md +56 -0
- package/user-documentation/solverfunctions/randomintegerbetween.md +72 -0
- package/user-documentation/solverfunctions/randomintegerupto.md +64 -0
- package/user-documentation/solverfunctions/refreshtabularsection.md +57 -0
- package/user-documentation/solverfunctions/resolvehtmlentities.md +64 -0
- package/user-documentation/solverfunctions/round.md +111 -0
- package/user-documentation/solverfunctions/runsolvers.md +49 -0
- package/user-documentation/solverfunctions/setconcatenate.md +64 -0
- package/user-documentation/solverfunctions/setgroupvisibility.md +60 -0
- package/user-documentation/solverfunctions/setsectionvisibility.md +59 -0
- package/user-documentation/solverfunctions/setsolverordinalenabled.md +59 -0
- package/user-documentation/solverfunctions/settabularrowlength.md +57 -0
- package/user-documentation/solverfunctions/setvalue.md +65 -0
- package/user-documentation/solverfunctions/showsections.md +58 -0
- package/user-documentation/solverfunctions/sin.md +83 -0
- package/user-documentation/solverfunctions/slice.md +80 -0
- package/user-documentation/solverfunctions/smallestinset.md +63 -0
- package/user-documentation/solverfunctions/sortarray.md +58 -0
- package/user-documentation/solverfunctions/sorthistogram.md +70 -0
- package/user-documentation/solverfunctions/sorthistogrambykeys.md +69 -0
- package/user-documentation/solverfunctions/sortset.md +75 -0
- package/user-documentation/solverfunctions/sqrt.md +85 -0
- package/user-documentation/solverfunctions/stdev.md +81 -0
- package/user-documentation/solverfunctions/stdeva.md +58 -0
- package/user-documentation/solverfunctions/stdevp.md +83 -0
- package/user-documentation/solverfunctions/stringcountsegments.md +66 -0
- package/user-documentation/solverfunctions/stringgetsegments.md +74 -0
- package/user-documentation/solverfunctions/subtractingsummation.md +66 -0
- package/user-documentation/solverfunctions/sum.md +78 -0
- package/user-documentation/solverfunctions/tan.md +78 -0
- package/user-documentation/solverfunctions/tofixed.md +75 -0
- package/user-documentation/solverfunctions/unionarrays.md +59 -0
- package/user-documentation/solverfunctions/uniquearray.md +58 -0
- package/user-documentation/solverfunctions/var.md +67 -0
- package/user-documentation/solverfunctions/vara.md +58 -0
- package/user-documentation/solverfunctions/varp.md +66 -0
- package/user-documentation/solverfunctions/when.md +98 -0
|
@@ -0,0 +1,4102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for Pict Section FormEditor
|
|
3
|
+
*
|
|
4
|
+
* @license MIT
|
|
5
|
+
*
|
|
6
|
+
* @author Steven Velozo <steven@velozo.com>
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
var libPict = require('pict');
|
|
10
|
+
|
|
11
|
+
var Chai = require("chai");
|
|
12
|
+
var Expect = Chai.expect;
|
|
13
|
+
|
|
14
|
+
var libPictSectionFormEditor = require('../source/Pict-Section-FormEditor.js');
|
|
15
|
+
|
|
16
|
+
suite
|
|
17
|
+
(
|
|
18
|
+
'Pict Section FormEditor',
|
|
19
|
+
function ()
|
|
20
|
+
{
|
|
21
|
+
suite
|
|
22
|
+
(
|
|
23
|
+
'Module Exports',
|
|
24
|
+
function ()
|
|
25
|
+
{
|
|
26
|
+
test
|
|
27
|
+
(
|
|
28
|
+
'Module should export the main view class',
|
|
29
|
+
function ()
|
|
30
|
+
{
|
|
31
|
+
Expect(libPictSectionFormEditor).to.be.a('function');
|
|
32
|
+
}
|
|
33
|
+
);
|
|
34
|
+
test
|
|
35
|
+
(
|
|
36
|
+
'Module should export default configuration',
|
|
37
|
+
function ()
|
|
38
|
+
{
|
|
39
|
+
Expect(libPictSectionFormEditor.default_configuration).to.be.an('object');
|
|
40
|
+
Expect(libPictSectionFormEditor.default_configuration.ViewIdentifier).to.equal('Pict-FormEditor');
|
|
41
|
+
Expect(libPictSectionFormEditor.default_configuration.CSS).to.be.a('string');
|
|
42
|
+
Expect(libPictSectionFormEditor.default_configuration.Templates).to.be.an('array');
|
|
43
|
+
Expect(libPictSectionFormEditor.default_configuration.Renderables).to.be.an('array');
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
suite
|
|
49
|
+
(
|
|
50
|
+
'View Instantiation',
|
|
51
|
+
function ()
|
|
52
|
+
{
|
|
53
|
+
test
|
|
54
|
+
(
|
|
55
|
+
'Should instantiate a FormEditor view',
|
|
56
|
+
function ()
|
|
57
|
+
{
|
|
58
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
59
|
+
let tmpView = tmpPict.addView('TestFormEditor',
|
|
60
|
+
{
|
|
61
|
+
ViewIdentifier: 'TestFormEditor',
|
|
62
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
63
|
+
}, libPictSectionFormEditor);
|
|
64
|
+
|
|
65
|
+
Expect(tmpView).to.be.an('object');
|
|
66
|
+
Expect(tmpView.options.ViewIdentifier).to.equal('TestFormEditor');
|
|
67
|
+
Expect(tmpView.options.ManifestDataAddress).to.equal('AppData.FormConfig');
|
|
68
|
+
}
|
|
69
|
+
);
|
|
70
|
+
test
|
|
71
|
+
(
|
|
72
|
+
'Should use default ManifestDataAddress when none provided',
|
|
73
|
+
function ()
|
|
74
|
+
{
|
|
75
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
76
|
+
let tmpView = tmpPict.addView('TestFormEditorDefault',
|
|
77
|
+
{
|
|
78
|
+
ViewIdentifier: 'TestFormEditorDefault'
|
|
79
|
+
}, libPictSectionFormEditor);
|
|
80
|
+
|
|
81
|
+
Expect(tmpView.options.ManifestDataAddress).to.equal('FormEditor.Manifest');
|
|
82
|
+
}
|
|
83
|
+
);
|
|
84
|
+
test
|
|
85
|
+
(
|
|
86
|
+
'Should initialize with an empty manifest when no data exists',
|
|
87
|
+
function ()
|
|
88
|
+
{
|
|
89
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
90
|
+
tmpPict.AppData = {};
|
|
91
|
+
|
|
92
|
+
let tmpView = tmpPict.addView('TestFormEditorInit',
|
|
93
|
+
{
|
|
94
|
+
ViewIdentifier: 'TestFormEditorInit',
|
|
95
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
96
|
+
}, libPictSectionFormEditor);
|
|
97
|
+
|
|
98
|
+
tmpView.initialize();
|
|
99
|
+
|
|
100
|
+
Expect(tmpPict.AppData.FormConfig).to.be.an('object');
|
|
101
|
+
Expect(tmpPict.AppData.FormConfig.Scope).to.equal('NewForm');
|
|
102
|
+
Expect(tmpPict.AppData.FormConfig.Sections).to.be.an('array');
|
|
103
|
+
Expect(tmpPict.AppData.FormConfig.Descriptors).to.be.an('object');
|
|
104
|
+
}
|
|
105
|
+
);
|
|
106
|
+
test
|
|
107
|
+
(
|
|
108
|
+
'Should preserve existing manifest data on initialize',
|
|
109
|
+
function ()
|
|
110
|
+
{
|
|
111
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
112
|
+
tmpPict.AppData = {};
|
|
113
|
+
tmpPict.AppData.FormConfig =
|
|
114
|
+
{
|
|
115
|
+
Scope: 'ExistingForm',
|
|
116
|
+
Sections:
|
|
117
|
+
[
|
|
118
|
+
{
|
|
119
|
+
Hash: 'Section1',
|
|
120
|
+
Name: 'My Section',
|
|
121
|
+
Groups: []
|
|
122
|
+
}
|
|
123
|
+
],
|
|
124
|
+
Descriptors: {}
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
let tmpView = tmpPict.addView('TestFormEditorPreserve',
|
|
128
|
+
{
|
|
129
|
+
ViewIdentifier: 'TestFormEditorPreserve',
|
|
130
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
131
|
+
}, libPictSectionFormEditor);
|
|
132
|
+
|
|
133
|
+
tmpView.initialize();
|
|
134
|
+
|
|
135
|
+
Expect(tmpPict.AppData.FormConfig.Scope).to.equal('ExistingForm');
|
|
136
|
+
Expect(tmpPict.AppData.FormConfig.Sections.length).to.equal(1);
|
|
137
|
+
Expect(tmpPict.AppData.FormConfig.Sections[0].Name).to.equal('My Section');
|
|
138
|
+
}
|
|
139
|
+
);
|
|
140
|
+
test
|
|
141
|
+
(
|
|
142
|
+
'Should create a code editor child view on initialize',
|
|
143
|
+
function ()
|
|
144
|
+
{
|
|
145
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
146
|
+
tmpPict.AppData = {};
|
|
147
|
+
|
|
148
|
+
let tmpView = tmpPict.addView('TestCodeEditorView',
|
|
149
|
+
{
|
|
150
|
+
ViewIdentifier: 'TestCodeEditorView',
|
|
151
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
152
|
+
}, libPictSectionFormEditor);
|
|
153
|
+
|
|
154
|
+
tmpView.initialize();
|
|
155
|
+
|
|
156
|
+
Expect(tmpView._CodeEditorView).to.be.an('object');
|
|
157
|
+
Expect(tmpView._CodeEditorView.options.Language).to.equal('json');
|
|
158
|
+
Expect(tmpView._CodeEditorView.options.LineNumbers).to.equal(true);
|
|
159
|
+
Expect(tmpView._CodeEditorView.options.ReadOnly).to.equal(false);
|
|
160
|
+
}
|
|
161
|
+
);
|
|
162
|
+
test
|
|
163
|
+
(
|
|
164
|
+
'Should update code editor content via _updateCodeEditor',
|
|
165
|
+
function ()
|
|
166
|
+
{
|
|
167
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
168
|
+
tmpPict.AppData = {};
|
|
169
|
+
|
|
170
|
+
let tmpView = tmpPict.addView('TestUpdateCodeEditor',
|
|
171
|
+
{
|
|
172
|
+
ViewIdentifier: 'TestUpdateCodeEditor',
|
|
173
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
174
|
+
}, libPictSectionFormEditor);
|
|
175
|
+
|
|
176
|
+
tmpView.initialize();
|
|
177
|
+
|
|
178
|
+
// Without a DOM, codeJar won't be initialized,
|
|
179
|
+
// so _updateCodeEditor should not throw
|
|
180
|
+
tmpView._UtilitiesProvider._updateCodeEditor();
|
|
181
|
+
}
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
);
|
|
185
|
+
suite
|
|
186
|
+
(
|
|
187
|
+
'Section Operations',
|
|
188
|
+
function ()
|
|
189
|
+
{
|
|
190
|
+
test
|
|
191
|
+
(
|
|
192
|
+
'Should add a section',
|
|
193
|
+
function ()
|
|
194
|
+
{
|
|
195
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
196
|
+
tmpPict.AppData = {};
|
|
197
|
+
|
|
198
|
+
let tmpView = tmpPict.addView('TestAddSection',
|
|
199
|
+
{
|
|
200
|
+
ViewIdentifier: 'TestAddSection',
|
|
201
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
202
|
+
}, libPictSectionFormEditor);
|
|
203
|
+
|
|
204
|
+
tmpView.initialize();
|
|
205
|
+
|
|
206
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
207
|
+
let tmpManifest = tmpPict.AppData.FormConfig;
|
|
208
|
+
Expect(tmpManifest.Sections.length).to.equal(1);
|
|
209
|
+
Expect(tmpManifest.Sections[0].Hash).to.equal('S1');
|
|
210
|
+
Expect(tmpManifest.Sections[0].Name).to.equal('Section 1');
|
|
211
|
+
Expect(tmpManifest.Sections[0].Groups).to.be.an('array');
|
|
212
|
+
|
|
213
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
214
|
+
Expect(tmpManifest.Sections.length).to.equal(2);
|
|
215
|
+
Expect(tmpManifest.Sections[1].Hash).to.equal('S2');
|
|
216
|
+
}
|
|
217
|
+
);
|
|
218
|
+
test
|
|
219
|
+
(
|
|
220
|
+
'Should remove a section',
|
|
221
|
+
function ()
|
|
222
|
+
{
|
|
223
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
224
|
+
tmpPict.AppData = {};
|
|
225
|
+
|
|
226
|
+
let tmpView = tmpPict.addView('TestRemoveSection',
|
|
227
|
+
{
|
|
228
|
+
ViewIdentifier: 'TestRemoveSection',
|
|
229
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
230
|
+
}, libPictSectionFormEditor);
|
|
231
|
+
|
|
232
|
+
tmpView.initialize();
|
|
233
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
234
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
235
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
236
|
+
|
|
237
|
+
Expect(tmpPict.AppData.FormConfig.Sections.length).to.equal(3);
|
|
238
|
+
|
|
239
|
+
tmpView._ManifestOpsProvider.removeSection(1);
|
|
240
|
+
Expect(tmpPict.AppData.FormConfig.Sections.length).to.equal(2);
|
|
241
|
+
Expect(tmpPict.AppData.FormConfig.Sections[0].Hash).to.equal('S1');
|
|
242
|
+
Expect(tmpPict.AppData.FormConfig.Sections[1].Hash).to.equal('S3');
|
|
243
|
+
}
|
|
244
|
+
);
|
|
245
|
+
test
|
|
246
|
+
(
|
|
247
|
+
'Should move sections up and down',
|
|
248
|
+
function ()
|
|
249
|
+
{
|
|
250
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
251
|
+
tmpPict.AppData = {};
|
|
252
|
+
|
|
253
|
+
let tmpView = tmpPict.addView('TestMoveSection',
|
|
254
|
+
{
|
|
255
|
+
ViewIdentifier: 'TestMoveSection',
|
|
256
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
257
|
+
}, libPictSectionFormEditor);
|
|
258
|
+
|
|
259
|
+
tmpView.initialize();
|
|
260
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
261
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
262
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
263
|
+
|
|
264
|
+
// Move section at index 2 up
|
|
265
|
+
tmpView._ManifestOpsProvider.moveSectionUp(2);
|
|
266
|
+
Expect(tmpPict.AppData.FormConfig.Sections[1].Hash).to.equal('S3');
|
|
267
|
+
Expect(tmpPict.AppData.FormConfig.Sections[2].Hash).to.equal('S2');
|
|
268
|
+
|
|
269
|
+
// Move section at index 0 down
|
|
270
|
+
tmpView._ManifestOpsProvider.moveSectionDown(0);
|
|
271
|
+
Expect(tmpPict.AppData.FormConfig.Sections[0].Hash).to.equal('S3');
|
|
272
|
+
Expect(tmpPict.AppData.FormConfig.Sections[1].Hash).to.equal('S1');
|
|
273
|
+
}
|
|
274
|
+
);
|
|
275
|
+
test
|
|
276
|
+
(
|
|
277
|
+
'Should update section properties',
|
|
278
|
+
function ()
|
|
279
|
+
{
|
|
280
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
281
|
+
tmpPict.AppData = {};
|
|
282
|
+
|
|
283
|
+
let tmpView = tmpPict.addView('TestUpdateSection',
|
|
284
|
+
{
|
|
285
|
+
ViewIdentifier: 'TestUpdateSection',
|
|
286
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
287
|
+
}, libPictSectionFormEditor);
|
|
288
|
+
|
|
289
|
+
tmpView.initialize();
|
|
290
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
291
|
+
|
|
292
|
+
tmpView._ManifestOpsProvider.updateSectionProperty(0, 'Name', 'Customer Info');
|
|
293
|
+
tmpView._ManifestOpsProvider.updateSectionProperty(0, 'Hash', 'CustomerInfo');
|
|
294
|
+
|
|
295
|
+
Expect(tmpPict.AppData.FormConfig.Sections[0].Name).to.equal('Customer Info');
|
|
296
|
+
Expect(tmpPict.AppData.FormConfig.Sections[0].Hash).to.equal('CustomerInfo');
|
|
297
|
+
}
|
|
298
|
+
);
|
|
299
|
+
test
|
|
300
|
+
(
|
|
301
|
+
'Should handle boundary conditions for section operations',
|
|
302
|
+
function ()
|
|
303
|
+
{
|
|
304
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
305
|
+
tmpPict.AppData = {};
|
|
306
|
+
|
|
307
|
+
let tmpView = tmpPict.addView('TestSectionBounds',
|
|
308
|
+
{
|
|
309
|
+
ViewIdentifier: 'TestSectionBounds',
|
|
310
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
311
|
+
}, libPictSectionFormEditor);
|
|
312
|
+
|
|
313
|
+
tmpView.initialize();
|
|
314
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
315
|
+
|
|
316
|
+
// Moving up at index 0 should be a no-op
|
|
317
|
+
tmpView._ManifestOpsProvider.moveSectionUp(0);
|
|
318
|
+
Expect(tmpPict.AppData.FormConfig.Sections[0].Hash).to.equal('S1');
|
|
319
|
+
|
|
320
|
+
// Moving down at last index should be a no-op
|
|
321
|
+
tmpView._ManifestOpsProvider.moveSectionDown(0);
|
|
322
|
+
Expect(tmpPict.AppData.FormConfig.Sections[0].Hash).to.equal('S1');
|
|
323
|
+
|
|
324
|
+
// Removing at invalid index should be a no-op
|
|
325
|
+
tmpView._ManifestOpsProvider.removeSection(5);
|
|
326
|
+
Expect(tmpPict.AppData.FormConfig.Sections.length).to.equal(1);
|
|
327
|
+
|
|
328
|
+
tmpView._ManifestOpsProvider.removeSection(-1);
|
|
329
|
+
Expect(tmpPict.AppData.FormConfig.Sections.length).to.equal(1);
|
|
330
|
+
}
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
);
|
|
334
|
+
suite
|
|
335
|
+
(
|
|
336
|
+
'Group Operations',
|
|
337
|
+
function ()
|
|
338
|
+
{
|
|
339
|
+
test
|
|
340
|
+
(
|
|
341
|
+
'Should add a group to a section',
|
|
342
|
+
function ()
|
|
343
|
+
{
|
|
344
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
345
|
+
tmpPict.AppData = {};
|
|
346
|
+
|
|
347
|
+
let tmpView = tmpPict.addView('TestAddGroup',
|
|
348
|
+
{
|
|
349
|
+
ViewIdentifier: 'TestAddGroup',
|
|
350
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
351
|
+
}, libPictSectionFormEditor);
|
|
352
|
+
|
|
353
|
+
tmpView.initialize();
|
|
354
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
355
|
+
|
|
356
|
+
// addSection creates a default group, so we already have one
|
|
357
|
+
let tmpSection = tmpPict.AppData.FormConfig.Sections[0];
|
|
358
|
+
Expect(tmpSection.Groups.length).to.equal(1);
|
|
359
|
+
Expect(tmpSection.Groups[0].Hash).to.equal('S1_G1');
|
|
360
|
+
Expect(tmpSection.Groups[0].Layout).to.equal('Record');
|
|
361
|
+
|
|
362
|
+
tmpView._ManifestOpsProvider.addGroup(0);
|
|
363
|
+
Expect(tmpSection.Groups.length).to.equal(2);
|
|
364
|
+
Expect(tmpSection.Groups[1].Hash).to.equal('S1_G2');
|
|
365
|
+
}
|
|
366
|
+
);
|
|
367
|
+
test
|
|
368
|
+
(
|
|
369
|
+
'Should remove a group from a section',
|
|
370
|
+
function ()
|
|
371
|
+
{
|
|
372
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
373
|
+
tmpPict.AppData = {};
|
|
374
|
+
|
|
375
|
+
let tmpView = tmpPict.addView('TestRemoveGroup',
|
|
376
|
+
{
|
|
377
|
+
ViewIdentifier: 'TestRemoveGroup',
|
|
378
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
379
|
+
}, libPictSectionFormEditor);
|
|
380
|
+
|
|
381
|
+
tmpView.initialize();
|
|
382
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
383
|
+
// addSection creates a default group; add two more
|
|
384
|
+
tmpView._ManifestOpsProvider.addGroup(0);
|
|
385
|
+
tmpView._ManifestOpsProvider.addGroup(0);
|
|
386
|
+
|
|
387
|
+
let tmpSection = tmpPict.AppData.FormConfig.Sections[0];
|
|
388
|
+
Expect(tmpSection.Groups.length).to.equal(3);
|
|
389
|
+
|
|
390
|
+
tmpView._ManifestOpsProvider.removeGroup(0, 1);
|
|
391
|
+
Expect(tmpSection.Groups.length).to.equal(2);
|
|
392
|
+
Expect(tmpSection.Groups[0].Hash).to.equal('S1_G1');
|
|
393
|
+
Expect(tmpSection.Groups[1].Hash).to.equal('S1_G3');
|
|
394
|
+
}
|
|
395
|
+
);
|
|
396
|
+
test
|
|
397
|
+
(
|
|
398
|
+
'Should move groups up and down',
|
|
399
|
+
function ()
|
|
400
|
+
{
|
|
401
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
402
|
+
tmpPict.AppData = {};
|
|
403
|
+
|
|
404
|
+
let tmpView = tmpPict.addView('TestMoveGroup',
|
|
405
|
+
{
|
|
406
|
+
ViewIdentifier: 'TestMoveGroup',
|
|
407
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
408
|
+
}, libPictSectionFormEditor);
|
|
409
|
+
|
|
410
|
+
tmpView.initialize();
|
|
411
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
412
|
+
// addSection creates a default group; add two more
|
|
413
|
+
tmpView._ManifestOpsProvider.addGroup(0);
|
|
414
|
+
tmpView._ManifestOpsProvider.addGroup(0);
|
|
415
|
+
|
|
416
|
+
let tmpSection = tmpPict.AppData.FormConfig.Sections[0];
|
|
417
|
+
|
|
418
|
+
tmpView._ManifestOpsProvider.moveGroupUp(0, 2);
|
|
419
|
+
Expect(tmpSection.Groups[1].Hash).to.equal('S1_G3');
|
|
420
|
+
Expect(tmpSection.Groups[2].Hash).to.equal('S1_G2');
|
|
421
|
+
|
|
422
|
+
tmpView._ManifestOpsProvider.moveGroupDown(0, 0);
|
|
423
|
+
Expect(tmpSection.Groups[0].Hash).to.equal('S1_G3');
|
|
424
|
+
Expect(tmpSection.Groups[1].Hash).to.equal('S1_G1');
|
|
425
|
+
}
|
|
426
|
+
);
|
|
427
|
+
test
|
|
428
|
+
(
|
|
429
|
+
'Should update group properties',
|
|
430
|
+
function ()
|
|
431
|
+
{
|
|
432
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
433
|
+
tmpPict.AppData = {};
|
|
434
|
+
|
|
435
|
+
let tmpView = tmpPict.addView('TestUpdateGroup',
|
|
436
|
+
{
|
|
437
|
+
ViewIdentifier: 'TestUpdateGroup',
|
|
438
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
439
|
+
}, libPictSectionFormEditor);
|
|
440
|
+
|
|
441
|
+
tmpView.initialize();
|
|
442
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
443
|
+
tmpView._ManifestOpsProvider.addGroup(0);
|
|
444
|
+
|
|
445
|
+
tmpView._ManifestOpsProvider.updateGroupProperty(0, 0, 'Name', 'Address Fields');
|
|
446
|
+
tmpView._ManifestOpsProvider.updateGroupProperty(0, 0, 'Hash', 'AddressFields');
|
|
447
|
+
tmpView._ManifestOpsProvider.updateGroupProperty(0, 0, 'Layout', 'Tabular');
|
|
448
|
+
|
|
449
|
+
let tmpGroup = tmpPict.AppData.FormConfig.Sections[0].Groups[0];
|
|
450
|
+
Expect(tmpGroup.Name).to.equal('Address Fields');
|
|
451
|
+
Expect(tmpGroup.Hash).to.equal('AddressFields');
|
|
452
|
+
Expect(tmpGroup.Layout).to.equal('Tabular');
|
|
453
|
+
}
|
|
454
|
+
);
|
|
455
|
+
}
|
|
456
|
+
);
|
|
457
|
+
suite
|
|
458
|
+
(
|
|
459
|
+
'Sanitize Object Key',
|
|
460
|
+
function ()
|
|
461
|
+
{
|
|
462
|
+
test
|
|
463
|
+
(
|
|
464
|
+
'Should sanitize strings into valid object keys',
|
|
465
|
+
function ()
|
|
466
|
+
{
|
|
467
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
468
|
+
let tmpView = tmpPict.addView('TestSanitize',
|
|
469
|
+
{
|
|
470
|
+
ViewIdentifier: 'TestSanitize',
|
|
471
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
472
|
+
}, libPictSectionFormEditor);
|
|
473
|
+
|
|
474
|
+
Expect(tmpView._UtilitiesProvider.sanitizeObjectKey('Section 1')).to.equal('Section_1');
|
|
475
|
+
Expect(tmpView._UtilitiesProvider.sanitizeObjectKey('Hello World')).to.equal('Hello_World');
|
|
476
|
+
Expect(tmpView._UtilitiesProvider.sanitizeObjectKey('foo--bar baz')).to.equal('foo_bar_baz');
|
|
477
|
+
Expect(tmpView._UtilitiesProvider.sanitizeObjectKey(' leading spaces ')).to.equal('leading_spaces');
|
|
478
|
+
Expect(tmpView._UtilitiesProvider.sanitizeObjectKey('AlreadyClean')).to.equal('AlreadyClean');
|
|
479
|
+
Expect(tmpView._UtilitiesProvider.sanitizeObjectKey('with_underscores')).to.equal('with_underscores');
|
|
480
|
+
Expect(tmpView._UtilitiesProvider.sanitizeObjectKey('')).to.equal('INVALID');
|
|
481
|
+
Expect(tmpView._UtilitiesProvider.sanitizeObjectKey(null)).to.equal('INVALID');
|
|
482
|
+
Expect(tmpView._UtilitiesProvider.sanitizeObjectKey(undefined)).to.equal('INVALID');
|
|
483
|
+
Expect(tmpView._UtilitiesProvider.sanitizeObjectKey(42)).to.equal('INVALID');
|
|
484
|
+
}
|
|
485
|
+
);
|
|
486
|
+
test
|
|
487
|
+
(
|
|
488
|
+
'Should cascade section hash changes to auto-generated group hashes',
|
|
489
|
+
function ()
|
|
490
|
+
{
|
|
491
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
492
|
+
tmpPict.AppData = {};
|
|
493
|
+
|
|
494
|
+
let tmpView = tmpPict.addView('TestCascade',
|
|
495
|
+
{
|
|
496
|
+
ViewIdentifier: 'TestCascade',
|
|
497
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
498
|
+
}, libPictSectionFormEditor);
|
|
499
|
+
|
|
500
|
+
tmpView.initialize();
|
|
501
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
502
|
+
tmpView._ManifestOpsProvider.addGroup(0);
|
|
503
|
+
|
|
504
|
+
let tmpSection = tmpPict.AppData.FormConfig.Sections[0];
|
|
505
|
+
Expect(tmpSection.Groups[0].Hash).to.equal('S1_G1');
|
|
506
|
+
Expect(tmpSection.Groups[1].Hash).to.equal('S1_G2');
|
|
507
|
+
|
|
508
|
+
// Rename the section hash; groups should cascade
|
|
509
|
+
tmpView._ManifestOpsProvider.updateSectionProperty(0, 'Hash', 'CustomerInfo');
|
|
510
|
+
Expect(tmpSection.Groups[0].Hash).to.equal('CustomerInfo_G1');
|
|
511
|
+
Expect(tmpSection.Groups[1].Hash).to.equal('CustomerInfo_G2');
|
|
512
|
+
}
|
|
513
|
+
);
|
|
514
|
+
test
|
|
515
|
+
(
|
|
516
|
+
'Should not cascade to manually customized group hashes',
|
|
517
|
+
function ()
|
|
518
|
+
{
|
|
519
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
520
|
+
tmpPict.AppData = {};
|
|
521
|
+
|
|
522
|
+
let tmpView = tmpPict.addView('TestNoCascade',
|
|
523
|
+
{
|
|
524
|
+
ViewIdentifier: 'TestNoCascade',
|
|
525
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
526
|
+
}, libPictSectionFormEditor);
|
|
527
|
+
|
|
528
|
+
tmpView.initialize();
|
|
529
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
530
|
+
tmpView._ManifestOpsProvider.addGroup(0);
|
|
531
|
+
|
|
532
|
+
let tmpSection = tmpPict.AppData.FormConfig.Sections[0];
|
|
533
|
+
|
|
534
|
+
// Manually customize the second group's hash (no _G prefix)
|
|
535
|
+
tmpSection.Groups[1].Hash = 'MyCustomHash';
|
|
536
|
+
|
|
537
|
+
// Rename the section hash; only auto-generated groups
|
|
538
|
+
// (those with the _G prefix) should cascade
|
|
539
|
+
tmpView._ManifestOpsProvider.updateSectionProperty(0, 'Hash', 'CustomerInfo');
|
|
540
|
+
Expect(tmpSection.Groups[0].Hash).to.equal('CustomerInfo_G1');
|
|
541
|
+
Expect(tmpSection.Groups[1].Hash).to.equal('MyCustomHash');
|
|
542
|
+
}
|
|
543
|
+
);
|
|
544
|
+
test
|
|
545
|
+
(
|
|
546
|
+
'Should cascade past a customized middle group',
|
|
547
|
+
function ()
|
|
548
|
+
{
|
|
549
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
550
|
+
tmpPict.AppData = {};
|
|
551
|
+
|
|
552
|
+
let tmpView = tmpPict.addView('TestCascadePast',
|
|
553
|
+
{
|
|
554
|
+
ViewIdentifier: 'TestCascadePast',
|
|
555
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
556
|
+
}, libPictSectionFormEditor);
|
|
557
|
+
|
|
558
|
+
tmpView.initialize();
|
|
559
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
560
|
+
tmpView._ManifestOpsProvider.addGroup(0);
|
|
561
|
+
tmpView._ManifestOpsProvider.addGroup(0);
|
|
562
|
+
|
|
563
|
+
let tmpSection = tmpPict.AppData.FormConfig.Sections[0];
|
|
564
|
+
Expect(tmpSection.Groups.length).to.equal(3);
|
|
565
|
+
|
|
566
|
+
// Customize the middle group's hash
|
|
567
|
+
tmpSection.Groups[1].Hash = 'CustomMiddle';
|
|
568
|
+
|
|
569
|
+
// Change section hash; groups 0 and 2 should update, group 1 stays
|
|
570
|
+
tmpView._ManifestOpsProvider.updateSectionProperty(0, 'Hash', 'NewSection');
|
|
571
|
+
Expect(tmpSection.Groups[0].Hash).to.equal('NewSection_G1');
|
|
572
|
+
Expect(tmpSection.Groups[1].Hash).to.equal('CustomMiddle');
|
|
573
|
+
Expect(tmpSection.Groups[2].Hash).to.equal('NewSection_G3');
|
|
574
|
+
}
|
|
575
|
+
);
|
|
576
|
+
}
|
|
577
|
+
);
|
|
578
|
+
suite
|
|
579
|
+
(
|
|
580
|
+
'Row Operations',
|
|
581
|
+
function ()
|
|
582
|
+
{
|
|
583
|
+
test
|
|
584
|
+
(
|
|
585
|
+
'Should add a row to a group',
|
|
586
|
+
function ()
|
|
587
|
+
{
|
|
588
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
589
|
+
tmpPict.AppData = {};
|
|
590
|
+
|
|
591
|
+
let tmpView = tmpPict.addView('TestAddRow',
|
|
592
|
+
{
|
|
593
|
+
ViewIdentifier: 'TestAddRow',
|
|
594
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
595
|
+
}, libPictSectionFormEditor);
|
|
596
|
+
|
|
597
|
+
tmpView.initialize();
|
|
598
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
599
|
+
|
|
600
|
+
let tmpGroup = tmpPict.AppData.FormConfig.Sections[0].Groups[0];
|
|
601
|
+
Expect(tmpGroup.Rows).to.be.undefined;
|
|
602
|
+
|
|
603
|
+
tmpView._ManifestOpsProvider.addRow(0, 0);
|
|
604
|
+
Expect(tmpGroup.Rows).to.be.an('array');
|
|
605
|
+
Expect(tmpGroup.Rows.length).to.equal(1);
|
|
606
|
+
Expect(tmpGroup.Rows[0].Inputs).to.be.an('array');
|
|
607
|
+
Expect(tmpGroup.Rows[0].Inputs.length).to.equal(0);
|
|
608
|
+
|
|
609
|
+
tmpView._ManifestOpsProvider.addRow(0, 0);
|
|
610
|
+
Expect(tmpGroup.Rows.length).to.equal(2);
|
|
611
|
+
}
|
|
612
|
+
);
|
|
613
|
+
test
|
|
614
|
+
(
|
|
615
|
+
'Should remove a row from a group',
|
|
616
|
+
function ()
|
|
617
|
+
{
|
|
618
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
619
|
+
tmpPict.AppData = {};
|
|
620
|
+
|
|
621
|
+
let tmpView = tmpPict.addView('TestRemoveRow',
|
|
622
|
+
{
|
|
623
|
+
ViewIdentifier: 'TestRemoveRow',
|
|
624
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
625
|
+
}, libPictSectionFormEditor);
|
|
626
|
+
|
|
627
|
+
tmpView.initialize();
|
|
628
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
629
|
+
tmpView._ManifestOpsProvider.addRow(0, 0);
|
|
630
|
+
tmpView._ManifestOpsProvider.addRow(0, 0);
|
|
631
|
+
tmpView._ManifestOpsProvider.addRow(0, 0);
|
|
632
|
+
|
|
633
|
+
let tmpGroup = tmpPict.AppData.FormConfig.Sections[0].Groups[0];
|
|
634
|
+
Expect(tmpGroup.Rows.length).to.equal(3);
|
|
635
|
+
|
|
636
|
+
tmpView._ManifestOpsProvider.removeRow(0, 0, 1);
|
|
637
|
+
Expect(tmpGroup.Rows.length).to.equal(2);
|
|
638
|
+
}
|
|
639
|
+
);
|
|
640
|
+
test
|
|
641
|
+
(
|
|
642
|
+
'Should move rows up and down',
|
|
643
|
+
function ()
|
|
644
|
+
{
|
|
645
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
646
|
+
tmpPict.AppData = {};
|
|
647
|
+
|
|
648
|
+
let tmpView = tmpPict.addView('TestMoveRow',
|
|
649
|
+
{
|
|
650
|
+
ViewIdentifier: 'TestMoveRow',
|
|
651
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
652
|
+
}, libPictSectionFormEditor);
|
|
653
|
+
|
|
654
|
+
tmpView.initialize();
|
|
655
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
656
|
+
tmpView._ManifestOpsProvider.addRow(0, 0);
|
|
657
|
+
tmpView._ManifestOpsProvider.addRow(0, 0);
|
|
658
|
+
tmpView._ManifestOpsProvider.addRow(0, 0);
|
|
659
|
+
|
|
660
|
+
let tmpGroup = tmpPict.AppData.FormConfig.Sections[0].Groups[0];
|
|
661
|
+
|
|
662
|
+
// Tag each row so we can track reordering
|
|
663
|
+
tmpGroup.Rows[0]._tag = 'A';
|
|
664
|
+
tmpGroup.Rows[1]._tag = 'B';
|
|
665
|
+
tmpGroup.Rows[2]._tag = 'C';
|
|
666
|
+
|
|
667
|
+
tmpView._ManifestOpsProvider.moveRowUp(0, 0, 2);
|
|
668
|
+
Expect(tmpGroup.Rows[1]._tag).to.equal('C');
|
|
669
|
+
Expect(tmpGroup.Rows[2]._tag).to.equal('B');
|
|
670
|
+
|
|
671
|
+
tmpView._ManifestOpsProvider.moveRowDown(0, 0, 0);
|
|
672
|
+
Expect(tmpGroup.Rows[0]._tag).to.equal('C');
|
|
673
|
+
Expect(tmpGroup.Rows[1]._tag).to.equal('A');
|
|
674
|
+
}
|
|
675
|
+
);
|
|
676
|
+
}
|
|
677
|
+
);
|
|
678
|
+
suite
|
|
679
|
+
(
|
|
680
|
+
'Input Operations',
|
|
681
|
+
function ()
|
|
682
|
+
{
|
|
683
|
+
test
|
|
684
|
+
(
|
|
685
|
+
'Should add an input to a row and create a Descriptor',
|
|
686
|
+
function ()
|
|
687
|
+
{
|
|
688
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
689
|
+
tmpPict.AppData = {};
|
|
690
|
+
|
|
691
|
+
let tmpView = tmpPict.addView('TestAddInput',
|
|
692
|
+
{
|
|
693
|
+
ViewIdentifier: 'TestAddInput',
|
|
694
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
695
|
+
}, libPictSectionFormEditor);
|
|
696
|
+
|
|
697
|
+
tmpView.initialize();
|
|
698
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
699
|
+
tmpView._ManifestOpsProvider.addRow(0, 0);
|
|
700
|
+
|
|
701
|
+
let tmpManifest = tmpPict.AppData.FormConfig;
|
|
702
|
+
let tmpRow = tmpManifest.Sections[0].Groups[0].Rows[0];
|
|
703
|
+
Expect(tmpRow.Inputs.length).to.equal(0);
|
|
704
|
+
|
|
705
|
+
tmpView._ManifestOpsProvider.addInput(0, 0, 0);
|
|
706
|
+
Expect(tmpRow.Inputs.length).to.equal(1);
|
|
707
|
+
|
|
708
|
+
// Inputs are now address strings referencing Descriptors
|
|
709
|
+
let tmpAddress1 = tmpRow.Inputs[0];
|
|
710
|
+
Expect(typeof tmpAddress1).to.equal('string');
|
|
711
|
+
Expect(tmpManifest.Descriptors).to.have.property(tmpAddress1);
|
|
712
|
+
|
|
713
|
+
let tmpDescriptor1 = tmpManifest.Descriptors[tmpAddress1];
|
|
714
|
+
Expect(tmpDescriptor1.DataType).to.equal('String');
|
|
715
|
+
Expect(tmpDescriptor1.Name).to.be.a('string');
|
|
716
|
+
Expect(tmpDescriptor1.Hash).to.be.a('string');
|
|
717
|
+
Expect(tmpDescriptor1.PictForm).to.be.an('object');
|
|
718
|
+
Expect(tmpDescriptor1.PictForm.Section).to.equal('S1');
|
|
719
|
+
Expect(tmpDescriptor1.PictForm.Group).to.equal('S1_G1');
|
|
720
|
+
Expect(tmpDescriptor1.PictForm.Row).to.equal(1);
|
|
721
|
+
|
|
722
|
+
tmpView._ManifestOpsProvider.addInput(0, 0, 0);
|
|
723
|
+
Expect(tmpRow.Inputs.length).to.equal(2);
|
|
724
|
+
let tmpAddress2 = tmpRow.Inputs[1];
|
|
725
|
+
Expect(tmpManifest.Descriptors).to.have.property(tmpAddress2);
|
|
726
|
+
Expect(tmpAddress1).to.not.equal(tmpAddress2);
|
|
727
|
+
}
|
|
728
|
+
);
|
|
729
|
+
test
|
|
730
|
+
(
|
|
731
|
+
'Should remove an input and its Descriptor',
|
|
732
|
+
function ()
|
|
733
|
+
{
|
|
734
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
735
|
+
tmpPict.AppData = {};
|
|
736
|
+
|
|
737
|
+
let tmpView = tmpPict.addView('TestRemoveInput',
|
|
738
|
+
{
|
|
739
|
+
ViewIdentifier: 'TestRemoveInput',
|
|
740
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
741
|
+
}, libPictSectionFormEditor);
|
|
742
|
+
|
|
743
|
+
tmpView.initialize();
|
|
744
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
745
|
+
tmpView._ManifestOpsProvider.addRow(0, 0);
|
|
746
|
+
tmpView._ManifestOpsProvider.addInput(0, 0, 0);
|
|
747
|
+
tmpView._ManifestOpsProvider.addInput(0, 0, 0);
|
|
748
|
+
tmpView._ManifestOpsProvider.addInput(0, 0, 0);
|
|
749
|
+
|
|
750
|
+
let tmpManifest = tmpPict.AppData.FormConfig;
|
|
751
|
+
let tmpRow = tmpManifest.Sections[0].Groups[0].Rows[0];
|
|
752
|
+
Expect(tmpRow.Inputs.length).to.equal(3);
|
|
753
|
+
|
|
754
|
+
let tmpAddress1 = tmpRow.Inputs[0];
|
|
755
|
+
let tmpAddress2 = tmpRow.Inputs[1];
|
|
756
|
+
let tmpAddress3 = tmpRow.Inputs[2];
|
|
757
|
+
|
|
758
|
+
// Remove the middle input
|
|
759
|
+
tmpView._ManifestOpsProvider.removeInput(0, 0, 0, 1);
|
|
760
|
+
Expect(tmpRow.Inputs.length).to.equal(2);
|
|
761
|
+
Expect(tmpRow.Inputs[0]).to.equal(tmpAddress1);
|
|
762
|
+
Expect(tmpRow.Inputs[1]).to.equal(tmpAddress3);
|
|
763
|
+
|
|
764
|
+
// The removed Descriptor should be gone
|
|
765
|
+
Expect(tmpManifest.Descriptors).to.not.have.property(tmpAddress2);
|
|
766
|
+
// The remaining Descriptors should still exist
|
|
767
|
+
Expect(tmpManifest.Descriptors).to.have.property(tmpAddress1);
|
|
768
|
+
Expect(tmpManifest.Descriptors).to.have.property(tmpAddress3);
|
|
769
|
+
}
|
|
770
|
+
);
|
|
771
|
+
test
|
|
772
|
+
(
|
|
773
|
+
'Should remove Descriptors when removing a row',
|
|
774
|
+
function ()
|
|
775
|
+
{
|
|
776
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
777
|
+
tmpPict.AppData = {};
|
|
778
|
+
|
|
779
|
+
let tmpView = tmpPict.addView('TestRemoveRowDescriptors',
|
|
780
|
+
{
|
|
781
|
+
ViewIdentifier: 'TestRemoveRowDescriptors',
|
|
782
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
783
|
+
}, libPictSectionFormEditor);
|
|
784
|
+
|
|
785
|
+
tmpView.initialize();
|
|
786
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
787
|
+
tmpView._ManifestOpsProvider.addRow(0, 0);
|
|
788
|
+
tmpView._ManifestOpsProvider.addRow(0, 0);
|
|
789
|
+
tmpView._ManifestOpsProvider.addInput(0, 0, 0);
|
|
790
|
+
tmpView._ManifestOpsProvider.addInput(0, 0, 0);
|
|
791
|
+
tmpView._ManifestOpsProvider.addInput(0, 0, 1);
|
|
792
|
+
|
|
793
|
+
let tmpManifest = tmpPict.AppData.FormConfig;
|
|
794
|
+
let tmpGroup = tmpManifest.Sections[0].Groups[0];
|
|
795
|
+
let tmpRow1Address1 = tmpGroup.Rows[0].Inputs[0];
|
|
796
|
+
let tmpRow1Address2 = tmpGroup.Rows[0].Inputs[1];
|
|
797
|
+
let tmpRow2Address1 = tmpGroup.Rows[1].Inputs[0];
|
|
798
|
+
|
|
799
|
+
Expect(Object.keys(tmpManifest.Descriptors).length).to.equal(3);
|
|
800
|
+
|
|
801
|
+
// Remove row 0 — its two descriptors should be deleted
|
|
802
|
+
tmpView._ManifestOpsProvider.removeRow(0, 0, 0);
|
|
803
|
+
Expect(tmpManifest.Descriptors).to.not.have.property(tmpRow1Address1);
|
|
804
|
+
Expect(tmpManifest.Descriptors).to.not.have.property(tmpRow1Address2);
|
|
805
|
+
Expect(tmpManifest.Descriptors).to.have.property(tmpRow2Address1);
|
|
806
|
+
Expect(Object.keys(tmpManifest.Descriptors).length).to.equal(1);
|
|
807
|
+
|
|
808
|
+
// Row 2 is now Row 1; its Descriptor PictForm.Row should be updated
|
|
809
|
+
Expect(tmpManifest.Descriptors[tmpRow2Address1].PictForm.Row).to.equal(1);
|
|
810
|
+
}
|
|
811
|
+
);
|
|
812
|
+
test
|
|
813
|
+
(
|
|
814
|
+
'Should remove Descriptors when removing a group',
|
|
815
|
+
function ()
|
|
816
|
+
{
|
|
817
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
818
|
+
tmpPict.AppData = {};
|
|
819
|
+
|
|
820
|
+
let tmpView = tmpPict.addView('TestRemoveGroupDescriptors',
|
|
821
|
+
{
|
|
822
|
+
ViewIdentifier: 'TestRemoveGroupDescriptors',
|
|
823
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
824
|
+
}, libPictSectionFormEditor);
|
|
825
|
+
|
|
826
|
+
tmpView.initialize();
|
|
827
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
828
|
+
tmpView._ManifestOpsProvider.addGroup(0);
|
|
829
|
+
tmpView._ManifestOpsProvider.addRow(0, 0);
|
|
830
|
+
tmpView._ManifestOpsProvider.addInput(0, 0, 0);
|
|
831
|
+
tmpView._ManifestOpsProvider.addRow(0, 1);
|
|
832
|
+
tmpView._ManifestOpsProvider.addInput(0, 1, 0);
|
|
833
|
+
|
|
834
|
+
let tmpManifest = tmpPict.AppData.FormConfig;
|
|
835
|
+
let tmpGroup0Address = tmpManifest.Sections[0].Groups[0].Rows[0].Inputs[0];
|
|
836
|
+
let tmpGroup1Address = tmpManifest.Sections[0].Groups[1].Rows[0].Inputs[0];
|
|
837
|
+
|
|
838
|
+
Expect(Object.keys(tmpManifest.Descriptors).length).to.equal(2);
|
|
839
|
+
|
|
840
|
+
// Remove group 0
|
|
841
|
+
tmpView._ManifestOpsProvider.removeGroup(0, 0);
|
|
842
|
+
Expect(tmpManifest.Descriptors).to.not.have.property(tmpGroup0Address);
|
|
843
|
+
Expect(tmpManifest.Descriptors).to.have.property(tmpGroup1Address);
|
|
844
|
+
Expect(Object.keys(tmpManifest.Descriptors).length).to.equal(1);
|
|
845
|
+
}
|
|
846
|
+
);
|
|
847
|
+
test
|
|
848
|
+
(
|
|
849
|
+
'Should remove Descriptors when removing a section',
|
|
850
|
+
function ()
|
|
851
|
+
{
|
|
852
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
853
|
+
tmpPict.AppData = {};
|
|
854
|
+
|
|
855
|
+
let tmpView = tmpPict.addView('TestRemoveSectionDescriptors',
|
|
856
|
+
{
|
|
857
|
+
ViewIdentifier: 'TestRemoveSectionDescriptors',
|
|
858
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
859
|
+
}, libPictSectionFormEditor);
|
|
860
|
+
|
|
861
|
+
tmpView.initialize();
|
|
862
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
863
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
864
|
+
tmpView._ManifestOpsProvider.addRow(0, 0);
|
|
865
|
+
tmpView._ManifestOpsProvider.addInput(0, 0, 0);
|
|
866
|
+
tmpView._ManifestOpsProvider.addRow(1, 0);
|
|
867
|
+
tmpView._ManifestOpsProvider.addInput(1, 0, 0);
|
|
868
|
+
|
|
869
|
+
let tmpManifest = tmpPict.AppData.FormConfig;
|
|
870
|
+
let tmpSection0Address = tmpManifest.Sections[0].Groups[0].Rows[0].Inputs[0];
|
|
871
|
+
let tmpSection1Address = tmpManifest.Sections[1].Groups[0].Rows[0].Inputs[0];
|
|
872
|
+
|
|
873
|
+
Expect(Object.keys(tmpManifest.Descriptors).length).to.equal(2);
|
|
874
|
+
|
|
875
|
+
// Remove section 0
|
|
876
|
+
tmpView._ManifestOpsProvider.removeSection(0);
|
|
877
|
+
Expect(tmpManifest.Descriptors).to.not.have.property(tmpSection0Address);
|
|
878
|
+
Expect(tmpManifest.Descriptors).to.have.property(tmpSection1Address);
|
|
879
|
+
Expect(Object.keys(tmpManifest.Descriptors).length).to.equal(1);
|
|
880
|
+
}
|
|
881
|
+
);
|
|
882
|
+
test
|
|
883
|
+
(
|
|
884
|
+
'Should sync PictForm.Row when rows are reordered',
|
|
885
|
+
function ()
|
|
886
|
+
{
|
|
887
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
888
|
+
tmpPict.AppData = {};
|
|
889
|
+
|
|
890
|
+
let tmpView = tmpPict.addView('TestRowSync',
|
|
891
|
+
{
|
|
892
|
+
ViewIdentifier: 'TestRowSync',
|
|
893
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
894
|
+
}, libPictSectionFormEditor);
|
|
895
|
+
|
|
896
|
+
tmpView.initialize();
|
|
897
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
898
|
+
tmpView._ManifestOpsProvider.addRow(0, 0);
|
|
899
|
+
tmpView._ManifestOpsProvider.addRow(0, 0);
|
|
900
|
+
tmpView._ManifestOpsProvider.addRow(0, 0);
|
|
901
|
+
tmpView._ManifestOpsProvider.addInput(0, 0, 0);
|
|
902
|
+
tmpView._ManifestOpsProvider.addInput(0, 0, 1);
|
|
903
|
+
tmpView._ManifestOpsProvider.addInput(0, 0, 2);
|
|
904
|
+
|
|
905
|
+
let tmpManifest = tmpPict.AppData.FormConfig;
|
|
906
|
+
let tmpGroup = tmpManifest.Sections[0].Groups[0];
|
|
907
|
+
let tmpAddr0 = tmpGroup.Rows[0].Inputs[0];
|
|
908
|
+
let tmpAddr1 = tmpGroup.Rows[1].Inputs[0];
|
|
909
|
+
let tmpAddr2 = tmpGroup.Rows[2].Inputs[0];
|
|
910
|
+
|
|
911
|
+
// Verify initial row assignments
|
|
912
|
+
Expect(tmpManifest.Descriptors[tmpAddr0].PictForm.Row).to.equal(1);
|
|
913
|
+
Expect(tmpManifest.Descriptors[tmpAddr1].PictForm.Row).to.equal(2);
|
|
914
|
+
Expect(tmpManifest.Descriptors[tmpAddr2].PictForm.Row).to.equal(3);
|
|
915
|
+
|
|
916
|
+
// Move row 2 up — swaps row 1 and row 2
|
|
917
|
+
tmpView._ManifestOpsProvider.moveRowUp(0, 0, 2);
|
|
918
|
+
Expect(tmpManifest.Descriptors[tmpAddr0].PictForm.Row).to.equal(1);
|
|
919
|
+
Expect(tmpManifest.Descriptors[tmpAddr2].PictForm.Row).to.equal(2);
|
|
920
|
+
Expect(tmpManifest.Descriptors[tmpAddr1].PictForm.Row).to.equal(3);
|
|
921
|
+
|
|
922
|
+
// Move row 0 down — swaps row 0 and row 1 (which is now addr2)
|
|
923
|
+
tmpView._ManifestOpsProvider.moveRowDown(0, 0, 0);
|
|
924
|
+
Expect(tmpManifest.Descriptors[tmpAddr2].PictForm.Row).to.equal(1);
|
|
925
|
+
Expect(tmpManifest.Descriptors[tmpAddr0].PictForm.Row).to.equal(2);
|
|
926
|
+
Expect(tmpManifest.Descriptors[tmpAddr1].PictForm.Row).to.equal(3);
|
|
927
|
+
}
|
|
928
|
+
);
|
|
929
|
+
test
|
|
930
|
+
(
|
|
931
|
+
'Should expose the full list of Manyfest DataTypes',
|
|
932
|
+
function ()
|
|
933
|
+
{
|
|
934
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
935
|
+
let tmpView = tmpPict.addView('TestDataTypes',
|
|
936
|
+
{
|
|
937
|
+
ViewIdentifier: 'TestDataTypes',
|
|
938
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
939
|
+
}, libPictSectionFormEditor);
|
|
940
|
+
|
|
941
|
+
Expect(tmpView._ManyfestDataTypes).to.be.an('array');
|
|
942
|
+
Expect(tmpView._ManyfestDataTypes).to.include('String');
|
|
943
|
+
Expect(tmpView._ManyfestDataTypes).to.include('Number');
|
|
944
|
+
Expect(tmpView._ManyfestDataTypes).to.include('Float');
|
|
945
|
+
Expect(tmpView._ManyfestDataTypes).to.include('Integer');
|
|
946
|
+
Expect(tmpView._ManyfestDataTypes).to.include('PreciseNumber');
|
|
947
|
+
Expect(tmpView._ManyfestDataTypes).to.include('Boolean');
|
|
948
|
+
Expect(tmpView._ManyfestDataTypes).to.include('Binary');
|
|
949
|
+
Expect(tmpView._ManyfestDataTypes).to.include('DateTime');
|
|
950
|
+
Expect(tmpView._ManyfestDataTypes).to.include('Array');
|
|
951
|
+
Expect(tmpView._ManyfestDataTypes).to.include('Object');
|
|
952
|
+
Expect(tmpView._ManyfestDataTypes).to.include('Null');
|
|
953
|
+
Expect(tmpView._ManyfestDataTypes.length).to.equal(11);
|
|
954
|
+
}
|
|
955
|
+
);
|
|
956
|
+
test
|
|
957
|
+
(
|
|
958
|
+
'Should expose InputType definitions as rich objects with Hash, Name, Description, Category',
|
|
959
|
+
function ()
|
|
960
|
+
{
|
|
961
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
962
|
+
let tmpView = tmpPict.addView('TestInputTypes',
|
|
963
|
+
{
|
|
964
|
+
ViewIdentifier: 'TestInputTypes',
|
|
965
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
966
|
+
}, libPictSectionFormEditor);
|
|
967
|
+
|
|
968
|
+
Expect(tmpView._InputTypeDefinitions).to.be.an('array');
|
|
969
|
+
Expect(tmpView._InputTypeDefinitions.length).to.equal(16);
|
|
970
|
+
|
|
971
|
+
// Check that each entry is a rich object
|
|
972
|
+
for (let i = 0; i < tmpView._InputTypeDefinitions.length; i++)
|
|
973
|
+
{
|
|
974
|
+
let tmpDef = tmpView._InputTypeDefinitions[i];
|
|
975
|
+
Expect(tmpDef).to.be.an('object');
|
|
976
|
+
Expect(tmpDef.Hash).to.be.a('string');
|
|
977
|
+
Expect(tmpDef.Name).to.be.a('string');
|
|
978
|
+
Expect(tmpDef.Description).to.be.a('string');
|
|
979
|
+
Expect(tmpDef.Category).to.be.a('string');
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
// Verify all 16 built-in InputTypes are present by Hash
|
|
983
|
+
let tmpHashes = tmpView._InputTypeDefinitions.map(function(d) { return d.Hash; });
|
|
984
|
+
Expect(tmpHashes).to.include('TextArea');
|
|
985
|
+
Expect(tmpHashes).to.include('Option');
|
|
986
|
+
Expect(tmpHashes).to.include('Boolean');
|
|
987
|
+
Expect(tmpHashes).to.include('Hidden');
|
|
988
|
+
Expect(tmpHashes).to.include('Color');
|
|
989
|
+
Expect(tmpHashes).to.include('DisplayOnly');
|
|
990
|
+
Expect(tmpHashes).to.include('ReadOnly');
|
|
991
|
+
Expect(tmpHashes).to.include('Link');
|
|
992
|
+
Expect(tmpHashes).to.include('Chart');
|
|
993
|
+
Expect(tmpHashes).to.include('Markdown');
|
|
994
|
+
Expect(tmpHashes).to.include('HTML');
|
|
995
|
+
Expect(tmpHashes).to.include('PreciseNumberReadOnly');
|
|
996
|
+
Expect(tmpHashes).to.include('Templated');
|
|
997
|
+
Expect(tmpHashes).to.include('TemplatedEntityLookup');
|
|
998
|
+
Expect(tmpHashes).to.include('TabGroupSelector');
|
|
999
|
+
Expect(tmpHashes).to.include('TabSectionSelector');
|
|
1000
|
+
}
|
|
1001
|
+
);
|
|
1002
|
+
test
|
|
1003
|
+
(
|
|
1004
|
+
'Should allow embedders to add custom InputType definitions via options',
|
|
1005
|
+
function ()
|
|
1006
|
+
{
|
|
1007
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
1008
|
+
let tmpView = tmpPict.addView('TestCustomInputTypes',
|
|
1009
|
+
{
|
|
1010
|
+
ViewIdentifier: 'TestCustomInputTypes',
|
|
1011
|
+
ManifestDataAddress: 'AppData.FormConfig',
|
|
1012
|
+
InputTypeDefinitions:
|
|
1013
|
+
[
|
|
1014
|
+
{ Hash: 'CustomWidget', Name: 'Custom Widget', Description: 'A custom widget type', Category: 'Custom' },
|
|
1015
|
+
{ Hash: 'CustomChart', Name: 'Custom Chart', Description: 'An extended chart type', Category: 'Custom' }
|
|
1016
|
+
]
|
|
1017
|
+
}, libPictSectionFormEditor);
|
|
1018
|
+
|
|
1019
|
+
Expect(tmpView._InputTypeDefinitions).to.be.an('array');
|
|
1020
|
+
// 16 defaults + 2 custom = 18
|
|
1021
|
+
Expect(tmpView._InputTypeDefinitions.length).to.equal(18);
|
|
1022
|
+
|
|
1023
|
+
let tmpHashes = tmpView._InputTypeDefinitions.map(function(d) { return d.Hash; });
|
|
1024
|
+
Expect(tmpHashes).to.include('CustomWidget');
|
|
1025
|
+
Expect(tmpHashes).to.include('CustomChart');
|
|
1026
|
+
// Built-in types should still be there
|
|
1027
|
+
Expect(tmpHashes).to.include('TextArea');
|
|
1028
|
+
Expect(tmpHashes).to.include('Boolean');
|
|
1029
|
+
}
|
|
1030
|
+
);
|
|
1031
|
+
test
|
|
1032
|
+
(
|
|
1033
|
+
'Should allow embedders to override built-in InputType definitions',
|
|
1034
|
+
function ()
|
|
1035
|
+
{
|
|
1036
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
1037
|
+
let tmpView = tmpPict.addView('TestOverrideInputTypes',
|
|
1038
|
+
{
|
|
1039
|
+
ViewIdentifier: 'TestOverrideInputTypes',
|
|
1040
|
+
ManifestDataAddress: 'AppData.FormConfig',
|
|
1041
|
+
InputTypeDefinitions:
|
|
1042
|
+
[
|
|
1043
|
+
{ Hash: 'Boolean', Name: 'Yes/No Toggle', Description: 'Overridden boolean' }
|
|
1044
|
+
]
|
|
1045
|
+
}, libPictSectionFormEditor);
|
|
1046
|
+
|
|
1047
|
+
// Count should stay at 16 since we overrode, not appended
|
|
1048
|
+
Expect(tmpView._InputTypeDefinitions.length).to.equal(16);
|
|
1049
|
+
|
|
1050
|
+
// Find the Boolean entry and verify it was overridden
|
|
1051
|
+
let tmpBoolDef = null;
|
|
1052
|
+
for (let i = 0; i < tmpView._InputTypeDefinitions.length; i++)
|
|
1053
|
+
{
|
|
1054
|
+
if (tmpView._InputTypeDefinitions[i].Hash === 'Boolean')
|
|
1055
|
+
{
|
|
1056
|
+
tmpBoolDef = tmpView._InputTypeDefinitions[i];
|
|
1057
|
+
break;
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
Expect(tmpBoolDef).to.not.be.null;
|
|
1061
|
+
Expect(tmpBoolDef.Name).to.equal('Yes/No Toggle');
|
|
1062
|
+
Expect(tmpBoolDef.Description).to.equal('Overridden boolean');
|
|
1063
|
+
// Category should be preserved from the default
|
|
1064
|
+
Expect(tmpBoolDef.Category).to.equal('Selection');
|
|
1065
|
+
}
|
|
1066
|
+
);
|
|
1067
|
+
test
|
|
1068
|
+
(
|
|
1069
|
+
'Should group InputType definitions by category',
|
|
1070
|
+
function ()
|
|
1071
|
+
{
|
|
1072
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
1073
|
+
let tmpView = tmpPict.addView('TestCategories',
|
|
1074
|
+
{
|
|
1075
|
+
ViewIdentifier: 'TestCategories',
|
|
1076
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
1077
|
+
}, libPictSectionFormEditor);
|
|
1078
|
+
|
|
1079
|
+
let tmpCategories = tmpView._UtilitiesProvider._getInputTypeCategories();
|
|
1080
|
+
Expect(tmpCategories).to.be.an('array');
|
|
1081
|
+
Expect(tmpCategories).to.include('Text & Content');
|
|
1082
|
+
Expect(tmpCategories).to.include('Selection');
|
|
1083
|
+
Expect(tmpCategories).to.include('Display');
|
|
1084
|
+
Expect(tmpCategories).to.include('Navigation');
|
|
1085
|
+
Expect(tmpCategories).to.include('Advanced');
|
|
1086
|
+
}
|
|
1087
|
+
);
|
|
1088
|
+
test
|
|
1089
|
+
(
|
|
1090
|
+
'Should filter InputType definitions by search query',
|
|
1091
|
+
function ()
|
|
1092
|
+
{
|
|
1093
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
1094
|
+
let tmpView = tmpPict.addView('TestFilter',
|
|
1095
|
+
{
|
|
1096
|
+
ViewIdentifier: 'TestFilter',
|
|
1097
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
1098
|
+
}, libPictSectionFormEditor);
|
|
1099
|
+
|
|
1100
|
+
// Search for "read" should find ReadOnly and PreciseNumberReadOnly
|
|
1101
|
+
let tmpFiltered = tmpView._UtilitiesProvider._filterInputTypeDefinitions('read');
|
|
1102
|
+
Expect(tmpFiltered).to.be.an('array');
|
|
1103
|
+
Expect(tmpFiltered.length).to.be.at.least(2);
|
|
1104
|
+
let tmpFilteredHashes = tmpFiltered.map(function(d) { return d.Hash; });
|
|
1105
|
+
Expect(tmpFilteredHashes).to.include('ReadOnly');
|
|
1106
|
+
Expect(tmpFilteredHashes).to.include('PreciseNumberReadOnly');
|
|
1107
|
+
|
|
1108
|
+
// Empty query should return all definitions
|
|
1109
|
+
let tmpAll = tmpView._UtilitiesProvider._filterInputTypeDefinitions('');
|
|
1110
|
+
Expect(tmpAll.length).to.equal(16);
|
|
1111
|
+
|
|
1112
|
+
// Non-matching query should return empty
|
|
1113
|
+
let tmpNone = tmpView._UtilitiesProvider._filterInputTypeDefinitions('zzzznonexistent');
|
|
1114
|
+
Expect(tmpNone.length).to.equal(0);
|
|
1115
|
+
}
|
|
1116
|
+
);
|
|
1117
|
+
}
|
|
1118
|
+
);
|
|
1119
|
+
suite
|
|
1120
|
+
(
|
|
1121
|
+
'Manifest Reconciliation',
|
|
1122
|
+
function ()
|
|
1123
|
+
{
|
|
1124
|
+
test
|
|
1125
|
+
(
|
|
1126
|
+
'Should build Rows and Inputs from Descriptors on an existing manifest',
|
|
1127
|
+
function ()
|
|
1128
|
+
{
|
|
1129
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
1130
|
+
tmpPict.AppData = {};
|
|
1131
|
+
tmpPict.AppData.FormConfig =
|
|
1132
|
+
{
|
|
1133
|
+
Scope: 'TestReconcile',
|
|
1134
|
+
Sections:
|
|
1135
|
+
[
|
|
1136
|
+
{
|
|
1137
|
+
Hash: 'Area',
|
|
1138
|
+
Name: 'Area Calculator',
|
|
1139
|
+
Groups:
|
|
1140
|
+
[
|
|
1141
|
+
{
|
|
1142
|
+
Hash: 'AreaDefault',
|
|
1143
|
+
Name: 'Default',
|
|
1144
|
+
Layout: 'Record'
|
|
1145
|
+
}
|
|
1146
|
+
]
|
|
1147
|
+
}
|
|
1148
|
+
],
|
|
1149
|
+
Descriptors:
|
|
1150
|
+
{
|
|
1151
|
+
'Name':
|
|
1152
|
+
{
|
|
1153
|
+
Name: 'Object Name',
|
|
1154
|
+
Hash: 'Name',
|
|
1155
|
+
DataType: 'String',
|
|
1156
|
+
PictForm: { Section: 'Area', Row: 1 }
|
|
1157
|
+
},
|
|
1158
|
+
'Width':
|
|
1159
|
+
{
|
|
1160
|
+
Name: 'Width',
|
|
1161
|
+
Hash: 'Width',
|
|
1162
|
+
DataType: 'Number',
|
|
1163
|
+
PictForm: { Section: 'Area', Row: 2 }
|
|
1164
|
+
},
|
|
1165
|
+
'Height':
|
|
1166
|
+
{
|
|
1167
|
+
Name: 'Height',
|
|
1168
|
+
Hash: 'Height',
|
|
1169
|
+
DataType: 'Number',
|
|
1170
|
+
PictForm: { Section: 'Area', Row: 2 }
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
};
|
|
1174
|
+
|
|
1175
|
+
let tmpView = tmpPict.addView('TestReconcile',
|
|
1176
|
+
{
|
|
1177
|
+
ViewIdentifier: 'TestReconcile',
|
|
1178
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
1179
|
+
}, libPictSectionFormEditor);
|
|
1180
|
+
|
|
1181
|
+
tmpView.initialize();
|
|
1182
|
+
tmpView._ManifestOpsProvider._reconcileManifestStructure();
|
|
1183
|
+
|
|
1184
|
+
let tmpGroup = tmpPict.AppData.FormConfig.Sections[0].Groups[0];
|
|
1185
|
+
Expect(tmpGroup.Rows).to.be.an('array');
|
|
1186
|
+
Expect(tmpGroup.Rows.length).to.equal(2);
|
|
1187
|
+
|
|
1188
|
+
// Row 1 should have one input: 'Name'
|
|
1189
|
+
Expect(tmpGroup.Rows[0].Inputs).to.be.an('array');
|
|
1190
|
+
Expect(tmpGroup.Rows[0].Inputs.length).to.equal(1);
|
|
1191
|
+
Expect(tmpGroup.Rows[0].Inputs[0]).to.equal('Name');
|
|
1192
|
+
|
|
1193
|
+
// Row 2 should have two inputs: 'Width' and 'Height'
|
|
1194
|
+
Expect(tmpGroup.Rows[1].Inputs).to.be.an('array');
|
|
1195
|
+
Expect(tmpGroup.Rows[1].Inputs.length).to.equal(2);
|
|
1196
|
+
Expect(tmpGroup.Rows[1].Inputs).to.include('Width');
|
|
1197
|
+
Expect(tmpGroup.Rows[1].Inputs).to.include('Height');
|
|
1198
|
+
}
|
|
1199
|
+
);
|
|
1200
|
+
test
|
|
1201
|
+
(
|
|
1202
|
+
'Should default to first group when PictForm.Group is omitted',
|
|
1203
|
+
function ()
|
|
1204
|
+
{
|
|
1205
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
1206
|
+
tmpPict.AppData = {};
|
|
1207
|
+
tmpPict.AppData.FormConfig =
|
|
1208
|
+
{
|
|
1209
|
+
Scope: 'TestDefaultGroup',
|
|
1210
|
+
Sections:
|
|
1211
|
+
[
|
|
1212
|
+
{
|
|
1213
|
+
Hash: 'Info',
|
|
1214
|
+
Name: 'Info Section',
|
|
1215
|
+
Groups:
|
|
1216
|
+
[
|
|
1217
|
+
{ Hash: 'Main', Name: 'Main', Layout: 'Record' },
|
|
1218
|
+
{ Hash: 'Extra', Name: 'Extra', Layout: 'Record' }
|
|
1219
|
+
]
|
|
1220
|
+
}
|
|
1221
|
+
],
|
|
1222
|
+
Descriptors:
|
|
1223
|
+
{
|
|
1224
|
+
'FirstName':
|
|
1225
|
+
{
|
|
1226
|
+
Name: 'First Name',
|
|
1227
|
+
Hash: 'FirstName',
|
|
1228
|
+
DataType: 'String',
|
|
1229
|
+
PictForm: { Section: 'Info', Row: 1 }
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
};
|
|
1233
|
+
|
|
1234
|
+
let tmpView = tmpPict.addView('TestDefaultGroup',
|
|
1235
|
+
{
|
|
1236
|
+
ViewIdentifier: 'TestDefaultGroup',
|
|
1237
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
1238
|
+
}, libPictSectionFormEditor);
|
|
1239
|
+
|
|
1240
|
+
tmpView.initialize();
|
|
1241
|
+
tmpView._ManifestOpsProvider._reconcileManifestStructure();
|
|
1242
|
+
|
|
1243
|
+
// Should land in the first group (Main)
|
|
1244
|
+
let tmpMainGroup = tmpPict.AppData.FormConfig.Sections[0].Groups[0];
|
|
1245
|
+
Expect(tmpMainGroup.Rows).to.be.an('array');
|
|
1246
|
+
Expect(tmpMainGroup.Rows[0].Inputs).to.include('FirstName');
|
|
1247
|
+
}
|
|
1248
|
+
);
|
|
1249
|
+
test
|
|
1250
|
+
(
|
|
1251
|
+
'Should place inputs in the correct named group',
|
|
1252
|
+
function ()
|
|
1253
|
+
{
|
|
1254
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
1255
|
+
tmpPict.AppData = {};
|
|
1256
|
+
tmpPict.AppData.FormConfig =
|
|
1257
|
+
{
|
|
1258
|
+
Scope: 'TestNamedGroup',
|
|
1259
|
+
Sections:
|
|
1260
|
+
[
|
|
1261
|
+
{
|
|
1262
|
+
Hash: 'Area',
|
|
1263
|
+
Name: 'Area',
|
|
1264
|
+
Groups:
|
|
1265
|
+
[
|
|
1266
|
+
{ Hash: 'Default', Name: 'Default', Layout: 'Record' },
|
|
1267
|
+
{ Hash: 'Help', Name: 'Help', Layout: 'Record' }
|
|
1268
|
+
]
|
|
1269
|
+
}
|
|
1270
|
+
],
|
|
1271
|
+
Descriptors:
|
|
1272
|
+
{
|
|
1273
|
+
'Help.Content':
|
|
1274
|
+
{
|
|
1275
|
+
Name: 'Help Content',
|
|
1276
|
+
Hash: 'HelpContent',
|
|
1277
|
+
DataType: 'String',
|
|
1278
|
+
PictForm: { Section: 'Area', Group: 'Help', Row: 1 }
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
};
|
|
1282
|
+
|
|
1283
|
+
let tmpView = tmpPict.addView('TestNamedGroup',
|
|
1284
|
+
{
|
|
1285
|
+
ViewIdentifier: 'TestNamedGroup',
|
|
1286
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
1287
|
+
}, libPictSectionFormEditor);
|
|
1288
|
+
|
|
1289
|
+
tmpView.initialize();
|
|
1290
|
+
tmpView._ManifestOpsProvider._reconcileManifestStructure();
|
|
1291
|
+
|
|
1292
|
+
// Should be in the Help group, not Default
|
|
1293
|
+
let tmpDefaultGroup = tmpPict.AppData.FormConfig.Sections[0].Groups[0];
|
|
1294
|
+
let tmpHelpGroup = tmpPict.AppData.FormConfig.Sections[0].Groups[1];
|
|
1295
|
+
Expect(tmpDefaultGroup.Rows).to.be.undefined;
|
|
1296
|
+
Expect(tmpHelpGroup.Rows).to.be.an('array');
|
|
1297
|
+
Expect(tmpHelpGroup.Rows[0].Inputs).to.include('Help.Content');
|
|
1298
|
+
}
|
|
1299
|
+
);
|
|
1300
|
+
test
|
|
1301
|
+
(
|
|
1302
|
+
'Should create a default group when section has no groups',
|
|
1303
|
+
function ()
|
|
1304
|
+
{
|
|
1305
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
1306
|
+
tmpPict.AppData = {};
|
|
1307
|
+
tmpPict.AppData.FormConfig =
|
|
1308
|
+
{
|
|
1309
|
+
Scope: 'TestNoGroups',
|
|
1310
|
+
Sections:
|
|
1311
|
+
[
|
|
1312
|
+
{
|
|
1313
|
+
Hash: 'SectionA',
|
|
1314
|
+
Name: 'Section A'
|
|
1315
|
+
}
|
|
1316
|
+
],
|
|
1317
|
+
Descriptors:
|
|
1318
|
+
{
|
|
1319
|
+
'SectionA.Amount':
|
|
1320
|
+
{
|
|
1321
|
+
Name: 'Amount in A',
|
|
1322
|
+
Hash: 'SectionAAmount',
|
|
1323
|
+
DataType: 'Number',
|
|
1324
|
+
PictForm: { Section: 'SectionA', Row: 1 }
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
};
|
|
1328
|
+
|
|
1329
|
+
let tmpView = tmpPict.addView('TestNoGroups',
|
|
1330
|
+
{
|
|
1331
|
+
ViewIdentifier: 'TestNoGroups',
|
|
1332
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
1333
|
+
}, libPictSectionFormEditor);
|
|
1334
|
+
|
|
1335
|
+
tmpView.initialize();
|
|
1336
|
+
tmpView._ManifestOpsProvider._reconcileManifestStructure();
|
|
1337
|
+
|
|
1338
|
+
let tmpSection = tmpPict.AppData.FormConfig.Sections[0];
|
|
1339
|
+
Expect(tmpSection.Groups).to.be.an('array');
|
|
1340
|
+
Expect(tmpSection.Groups.length).to.equal(1);
|
|
1341
|
+
Expect(tmpSection.Groups[0].Rows[0].Inputs).to.include('SectionA.Amount');
|
|
1342
|
+
}
|
|
1343
|
+
);
|
|
1344
|
+
test
|
|
1345
|
+
(
|
|
1346
|
+
'Should not duplicate inputs on repeated reconciliation calls',
|
|
1347
|
+
function ()
|
|
1348
|
+
{
|
|
1349
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
1350
|
+
tmpPict.AppData = {};
|
|
1351
|
+
tmpPict.AppData.FormConfig =
|
|
1352
|
+
{
|
|
1353
|
+
Scope: 'TestIdempotent',
|
|
1354
|
+
Sections:
|
|
1355
|
+
[
|
|
1356
|
+
{
|
|
1357
|
+
Hash: 'Sec',
|
|
1358
|
+
Name: 'Section',
|
|
1359
|
+
Groups:
|
|
1360
|
+
[
|
|
1361
|
+
{ Hash: 'Grp', Name: 'Group', Layout: 'Record' }
|
|
1362
|
+
]
|
|
1363
|
+
}
|
|
1364
|
+
],
|
|
1365
|
+
Descriptors:
|
|
1366
|
+
{
|
|
1367
|
+
'Field1':
|
|
1368
|
+
{
|
|
1369
|
+
Name: 'Field One',
|
|
1370
|
+
Hash: 'Field1',
|
|
1371
|
+
DataType: 'String',
|
|
1372
|
+
PictForm: { Section: 'Sec', Row: 1 }
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1375
|
+
};
|
|
1376
|
+
|
|
1377
|
+
let tmpView = tmpPict.addView('TestIdempotent',
|
|
1378
|
+
{
|
|
1379
|
+
ViewIdentifier: 'TestIdempotent',
|
|
1380
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
1381
|
+
}, libPictSectionFormEditor);
|
|
1382
|
+
|
|
1383
|
+
tmpView.initialize();
|
|
1384
|
+
|
|
1385
|
+
// Call reconcile multiple times
|
|
1386
|
+
tmpView._ManifestOpsProvider._reconcileManifestStructure();
|
|
1387
|
+
tmpView._ManifestOpsProvider._reconcileManifestStructure();
|
|
1388
|
+
tmpView._ManifestOpsProvider._reconcileManifestStructure();
|
|
1389
|
+
|
|
1390
|
+
let tmpGroup = tmpPict.AppData.FormConfig.Sections[0].Groups[0];
|
|
1391
|
+
Expect(tmpGroup.Rows[0].Inputs.length).to.equal(1);
|
|
1392
|
+
Expect(tmpGroup.Rows[0].Inputs[0]).to.equal('Field1');
|
|
1393
|
+
}
|
|
1394
|
+
);
|
|
1395
|
+
}
|
|
1396
|
+
);
|
|
1397
|
+
suite
|
|
1398
|
+
(
|
|
1399
|
+
'Tab Management',
|
|
1400
|
+
function ()
|
|
1401
|
+
{
|
|
1402
|
+
test
|
|
1403
|
+
(
|
|
1404
|
+
'Should default to visual tab',
|
|
1405
|
+
function ()
|
|
1406
|
+
{
|
|
1407
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
1408
|
+
let tmpView = tmpPict.addView('TestTabDefault',
|
|
1409
|
+
{
|
|
1410
|
+
ViewIdentifier: 'TestTabDefault',
|
|
1411
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
1412
|
+
}, libPictSectionFormEditor);
|
|
1413
|
+
|
|
1414
|
+
Expect(tmpView._ActiveTab).to.equal('visual');
|
|
1415
|
+
}
|
|
1416
|
+
);
|
|
1417
|
+
test
|
|
1418
|
+
(
|
|
1419
|
+
'Should switch tabs',
|
|
1420
|
+
function ()
|
|
1421
|
+
{
|
|
1422
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
1423
|
+
tmpPict.AppData = {};
|
|
1424
|
+
|
|
1425
|
+
let tmpView = tmpPict.addView('TestTabSwitch',
|
|
1426
|
+
{
|
|
1427
|
+
ViewIdentifier: 'TestTabSwitch',
|
|
1428
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
1429
|
+
}, libPictSectionFormEditor);
|
|
1430
|
+
|
|
1431
|
+
tmpView.initialize();
|
|
1432
|
+
|
|
1433
|
+
tmpView.switchTab('objecteditor');
|
|
1434
|
+
Expect(tmpView._ActiveTab).to.equal('objecteditor');
|
|
1435
|
+
|
|
1436
|
+
tmpView.switchTab('json');
|
|
1437
|
+
Expect(tmpView._ActiveTab).to.equal('json');
|
|
1438
|
+
|
|
1439
|
+
tmpView.switchTab('visual');
|
|
1440
|
+
Expect(tmpView._ActiveTab).to.equal('visual');
|
|
1441
|
+
}
|
|
1442
|
+
);
|
|
1443
|
+
}
|
|
1444
|
+
);
|
|
1445
|
+
suite
|
|
1446
|
+
(
|
|
1447
|
+
'Utility Methods',
|
|
1448
|
+
function ()
|
|
1449
|
+
{
|
|
1450
|
+
test
|
|
1451
|
+
(
|
|
1452
|
+
'Should escape HTML correctly',
|
|
1453
|
+
function ()
|
|
1454
|
+
{
|
|
1455
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
1456
|
+
let tmpView = tmpPict.addView('TestEscape',
|
|
1457
|
+
{
|
|
1458
|
+
ViewIdentifier: 'TestEscape',
|
|
1459
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
1460
|
+
}, libPictSectionFormEditor);
|
|
1461
|
+
|
|
1462
|
+
Expect(tmpView._UtilitiesProvider._escapeHTML('<script>alert("xss")</script>')).to.equal('<script>alert("xss")</script>');
|
|
1463
|
+
Expect(tmpView._UtilitiesProvider._escapeHTML('')).to.equal('');
|
|
1464
|
+
Expect(tmpView._UtilitiesProvider._escapeHTML(null)).to.equal('');
|
|
1465
|
+
Expect(tmpView._UtilitiesProvider._escapeHTML(undefined)).to.equal('');
|
|
1466
|
+
}
|
|
1467
|
+
);
|
|
1468
|
+
test
|
|
1469
|
+
(
|
|
1470
|
+
'Should escape attributes correctly',
|
|
1471
|
+
function ()
|
|
1472
|
+
{
|
|
1473
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
1474
|
+
let tmpView = tmpPict.addView('TestEscapeAttr',
|
|
1475
|
+
{
|
|
1476
|
+
ViewIdentifier: 'TestEscapeAttr',
|
|
1477
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
1478
|
+
}, libPictSectionFormEditor);
|
|
1479
|
+
|
|
1480
|
+
Expect(tmpView._UtilitiesProvider._escapeAttr('value with "quotes" and \'apostrophes\'')).to.equal('value with "quotes" and 'apostrophes'');
|
|
1481
|
+
}
|
|
1482
|
+
);
|
|
1483
|
+
}
|
|
1484
|
+
);
|
|
1485
|
+
suite
|
|
1486
|
+
(
|
|
1487
|
+
'Iconography Provider',
|
|
1488
|
+
function ()
|
|
1489
|
+
{
|
|
1490
|
+
test
|
|
1491
|
+
(
|
|
1492
|
+
'Should expose the iconography provider on the view',
|
|
1493
|
+
function ()
|
|
1494
|
+
{
|
|
1495
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
1496
|
+
let tmpView = tmpPict.addView('TestIconProvider',
|
|
1497
|
+
{
|
|
1498
|
+
ViewIdentifier: 'TestIconProvider',
|
|
1499
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
1500
|
+
}, libPictSectionFormEditor);
|
|
1501
|
+
|
|
1502
|
+
Expect(tmpView._IconographyProvider).to.be.an('object');
|
|
1503
|
+
}
|
|
1504
|
+
);
|
|
1505
|
+
test
|
|
1506
|
+
(
|
|
1507
|
+
'Should export the IconographyProvider class from the module',
|
|
1508
|
+
function ()
|
|
1509
|
+
{
|
|
1510
|
+
Expect(libPictSectionFormEditor.IconographyProvider).to.be.a('function');
|
|
1511
|
+
}
|
|
1512
|
+
);
|
|
1513
|
+
test
|
|
1514
|
+
(
|
|
1515
|
+
'Should register expected variants for each structural category',
|
|
1516
|
+
function ()
|
|
1517
|
+
{
|
|
1518
|
+
var libIconography = libPictSectionFormEditor.IconographyProvider;
|
|
1519
|
+
var tmpProvider = new libIconography();
|
|
1520
|
+
|
|
1521
|
+
var tmpSectionVariants = tmpProvider.getVariants('Section');
|
|
1522
|
+
var tmpGroupVariants = tmpProvider.getVariants('Group');
|
|
1523
|
+
var tmpRowVariants = tmpProvider.getVariants('Row');
|
|
1524
|
+
var tmpInputVariants = tmpProvider.getVariants('Input');
|
|
1525
|
+
|
|
1526
|
+
Expect(tmpSectionVariants.length).to.equal(11);
|
|
1527
|
+
Expect(tmpGroupVariants.length).to.equal(11);
|
|
1528
|
+
Expect(tmpRowVariants.length).to.equal(11);
|
|
1529
|
+
Expect(tmpInputVariants.length).to.equal(10);
|
|
1530
|
+
}
|
|
1531
|
+
);
|
|
1532
|
+
test
|
|
1533
|
+
(
|
|
1534
|
+
'Should return SVG strings for all structural icon variants',
|
|
1535
|
+
function ()
|
|
1536
|
+
{
|
|
1537
|
+
var libIconography = libPictSectionFormEditor.IconographyProvider;
|
|
1538
|
+
var tmpProvider = new libIconography();
|
|
1539
|
+
|
|
1540
|
+
var tmpCategories = ['Section', 'Group', 'Row', 'Input'];
|
|
1541
|
+
for (var c = 0; c < tmpCategories.length; c++)
|
|
1542
|
+
{
|
|
1543
|
+
var tmpVariants = tmpProvider.getVariants(tmpCategories[c]);
|
|
1544
|
+
for (var v = 0; v < tmpVariants.length; v++)
|
|
1545
|
+
{
|
|
1546
|
+
var tmpSVG = tmpProvider.getIcon(tmpCategories[c], tmpVariants[v]);
|
|
1547
|
+
Expect(tmpSVG).to.be.a('string');
|
|
1548
|
+
Expect(tmpSVG.indexOf('<svg')).to.equal(0);
|
|
1549
|
+
Expect(tmpSVG.indexOf('</svg>')).to.be.above(0);
|
|
1550
|
+
}
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
);
|
|
1554
|
+
test
|
|
1555
|
+
(
|
|
1556
|
+
'Should return SVG strings at custom sizes',
|
|
1557
|
+
function ()
|
|
1558
|
+
{
|
|
1559
|
+
var libIconography = libPictSectionFormEditor.IconographyProvider;
|
|
1560
|
+
var tmpProvider = new libIconography();
|
|
1561
|
+
|
|
1562
|
+
var tmpSVG16 = tmpProvider.getIcon('Section', 'Default', 16);
|
|
1563
|
+
var tmpSVG32 = tmpProvider.getIcon('Section', 'Default', 32);
|
|
1564
|
+
|
|
1565
|
+
Expect(tmpSVG16).to.contain('width="16"');
|
|
1566
|
+
Expect(tmpSVG16).to.contain('height="16"');
|
|
1567
|
+
Expect(tmpSVG32).to.contain('width="32"');
|
|
1568
|
+
Expect(tmpSVG32).to.contain('height="32"');
|
|
1569
|
+
}
|
|
1570
|
+
);
|
|
1571
|
+
test
|
|
1572
|
+
(
|
|
1573
|
+
'Should fall back to Default variant for unknown variant names',
|
|
1574
|
+
function ()
|
|
1575
|
+
{
|
|
1576
|
+
var libIconography = libPictSectionFormEditor.IconographyProvider;
|
|
1577
|
+
var tmpProvider = new libIconography();
|
|
1578
|
+
|
|
1579
|
+
var tmpSVG = tmpProvider.getIcon('Section', 'NonExistentVariant');
|
|
1580
|
+
var tmpDefault = tmpProvider.getIcon('Section', 'Default');
|
|
1581
|
+
Expect(tmpSVG).to.equal(tmpDefault);
|
|
1582
|
+
}
|
|
1583
|
+
);
|
|
1584
|
+
test
|
|
1585
|
+
(
|
|
1586
|
+
'Should return empty string for unknown category',
|
|
1587
|
+
function ()
|
|
1588
|
+
{
|
|
1589
|
+
var libIconography = libPictSectionFormEditor.IconographyProvider;
|
|
1590
|
+
var tmpProvider = new libIconography();
|
|
1591
|
+
|
|
1592
|
+
var tmpSVG = tmpProvider.getIcon('NonExistent', 'Default');
|
|
1593
|
+
Expect(tmpSVG).to.equal('');
|
|
1594
|
+
}
|
|
1595
|
+
);
|
|
1596
|
+
test
|
|
1597
|
+
(
|
|
1598
|
+
'Should register InputType icons for all built-in types',
|
|
1599
|
+
function ()
|
|
1600
|
+
{
|
|
1601
|
+
var libIconography = libPictSectionFormEditor.IconographyProvider;
|
|
1602
|
+
var tmpProvider = new libIconography();
|
|
1603
|
+
|
|
1604
|
+
var tmpHashes = tmpProvider.getInputTypeIconHashes();
|
|
1605
|
+
Expect(tmpHashes).to.be.an('array');
|
|
1606
|
+
Expect(tmpHashes.length).to.be.at.least(16);
|
|
1607
|
+
|
|
1608
|
+
// Check a sampling of known InputType icons
|
|
1609
|
+
Expect(tmpProvider.hasInputTypeIcon('TextArea')).to.be.true;
|
|
1610
|
+
Expect(tmpProvider.hasInputTypeIcon('Boolean')).to.be.true;
|
|
1611
|
+
Expect(tmpProvider.hasInputTypeIcon('DisplayOnly')).to.be.true;
|
|
1612
|
+
Expect(tmpProvider.hasInputTypeIcon('Hidden')).to.be.true;
|
|
1613
|
+
Expect(tmpProvider.hasInputTypeIcon('Chart')).to.be.true;
|
|
1614
|
+
Expect(tmpProvider.hasInputTypeIcon('Link')).to.be.true;
|
|
1615
|
+
Expect(tmpProvider.hasInputTypeIcon('Templated')).to.be.true;
|
|
1616
|
+
}
|
|
1617
|
+
);
|
|
1618
|
+
test
|
|
1619
|
+
(
|
|
1620
|
+
'Should return SVG strings for InputType icons',
|
|
1621
|
+
function ()
|
|
1622
|
+
{
|
|
1623
|
+
var libIconography = libPictSectionFormEditor.IconographyProvider;
|
|
1624
|
+
var tmpProvider = new libIconography();
|
|
1625
|
+
|
|
1626
|
+
var tmpSVG = tmpProvider.getInputTypeIcon('TextArea');
|
|
1627
|
+
Expect(tmpSVG).to.be.a('string');
|
|
1628
|
+
Expect(tmpSVG.indexOf('<svg')).to.equal(0);
|
|
1629
|
+
|
|
1630
|
+
var tmpSVG2 = tmpProvider.getInputTypeIcon('Boolean', 24);
|
|
1631
|
+
Expect(tmpSVG2).to.contain('width="24"');
|
|
1632
|
+
}
|
|
1633
|
+
);
|
|
1634
|
+
test
|
|
1635
|
+
(
|
|
1636
|
+
'Should return empty string for unknown InputType icon',
|
|
1637
|
+
function ()
|
|
1638
|
+
{
|
|
1639
|
+
var libIconography = libPictSectionFormEditor.IconographyProvider;
|
|
1640
|
+
var tmpProvider = new libIconography();
|
|
1641
|
+
|
|
1642
|
+
var tmpSVG = tmpProvider.getInputTypeIcon('CompletelyFakeType');
|
|
1643
|
+
Expect(tmpSVG).to.equal('');
|
|
1644
|
+
}
|
|
1645
|
+
);
|
|
1646
|
+
test
|
|
1647
|
+
(
|
|
1648
|
+
'Should allow overriding structural icons via setIcon',
|
|
1649
|
+
function ()
|
|
1650
|
+
{
|
|
1651
|
+
var libIconography = libPictSectionFormEditor.IconographyProvider;
|
|
1652
|
+
var tmpProvider = new libIconography();
|
|
1653
|
+
|
|
1654
|
+
var tmpCustomFactory = function(pSize, pColors, pSW)
|
|
1655
|
+
{
|
|
1656
|
+
return '<svg class="custom" width="' + pSize + '"></svg>';
|
|
1657
|
+
};
|
|
1658
|
+
|
|
1659
|
+
tmpProvider.setIcon('Section', 'Default', tmpCustomFactory);
|
|
1660
|
+
var tmpSVG = tmpProvider.getIcon('Section', 'Default');
|
|
1661
|
+
Expect(tmpSVG).to.contain('class="custom"');
|
|
1662
|
+
}
|
|
1663
|
+
);
|
|
1664
|
+
test
|
|
1665
|
+
(
|
|
1666
|
+
'Should allow adding new structural icon variants via setIcon',
|
|
1667
|
+
function ()
|
|
1668
|
+
{
|
|
1669
|
+
var libIconography = libPictSectionFormEditor.IconographyProvider;
|
|
1670
|
+
var tmpProvider = new libIconography();
|
|
1671
|
+
|
|
1672
|
+
var tmpCustomFactory = function(pSize, pColors, pSW)
|
|
1673
|
+
{
|
|
1674
|
+
return '<svg class="brand-new" width="' + pSize + '"></svg>';
|
|
1675
|
+
};
|
|
1676
|
+
|
|
1677
|
+
tmpProvider.setIcon('Section', 'MyBrandNew', tmpCustomFactory);
|
|
1678
|
+
Expect(tmpProvider.hasIcon('Section', 'MyBrandNew')).to.be.true;
|
|
1679
|
+
var tmpSVG = tmpProvider.getIcon('Section', 'MyBrandNew');
|
|
1680
|
+
Expect(tmpSVG).to.contain('class="brand-new"');
|
|
1681
|
+
}
|
|
1682
|
+
);
|
|
1683
|
+
test
|
|
1684
|
+
(
|
|
1685
|
+
'Should allow overriding InputType icons via setInputTypeIcon',
|
|
1686
|
+
function ()
|
|
1687
|
+
{
|
|
1688
|
+
var libIconography = libPictSectionFormEditor.IconographyProvider;
|
|
1689
|
+
var tmpProvider = new libIconography();
|
|
1690
|
+
|
|
1691
|
+
var tmpCustomFactory = function(pSize, pColors, pSW)
|
|
1692
|
+
{
|
|
1693
|
+
return '<svg class="custom-boolean" width="' + pSize + '"></svg>';
|
|
1694
|
+
};
|
|
1695
|
+
|
|
1696
|
+
tmpProvider.setInputTypeIcon('Boolean', tmpCustomFactory);
|
|
1697
|
+
var tmpSVG = tmpProvider.getInputTypeIcon('Boolean');
|
|
1698
|
+
Expect(tmpSVG).to.contain('class="custom-boolean"');
|
|
1699
|
+
}
|
|
1700
|
+
);
|
|
1701
|
+
test
|
|
1702
|
+
(
|
|
1703
|
+
'Should allow adding new InputType icons via setInputTypeIcon',
|
|
1704
|
+
function ()
|
|
1705
|
+
{
|
|
1706
|
+
var libIconography = libPictSectionFormEditor.IconographyProvider;
|
|
1707
|
+
var tmpProvider = new libIconography();
|
|
1708
|
+
|
|
1709
|
+
var tmpCustomFactory = function(pSize, pColors, pSW)
|
|
1710
|
+
{
|
|
1711
|
+
return '<svg class="custom-widget" width="' + pSize + '"></svg>';
|
|
1712
|
+
};
|
|
1713
|
+
|
|
1714
|
+
tmpProvider.setInputTypeIcon('CustomWidget', tmpCustomFactory);
|
|
1715
|
+
Expect(tmpProvider.hasInputTypeIcon('CustomWidget')).to.be.true;
|
|
1716
|
+
var tmpSVG = tmpProvider.getInputTypeIcon('CustomWidget');
|
|
1717
|
+
Expect(tmpSVG).to.contain('class="custom-widget"');
|
|
1718
|
+
}
|
|
1719
|
+
);
|
|
1720
|
+
test
|
|
1721
|
+
(
|
|
1722
|
+
'Should accept icon overrides via constructor options',
|
|
1723
|
+
function ()
|
|
1724
|
+
{
|
|
1725
|
+
var libIconography = libPictSectionFormEditor.IconographyProvider;
|
|
1726
|
+
var tmpProvider = new libIconography(
|
|
1727
|
+
{
|
|
1728
|
+
IconOverrides:
|
|
1729
|
+
{
|
|
1730
|
+
Section:
|
|
1731
|
+
{
|
|
1732
|
+
Default: function(pSize, pColors, pSW) { return '<svg class="opts-override" width="' + pSize + '"></svg>'; }
|
|
1733
|
+
}
|
|
1734
|
+
},
|
|
1735
|
+
InputTypeIconOverrides:
|
|
1736
|
+
{
|
|
1737
|
+
TextArea: function(pSize, pColors, pSW) { return '<svg class="opts-textarea" width="' + pSize + '"></svg>'; }
|
|
1738
|
+
}
|
|
1739
|
+
});
|
|
1740
|
+
|
|
1741
|
+
var tmpSVG = tmpProvider.getIcon('Section', 'Default');
|
|
1742
|
+
Expect(tmpSVG).to.contain('class="opts-override"');
|
|
1743
|
+
|
|
1744
|
+
var tmpSVG2 = tmpProvider.getInputTypeIcon('TextArea');
|
|
1745
|
+
Expect(tmpSVG2).to.contain('class="opts-textarea"');
|
|
1746
|
+
}
|
|
1747
|
+
);
|
|
1748
|
+
test
|
|
1749
|
+
(
|
|
1750
|
+
'Should support custom color tokens',
|
|
1751
|
+
function ()
|
|
1752
|
+
{
|
|
1753
|
+
var libIconography = libPictSectionFormEditor.IconographyProvider;
|
|
1754
|
+
var tmpProvider = new libIconography(
|
|
1755
|
+
{
|
|
1756
|
+
Colors:
|
|
1757
|
+
{
|
|
1758
|
+
Primary: '#FF0000',
|
|
1759
|
+
Accent: '#00FF00',
|
|
1760
|
+
Muted: '#0000FF',
|
|
1761
|
+
Fill: '#FFFFFF'
|
|
1762
|
+
}
|
|
1763
|
+
});
|
|
1764
|
+
|
|
1765
|
+
var tmpSVG = tmpProvider.getIcon('Section', 'Default');
|
|
1766
|
+
Expect(tmpSVG).to.contain('#FF0000');
|
|
1767
|
+
Expect(tmpSVG).to.contain('#FFFFFF');
|
|
1768
|
+
}
|
|
1769
|
+
);
|
|
1770
|
+
test
|
|
1771
|
+
(
|
|
1772
|
+
'Should have hasIcon and hasInputTypeIcon return correct booleans',
|
|
1773
|
+
function ()
|
|
1774
|
+
{
|
|
1775
|
+
var libIconography = libPictSectionFormEditor.IconographyProvider;
|
|
1776
|
+
var tmpProvider = new libIconography();
|
|
1777
|
+
|
|
1778
|
+
Expect(tmpProvider.hasIcon('Section', 'Default')).to.be.true;
|
|
1779
|
+
Expect(tmpProvider.hasIcon('Section', 'Layers')).to.be.true;
|
|
1780
|
+
Expect(tmpProvider.hasIcon('Section', 'NonExistent')).to.be.false;
|
|
1781
|
+
Expect(tmpProvider.hasIcon('FakeCategory', 'Default')).to.be.false;
|
|
1782
|
+
|
|
1783
|
+
Expect(tmpProvider.hasInputTypeIcon('TextArea')).to.be.true;
|
|
1784
|
+
Expect(tmpProvider.hasInputTypeIcon('FakeHash')).to.be.false;
|
|
1785
|
+
}
|
|
1786
|
+
);
|
|
1787
|
+
test
|
|
1788
|
+
(
|
|
1789
|
+
'Should make the iconography provider accessible on the FormEditor view with custom options',
|
|
1790
|
+
function ()
|
|
1791
|
+
{
|
|
1792
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
1793
|
+
let tmpView = tmpPict.addView('TestIconProviderOpts',
|
|
1794
|
+
{
|
|
1795
|
+
ViewIdentifier: 'TestIconProviderOpts',
|
|
1796
|
+
ManifestDataAddress: 'AppData.FormConfig',
|
|
1797
|
+
Iconography:
|
|
1798
|
+
{
|
|
1799
|
+
Colors:
|
|
1800
|
+
{
|
|
1801
|
+
Primary: '#112233',
|
|
1802
|
+
Accent: '#445566',
|
|
1803
|
+
Muted: '#778899',
|
|
1804
|
+
Fill: '#AABBCC'
|
|
1805
|
+
}
|
|
1806
|
+
}
|
|
1807
|
+
}, libPictSectionFormEditor);
|
|
1808
|
+
|
|
1809
|
+
var tmpSVG = tmpView._IconographyProvider.getIcon('Section', 'Default');
|
|
1810
|
+
Expect(tmpSVG).to.contain('#112233');
|
|
1811
|
+
Expect(tmpSVG).to.contain('#AABBCC');
|
|
1812
|
+
}
|
|
1813
|
+
);
|
|
1814
|
+
test
|
|
1815
|
+
(
|
|
1816
|
+
'Should have a DragHandle icon in the Action category',
|
|
1817
|
+
function ()
|
|
1818
|
+
{
|
|
1819
|
+
var libIconography = libPictSectionFormEditor.IconographyProvider;
|
|
1820
|
+
var tmpProvider = new libIconography();
|
|
1821
|
+
|
|
1822
|
+
var tmpActionVariants = tmpProvider.getVariants('Action');
|
|
1823
|
+
Expect(tmpActionVariants).to.be.an('array');
|
|
1824
|
+
Expect(tmpActionVariants.length).to.equal(2);
|
|
1825
|
+
Expect(tmpActionVariants).to.include('Add');
|
|
1826
|
+
Expect(tmpActionVariants).to.include('DragHandle');
|
|
1827
|
+
|
|
1828
|
+
var tmpSVG = tmpProvider.getIcon('Action', 'DragHandle');
|
|
1829
|
+
Expect(tmpSVG).to.be.a('string');
|
|
1830
|
+
Expect(tmpSVG.indexOf('<svg')).to.equal(0);
|
|
1831
|
+
Expect(tmpSVG).to.contain('currentColor');
|
|
1832
|
+
}
|
|
1833
|
+
);
|
|
1834
|
+
test
|
|
1835
|
+
(
|
|
1836
|
+
'Should have drag-and-drop disabled by default',
|
|
1837
|
+
function ()
|
|
1838
|
+
{
|
|
1839
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
1840
|
+
let tmpView = tmpPict.addView('TestDragDropDefault',
|
|
1841
|
+
{
|
|
1842
|
+
ViewIdentifier: 'TestDragDropDefault',
|
|
1843
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
1844
|
+
}, libPictSectionFormEditor);
|
|
1845
|
+
|
|
1846
|
+
Expect(tmpView._DragAndDropEnabled).to.equal(false);
|
|
1847
|
+
Expect(tmpView._DragState).to.equal(null);
|
|
1848
|
+
}
|
|
1849
|
+
);
|
|
1850
|
+
test
|
|
1851
|
+
(
|
|
1852
|
+
'Should enable and disable drag-and-drop via setDragAndDropEnabled',
|
|
1853
|
+
function (fDone)
|
|
1854
|
+
{
|
|
1855
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
1856
|
+
tmpPict.AppData.FormConfig =
|
|
1857
|
+
{
|
|
1858
|
+
Scope: 'TestDragDrop',
|
|
1859
|
+
Sections: [],
|
|
1860
|
+
Descriptors: {}
|
|
1861
|
+
};
|
|
1862
|
+
|
|
1863
|
+
let tmpView = tmpPict.addView('TestDragDropToggle',
|
|
1864
|
+
{
|
|
1865
|
+
ViewIdentifier: 'TestDragDropToggle',
|
|
1866
|
+
ManifestDataAddress: 'AppData.FormConfig',
|
|
1867
|
+
DefaultDestinationAddress: '#FormEditor-Container',
|
|
1868
|
+
Renderables:
|
|
1869
|
+
[
|
|
1870
|
+
{
|
|
1871
|
+
RenderableHash: 'FormEditor-Container',
|
|
1872
|
+
TemplateHash: 'FormEditor-Container-Template',
|
|
1873
|
+
DestinationAddress: '#FormEditor-Container',
|
|
1874
|
+
RenderMethod: 'replace'
|
|
1875
|
+
}
|
|
1876
|
+
]
|
|
1877
|
+
}, libPictSectionFormEditor);
|
|
1878
|
+
|
|
1879
|
+
tmpView.initialize();
|
|
1880
|
+
tmpView.render();
|
|
1881
|
+
|
|
1882
|
+
Expect(tmpView._DragAndDropEnabled).to.equal(false);
|
|
1883
|
+
|
|
1884
|
+
tmpView._DragDropProvider.setDragAndDropEnabled(true);
|
|
1885
|
+
Expect(tmpView._DragAndDropEnabled).to.equal(true);
|
|
1886
|
+
|
|
1887
|
+
tmpView._DragDropProvider.setDragAndDropEnabled(false);
|
|
1888
|
+
Expect(tmpView._DragAndDropEnabled).to.equal(false);
|
|
1889
|
+
|
|
1890
|
+
fDone();
|
|
1891
|
+
}
|
|
1892
|
+
);
|
|
1893
|
+
test
|
|
1894
|
+
(
|
|
1895
|
+
'Should build drag attributes only when enabled',
|
|
1896
|
+
function ()
|
|
1897
|
+
{
|
|
1898
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
1899
|
+
let tmpView = tmpPict.addView('TestDragAttrs',
|
|
1900
|
+
{
|
|
1901
|
+
ViewIdentifier: 'TestDragAttrs',
|
|
1902
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
1903
|
+
}, libPictSectionFormEditor);
|
|
1904
|
+
|
|
1905
|
+
// Disabled — should return empty string
|
|
1906
|
+
var tmpAttrs = tmpView._DragDropProvider._buildDragAttributes('section', [0]);
|
|
1907
|
+
Expect(tmpAttrs).to.equal('');
|
|
1908
|
+
|
|
1909
|
+
var tmpHandle = tmpView._DragDropProvider._buildDragHandleHTML(12);
|
|
1910
|
+
Expect(tmpHandle).to.equal('');
|
|
1911
|
+
|
|
1912
|
+
// Enabled — should return drag attribute string
|
|
1913
|
+
tmpView._DragAndDropEnabled = true;
|
|
1914
|
+
tmpAttrs = tmpView._DragDropProvider._buildDragAttributes('section', [0]);
|
|
1915
|
+
Expect(tmpAttrs).to.contain('draggable="true"');
|
|
1916
|
+
Expect(tmpAttrs).to.contain('ondragstart');
|
|
1917
|
+
Expect(tmpAttrs).to.contain('ondrop');
|
|
1918
|
+
|
|
1919
|
+
tmpHandle = tmpView._DragDropProvider._buildDragHandleHTML(12);
|
|
1920
|
+
Expect(tmpHandle).to.contain('pict-fe-drag-handle');
|
|
1921
|
+
Expect(tmpHandle).to.contain('<svg');
|
|
1922
|
+
}
|
|
1923
|
+
);
|
|
1924
|
+
test
|
|
1925
|
+
(
|
|
1926
|
+
'Should correctly determine if drag indices share a parent',
|
|
1927
|
+
function ()
|
|
1928
|
+
{
|
|
1929
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
1930
|
+
let tmpView = tmpPict.addView('TestDragParent',
|
|
1931
|
+
{
|
|
1932
|
+
ViewIdentifier: 'TestDragParent',
|
|
1933
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
1934
|
+
}, libPictSectionFormEditor);
|
|
1935
|
+
|
|
1936
|
+
// Sections (1 index) — always share root
|
|
1937
|
+
Expect(tmpView._DragDropProvider._dragIndicesShareParent([0], [1])).to.equal(true);
|
|
1938
|
+
Expect(tmpView._DragDropProvider._dragIndicesShareParent([0], [2])).to.equal(true);
|
|
1939
|
+
|
|
1940
|
+
// Groups (2 indices) — must share section
|
|
1941
|
+
Expect(tmpView._DragDropProvider._dragIndicesShareParent([0, 1], [0, 2])).to.equal(true);
|
|
1942
|
+
Expect(tmpView._DragDropProvider._dragIndicesShareParent([0, 1], [1, 2])).to.equal(false);
|
|
1943
|
+
|
|
1944
|
+
// Rows (3 indices) — must share section + group
|
|
1945
|
+
Expect(tmpView._DragDropProvider._dragIndicesShareParent([0, 0, 1], [0, 0, 3])).to.equal(true);
|
|
1946
|
+
Expect(tmpView._DragDropProvider._dragIndicesShareParent([0, 0, 1], [0, 1, 3])).to.equal(false);
|
|
1947
|
+
|
|
1948
|
+
// Inputs (4 indices) — must share section + group + row
|
|
1949
|
+
Expect(tmpView._DragDropProvider._dragIndicesShareParent([0, 0, 0, 1], [0, 0, 0, 3])).to.equal(true);
|
|
1950
|
+
Expect(tmpView._DragDropProvider._dragIndicesShareParent([0, 0, 0, 1], [0, 0, 1, 3])).to.equal(false);
|
|
1951
|
+
|
|
1952
|
+
// Mismatched lengths
|
|
1953
|
+
Expect(tmpView._DragDropProvider._dragIndicesShareParent([0], [0, 1])).to.equal(false);
|
|
1954
|
+
}
|
|
1955
|
+
);
|
|
1956
|
+
test
|
|
1957
|
+
(
|
|
1958
|
+
'Should support cross-container drag and drop for groups',
|
|
1959
|
+
function (fDone)
|
|
1960
|
+
{
|
|
1961
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
1962
|
+
tmpPict.AppData.FormConfig =
|
|
1963
|
+
{
|
|
1964
|
+
Scope: 'CrossDragGroup',
|
|
1965
|
+
Sections:
|
|
1966
|
+
[
|
|
1967
|
+
{
|
|
1968
|
+
Name: 'Section A', Hash: 'SectionA',
|
|
1969
|
+
Groups:
|
|
1970
|
+
[
|
|
1971
|
+
{ Name: 'Group A1', Hash: 'GroupA1', Rows: [] },
|
|
1972
|
+
{ Name: 'Group A2', Hash: 'GroupA2', Rows: [] }
|
|
1973
|
+
]
|
|
1974
|
+
},
|
|
1975
|
+
{
|
|
1976
|
+
Name: 'Section B', Hash: 'SectionB',
|
|
1977
|
+
Groups:
|
|
1978
|
+
[
|
|
1979
|
+
{ Name: 'Group B1', Hash: 'GroupB1', Rows: [] }
|
|
1980
|
+
]
|
|
1981
|
+
}
|
|
1982
|
+
],
|
|
1983
|
+
Descriptors: {}
|
|
1984
|
+
};
|
|
1985
|
+
|
|
1986
|
+
let tmpView = tmpPict.addView('TestCrossDragGroup',
|
|
1987
|
+
{
|
|
1988
|
+
ViewIdentifier: 'TestCrossDragGroup',
|
|
1989
|
+
ManifestDataAddress: 'AppData.FormConfig',
|
|
1990
|
+
DefaultDestinationAddress: '#FormEditor-Container',
|
|
1991
|
+
Renderables:
|
|
1992
|
+
[
|
|
1993
|
+
{
|
|
1994
|
+
RenderableHash: 'FormEditor-Container',
|
|
1995
|
+
TemplateHash: 'FormEditor-Container-Template',
|
|
1996
|
+
DestinationAddress: '#FormEditor-Container',
|
|
1997
|
+
RenderMethod: 'replace'
|
|
1998
|
+
}
|
|
1999
|
+
]
|
|
2000
|
+
}, libPictSectionFormEditor);
|
|
2001
|
+
|
|
2002
|
+
tmpView.initialize();
|
|
2003
|
+
tmpView.render();
|
|
2004
|
+
tmpView._DragAndDropEnabled = true;
|
|
2005
|
+
|
|
2006
|
+
// Move Group A2 from Section A to Section B (drop on Group B1)
|
|
2007
|
+
tmpView._DragState = { Type: 'group', Indices: [0, 1] };
|
|
2008
|
+
tmpView._DragDropProvider.onDrop(
|
|
2009
|
+
{ preventDefault: function() {} },
|
|
2010
|
+
'group', 1, 0
|
|
2011
|
+
);
|
|
2012
|
+
|
|
2013
|
+
var tmpManifest = tmpPict.AppData.FormConfig;
|
|
2014
|
+
// Section A should now have 1 group
|
|
2015
|
+
Expect(tmpManifest.Sections[0].Groups.length).to.equal(1);
|
|
2016
|
+
Expect(tmpManifest.Sections[0].Groups[0].Hash).to.equal('GroupA1');
|
|
2017
|
+
// Section B should now have 2 groups (GroupA2 inserted before GroupB1)
|
|
2018
|
+
Expect(tmpManifest.Sections[1].Groups.length).to.equal(2);
|
|
2019
|
+
Expect(tmpManifest.Sections[1].Groups[0].Hash).to.equal('GroupA2');
|
|
2020
|
+
Expect(tmpManifest.Sections[1].Groups[1].Hash).to.equal('GroupB1');
|
|
2021
|
+
|
|
2022
|
+
fDone();
|
|
2023
|
+
}
|
|
2024
|
+
);
|
|
2025
|
+
test
|
|
2026
|
+
(
|
|
2027
|
+
'Should support cross-container drag and drop for rows',
|
|
2028
|
+
function (fDone)
|
|
2029
|
+
{
|
|
2030
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
2031
|
+
tmpPict.AppData.FormConfig =
|
|
2032
|
+
{
|
|
2033
|
+
Scope: 'CrossDragRow',
|
|
2034
|
+
Sections:
|
|
2035
|
+
[
|
|
2036
|
+
{
|
|
2037
|
+
Name: 'Section A', Hash: 'SectionA',
|
|
2038
|
+
Groups:
|
|
2039
|
+
[
|
|
2040
|
+
{
|
|
2041
|
+
Name: 'Group A1', Hash: 'GroupA1',
|
|
2042
|
+
Rows:
|
|
2043
|
+
[
|
|
2044
|
+
{ Inputs: ['addrA'] },
|
|
2045
|
+
{ Inputs: ['addrB'] }
|
|
2046
|
+
]
|
|
2047
|
+
},
|
|
2048
|
+
{
|
|
2049
|
+
Name: 'Group A2', Hash: 'GroupA2',
|
|
2050
|
+
Rows:
|
|
2051
|
+
[
|
|
2052
|
+
{ Inputs: ['addrC'] }
|
|
2053
|
+
]
|
|
2054
|
+
}
|
|
2055
|
+
]
|
|
2056
|
+
}
|
|
2057
|
+
],
|
|
2058
|
+
Descriptors:
|
|
2059
|
+
{
|
|
2060
|
+
addrA: { Name: 'InputA', Hash: 'InputA', DataType: 'String', PictForm: { Section: 'SectionA', Group: 'GroupA1', Row: 1 } },
|
|
2061
|
+
addrB: { Name: 'InputB', Hash: 'InputB', DataType: 'String', PictForm: { Section: 'SectionA', Group: 'GroupA1', Row: 2 } },
|
|
2062
|
+
addrC: { Name: 'InputC', Hash: 'InputC', DataType: 'String', PictForm: { Section: 'SectionA', Group: 'GroupA2', Row: 1 } }
|
|
2063
|
+
}
|
|
2064
|
+
};
|
|
2065
|
+
|
|
2066
|
+
let tmpView = tmpPict.addView('TestCrossDragRow',
|
|
2067
|
+
{
|
|
2068
|
+
ViewIdentifier: 'TestCrossDragRow',
|
|
2069
|
+
ManifestDataAddress: 'AppData.FormConfig',
|
|
2070
|
+
DefaultDestinationAddress: '#FormEditor-Container',
|
|
2071
|
+
Renderables:
|
|
2072
|
+
[
|
|
2073
|
+
{
|
|
2074
|
+
RenderableHash: 'FormEditor-Container',
|
|
2075
|
+
TemplateHash: 'FormEditor-Container-Template',
|
|
2076
|
+
DestinationAddress: '#FormEditor-Container',
|
|
2077
|
+
RenderMethod: 'replace'
|
|
2078
|
+
}
|
|
2079
|
+
]
|
|
2080
|
+
}, libPictSectionFormEditor);
|
|
2081
|
+
|
|
2082
|
+
tmpView.initialize();
|
|
2083
|
+
tmpView.render();
|
|
2084
|
+
tmpView._DragAndDropEnabled = true;
|
|
2085
|
+
|
|
2086
|
+
// Move Row 2 from Group A1 to Group A2 (drop on Row 1 of Group A2)
|
|
2087
|
+
tmpView._DragState = { Type: 'row', Indices: [0, 0, 1] };
|
|
2088
|
+
tmpView._DragDropProvider.onDrop(
|
|
2089
|
+
{ preventDefault: function() {} },
|
|
2090
|
+
'row', 0, 1, 0
|
|
2091
|
+
);
|
|
2092
|
+
|
|
2093
|
+
var tmpManifest = tmpPict.AppData.FormConfig;
|
|
2094
|
+
// Group A1 should have 1 row
|
|
2095
|
+
Expect(tmpManifest.Sections[0].Groups[0].Rows.length).to.equal(1);
|
|
2096
|
+
Expect(tmpManifest.Sections[0].Groups[0].Rows[0].Inputs[0]).to.equal('addrA');
|
|
2097
|
+
// Group A2 should have 2 rows (addrB row inserted before addrC row)
|
|
2098
|
+
Expect(tmpManifest.Sections[0].Groups[1].Rows.length).to.equal(2);
|
|
2099
|
+
Expect(tmpManifest.Sections[0].Groups[1].Rows[0].Inputs[0]).to.equal('addrB');
|
|
2100
|
+
Expect(tmpManifest.Sections[0].Groups[1].Rows[1].Inputs[0]).to.equal('addrC');
|
|
2101
|
+
|
|
2102
|
+
fDone();
|
|
2103
|
+
}
|
|
2104
|
+
);
|
|
2105
|
+
test
|
|
2106
|
+
(
|
|
2107
|
+
'Should support cross-container drag and drop for inputs and update PictForm metadata',
|
|
2108
|
+
function (fDone)
|
|
2109
|
+
{
|
|
2110
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
2111
|
+
tmpPict.AppData.FormConfig =
|
|
2112
|
+
{
|
|
2113
|
+
Scope: 'CrossDragInput',
|
|
2114
|
+
Sections:
|
|
2115
|
+
[
|
|
2116
|
+
{
|
|
2117
|
+
Name: 'Section A', Hash: 'SectionA',
|
|
2118
|
+
Groups:
|
|
2119
|
+
[
|
|
2120
|
+
{
|
|
2121
|
+
Name: 'Group A1', Hash: 'GroupA1',
|
|
2122
|
+
Rows:
|
|
2123
|
+
[
|
|
2124
|
+
{ Inputs: ['addrX', 'addrY'] }
|
|
2125
|
+
]
|
|
2126
|
+
}
|
|
2127
|
+
]
|
|
2128
|
+
},
|
|
2129
|
+
{
|
|
2130
|
+
Name: 'Section B', Hash: 'SectionB',
|
|
2131
|
+
Groups:
|
|
2132
|
+
[
|
|
2133
|
+
{
|
|
2134
|
+
Name: 'Group B1', Hash: 'GroupB1',
|
|
2135
|
+
Rows:
|
|
2136
|
+
[
|
|
2137
|
+
{ Inputs: ['addrZ'] }
|
|
2138
|
+
]
|
|
2139
|
+
}
|
|
2140
|
+
]
|
|
2141
|
+
}
|
|
2142
|
+
],
|
|
2143
|
+
Descriptors:
|
|
2144
|
+
{
|
|
2145
|
+
addrX: { Name: 'InputX', Hash: 'InputX', DataType: 'String', PictForm: { Section: 'SectionA', Group: 'GroupA1', Row: 1 } },
|
|
2146
|
+
addrY: { Name: 'InputY', Hash: 'InputY', DataType: 'String', PictForm: { Section: 'SectionA', Group: 'GroupA1', Row: 1 } },
|
|
2147
|
+
addrZ: { Name: 'InputZ', Hash: 'InputZ', DataType: 'String', PictForm: { Section: 'SectionB', Group: 'GroupB1', Row: 1 } }
|
|
2148
|
+
}
|
|
2149
|
+
};
|
|
2150
|
+
|
|
2151
|
+
let tmpView = tmpPict.addView('TestCrossDragInput',
|
|
2152
|
+
{
|
|
2153
|
+
ViewIdentifier: 'TestCrossDragInput',
|
|
2154
|
+
ManifestDataAddress: 'AppData.FormConfig',
|
|
2155
|
+
DefaultDestinationAddress: '#FormEditor-Container',
|
|
2156
|
+
Renderables:
|
|
2157
|
+
[
|
|
2158
|
+
{
|
|
2159
|
+
RenderableHash: 'FormEditor-Container',
|
|
2160
|
+
TemplateHash: 'FormEditor-Container-Template',
|
|
2161
|
+
DestinationAddress: '#FormEditor-Container',
|
|
2162
|
+
RenderMethod: 'replace'
|
|
2163
|
+
}
|
|
2164
|
+
]
|
|
2165
|
+
}, libPictSectionFormEditor);
|
|
2166
|
+
|
|
2167
|
+
tmpView.initialize();
|
|
2168
|
+
tmpView.render();
|
|
2169
|
+
tmpView._DragAndDropEnabled = true;
|
|
2170
|
+
|
|
2171
|
+
// Move addrY from Section A / Group A1 / Row 0 to Section B / Group B1 / Row 0 (drop on addrZ position)
|
|
2172
|
+
tmpView._DragState = { Type: 'input', Indices: [0, 0, 0, 1] };
|
|
2173
|
+
tmpView._DragDropProvider.onDrop(
|
|
2174
|
+
{ preventDefault: function() {} },
|
|
2175
|
+
'input', 1, 0, 0, 0
|
|
2176
|
+
);
|
|
2177
|
+
|
|
2178
|
+
var tmpManifest = tmpPict.AppData.FormConfig;
|
|
2179
|
+
// Source row should have 1 input
|
|
2180
|
+
Expect(tmpManifest.Sections[0].Groups[0].Rows[0].Inputs.length).to.equal(1);
|
|
2181
|
+
Expect(tmpManifest.Sections[0].Groups[0].Rows[0].Inputs[0]).to.equal('addrX');
|
|
2182
|
+
// Target row should have 2 inputs (addrY inserted before addrZ)
|
|
2183
|
+
Expect(tmpManifest.Sections[1].Groups[0].Rows[0].Inputs.length).to.equal(2);
|
|
2184
|
+
Expect(tmpManifest.Sections[1].Groups[0].Rows[0].Inputs[0]).to.equal('addrY');
|
|
2185
|
+
Expect(tmpManifest.Sections[1].Groups[0].Rows[0].Inputs[1]).to.equal('addrZ');
|
|
2186
|
+
|
|
2187
|
+
// Verify PictForm metadata was updated
|
|
2188
|
+
Expect(tmpManifest.Descriptors.addrY.PictForm.Section).to.equal('SectionB');
|
|
2189
|
+
Expect(tmpManifest.Descriptors.addrY.PictForm.Group).to.equal('GroupB1');
|
|
2190
|
+
Expect(tmpManifest.Descriptors.addrY.PictForm.Row).to.equal(1);
|
|
2191
|
+
|
|
2192
|
+
fDone();
|
|
2193
|
+
}
|
|
2194
|
+
);
|
|
2195
|
+
}
|
|
2196
|
+
);
|
|
2197
|
+
suite
|
|
2198
|
+
(
|
|
2199
|
+
'DataType Icons',
|
|
2200
|
+
function ()
|
|
2201
|
+
{
|
|
2202
|
+
test
|
|
2203
|
+
(
|
|
2204
|
+
'Should register DataType icons for all 11 Manyfest DataTypes',
|
|
2205
|
+
function ()
|
|
2206
|
+
{
|
|
2207
|
+
var libIconography = libPictSectionFormEditor.IconographyProvider;
|
|
2208
|
+
var tmpProvider = new libIconography();
|
|
2209
|
+
|
|
2210
|
+
var tmpExpectedTypes = ['String', 'Number', 'Float', 'Integer', 'PreciseNumber', 'Boolean', 'Binary', 'DateTime', 'Array', 'Object', 'Null'];
|
|
2211
|
+
var tmpHashes = tmpProvider.getDataTypeIconHashes();
|
|
2212
|
+
|
|
2213
|
+
Expect(tmpHashes).to.be.an('array');
|
|
2214
|
+
Expect(tmpHashes.length).to.equal(11);
|
|
2215
|
+
|
|
2216
|
+
for (var i = 0; i < tmpExpectedTypes.length; i++)
|
|
2217
|
+
{
|
|
2218
|
+
Expect(tmpProvider.hasDataTypeIcon(tmpExpectedTypes[i])).to.be.true;
|
|
2219
|
+
}
|
|
2220
|
+
}
|
|
2221
|
+
);
|
|
2222
|
+
test
|
|
2223
|
+
(
|
|
2224
|
+
'Should return SVG strings for all DataType icons',
|
|
2225
|
+
function ()
|
|
2226
|
+
{
|
|
2227
|
+
var libIconography = libPictSectionFormEditor.IconographyProvider;
|
|
2228
|
+
var tmpProvider = new libIconography();
|
|
2229
|
+
|
|
2230
|
+
var tmpHashes = tmpProvider.getDataTypeIconHashes();
|
|
2231
|
+
for (var i = 0; i < tmpHashes.length; i++)
|
|
2232
|
+
{
|
|
2233
|
+
var tmpSVG = tmpProvider.getDataTypeIcon(tmpHashes[i]);
|
|
2234
|
+
Expect(tmpSVG).to.be.a('string');
|
|
2235
|
+
Expect(tmpSVG.indexOf('<svg')).to.equal(0);
|
|
2236
|
+
Expect(tmpSVG.indexOf('</svg>')).to.be.above(0);
|
|
2237
|
+
}
|
|
2238
|
+
}
|
|
2239
|
+
);
|
|
2240
|
+
test
|
|
2241
|
+
(
|
|
2242
|
+
'Should return SVG strings at custom sizes',
|
|
2243
|
+
function ()
|
|
2244
|
+
{
|
|
2245
|
+
var libIconography = libPictSectionFormEditor.IconographyProvider;
|
|
2246
|
+
var tmpProvider = new libIconography();
|
|
2247
|
+
|
|
2248
|
+
var tmpSVG12 = tmpProvider.getDataTypeIcon('String', 12);
|
|
2249
|
+
var tmpSVG32 = tmpProvider.getDataTypeIcon('String', 32);
|
|
2250
|
+
|
|
2251
|
+
Expect(tmpSVG12).to.contain('width="12"');
|
|
2252
|
+
Expect(tmpSVG32).to.contain('width="32"');
|
|
2253
|
+
}
|
|
2254
|
+
);
|
|
2255
|
+
test
|
|
2256
|
+
(
|
|
2257
|
+
'Should return empty string for unknown DataType',
|
|
2258
|
+
function ()
|
|
2259
|
+
{
|
|
2260
|
+
var libIconography = libPictSectionFormEditor.IconographyProvider;
|
|
2261
|
+
var tmpProvider = new libIconography();
|
|
2262
|
+
|
|
2263
|
+
var tmpSVG = tmpProvider.getDataTypeIcon('CompletelyFakeType');
|
|
2264
|
+
Expect(tmpSVG).to.equal('');
|
|
2265
|
+
}
|
|
2266
|
+
);
|
|
2267
|
+
test
|
|
2268
|
+
(
|
|
2269
|
+
'Should allow overriding DataType icons via setDataTypeIcon',
|
|
2270
|
+
function ()
|
|
2271
|
+
{
|
|
2272
|
+
var libIconography = libPictSectionFormEditor.IconographyProvider;
|
|
2273
|
+
var tmpProvider = new libIconography();
|
|
2274
|
+
|
|
2275
|
+
var tmpCustomFactory = function(pSize, pColors, pSW)
|
|
2276
|
+
{
|
|
2277
|
+
return '<svg class="custom-datatype" width="' + pSize + '"></svg>';
|
|
2278
|
+
};
|
|
2279
|
+
|
|
2280
|
+
tmpProvider.setDataTypeIcon('String', tmpCustomFactory);
|
|
2281
|
+
var tmpSVG = tmpProvider.getDataTypeIcon('String');
|
|
2282
|
+
Expect(tmpSVG).to.contain('class="custom-datatype"');
|
|
2283
|
+
}
|
|
2284
|
+
);
|
|
2285
|
+
test
|
|
2286
|
+
(
|
|
2287
|
+
'hasDataTypeIcon should return correct booleans',
|
|
2288
|
+
function ()
|
|
2289
|
+
{
|
|
2290
|
+
var libIconography = libPictSectionFormEditor.IconographyProvider;
|
|
2291
|
+
var tmpProvider = new libIconography();
|
|
2292
|
+
|
|
2293
|
+
Expect(tmpProvider.hasDataTypeIcon('String')).to.be.true;
|
|
2294
|
+
Expect(tmpProvider.hasDataTypeIcon('Boolean')).to.be.true;
|
|
2295
|
+
Expect(tmpProvider.hasDataTypeIcon('FakeType')).to.be.false;
|
|
2296
|
+
}
|
|
2297
|
+
);
|
|
2298
|
+
}
|
|
2299
|
+
);
|
|
2300
|
+
suite
|
|
2301
|
+
(
|
|
2302
|
+
'Input Selection and Display Mode',
|
|
2303
|
+
function ()
|
|
2304
|
+
{
|
|
2305
|
+
test
|
|
2306
|
+
(
|
|
2307
|
+
'Should have default input display mode of name',
|
|
2308
|
+
function ()
|
|
2309
|
+
{
|
|
2310
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
2311
|
+
let tmpView = tmpPict.addView('TestDisplayMode',
|
|
2312
|
+
{
|
|
2313
|
+
ViewIdentifier: 'TestDisplayMode',
|
|
2314
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
2315
|
+
}, libPictSectionFormEditor);
|
|
2316
|
+
|
|
2317
|
+
Expect(tmpView._InputDisplayMode).to.equal('name');
|
|
2318
|
+
}
|
|
2319
|
+
);
|
|
2320
|
+
test
|
|
2321
|
+
(
|
|
2322
|
+
'Should toggle input display mode via setInputDisplayMode',
|
|
2323
|
+
function ()
|
|
2324
|
+
{
|
|
2325
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
2326
|
+
tmpPict.AppData.FormConfig =
|
|
2327
|
+
{
|
|
2328
|
+
Scope: 'TestDisplayToggle',
|
|
2329
|
+
Sections: [],
|
|
2330
|
+
Descriptors: {}
|
|
2331
|
+
};
|
|
2332
|
+
|
|
2333
|
+
let tmpView = tmpPict.addView('TestDisplayToggle',
|
|
2334
|
+
{
|
|
2335
|
+
ViewIdentifier: 'TestDisplayToggle',
|
|
2336
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
2337
|
+
}, libPictSectionFormEditor);
|
|
2338
|
+
|
|
2339
|
+
Expect(tmpView._InputDisplayMode).to.equal('name');
|
|
2340
|
+
|
|
2341
|
+
tmpView._UtilitiesProvider.setInputDisplayMode('hash');
|
|
2342
|
+
Expect(tmpView._InputDisplayMode).to.equal('hash');
|
|
2343
|
+
|
|
2344
|
+
tmpView._UtilitiesProvider.setInputDisplayMode('name');
|
|
2345
|
+
Expect(tmpView._InputDisplayMode).to.equal('name');
|
|
2346
|
+
}
|
|
2347
|
+
);
|
|
2348
|
+
test
|
|
2349
|
+
(
|
|
2350
|
+
'Should ignore invalid display mode values',
|
|
2351
|
+
function ()
|
|
2352
|
+
{
|
|
2353
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
2354
|
+
let tmpView = tmpPict.addView('TestDisplayModeInvalid',
|
|
2355
|
+
{
|
|
2356
|
+
ViewIdentifier: 'TestDisplayModeInvalid',
|
|
2357
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
2358
|
+
}, libPictSectionFormEditor);
|
|
2359
|
+
|
|
2360
|
+
tmpView._UtilitiesProvider.setInputDisplayMode('invalid');
|
|
2361
|
+
Expect(tmpView._InputDisplayMode).to.equal('name');
|
|
2362
|
+
}
|
|
2363
|
+
);
|
|
2364
|
+
test
|
|
2365
|
+
(
|
|
2366
|
+
'Should have null selected input by default',
|
|
2367
|
+
function ()
|
|
2368
|
+
{
|
|
2369
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
2370
|
+
let tmpView = tmpPict.addView('TestSelection',
|
|
2371
|
+
{
|
|
2372
|
+
ViewIdentifier: 'TestSelection',
|
|
2373
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
2374
|
+
}, libPictSectionFormEditor);
|
|
2375
|
+
|
|
2376
|
+
Expect(tmpView._SelectedInputIndices).to.equal(null);
|
|
2377
|
+
}
|
|
2378
|
+
);
|
|
2379
|
+
test
|
|
2380
|
+
(
|
|
2381
|
+
'Should track selected input indices via selectInput',
|
|
2382
|
+
function ()
|
|
2383
|
+
{
|
|
2384
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
2385
|
+
tmpPict.AppData.FormConfig =
|
|
2386
|
+
{
|
|
2387
|
+
Scope: 'TestSelect',
|
|
2388
|
+
Sections:
|
|
2389
|
+
[
|
|
2390
|
+
{
|
|
2391
|
+
Hash: 'S1',
|
|
2392
|
+
Name: 'Section 1',
|
|
2393
|
+
Groups:
|
|
2394
|
+
[
|
|
2395
|
+
{
|
|
2396
|
+
Hash: 'G1',
|
|
2397
|
+
Name: 'Group 1',
|
|
2398
|
+
Layout: 'Record',
|
|
2399
|
+
Rows:
|
|
2400
|
+
[
|
|
2401
|
+
{ Inputs: ['addr1'] }
|
|
2402
|
+
]
|
|
2403
|
+
}
|
|
2404
|
+
]
|
|
2405
|
+
}
|
|
2406
|
+
],
|
|
2407
|
+
Descriptors:
|
|
2408
|
+
{
|
|
2409
|
+
addr1:
|
|
2410
|
+
{
|
|
2411
|
+
Name: 'Input 1',
|
|
2412
|
+
Hash: 'Input1',
|
|
2413
|
+
DataType: 'String',
|
|
2414
|
+
PictForm: { Section: 'S1', Group: 'G1', Row: 1 }
|
|
2415
|
+
}
|
|
2416
|
+
}
|
|
2417
|
+
};
|
|
2418
|
+
|
|
2419
|
+
let tmpView = tmpPict.addView('TestSelectInput',
|
|
2420
|
+
{
|
|
2421
|
+
ViewIdentifier: 'TestSelectInput',
|
|
2422
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
2423
|
+
}, libPictSectionFormEditor);
|
|
2424
|
+
|
|
2425
|
+
tmpView._UtilitiesProvider.selectInput(0, 0, 0, 0);
|
|
2426
|
+
Expect(tmpView._SelectedInputIndices).to.be.an('array');
|
|
2427
|
+
Expect(tmpView._SelectedInputIndices).to.deep.equal([0, 0, 0, 0]);
|
|
2428
|
+
}
|
|
2429
|
+
);
|
|
2430
|
+
test
|
|
2431
|
+
(
|
|
2432
|
+
'Should clear selection via deselectInput',
|
|
2433
|
+
function ()
|
|
2434
|
+
{
|
|
2435
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
2436
|
+
tmpPict.AppData.FormConfig =
|
|
2437
|
+
{
|
|
2438
|
+
Scope: 'TestDeselect',
|
|
2439
|
+
Sections: [],
|
|
2440
|
+
Descriptors: {}
|
|
2441
|
+
};
|
|
2442
|
+
|
|
2443
|
+
let tmpView = tmpPict.addView('TestDeselectInput',
|
|
2444
|
+
{
|
|
2445
|
+
ViewIdentifier: 'TestDeselectInput',
|
|
2446
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
2447
|
+
}, libPictSectionFormEditor);
|
|
2448
|
+
|
|
2449
|
+
tmpView._SelectedInputIndices = [0, 0, 0, 0];
|
|
2450
|
+
tmpView._UtilitiesProvider.deselectInput();
|
|
2451
|
+
Expect(tmpView._SelectedInputIndices).to.equal(null);
|
|
2452
|
+
}
|
|
2453
|
+
);
|
|
2454
|
+
}
|
|
2455
|
+
);
|
|
2456
|
+
suite
|
|
2457
|
+
(
|
|
2458
|
+
'Properties Panel',
|
|
2459
|
+
function ()
|
|
2460
|
+
{
|
|
2461
|
+
test
|
|
2462
|
+
(
|
|
2463
|
+
'Should export the PropertiesPanel class from the module',
|
|
2464
|
+
function ()
|
|
2465
|
+
{
|
|
2466
|
+
Expect(libPictSectionFormEditor.PropertiesPanel).to.be.a('function');
|
|
2467
|
+
}
|
|
2468
|
+
);
|
|
2469
|
+
test
|
|
2470
|
+
(
|
|
2471
|
+
'Properties panel should instantiate without errors',
|
|
2472
|
+
function ()
|
|
2473
|
+
{
|
|
2474
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
2475
|
+
let tmpPropertiesPanel = require('../source/views/PictView-FormEditor-PropertiesPanel.js');
|
|
2476
|
+
|
|
2477
|
+
let tmpView = tmpPict.addView('TestPropsPanel',
|
|
2478
|
+
{
|
|
2479
|
+
ViewIdentifier: 'TestPropsPanel'
|
|
2480
|
+
}, tmpPropertiesPanel);
|
|
2481
|
+
|
|
2482
|
+
Expect(tmpView).to.be.an('object');
|
|
2483
|
+
Expect(tmpView._SelectedInput).to.equal(null);
|
|
2484
|
+
Expect(tmpView._ParentFormEditor).to.equal(null);
|
|
2485
|
+
}
|
|
2486
|
+
);
|
|
2487
|
+
test
|
|
2488
|
+
(
|
|
2489
|
+
'Properties panel selectInput should set state',
|
|
2490
|
+
function ()
|
|
2491
|
+
{
|
|
2492
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
2493
|
+
let tmpPropertiesPanel = require('../source/views/PictView-FormEditor-PropertiesPanel.js');
|
|
2494
|
+
|
|
2495
|
+
let tmpView = tmpPict.addView('TestPropsPanelSelect',
|
|
2496
|
+
{
|
|
2497
|
+
ViewIdentifier: 'TestPropsPanelSelect'
|
|
2498
|
+
}, tmpPropertiesPanel);
|
|
2499
|
+
|
|
2500
|
+
tmpView.selectInput(1, 2, 3, 4);
|
|
2501
|
+
Expect(tmpView._SelectedInput).to.be.an('object');
|
|
2502
|
+
Expect(tmpView._SelectedInput.SectionIndex).to.equal(1);
|
|
2503
|
+
Expect(tmpView._SelectedInput.GroupIndex).to.equal(2);
|
|
2504
|
+
Expect(tmpView._SelectedInput.RowIndex).to.equal(3);
|
|
2505
|
+
Expect(tmpView._SelectedInput.InputIndex).to.equal(4);
|
|
2506
|
+
}
|
|
2507
|
+
);
|
|
2508
|
+
test
|
|
2509
|
+
(
|
|
2510
|
+
'Properties panel deselectInput should clear state',
|
|
2511
|
+
function ()
|
|
2512
|
+
{
|
|
2513
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
2514
|
+
let tmpPropertiesPanel = require('../source/views/PictView-FormEditor-PropertiesPanel.js');
|
|
2515
|
+
|
|
2516
|
+
let tmpView = tmpPict.addView('TestPropsPanelDeselect',
|
|
2517
|
+
{
|
|
2518
|
+
ViewIdentifier: 'TestPropsPanelDeselect'
|
|
2519
|
+
}, tmpPropertiesPanel);
|
|
2520
|
+
|
|
2521
|
+
tmpView.selectInput(0, 0, 0, 0);
|
|
2522
|
+
Expect(tmpView._SelectedInput).to.not.equal(null);
|
|
2523
|
+
|
|
2524
|
+
tmpView.deselectInput();
|
|
2525
|
+
Expect(tmpView._SelectedInput).to.equal(null);
|
|
2526
|
+
}
|
|
2527
|
+
);
|
|
2528
|
+
}
|
|
2529
|
+
);
|
|
2530
|
+
suite
|
|
2531
|
+
(
|
|
2532
|
+
'Panel State and Tabs',
|
|
2533
|
+
function ()
|
|
2534
|
+
{
|
|
2535
|
+
test
|
|
2536
|
+
(
|
|
2537
|
+
'Should default _PanelCollapsed to false and _PanelActiveTab to form',
|
|
2538
|
+
function ()
|
|
2539
|
+
{
|
|
2540
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
2541
|
+
let tmpView = tmpPict.addView('TestPanelDefaults',
|
|
2542
|
+
{
|
|
2543
|
+
ViewIdentifier: 'TestPanelDefaults',
|
|
2544
|
+
ManifestDataAddress: 'AppData.PanelDefaults'
|
|
2545
|
+
}, libPictSectionFormEditor);
|
|
2546
|
+
|
|
2547
|
+
Expect(tmpView._PanelCollapsed).to.equal(false);
|
|
2548
|
+
Expect(tmpView._PanelActiveTab).to.equal('form');
|
|
2549
|
+
}
|
|
2550
|
+
);
|
|
2551
|
+
test
|
|
2552
|
+
(
|
|
2553
|
+
'togglePropertiesPanel should flip _PanelCollapsed',
|
|
2554
|
+
function ()
|
|
2555
|
+
{
|
|
2556
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
2557
|
+
let tmpView = tmpPict.addView('TestPanelToggle',
|
|
2558
|
+
{
|
|
2559
|
+
ViewIdentifier: 'TestPanelToggle',
|
|
2560
|
+
ManifestDataAddress: 'AppData.PanelToggle'
|
|
2561
|
+
}, libPictSectionFormEditor);
|
|
2562
|
+
tmpView.initialize();
|
|
2563
|
+
|
|
2564
|
+
Expect(tmpView._PanelCollapsed).to.equal(false);
|
|
2565
|
+
|
|
2566
|
+
tmpView._UtilitiesProvider.togglePropertiesPanel();
|
|
2567
|
+
Expect(tmpView._PanelCollapsed).to.equal(true);
|
|
2568
|
+
|
|
2569
|
+
tmpView._UtilitiesProvider.togglePropertiesPanel();
|
|
2570
|
+
Expect(tmpView._PanelCollapsed).to.equal(false);
|
|
2571
|
+
}
|
|
2572
|
+
);
|
|
2573
|
+
test
|
|
2574
|
+
(
|
|
2575
|
+
'setPanelTab should switch active tab',
|
|
2576
|
+
function ()
|
|
2577
|
+
{
|
|
2578
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
2579
|
+
let tmpView = tmpPict.addView('TestSetPanelTab',
|
|
2580
|
+
{
|
|
2581
|
+
ViewIdentifier: 'TestSetPanelTab',
|
|
2582
|
+
ManifestDataAddress: 'AppData.SetPanelTab'
|
|
2583
|
+
}, libPictSectionFormEditor);
|
|
2584
|
+
tmpView.initialize();
|
|
2585
|
+
|
|
2586
|
+
Expect(tmpView._PanelActiveTab).to.equal('form');
|
|
2587
|
+
|
|
2588
|
+
tmpView._UtilitiesProvider.setPanelTab('properties');
|
|
2589
|
+
Expect(tmpView._PanelActiveTab).to.equal('properties');
|
|
2590
|
+
|
|
2591
|
+
tmpView._UtilitiesProvider.setPanelTab('form');
|
|
2592
|
+
Expect(tmpView._PanelActiveTab).to.equal('form');
|
|
2593
|
+
}
|
|
2594
|
+
);
|
|
2595
|
+
test
|
|
2596
|
+
(
|
|
2597
|
+
'setPanelTab should ignore invalid tab names',
|
|
2598
|
+
function ()
|
|
2599
|
+
{
|
|
2600
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
2601
|
+
let tmpView = tmpPict.addView('TestSetPanelTabInvalid',
|
|
2602
|
+
{
|
|
2603
|
+
ViewIdentifier: 'TestSetPanelTabInvalid',
|
|
2604
|
+
ManifestDataAddress: 'AppData.SetPanelTabInvalid'
|
|
2605
|
+
}, libPictSectionFormEditor);
|
|
2606
|
+
tmpView.initialize();
|
|
2607
|
+
|
|
2608
|
+
tmpView._UtilitiesProvider.setPanelTab('properties');
|
|
2609
|
+
Expect(tmpView._PanelActiveTab).to.equal('properties');
|
|
2610
|
+
|
|
2611
|
+
tmpView._UtilitiesProvider.setPanelTab('invalid');
|
|
2612
|
+
Expect(tmpView._PanelActiveTab).to.equal('properties');
|
|
2613
|
+
|
|
2614
|
+
tmpView._UtilitiesProvider.setPanelTab('');
|
|
2615
|
+
Expect(tmpView._PanelActiveTab).to.equal('properties');
|
|
2616
|
+
|
|
2617
|
+
tmpView._UtilitiesProvider.setPanelTab(null);
|
|
2618
|
+
Expect(tmpView._PanelActiveTab).to.equal('properties');
|
|
2619
|
+
}
|
|
2620
|
+
);
|
|
2621
|
+
test
|
|
2622
|
+
(
|
|
2623
|
+
'selectInput should auto-switch to properties tab and expand panel',
|
|
2624
|
+
function ()
|
|
2625
|
+
{
|
|
2626
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
2627
|
+
let tmpView = tmpPict.addView('TestSelectAutoSwitch',
|
|
2628
|
+
{
|
|
2629
|
+
ViewIdentifier: 'TestSelectAutoSwitch',
|
|
2630
|
+
ManifestDataAddress: 'AppData.SelectAutoSwitch'
|
|
2631
|
+
}, libPictSectionFormEditor);
|
|
2632
|
+
tmpView.initialize();
|
|
2633
|
+
|
|
2634
|
+
// Start with form tab and collapsed panel
|
|
2635
|
+
tmpView._PanelActiveTab = 'form';
|
|
2636
|
+
tmpView._PanelCollapsed = true;
|
|
2637
|
+
|
|
2638
|
+
// Add a section/group/row/input so selectInput has something to select
|
|
2639
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
2640
|
+
tmpView._ManifestOpsProvider.addGroup(0);
|
|
2641
|
+
tmpView._ManifestOpsProvider.addRow(0, 0);
|
|
2642
|
+
tmpView._ManifestOpsProvider.addInput(0, 0, 0);
|
|
2643
|
+
|
|
2644
|
+
tmpView._UtilitiesProvider.selectInput(0, 0, 0, 0);
|
|
2645
|
+
|
|
2646
|
+
Expect(tmpView._PanelActiveTab).to.equal('properties');
|
|
2647
|
+
Expect(tmpView._PanelCollapsed).to.equal(false);
|
|
2648
|
+
}
|
|
2649
|
+
);
|
|
2650
|
+
test
|
|
2651
|
+
(
|
|
2652
|
+
'deselectInput should NOT collapse the panel',
|
|
2653
|
+
function ()
|
|
2654
|
+
{
|
|
2655
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
2656
|
+
let tmpView = tmpPict.addView('TestDeselectNoCollapse',
|
|
2657
|
+
{
|
|
2658
|
+
ViewIdentifier: 'TestDeselectNoCollapse',
|
|
2659
|
+
ManifestDataAddress: 'AppData.DeselectNoCollapse'
|
|
2660
|
+
}, libPictSectionFormEditor);
|
|
2661
|
+
tmpView.initialize();
|
|
2662
|
+
|
|
2663
|
+
tmpView._PanelCollapsed = false;
|
|
2664
|
+
tmpView._PanelActiveTab = 'properties';
|
|
2665
|
+
|
|
2666
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
2667
|
+
tmpView._ManifestOpsProvider.addGroup(0);
|
|
2668
|
+
tmpView._ManifestOpsProvider.addRow(0, 0);
|
|
2669
|
+
tmpView._ManifestOpsProvider.addInput(0, 0, 0);
|
|
2670
|
+
|
|
2671
|
+
tmpView._UtilitiesProvider.selectInput(0, 0, 0, 0);
|
|
2672
|
+
tmpView._UtilitiesProvider.deselectInput();
|
|
2673
|
+
|
|
2674
|
+
Expect(tmpView._PanelCollapsed).to.equal(false);
|
|
2675
|
+
Expect(tmpView._SelectedInputIndices).to.equal(null);
|
|
2676
|
+
}
|
|
2677
|
+
);
|
|
2678
|
+
test
|
|
2679
|
+
(
|
|
2680
|
+
'getFormStats should return correct counts',
|
|
2681
|
+
function ()
|
|
2682
|
+
{
|
|
2683
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
2684
|
+
let tmpView = tmpPict.addView('TestFormStats',
|
|
2685
|
+
{
|
|
2686
|
+
ViewIdentifier: 'TestFormStats',
|
|
2687
|
+
ManifestDataAddress: 'AppData.FormStats'
|
|
2688
|
+
}, libPictSectionFormEditor);
|
|
2689
|
+
tmpView.initialize();
|
|
2690
|
+
|
|
2691
|
+
// Empty manifest
|
|
2692
|
+
let tmpStats = tmpView._UtilitiesProvider.getFormStats();
|
|
2693
|
+
Expect(tmpStats.Sections).to.equal(0);
|
|
2694
|
+
Expect(tmpStats.Groups).to.equal(0);
|
|
2695
|
+
Expect(tmpStats.Inputs).to.equal(0);
|
|
2696
|
+
Expect(tmpStats.Descriptors).to.equal(0);
|
|
2697
|
+
|
|
2698
|
+
// Add content
|
|
2699
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
2700
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
2701
|
+
tmpView._ManifestOpsProvider.addGroup(0);
|
|
2702
|
+
tmpView._ManifestOpsProvider.addGroup(1);
|
|
2703
|
+
tmpView._ManifestOpsProvider.addRow(0, 0);
|
|
2704
|
+
tmpView._ManifestOpsProvider.addRow(1, 0);
|
|
2705
|
+
tmpView._ManifestOpsProvider.addInput(0, 0, 0);
|
|
2706
|
+
tmpView._ManifestOpsProvider.addInput(0, 0, 0);
|
|
2707
|
+
tmpView._ManifestOpsProvider.addInput(1, 0, 0);
|
|
2708
|
+
|
|
2709
|
+
tmpStats = tmpView._UtilitiesProvider.getFormStats();
|
|
2710
|
+
Expect(tmpStats.Sections).to.equal(2);
|
|
2711
|
+
// Each addSection() creates 1 default group, + addGroup() adds 1 more each = 4 total
|
|
2712
|
+
Expect(tmpStats.Groups).to.equal(4);
|
|
2713
|
+
Expect(tmpStats.Inputs).to.equal(3);
|
|
2714
|
+
Expect(tmpStats.Descriptors).to.equal(3);
|
|
2715
|
+
}
|
|
2716
|
+
);
|
|
2717
|
+
test
|
|
2718
|
+
(
|
|
2719
|
+
'getFormStats should return zeros for empty manifest',
|
|
2720
|
+
function ()
|
|
2721
|
+
{
|
|
2722
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
2723
|
+
let tmpView = tmpPict.addView('TestFormStatsEmpty',
|
|
2724
|
+
{
|
|
2725
|
+
ViewIdentifier: 'TestFormStatsEmpty',
|
|
2726
|
+
ManifestDataAddress: 'AppData.FormStatsEmpty'
|
|
2727
|
+
}, libPictSectionFormEditor);
|
|
2728
|
+
tmpView.initialize();
|
|
2729
|
+
|
|
2730
|
+
// Clear manifest entirely
|
|
2731
|
+
tmpView._setManifestData({});
|
|
2732
|
+
|
|
2733
|
+
let tmpStats = tmpView._UtilitiesProvider.getFormStats();
|
|
2734
|
+
Expect(tmpStats.Sections).to.equal(0);
|
|
2735
|
+
Expect(tmpStats.Groups).to.equal(0);
|
|
2736
|
+
Expect(tmpStats.Inputs).to.equal(0);
|
|
2737
|
+
Expect(tmpStats.Descriptors).to.equal(0);
|
|
2738
|
+
}
|
|
2739
|
+
);
|
|
2740
|
+
test
|
|
2741
|
+
(
|
|
2742
|
+
'getAllInputEntries should enumerate all inputs with indices',
|
|
2743
|
+
function ()
|
|
2744
|
+
{
|
|
2745
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
2746
|
+
let tmpView = tmpPict.addView('TestAllInputEntries',
|
|
2747
|
+
{
|
|
2748
|
+
ViewIdentifier: 'TestAllInputEntries',
|
|
2749
|
+
ManifestDataAddress: 'AppData.AllInputEntries'
|
|
2750
|
+
}, libPictSectionFormEditor);
|
|
2751
|
+
tmpView.initialize();
|
|
2752
|
+
|
|
2753
|
+
// Empty manifest
|
|
2754
|
+
let tmpEntries = tmpView._UtilitiesProvider.getAllInputEntries();
|
|
2755
|
+
Expect(tmpEntries).to.be.an('array');
|
|
2756
|
+
Expect(tmpEntries.length).to.equal(0);
|
|
2757
|
+
|
|
2758
|
+
// Add content
|
|
2759
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
2760
|
+
tmpView._ManifestOpsProvider.addGroup(0);
|
|
2761
|
+
tmpView._ManifestOpsProvider.addRow(0, 0);
|
|
2762
|
+
tmpView._ManifestOpsProvider.addInput(0, 0, 0);
|
|
2763
|
+
tmpView._ManifestOpsProvider.addInput(0, 0, 0);
|
|
2764
|
+
|
|
2765
|
+
tmpEntries = tmpView._UtilitiesProvider.getAllInputEntries();
|
|
2766
|
+
Expect(tmpEntries.length).to.equal(2);
|
|
2767
|
+
|
|
2768
|
+
// Check structure of each entry
|
|
2769
|
+
Expect(tmpEntries[0].SectionIndex).to.equal(0);
|
|
2770
|
+
Expect(tmpEntries[0].GroupIndex).to.equal(0);
|
|
2771
|
+
Expect(tmpEntries[0].RowIndex).to.equal(0);
|
|
2772
|
+
Expect(tmpEntries[0].InputIndex).to.equal(0);
|
|
2773
|
+
Expect(tmpEntries[0].Address).to.be.a('string');
|
|
2774
|
+
Expect(tmpEntries[0].Label).to.be.a('string');
|
|
2775
|
+
Expect(tmpEntries[0].SectionName).to.be.a('string');
|
|
2776
|
+
|
|
2777
|
+
Expect(tmpEntries[1].InputIndex).to.equal(1);
|
|
2778
|
+
}
|
|
2779
|
+
);
|
|
2780
|
+
test
|
|
2781
|
+
(
|
|
2782
|
+
'onInputSelectorChange should forward selection to parent',
|
|
2783
|
+
function ()
|
|
2784
|
+
{
|
|
2785
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
2786
|
+
let tmpPropertiesPanel = require('../source/views/PictView-FormEditor-PropertiesPanel.js');
|
|
2787
|
+
|
|
2788
|
+
let tmpFormEditor = tmpPict.addView('TestSelectorParent',
|
|
2789
|
+
{
|
|
2790
|
+
ViewIdentifier: 'TestSelectorParent',
|
|
2791
|
+
ManifestDataAddress: 'AppData.SelectorParent'
|
|
2792
|
+
}, libPictSectionFormEditor);
|
|
2793
|
+
tmpFormEditor.initialize();
|
|
2794
|
+
|
|
2795
|
+
tmpFormEditor._ManifestOpsProvider.addSection();
|
|
2796
|
+
tmpFormEditor._ManifestOpsProvider.addGroup(0);
|
|
2797
|
+
tmpFormEditor._ManifestOpsProvider.addRow(0, 0);
|
|
2798
|
+
tmpFormEditor._ManifestOpsProvider.addInput(0, 0, 0);
|
|
2799
|
+
|
|
2800
|
+
let tmpPanel = tmpPict.addView('TestSelectorPanel',
|
|
2801
|
+
{
|
|
2802
|
+
ViewIdentifier: 'TestSelectorPanel'
|
|
2803
|
+
}, tmpPropertiesPanel);
|
|
2804
|
+
tmpPanel._ParentFormEditor = tmpFormEditor;
|
|
2805
|
+
|
|
2806
|
+
// Select via the selector
|
|
2807
|
+
tmpPanel.onInputSelectorChange('0,0,0,0');
|
|
2808
|
+
|
|
2809
|
+
Expect(tmpFormEditor._SelectedInputIndices).to.be.an('array');
|
|
2810
|
+
Expect(tmpFormEditor._SelectedInputIndices[0]).to.equal(0);
|
|
2811
|
+
Expect(tmpFormEditor._SelectedInputIndices[1]).to.equal(0);
|
|
2812
|
+
Expect(tmpFormEditor._SelectedInputIndices[2]).to.equal(0);
|
|
2813
|
+
Expect(tmpFormEditor._SelectedInputIndices[3]).to.equal(0);
|
|
2814
|
+
}
|
|
2815
|
+
);
|
|
2816
|
+
test
|
|
2817
|
+
(
|
|
2818
|
+
'onInputSelectorChange with empty value should deselect',
|
|
2819
|
+
function ()
|
|
2820
|
+
{
|
|
2821
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
2822
|
+
let tmpPropertiesPanel = require('../source/views/PictView-FormEditor-PropertiesPanel.js');
|
|
2823
|
+
|
|
2824
|
+
let tmpFormEditor = tmpPict.addView('TestSelectorDeselect',
|
|
2825
|
+
{
|
|
2826
|
+
ViewIdentifier: 'TestSelectorDeselect',
|
|
2827
|
+
ManifestDataAddress: 'AppData.SelectorDeselect'
|
|
2828
|
+
}, libPictSectionFormEditor);
|
|
2829
|
+
tmpFormEditor.initialize();
|
|
2830
|
+
|
|
2831
|
+
tmpFormEditor._ManifestOpsProvider.addSection();
|
|
2832
|
+
tmpFormEditor._ManifestOpsProvider.addGroup(0);
|
|
2833
|
+
tmpFormEditor._ManifestOpsProvider.addRow(0, 0);
|
|
2834
|
+
tmpFormEditor._ManifestOpsProvider.addInput(0, 0, 0);
|
|
2835
|
+
|
|
2836
|
+
let tmpPanel = tmpPict.addView('TestSelectorDeselectPanel',
|
|
2837
|
+
{
|
|
2838
|
+
ViewIdentifier: 'TestSelectorDeselectPanel'
|
|
2839
|
+
}, tmpPropertiesPanel);
|
|
2840
|
+
tmpPanel._ParentFormEditor = tmpFormEditor;
|
|
2841
|
+
|
|
2842
|
+
// Select first, then deselect
|
|
2843
|
+
tmpFormEditor._UtilitiesProvider.selectInput(0, 0, 0, 0);
|
|
2844
|
+
Expect(tmpFormEditor._SelectedInputIndices).to.not.equal(null);
|
|
2845
|
+
|
|
2846
|
+
tmpPanel.onInputSelectorChange('');
|
|
2847
|
+
Expect(tmpFormEditor._SelectedInputIndices).to.equal(null);
|
|
2848
|
+
}
|
|
2849
|
+
);
|
|
2850
|
+
test
|
|
2851
|
+
(
|
|
2852
|
+
'onInputSelectorChange should ignore invalid values',
|
|
2853
|
+
function ()
|
|
2854
|
+
{
|
|
2855
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
2856
|
+
let tmpPropertiesPanel = require('../source/views/PictView-FormEditor-PropertiesPanel.js');
|
|
2857
|
+
|
|
2858
|
+
let tmpFormEditor = tmpPict.addView('TestSelectorInvalid',
|
|
2859
|
+
{
|
|
2860
|
+
ViewIdentifier: 'TestSelectorInvalid',
|
|
2861
|
+
ManifestDataAddress: 'AppData.SelectorInvalid'
|
|
2862
|
+
}, libPictSectionFormEditor);
|
|
2863
|
+
tmpFormEditor.initialize();
|
|
2864
|
+
|
|
2865
|
+
let tmpPanel = tmpPict.addView('TestSelectorInvalidPanel',
|
|
2866
|
+
{
|
|
2867
|
+
ViewIdentifier: 'TestSelectorInvalidPanel'
|
|
2868
|
+
}, tmpPropertiesPanel);
|
|
2869
|
+
tmpPanel._ParentFormEditor = tmpFormEditor;
|
|
2870
|
+
|
|
2871
|
+
// These should not throw
|
|
2872
|
+
tmpPanel.onInputSelectorChange('bad');
|
|
2873
|
+
tmpPanel.onInputSelectorChange('1,2');
|
|
2874
|
+
tmpPanel.onInputSelectorChange('a,b,c,d');
|
|
2875
|
+
|
|
2876
|
+
Expect(tmpFormEditor._SelectedInputIndices).to.equal(null);
|
|
2877
|
+
}
|
|
2878
|
+
);
|
|
2879
|
+
test
|
|
2880
|
+
(
|
|
2881
|
+
'scrollToInput should not throw in node environment',
|
|
2882
|
+
function ()
|
|
2883
|
+
{
|
|
2884
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
2885
|
+
let tmpView = tmpPict.addView('TestScrollToInput',
|
|
2886
|
+
{
|
|
2887
|
+
ViewIdentifier: 'TestScrollToInput',
|
|
2888
|
+
ManifestDataAddress: 'AppData.ScrollToInput'
|
|
2889
|
+
}, libPictSectionFormEditor);
|
|
2890
|
+
tmpView.initialize();
|
|
2891
|
+
|
|
2892
|
+
// Should not throw even without a DOM
|
|
2893
|
+
tmpView._UtilitiesProvider.scrollToInput(0, 0, 0, 0);
|
|
2894
|
+
}
|
|
2895
|
+
);
|
|
2896
|
+
}
|
|
2897
|
+
);
|
|
2898
|
+
suite
|
|
2899
|
+
(
|
|
2900
|
+
'InputType Manifests',
|
|
2901
|
+
function ()
|
|
2902
|
+
{
|
|
2903
|
+
test
|
|
2904
|
+
(
|
|
2905
|
+
'InputType definitions with manifests should have valid Descriptor structures',
|
|
2906
|
+
function ()
|
|
2907
|
+
{
|
|
2908
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
2909
|
+
let tmpView = tmpPict.addView('TestManifestStructure',
|
|
2910
|
+
{
|
|
2911
|
+
ViewIdentifier: 'TestManifestStructure',
|
|
2912
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
2913
|
+
}, libPictSectionFormEditor);
|
|
2914
|
+
|
|
2915
|
+
let tmpTypesWithManifests = ['Option', 'PreciseNumberReadOnly', 'Chart', 'TabSectionSelector', 'TabGroupSelector', 'Templated', 'TemplatedEntityLookup'];
|
|
2916
|
+
|
|
2917
|
+
for (let i = 0; i < tmpView._InputTypeDefinitions.length; i++)
|
|
2918
|
+
{
|
|
2919
|
+
let tmpDef = tmpView._InputTypeDefinitions[i];
|
|
2920
|
+
if (tmpDef.Manifest)
|
|
2921
|
+
{
|
|
2922
|
+
Expect(tmpDef.Manifest).to.be.an('object');
|
|
2923
|
+
Expect(tmpDef.Manifest.Descriptors).to.be.an('object');
|
|
2924
|
+
|
|
2925
|
+
let tmpKeys = Object.keys(tmpDef.Manifest.Descriptors);
|
|
2926
|
+
Expect(tmpKeys.length).to.be.greaterThan(0);
|
|
2927
|
+
|
|
2928
|
+
for (let j = 0; j < tmpKeys.length; j++)
|
|
2929
|
+
{
|
|
2930
|
+
let tmpDesc = tmpDef.Manifest.Descriptors[tmpKeys[j]];
|
|
2931
|
+
Expect(tmpDesc).to.be.an('object');
|
|
2932
|
+
Expect(tmpDesc.Name).to.be.a('string');
|
|
2933
|
+
Expect(tmpDesc.Hash).to.be.a('string');
|
|
2934
|
+
Expect(tmpDesc.DataType).to.be.a('string');
|
|
2935
|
+
Expect(tmpDesc.Description).to.be.a('string');
|
|
2936
|
+
}
|
|
2937
|
+
}
|
|
2938
|
+
}
|
|
2939
|
+
}
|
|
2940
|
+
);
|
|
2941
|
+
test
|
|
2942
|
+
(
|
|
2943
|
+
'_getInputTypeManifest should return manifest for types that have one',
|
|
2944
|
+
function ()
|
|
2945
|
+
{
|
|
2946
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
2947
|
+
let tmpView = tmpPict.addView('TestGetManifest',
|
|
2948
|
+
{
|
|
2949
|
+
ViewIdentifier: 'TestGetManifest',
|
|
2950
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
2951
|
+
}, libPictSectionFormEditor);
|
|
2952
|
+
|
|
2953
|
+
let tmpOptionManifest = tmpView._UtilitiesProvider._getInputTypeManifest('Option');
|
|
2954
|
+
Expect(tmpOptionManifest).to.be.an('object');
|
|
2955
|
+
Expect(tmpOptionManifest.Descriptors).to.be.an('object');
|
|
2956
|
+
Expect(tmpOptionManifest.Descriptors['SelectOptions']).to.be.an('object');
|
|
2957
|
+
Expect(tmpOptionManifest.Descriptors['SelectOptionsPickList']).to.be.an('object');
|
|
2958
|
+
|
|
2959
|
+
let tmpChartManifest = tmpView._UtilitiesProvider._getInputTypeManifest('Chart');
|
|
2960
|
+
Expect(tmpChartManifest).to.be.an('object');
|
|
2961
|
+
Expect(tmpChartManifest.Descriptors['ChartType']).to.be.an('object');
|
|
2962
|
+
|
|
2963
|
+
let tmpPNROManifest = tmpView._UtilitiesProvider._getInputTypeManifest('PreciseNumberReadOnly');
|
|
2964
|
+
Expect(tmpPNROManifest).to.be.an('object');
|
|
2965
|
+
Expect(tmpPNROManifest.Descriptors['DecimalPrecision']).to.be.an('object');
|
|
2966
|
+
Expect(tmpPNROManifest.Descriptors['AddCommas']).to.be.an('object');
|
|
2967
|
+
Expect(tmpPNROManifest.Descriptors['DigitsPrefix']).to.be.an('object');
|
|
2968
|
+
Expect(tmpPNROManifest.Descriptors['DigitsPostfix']).to.be.an('object');
|
|
2969
|
+
}
|
|
2970
|
+
);
|
|
2971
|
+
test
|
|
2972
|
+
(
|
|
2973
|
+
'_getInputTypeManifest should return null for types without a manifest',
|
|
2974
|
+
function ()
|
|
2975
|
+
{
|
|
2976
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
2977
|
+
let tmpView = tmpPict.addView('TestGetManifestNull',
|
|
2978
|
+
{
|
|
2979
|
+
ViewIdentifier: 'TestGetManifestNull',
|
|
2980
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
2981
|
+
}, libPictSectionFormEditor);
|
|
2982
|
+
|
|
2983
|
+
Expect(tmpView._UtilitiesProvider._getInputTypeManifest('TextArea')).to.equal(null);
|
|
2984
|
+
Expect(tmpView._UtilitiesProvider._getInputTypeManifest('Boolean')).to.equal(null);
|
|
2985
|
+
Expect(tmpView._UtilitiesProvider._getInputTypeManifest('Hidden')).to.equal(null);
|
|
2986
|
+
Expect(tmpView._UtilitiesProvider._getInputTypeManifest('Link')).to.equal(null);
|
|
2987
|
+
Expect(tmpView._UtilitiesProvider._getInputTypeManifest('')).to.equal(null);
|
|
2988
|
+
Expect(tmpView._UtilitiesProvider._getInputTypeManifest(null)).to.equal(null);
|
|
2989
|
+
Expect(tmpView._UtilitiesProvider._getInputTypeManifest('NonExistent')).to.equal(null);
|
|
2990
|
+
}
|
|
2991
|
+
);
|
|
2992
|
+
test
|
|
2993
|
+
(
|
|
2994
|
+
'commitPictFormChange should update PictForm properties on the Descriptor',
|
|
2995
|
+
function ()
|
|
2996
|
+
{
|
|
2997
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
2998
|
+
let tmpPropertiesPanel = require('../source/views/PictView-FormEditor-PropertiesPanel.js');
|
|
2999
|
+
|
|
3000
|
+
let tmpView = tmpPict.addView('TestCommitPictForm',
|
|
3001
|
+
{
|
|
3002
|
+
ViewIdentifier: 'TestCommitPictForm'
|
|
3003
|
+
}, tmpPropertiesPanel);
|
|
3004
|
+
|
|
3005
|
+
// Create a mock parent form editor
|
|
3006
|
+
let tmpFormEditor = tmpPict.addView('TestCommitPictFormParent',
|
|
3007
|
+
{
|
|
3008
|
+
ViewIdentifier: 'TestCommitPictFormParent',
|
|
3009
|
+
ManifestDataAddress: 'AppData.TestCommitManifest'
|
|
3010
|
+
}, libPictSectionFormEditor);
|
|
3011
|
+
tmpFormEditor.initialize();
|
|
3012
|
+
|
|
3013
|
+
// Set up manifest data with a section/group/row/input
|
|
3014
|
+
tmpFormEditor._ManifestOpsProvider.addSection();
|
|
3015
|
+
tmpFormEditor._ManifestOpsProvider.addGroup(0);
|
|
3016
|
+
tmpFormEditor._ManifestOpsProvider.addRow(0, 0);
|
|
3017
|
+
tmpFormEditor._ManifestOpsProvider.addInput(0, 0, 0);
|
|
3018
|
+
|
|
3019
|
+
// Wire the properties panel to the form editor
|
|
3020
|
+
tmpView._ParentFormEditor = tmpFormEditor;
|
|
3021
|
+
tmpView.selectInput(0, 0, 0, 0);
|
|
3022
|
+
|
|
3023
|
+
// Test String property
|
|
3024
|
+
tmpView.commitPictFormChange('Template', 'Hello {~D:Name~}', 'String');
|
|
3025
|
+
let tmpManifest = tmpFormEditor._resolveManifestData();
|
|
3026
|
+
let tmpAddress = tmpManifest.Sections[0].Groups[0].Rows[0].Inputs[0];
|
|
3027
|
+
let tmpDescriptor = tmpManifest.Descriptors[tmpAddress];
|
|
3028
|
+
Expect(tmpDescriptor.PictForm.Template).to.equal('Hello {~D:Name~}');
|
|
3029
|
+
|
|
3030
|
+
// Test Number property
|
|
3031
|
+
tmpView.commitPictFormChange('DecimalPrecision', '2', 'Number');
|
|
3032
|
+
Expect(tmpDescriptor.PictForm.DecimalPrecision).to.equal(2);
|
|
3033
|
+
|
|
3034
|
+
// Test Boolean property
|
|
3035
|
+
tmpView.commitPictFormChange('AddCommas', true, 'Boolean');
|
|
3036
|
+
Expect(tmpDescriptor.PictForm.AddCommas).to.equal(true);
|
|
3037
|
+
|
|
3038
|
+
// Test empty Number removes property
|
|
3039
|
+
tmpView.commitPictFormChange('DecimalPrecision', '', 'Number');
|
|
3040
|
+
Expect(tmpDescriptor.PictForm.hasOwnProperty('DecimalPrecision')).to.equal(false);
|
|
3041
|
+
|
|
3042
|
+
// Test empty String removes property
|
|
3043
|
+
tmpView.commitPictFormChange('Template', '', 'String');
|
|
3044
|
+
Expect(tmpDescriptor.PictForm.hasOwnProperty('Template')).to.equal(false);
|
|
3045
|
+
|
|
3046
|
+
// Test JSON string auto-parsing
|
|
3047
|
+
tmpView.commitPictFormChange('SelectOptions', '[{"id":"1","text":"One"}]', 'String');
|
|
3048
|
+
Expect(Array.isArray(tmpDescriptor.PictForm.SelectOptions)).to.equal(true);
|
|
3049
|
+
Expect(tmpDescriptor.PictForm.SelectOptions[0].id).to.equal('1');
|
|
3050
|
+
}
|
|
3051
|
+
);
|
|
3052
|
+
test
|
|
3053
|
+
(
|
|
3054
|
+
'TabGroupSelector and TabSectionSelector should have correct manifest properties',
|
|
3055
|
+
function ()
|
|
3056
|
+
{
|
|
3057
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
3058
|
+
let tmpView = tmpPict.addView('TestTabManifests',
|
|
3059
|
+
{
|
|
3060
|
+
ViewIdentifier: 'TestTabManifests',
|
|
3061
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
3062
|
+
}, libPictSectionFormEditor);
|
|
3063
|
+
|
|
3064
|
+
let tmpTabGroupManifest = tmpView._UtilitiesProvider._getInputTypeManifest('TabGroupSelector');
|
|
3065
|
+
Expect(tmpTabGroupManifest.Descriptors['TabGroupSet']).to.be.an('object');
|
|
3066
|
+
Expect(tmpTabGroupManifest.Descriptors['DefaultTabGroupHash']).to.be.an('object');
|
|
3067
|
+
Expect(tmpTabGroupManifest.Descriptors['DefaultFromData']).to.be.an('object');
|
|
3068
|
+
Expect(tmpTabGroupManifest.Descriptors['DefaultFromData'].DataType).to.equal('Boolean');
|
|
3069
|
+
|
|
3070
|
+
let tmpTabSectionManifest = tmpView._UtilitiesProvider._getInputTypeManifest('TabSectionSelector');
|
|
3071
|
+
Expect(tmpTabSectionManifest.Descriptors['TabSectionSet']).to.be.an('object');
|
|
3072
|
+
Expect(tmpTabSectionManifest.Descriptors['DefaultTabSectionHash']).to.be.an('object');
|
|
3073
|
+
Expect(tmpTabSectionManifest.Descriptors['DefaultFromData']).to.be.an('object');
|
|
3074
|
+
}
|
|
3075
|
+
);
|
|
3076
|
+
test
|
|
3077
|
+
(
|
|
3078
|
+
'Custom InputType definitions with manifests should merge correctly',
|
|
3079
|
+
function ()
|
|
3080
|
+
{
|
|
3081
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
3082
|
+
let tmpView = tmpPict.addView('TestCustomManifests',
|
|
3083
|
+
{
|
|
3084
|
+
ViewIdentifier: 'TestCustomManifests',
|
|
3085
|
+
ManifestDataAddress: 'AppData.FormConfig',
|
|
3086
|
+
InputTypeDefinitions:
|
|
3087
|
+
[
|
|
3088
|
+
{
|
|
3089
|
+
Hash: 'CustomWidget',
|
|
3090
|
+
Name: 'Custom Widget',
|
|
3091
|
+
Description: 'A custom widget',
|
|
3092
|
+
Category: 'Custom',
|
|
3093
|
+
Manifest:
|
|
3094
|
+
{
|
|
3095
|
+
Descriptors:
|
|
3096
|
+
{
|
|
3097
|
+
'WidgetColor': { Name: 'Widget Color', Hash: 'WidgetColor', DataType: 'String', Description: 'The color of the widget' }
|
|
3098
|
+
}
|
|
3099
|
+
}
|
|
3100
|
+
}
|
|
3101
|
+
]
|
|
3102
|
+
}, libPictSectionFormEditor);
|
|
3103
|
+
|
|
3104
|
+
let tmpCustomManifest = tmpView._UtilitiesProvider._getInputTypeManifest('CustomWidget');
|
|
3105
|
+
Expect(tmpCustomManifest).to.be.an('object');
|
|
3106
|
+
Expect(tmpCustomManifest.Descriptors['WidgetColor']).to.be.an('object');
|
|
3107
|
+
Expect(tmpCustomManifest.Descriptors['WidgetColor'].DataType).to.equal('String');
|
|
3108
|
+
}
|
|
3109
|
+
);
|
|
3110
|
+
}
|
|
3111
|
+
);
|
|
3112
|
+
suite
|
|
3113
|
+
(
|
|
3114
|
+
'ReferenceManifest Management',
|
|
3115
|
+
function ()
|
|
3116
|
+
{
|
|
3117
|
+
test
|
|
3118
|
+
(
|
|
3119
|
+
'createReferenceManifest should create entry with Scope and empty Descriptors',
|
|
3120
|
+
function ()
|
|
3121
|
+
{
|
|
3122
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
3123
|
+
tmpPict.AppData = {};
|
|
3124
|
+
|
|
3125
|
+
let tmpView = tmpPict.addView('TestRefManifestCreate',
|
|
3126
|
+
{
|
|
3127
|
+
ViewIdentifier: 'TestRefManifestCreate',
|
|
3128
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
3129
|
+
}, libPictSectionFormEditor);
|
|
3130
|
+
|
|
3131
|
+
tmpView.initialize();
|
|
3132
|
+
|
|
3133
|
+
let tmpName = tmpView._ManifestOpsProvider.createReferenceManifest('MyManifest');
|
|
3134
|
+
Expect(tmpName).to.equal('MyManifest');
|
|
3135
|
+
|
|
3136
|
+
let tmpManifest = tmpView._resolveManifestData();
|
|
3137
|
+
Expect(tmpManifest.ReferenceManifests).to.be.an('object');
|
|
3138
|
+
Expect(tmpManifest.ReferenceManifests['MyManifest']).to.be.an('object');
|
|
3139
|
+
Expect(tmpManifest.ReferenceManifests['MyManifest'].Scope).to.equal('MyManifest');
|
|
3140
|
+
Expect(tmpManifest.ReferenceManifests['MyManifest'].Descriptors).to.be.an('object');
|
|
3141
|
+
Expect(Object.keys(tmpManifest.ReferenceManifests['MyManifest'].Descriptors).length).to.equal(0);
|
|
3142
|
+
}
|
|
3143
|
+
);
|
|
3144
|
+
test
|
|
3145
|
+
(
|
|
3146
|
+
'createReferenceManifest should generate unique names for duplicates',
|
|
3147
|
+
function ()
|
|
3148
|
+
{
|
|
3149
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
3150
|
+
tmpPict.AppData = {};
|
|
3151
|
+
|
|
3152
|
+
let tmpView = tmpPict.addView('TestRefManifestDup',
|
|
3153
|
+
{
|
|
3154
|
+
ViewIdentifier: 'TestRefManifestDup',
|
|
3155
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
3156
|
+
}, libPictSectionFormEditor);
|
|
3157
|
+
|
|
3158
|
+
tmpView.initialize();
|
|
3159
|
+
|
|
3160
|
+
let tmpName1 = tmpView._ManifestOpsProvider.createReferenceManifest('TestManifest');
|
|
3161
|
+
let tmpName2 = tmpView._ManifestOpsProvider.createReferenceManifest('TestManifest');
|
|
3162
|
+
let tmpName3 = tmpView._ManifestOpsProvider.createReferenceManifest('TestManifest');
|
|
3163
|
+
|
|
3164
|
+
Expect(tmpName1).to.equal('TestManifest');
|
|
3165
|
+
Expect(tmpName2).to.equal('TestManifest_2');
|
|
3166
|
+
Expect(tmpName3).to.equal('TestManifest_3');
|
|
3167
|
+
|
|
3168
|
+
let tmpNames = tmpView._ManifestOpsProvider.getReferenceManifestNames();
|
|
3169
|
+
Expect(tmpNames.length).to.equal(3);
|
|
3170
|
+
}
|
|
3171
|
+
);
|
|
3172
|
+
test
|
|
3173
|
+
(
|
|
3174
|
+
'getReferenceManifestNames should return list of manifest names',
|
|
3175
|
+
function ()
|
|
3176
|
+
{
|
|
3177
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
3178
|
+
tmpPict.AppData = {};
|
|
3179
|
+
|
|
3180
|
+
let tmpView = tmpPict.addView('TestRefManifestNames',
|
|
3181
|
+
{
|
|
3182
|
+
ViewIdentifier: 'TestRefManifestNames',
|
|
3183
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
3184
|
+
}, libPictSectionFormEditor);
|
|
3185
|
+
|
|
3186
|
+
tmpView.initialize();
|
|
3187
|
+
|
|
3188
|
+
let tmpNames = tmpView._ManifestOpsProvider.getReferenceManifestNames();
|
|
3189
|
+
Expect(tmpNames).to.be.an('array');
|
|
3190
|
+
Expect(tmpNames.length).to.equal(0);
|
|
3191
|
+
|
|
3192
|
+
tmpView._ManifestOpsProvider.createReferenceManifest('Alpha');
|
|
3193
|
+
tmpView._ManifestOpsProvider.createReferenceManifest('Beta');
|
|
3194
|
+
|
|
3195
|
+
tmpNames = tmpView._ManifestOpsProvider.getReferenceManifestNames();
|
|
3196
|
+
Expect(tmpNames.length).to.equal(2);
|
|
3197
|
+
Expect(tmpNames).to.include('Alpha');
|
|
3198
|
+
Expect(tmpNames).to.include('Beta');
|
|
3199
|
+
}
|
|
3200
|
+
);
|
|
3201
|
+
test
|
|
3202
|
+
(
|
|
3203
|
+
'_resolveReferenceManifest should return correct object or null',
|
|
3204
|
+
function ()
|
|
3205
|
+
{
|
|
3206
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
3207
|
+
tmpPict.AppData = {};
|
|
3208
|
+
|
|
3209
|
+
let tmpView = tmpPict.addView('TestResolveRef',
|
|
3210
|
+
{
|
|
3211
|
+
ViewIdentifier: 'TestResolveRef',
|
|
3212
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
3213
|
+
}, libPictSectionFormEditor);
|
|
3214
|
+
|
|
3215
|
+
tmpView.initialize();
|
|
3216
|
+
|
|
3217
|
+
Expect(tmpView._ManifestOpsProvider._resolveReferenceManifest('NonExistent')).to.equal(null);
|
|
3218
|
+
|
|
3219
|
+
tmpView._ManifestOpsProvider.createReferenceManifest('Existing');
|
|
3220
|
+
|
|
3221
|
+
let tmpResolved = tmpView._ManifestOpsProvider._resolveReferenceManifest('Existing');
|
|
3222
|
+
Expect(tmpResolved).to.be.an('object');
|
|
3223
|
+
Expect(tmpResolved.Scope).to.equal('Existing');
|
|
3224
|
+
}
|
|
3225
|
+
);
|
|
3226
|
+
test
|
|
3227
|
+
(
|
|
3228
|
+
'bindReferenceManifest should set group RecordManifest',
|
|
3229
|
+
function ()
|
|
3230
|
+
{
|
|
3231
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
3232
|
+
tmpPict.AppData = {};
|
|
3233
|
+
|
|
3234
|
+
let tmpView = tmpPict.addView('TestBindRef',
|
|
3235
|
+
{
|
|
3236
|
+
ViewIdentifier: 'TestBindRef',
|
|
3237
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
3238
|
+
}, libPictSectionFormEditor);
|
|
3239
|
+
|
|
3240
|
+
tmpView.initialize();
|
|
3241
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
3242
|
+
tmpView._ManifestOpsProvider.addGroup(0);
|
|
3243
|
+
tmpView._ManifestOpsProvider.createReferenceManifest('TestBind');
|
|
3244
|
+
|
|
3245
|
+
tmpView._ManifestOpsProvider.bindReferenceManifest(0, 0, 'TestBind');
|
|
3246
|
+
|
|
3247
|
+
let tmpManifest = tmpView._resolveManifestData();
|
|
3248
|
+
Expect(tmpManifest.Sections[0].Groups[0].RecordManifest).to.equal('TestBind');
|
|
3249
|
+
}
|
|
3250
|
+
);
|
|
3251
|
+
test
|
|
3252
|
+
(
|
|
3253
|
+
'unbindReferenceManifest should clear group RecordManifest',
|
|
3254
|
+
function ()
|
|
3255
|
+
{
|
|
3256
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
3257
|
+
tmpPict.AppData = {};
|
|
3258
|
+
|
|
3259
|
+
let tmpView = tmpPict.addView('TestUnbindRef',
|
|
3260
|
+
{
|
|
3261
|
+
ViewIdentifier: 'TestUnbindRef',
|
|
3262
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
3263
|
+
}, libPictSectionFormEditor);
|
|
3264
|
+
|
|
3265
|
+
tmpView.initialize();
|
|
3266
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
3267
|
+
tmpView._ManifestOpsProvider.addGroup(0);
|
|
3268
|
+
tmpView._ManifestOpsProvider.createReferenceManifest('TestUnbind');
|
|
3269
|
+
tmpView._ManifestOpsProvider.bindReferenceManifest(0, 0, 'TestUnbind');
|
|
3270
|
+
|
|
3271
|
+
Expect(tmpView._resolveManifestData().Sections[0].Groups[0].RecordManifest).to.equal('TestUnbind');
|
|
3272
|
+
|
|
3273
|
+
tmpView._ManifestOpsProvider.unbindReferenceManifest(0, 0);
|
|
3274
|
+
|
|
3275
|
+
Expect(tmpView._resolveManifestData().Sections[0].Groups[0].hasOwnProperty('RecordManifest')).to.equal(false);
|
|
3276
|
+
}
|
|
3277
|
+
);
|
|
3278
|
+
test
|
|
3279
|
+
(
|
|
3280
|
+
'createAndBindReferenceManifest should create and bind in one call',
|
|
3281
|
+
function ()
|
|
3282
|
+
{
|
|
3283
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
3284
|
+
tmpPict.AppData = {};
|
|
3285
|
+
|
|
3286
|
+
let tmpView = tmpPict.addView('TestCreateBind',
|
|
3287
|
+
{
|
|
3288
|
+
ViewIdentifier: 'TestCreateBind',
|
|
3289
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
3290
|
+
}, libPictSectionFormEditor);
|
|
3291
|
+
|
|
3292
|
+
tmpView.initialize();
|
|
3293
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
3294
|
+
tmpView._ManifestOpsProvider.addGroup(0);
|
|
3295
|
+
|
|
3296
|
+
let tmpGroup = tmpView._resolveManifestData().Sections[0].Groups[0];
|
|
3297
|
+
tmpGroup.Hash = 'TestGroup';
|
|
3298
|
+
|
|
3299
|
+
tmpView._ManifestOpsProvider.createAndBindReferenceManifest(0, 0);
|
|
3300
|
+
|
|
3301
|
+
let tmpManifest = tmpView._resolveManifestData();
|
|
3302
|
+
Expect(tmpManifest.Sections[0].Groups[0].RecordManifest).to.be.a('string');
|
|
3303
|
+
let tmpBoundName = tmpManifest.Sections[0].Groups[0].RecordManifest;
|
|
3304
|
+
Expect(tmpManifest.ReferenceManifests[tmpBoundName]).to.be.an('object');
|
|
3305
|
+
Expect(tmpManifest.ReferenceManifests[tmpBoundName].Descriptors).to.be.an('object');
|
|
3306
|
+
}
|
|
3307
|
+
);
|
|
3308
|
+
}
|
|
3309
|
+
);
|
|
3310
|
+
suite
|
|
3311
|
+
(
|
|
3312
|
+
'Submanifest Column Operations',
|
|
3313
|
+
function ()
|
|
3314
|
+
{
|
|
3315
|
+
test
|
|
3316
|
+
(
|
|
3317
|
+
'addSubmanifestColumn should add a Descriptor to bound ReferenceManifest',
|
|
3318
|
+
function ()
|
|
3319
|
+
{
|
|
3320
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
3321
|
+
tmpPict.AppData = {};
|
|
3322
|
+
|
|
3323
|
+
let tmpView = tmpPict.addView('TestAddSubCol',
|
|
3324
|
+
{
|
|
3325
|
+
ViewIdentifier: 'TestAddSubCol',
|
|
3326
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
3327
|
+
}, libPictSectionFormEditor);
|
|
3328
|
+
|
|
3329
|
+
tmpView.initialize();
|
|
3330
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
3331
|
+
tmpView._ManifestOpsProvider.addGroup(0);
|
|
3332
|
+
tmpView._ManifestOpsProvider.createAndBindReferenceManifest(0, 0);
|
|
3333
|
+
|
|
3334
|
+
tmpView._ManifestOpsProvider.addSubmanifestColumn(0, 0);
|
|
3335
|
+
|
|
3336
|
+
let tmpManifest = tmpView._resolveManifestData();
|
|
3337
|
+
let tmpRefName = tmpManifest.Sections[0].Groups[0].RecordManifest;
|
|
3338
|
+
let tmpRef = tmpManifest.ReferenceManifests[tmpRefName];
|
|
3339
|
+
let tmpKeys = Object.keys(tmpRef.Descriptors);
|
|
3340
|
+
|
|
3341
|
+
Expect(tmpKeys.length).to.equal(1);
|
|
3342
|
+
|
|
3343
|
+
let tmpDesc = tmpRef.Descriptors[tmpKeys[0]];
|
|
3344
|
+
Expect(tmpDesc.Name).to.be.a('string');
|
|
3345
|
+
Expect(tmpDesc.Hash).to.be.a('string');
|
|
3346
|
+
Expect(tmpDesc.DataType).to.equal('String');
|
|
3347
|
+
}
|
|
3348
|
+
);
|
|
3349
|
+
test
|
|
3350
|
+
(
|
|
3351
|
+
'addSubmanifestColumn should add multiple columns with unique addresses',
|
|
3352
|
+
function ()
|
|
3353
|
+
{
|
|
3354
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
3355
|
+
tmpPict.AppData = {};
|
|
3356
|
+
|
|
3357
|
+
let tmpView = tmpPict.addView('TestAddMultiSubCol',
|
|
3358
|
+
{
|
|
3359
|
+
ViewIdentifier: 'TestAddMultiSubCol',
|
|
3360
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
3361
|
+
}, libPictSectionFormEditor);
|
|
3362
|
+
|
|
3363
|
+
tmpView.initialize();
|
|
3364
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
3365
|
+
tmpView._ManifestOpsProvider.addGroup(0);
|
|
3366
|
+
tmpView._ManifestOpsProvider.createAndBindReferenceManifest(0, 0);
|
|
3367
|
+
|
|
3368
|
+
tmpView._ManifestOpsProvider.addSubmanifestColumn(0, 0);
|
|
3369
|
+
tmpView._ManifestOpsProvider.addSubmanifestColumn(0, 0);
|
|
3370
|
+
tmpView._ManifestOpsProvider.addSubmanifestColumn(0, 0);
|
|
3371
|
+
|
|
3372
|
+
let tmpManifest = tmpView._resolveManifestData();
|
|
3373
|
+
let tmpRefName = tmpManifest.Sections[0].Groups[0].RecordManifest;
|
|
3374
|
+
let tmpRef = tmpManifest.ReferenceManifests[tmpRefName];
|
|
3375
|
+
let tmpKeys = Object.keys(tmpRef.Descriptors);
|
|
3376
|
+
|
|
3377
|
+
Expect(tmpKeys.length).to.equal(3);
|
|
3378
|
+
// All keys should be unique
|
|
3379
|
+
let tmpUniqueKeys = new Set(tmpKeys);
|
|
3380
|
+
Expect(tmpUniqueKeys.size).to.equal(3);
|
|
3381
|
+
}
|
|
3382
|
+
);
|
|
3383
|
+
test
|
|
3384
|
+
(
|
|
3385
|
+
'removeSubmanifestColumn should remove Descriptor by address',
|
|
3386
|
+
function ()
|
|
3387
|
+
{
|
|
3388
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
3389
|
+
tmpPict.AppData = {};
|
|
3390
|
+
|
|
3391
|
+
let tmpView = tmpPict.addView('TestRemoveSubCol',
|
|
3392
|
+
{
|
|
3393
|
+
ViewIdentifier: 'TestRemoveSubCol',
|
|
3394
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
3395
|
+
}, libPictSectionFormEditor);
|
|
3396
|
+
|
|
3397
|
+
tmpView.initialize();
|
|
3398
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
3399
|
+
tmpView._ManifestOpsProvider.addGroup(0);
|
|
3400
|
+
tmpView._ManifestOpsProvider.createAndBindReferenceManifest(0, 0);
|
|
3401
|
+
|
|
3402
|
+
tmpView._ManifestOpsProvider.addSubmanifestColumn(0, 0);
|
|
3403
|
+
tmpView._ManifestOpsProvider.addSubmanifestColumn(0, 0);
|
|
3404
|
+
|
|
3405
|
+
let tmpManifest = tmpView._resolveManifestData();
|
|
3406
|
+
let tmpRefName = tmpManifest.Sections[0].Groups[0].RecordManifest;
|
|
3407
|
+
let tmpRef = tmpManifest.ReferenceManifests[tmpRefName];
|
|
3408
|
+
let tmpKeys = Object.keys(tmpRef.Descriptors);
|
|
3409
|
+
Expect(tmpKeys.length).to.equal(2);
|
|
3410
|
+
|
|
3411
|
+
let tmpFirstKey = tmpKeys[0];
|
|
3412
|
+
tmpView._ManifestOpsProvider.removeSubmanifestColumn(0, 0, tmpFirstKey);
|
|
3413
|
+
|
|
3414
|
+
tmpRef = tmpView._resolveManifestData().ReferenceManifests[tmpRefName];
|
|
3415
|
+
let tmpRemainingKeys = Object.keys(tmpRef.Descriptors);
|
|
3416
|
+
Expect(tmpRemainingKeys.length).to.equal(1);
|
|
3417
|
+
Expect(tmpRemainingKeys).to.not.include(tmpFirstKey);
|
|
3418
|
+
}
|
|
3419
|
+
);
|
|
3420
|
+
test
|
|
3421
|
+
(
|
|
3422
|
+
'moveSubmanifestColumnUp and Down should reorder Descriptors',
|
|
3423
|
+
function ()
|
|
3424
|
+
{
|
|
3425
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
3426
|
+
tmpPict.AppData = {};
|
|
3427
|
+
|
|
3428
|
+
let tmpView = tmpPict.addView('TestMoveSubCol',
|
|
3429
|
+
{
|
|
3430
|
+
ViewIdentifier: 'TestMoveSubCol',
|
|
3431
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
3432
|
+
}, libPictSectionFormEditor);
|
|
3433
|
+
|
|
3434
|
+
tmpView.initialize();
|
|
3435
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
3436
|
+
tmpView._ManifestOpsProvider.addGroup(0);
|
|
3437
|
+
tmpView._ManifestOpsProvider.createAndBindReferenceManifest(0, 0);
|
|
3438
|
+
|
|
3439
|
+
tmpView._ManifestOpsProvider.addSubmanifestColumn(0, 0);
|
|
3440
|
+
tmpView._ManifestOpsProvider.addSubmanifestColumn(0, 0);
|
|
3441
|
+
tmpView._ManifestOpsProvider.addSubmanifestColumn(0, 0);
|
|
3442
|
+
|
|
3443
|
+
let tmpManifest = tmpView._resolveManifestData();
|
|
3444
|
+
let tmpRefName = tmpManifest.Sections[0].Groups[0].RecordManifest;
|
|
3445
|
+
let tmpRef = tmpManifest.ReferenceManifests[tmpRefName];
|
|
3446
|
+
let tmpOriginalKeys = Object.keys(tmpRef.Descriptors);
|
|
3447
|
+
|
|
3448
|
+
// Move the last column up — it should swap with the middle
|
|
3449
|
+
tmpView._ManifestOpsProvider.moveSubmanifestColumnUp(0, 0, tmpOriginalKeys[2]);
|
|
3450
|
+
|
|
3451
|
+
tmpRef = tmpView._resolveManifestData().ReferenceManifests[tmpRefName];
|
|
3452
|
+
let tmpNewKeys = Object.keys(tmpRef.Descriptors);
|
|
3453
|
+
|
|
3454
|
+
Expect(tmpNewKeys[0]).to.equal(tmpOriginalKeys[0]);
|
|
3455
|
+
Expect(tmpNewKeys[1]).to.equal(tmpOriginalKeys[2]);
|
|
3456
|
+
Expect(tmpNewKeys[2]).to.equal(tmpOriginalKeys[1]);
|
|
3457
|
+
|
|
3458
|
+
// Move the first column down
|
|
3459
|
+
tmpView._ManifestOpsProvider.moveSubmanifestColumnDown(0, 0, tmpNewKeys[0]);
|
|
3460
|
+
|
|
3461
|
+
tmpRef = tmpView._resolveManifestData().ReferenceManifests[tmpRefName];
|
|
3462
|
+
let tmpFinalKeys = Object.keys(tmpRef.Descriptors);
|
|
3463
|
+
|
|
3464
|
+
Expect(tmpFinalKeys[0]).to.equal(tmpOriginalKeys[2]);
|
|
3465
|
+
Expect(tmpFinalKeys[1]).to.equal(tmpOriginalKeys[0]);
|
|
3466
|
+
}
|
|
3467
|
+
);
|
|
3468
|
+
test
|
|
3469
|
+
(
|
|
3470
|
+
'selectSubmanifestColumn should set _SelectedTabularColumn and clear _SelectedInputIndices',
|
|
3471
|
+
function ()
|
|
3472
|
+
{
|
|
3473
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
3474
|
+
tmpPict.AppData = {};
|
|
3475
|
+
|
|
3476
|
+
let tmpView = tmpPict.addView('TestSelectSubCol',
|
|
3477
|
+
{
|
|
3478
|
+
ViewIdentifier: 'TestSelectSubCol',
|
|
3479
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
3480
|
+
}, libPictSectionFormEditor);
|
|
3481
|
+
|
|
3482
|
+
tmpView.initialize();
|
|
3483
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
3484
|
+
tmpView._ManifestOpsProvider.addGroup(0);
|
|
3485
|
+
tmpView._ManifestOpsProvider.addRow(0, 0);
|
|
3486
|
+
tmpView._ManifestOpsProvider.addInput(0, 0, 0);
|
|
3487
|
+
tmpView._ManifestOpsProvider.createAndBindReferenceManifest(0, 0);
|
|
3488
|
+
tmpView._ManifestOpsProvider.addSubmanifestColumn(0, 0);
|
|
3489
|
+
|
|
3490
|
+
// First select a record input
|
|
3491
|
+
tmpView._UtilitiesProvider.selectInput(0, 0, 0, 0);
|
|
3492
|
+
Expect(tmpView._SelectedInputIndices).to.not.equal(null);
|
|
3493
|
+
|
|
3494
|
+
// Now select a submanifest column
|
|
3495
|
+
let tmpManifest = tmpView._resolveManifestData();
|
|
3496
|
+
let tmpRefName = tmpManifest.Sections[0].Groups[0].RecordManifest;
|
|
3497
|
+
let tmpRef = tmpManifest.ReferenceManifests[tmpRefName];
|
|
3498
|
+
let tmpAddress = Object.keys(tmpRef.Descriptors)[0];
|
|
3499
|
+
|
|
3500
|
+
tmpView._ManifestOpsProvider.selectSubmanifestColumn(0, 0, tmpAddress);
|
|
3501
|
+
|
|
3502
|
+
Expect(tmpView._SelectedTabularColumn).to.be.an('object');
|
|
3503
|
+
Expect(tmpView._SelectedTabularColumn.SectionIndex).to.equal(0);
|
|
3504
|
+
Expect(tmpView._SelectedTabularColumn.GroupIndex).to.equal(0);
|
|
3505
|
+
Expect(tmpView._SelectedTabularColumn.ColumnAddress).to.equal(tmpAddress);
|
|
3506
|
+
Expect(tmpView._SelectedInputIndices).to.equal(null);
|
|
3507
|
+
}
|
|
3508
|
+
);
|
|
3509
|
+
test
|
|
3510
|
+
(
|
|
3511
|
+
'addSubmanifestColumn should be a no-op when no ReferenceManifest is bound',
|
|
3512
|
+
function ()
|
|
3513
|
+
{
|
|
3514
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
3515
|
+
tmpPict.AppData = {};
|
|
3516
|
+
|
|
3517
|
+
let tmpView = tmpPict.addView('TestAddSubColNoRef',
|
|
3518
|
+
{
|
|
3519
|
+
ViewIdentifier: 'TestAddSubColNoRef',
|
|
3520
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
3521
|
+
}, libPictSectionFormEditor);
|
|
3522
|
+
|
|
3523
|
+
tmpView.initialize();
|
|
3524
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
3525
|
+
tmpView._ManifestOpsProvider.addGroup(0);
|
|
3526
|
+
|
|
3527
|
+
// No ReferenceManifest bound — should not throw
|
|
3528
|
+
tmpView._ManifestOpsProvider.addSubmanifestColumn(0, 0);
|
|
3529
|
+
|
|
3530
|
+
let tmpManifest = tmpView._resolveManifestData();
|
|
3531
|
+
// Manifest should not have any ReferenceManifests
|
|
3532
|
+
Expect(Object.keys(tmpManifest.ReferenceManifests).length).to.equal(0);
|
|
3533
|
+
}
|
|
3534
|
+
);
|
|
3535
|
+
test
|
|
3536
|
+
(
|
|
3537
|
+
'Shared ReferenceManifest edits via one group should affect the other',
|
|
3538
|
+
function ()
|
|
3539
|
+
{
|
|
3540
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
3541
|
+
tmpPict.AppData = {};
|
|
3542
|
+
|
|
3543
|
+
let tmpView = tmpPict.addView('TestSharedRef',
|
|
3544
|
+
{
|
|
3545
|
+
ViewIdentifier: 'TestSharedRef',
|
|
3546
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
3547
|
+
}, libPictSectionFormEditor);
|
|
3548
|
+
|
|
3549
|
+
tmpView.initialize();
|
|
3550
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
3551
|
+
tmpView._ManifestOpsProvider.addGroup(0);
|
|
3552
|
+
tmpView._ManifestOpsProvider.addGroup(0);
|
|
3553
|
+
tmpView._ManifestOpsProvider.createReferenceManifest('SharedManifest');
|
|
3554
|
+
tmpView._ManifestOpsProvider.bindReferenceManifest(0, 0, 'SharedManifest');
|
|
3555
|
+
tmpView._ManifestOpsProvider.bindReferenceManifest(0, 1, 'SharedManifest');
|
|
3556
|
+
|
|
3557
|
+
// Add a column via group 0
|
|
3558
|
+
tmpView._ManifestOpsProvider.addSubmanifestColumn(0, 0);
|
|
3559
|
+
|
|
3560
|
+
// Should be visible from group 1 since they share the manifest
|
|
3561
|
+
let tmpManifest = tmpView._resolveManifestData();
|
|
3562
|
+
let tmpRef = tmpManifest.ReferenceManifests['SharedManifest'];
|
|
3563
|
+
Expect(Object.keys(tmpRef.Descriptors).length).to.equal(1);
|
|
3564
|
+
}
|
|
3565
|
+
);
|
|
3566
|
+
}
|
|
3567
|
+
);
|
|
3568
|
+
suite
|
|
3569
|
+
(
|
|
3570
|
+
'Submanifest Row Helpers',
|
|
3571
|
+
function ()
|
|
3572
|
+
{
|
|
3573
|
+
test
|
|
3574
|
+
(
|
|
3575
|
+
'_getSubmanifestRows should group Descriptors by PictForm.Row',
|
|
3576
|
+
function ()
|
|
3577
|
+
{
|
|
3578
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
3579
|
+
tmpPict.AppData = {};
|
|
3580
|
+
|
|
3581
|
+
let tmpView = tmpPict.addView('TestGetSubRows',
|
|
3582
|
+
{
|
|
3583
|
+
ViewIdentifier: 'TestGetSubRows',
|
|
3584
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
3585
|
+
}, libPictSectionFormEditor);
|
|
3586
|
+
|
|
3587
|
+
tmpView.initialize();
|
|
3588
|
+
|
|
3589
|
+
let tmpRefManifest =
|
|
3590
|
+
{
|
|
3591
|
+
Scope: 'TestRows',
|
|
3592
|
+
Descriptors:
|
|
3593
|
+
{
|
|
3594
|
+
'col_a': { Name: 'A', Hash: 'A', DataType: 'String', PictForm: { Row: 1 } },
|
|
3595
|
+
'col_b': { Name: 'B', Hash: 'B', DataType: 'String', PictForm: { Row: 2 } },
|
|
3596
|
+
'col_c': { Name: 'C', Hash: 'C', DataType: 'String', PictForm: { Row: 1 } },
|
|
3597
|
+
'col_d': { Name: 'D', Hash: 'D', DataType: 'String', PictForm: { Row: 2 } }
|
|
3598
|
+
}
|
|
3599
|
+
};
|
|
3600
|
+
|
|
3601
|
+
let tmpRows = tmpView._ManifestOpsProvider._getSubmanifestRows(tmpRefManifest);
|
|
3602
|
+
Expect(tmpRows).to.be.an('array');
|
|
3603
|
+
Expect(tmpRows.length).to.equal(2);
|
|
3604
|
+
Expect(tmpRows[0].Row).to.equal(1);
|
|
3605
|
+
Expect(tmpRows[0].Columns.length).to.equal(2);
|
|
3606
|
+
Expect(tmpRows[0].Columns[0].Address).to.equal('col_a');
|
|
3607
|
+
Expect(tmpRows[0].Columns[1].Address).to.equal('col_c');
|
|
3608
|
+
Expect(tmpRows[1].Row).to.equal(2);
|
|
3609
|
+
Expect(tmpRows[1].Columns.length).to.equal(2);
|
|
3610
|
+
}
|
|
3611
|
+
);
|
|
3612
|
+
test
|
|
3613
|
+
(
|
|
3614
|
+
'_getSubmanifestRows should default Descriptors without PictForm.Row to row 1',
|
|
3615
|
+
function ()
|
|
3616
|
+
{
|
|
3617
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
3618
|
+
tmpPict.AppData = {};
|
|
3619
|
+
|
|
3620
|
+
let tmpView = tmpPict.addView('TestSubRowsDefault',
|
|
3621
|
+
{
|
|
3622
|
+
ViewIdentifier: 'TestSubRowsDefault',
|
|
3623
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
3624
|
+
}, libPictSectionFormEditor);
|
|
3625
|
+
|
|
3626
|
+
tmpView.initialize();
|
|
3627
|
+
|
|
3628
|
+
let tmpRefManifest =
|
|
3629
|
+
{
|
|
3630
|
+
Scope: 'TestDefault',
|
|
3631
|
+
Descriptors:
|
|
3632
|
+
{
|
|
3633
|
+
'col_a': { Name: 'A', Hash: 'A', DataType: 'String' },
|
|
3634
|
+
'col_b': { Name: 'B', Hash: 'B', DataType: 'String', PictForm: {} }
|
|
3635
|
+
}
|
|
3636
|
+
};
|
|
3637
|
+
|
|
3638
|
+
let tmpRows = tmpView._ManifestOpsProvider._getSubmanifestRows(tmpRefManifest);
|
|
3639
|
+
Expect(tmpRows.length).to.equal(1);
|
|
3640
|
+
Expect(tmpRows[0].Row).to.equal(1);
|
|
3641
|
+
Expect(tmpRows[0].Columns.length).to.equal(2);
|
|
3642
|
+
}
|
|
3643
|
+
);
|
|
3644
|
+
test
|
|
3645
|
+
(
|
|
3646
|
+
'_getSubmanifestMaxRow should return the highest row number',
|
|
3647
|
+
function ()
|
|
3648
|
+
{
|
|
3649
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
3650
|
+
tmpPict.AppData = {};
|
|
3651
|
+
|
|
3652
|
+
let tmpView = tmpPict.addView('TestMaxRow',
|
|
3653
|
+
{
|
|
3654
|
+
ViewIdentifier: 'TestMaxRow',
|
|
3655
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
3656
|
+
}, libPictSectionFormEditor);
|
|
3657
|
+
|
|
3658
|
+
tmpView.initialize();
|
|
3659
|
+
|
|
3660
|
+
let tmpRefManifest =
|
|
3661
|
+
{
|
|
3662
|
+
Scope: 'TestMax',
|
|
3663
|
+
Descriptors:
|
|
3664
|
+
{
|
|
3665
|
+
'col_a': { Name: 'A', Hash: 'A', DataType: 'String', PictForm: { Row: 1 } },
|
|
3666
|
+
'col_b': { Name: 'B', Hash: 'B', DataType: 'String', PictForm: { Row: 5 } },
|
|
3667
|
+
'col_c': { Name: 'C', Hash: 'C', DataType: 'String', PictForm: { Row: 3 } }
|
|
3668
|
+
}
|
|
3669
|
+
};
|
|
3670
|
+
|
|
3671
|
+
Expect(tmpView._ManifestOpsProvider._getSubmanifestMaxRow(tmpRefManifest)).to.equal(5);
|
|
3672
|
+
|
|
3673
|
+
// Empty Descriptors should return 0
|
|
3674
|
+
let tmpEmptyRef = { Scope: 'Empty', Descriptors: {} };
|
|
3675
|
+
Expect(tmpView._ManifestOpsProvider._getSubmanifestMaxRow(tmpEmptyRef)).to.equal(0);
|
|
3676
|
+
}
|
|
3677
|
+
);
|
|
3678
|
+
test
|
|
3679
|
+
(
|
|
3680
|
+
'addSubmanifestRow should create a column with the next row number',
|
|
3681
|
+
function ()
|
|
3682
|
+
{
|
|
3683
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
3684
|
+
tmpPict.AppData = {};
|
|
3685
|
+
|
|
3686
|
+
let tmpView = tmpPict.addView('TestAddSubRow',
|
|
3687
|
+
{
|
|
3688
|
+
ViewIdentifier: 'TestAddSubRow',
|
|
3689
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
3690
|
+
}, libPictSectionFormEditor);
|
|
3691
|
+
|
|
3692
|
+
tmpView.initialize();
|
|
3693
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
3694
|
+
tmpView._ManifestOpsProvider.addGroup(0);
|
|
3695
|
+
tmpView._ManifestOpsProvider.createAndBindReferenceManifest(0, 0);
|
|
3696
|
+
|
|
3697
|
+
// Add first column (row 1 by default)
|
|
3698
|
+
tmpView._ManifestOpsProvider.addSubmanifestColumn(0, 0);
|
|
3699
|
+
|
|
3700
|
+
// Add a new row — should create a column with Row: 2
|
|
3701
|
+
tmpView._ManifestOpsProvider.addSubmanifestRow(0, 0);
|
|
3702
|
+
|
|
3703
|
+
let tmpManifest = tmpView._resolveManifestData();
|
|
3704
|
+
let tmpRefName = tmpManifest.Sections[0].Groups[0].RecordManifest;
|
|
3705
|
+
let tmpRef = tmpManifest.ReferenceManifests[tmpRefName];
|
|
3706
|
+
let tmpKeys = Object.keys(tmpRef.Descriptors);
|
|
3707
|
+
|
|
3708
|
+
Expect(tmpKeys.length).to.equal(2);
|
|
3709
|
+
|
|
3710
|
+
// The second column should have PictForm.Row = 2
|
|
3711
|
+
let tmpSecondDesc = tmpRef.Descriptors[tmpKeys[1]];
|
|
3712
|
+
Expect(tmpSecondDesc.PictForm).to.be.an('object');
|
|
3713
|
+
Expect(tmpSecondDesc.PictForm.Row).to.equal(2);
|
|
3714
|
+
}
|
|
3715
|
+
);
|
|
3716
|
+
}
|
|
3717
|
+
);
|
|
3718
|
+
suite
|
|
3719
|
+
(
|
|
3720
|
+
'Tabular and RecordSet Rendering',
|
|
3721
|
+
function ()
|
|
3722
|
+
{
|
|
3723
|
+
test
|
|
3724
|
+
(
|
|
3725
|
+
'Loading Simple-Table manifest should not throw',
|
|
3726
|
+
function ()
|
|
3727
|
+
{
|
|
3728
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
3729
|
+
tmpPict.AppData = {};
|
|
3730
|
+
|
|
3731
|
+
let tmpSimpleTable =
|
|
3732
|
+
{
|
|
3733
|
+
"Scope": "SuperSimpleTabularForm",
|
|
3734
|
+
"Sections":
|
|
3735
|
+
[
|
|
3736
|
+
{
|
|
3737
|
+
"Hash": "FruitGrid",
|
|
3738
|
+
"Name": "Fruits of the World",
|
|
3739
|
+
"Groups":
|
|
3740
|
+
[
|
|
3741
|
+
{
|
|
3742
|
+
"Hash": "FruitGrid",
|
|
3743
|
+
"Name": "FruitGrid",
|
|
3744
|
+
"Layout": "Tabular",
|
|
3745
|
+
"RecordSetAddress": "FruitData.FruityVice",
|
|
3746
|
+
"RecordManifest": "FruitEditor"
|
|
3747
|
+
}
|
|
3748
|
+
]
|
|
3749
|
+
}
|
|
3750
|
+
],
|
|
3751
|
+
"Descriptors":
|
|
3752
|
+
{
|
|
3753
|
+
"FruitData.FruityVice":
|
|
3754
|
+
{
|
|
3755
|
+
"Name": "Fruits of the Earth",
|
|
3756
|
+
"Hash": "FruitGrid",
|
|
3757
|
+
"DataType": "Array",
|
|
3758
|
+
"Default": [],
|
|
3759
|
+
"PictForm": { "Section": "FruitGrid", "Group": "FruitGrid" }
|
|
3760
|
+
}
|
|
3761
|
+
},
|
|
3762
|
+
"ReferenceManifests":
|
|
3763
|
+
{
|
|
3764
|
+
"FruitEditor":
|
|
3765
|
+
{
|
|
3766
|
+
"Scope": "FruitEditor",
|
|
3767
|
+
"Descriptors":
|
|
3768
|
+
{
|
|
3769
|
+
"name": { "Name": "Fruit Name", "Hash": "Name", "DataType": "String" },
|
|
3770
|
+
"family": { "Name": "Family", "Hash": "Family", "DataType": "String" },
|
|
3771
|
+
"order": { "Name": "Order", "Hash": "Order", "DataType": "String" },
|
|
3772
|
+
"genus": { "Name": "Genus", "Hash": "Genus", "DataType": "String" },
|
|
3773
|
+
"nutritions.calories": { "Name": "Calories", "Hash": "Calories", "DataType": "Number" }
|
|
3774
|
+
}
|
|
3775
|
+
}
|
|
3776
|
+
}
|
|
3777
|
+
};
|
|
3778
|
+
|
|
3779
|
+
let tmpView = tmpPict.addView('TestSimpleTable',
|
|
3780
|
+
{
|
|
3781
|
+
ViewIdentifier: 'TestSimpleTable',
|
|
3782
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
3783
|
+
}, libPictSectionFormEditor);
|
|
3784
|
+
|
|
3785
|
+
tmpView.initialize();
|
|
3786
|
+
tmpPict.AppData.FormConfig = tmpSimpleTable;
|
|
3787
|
+
|
|
3788
|
+
// Verify it loaded correctly
|
|
3789
|
+
let tmpManifest = tmpView._resolveManifestData();
|
|
3790
|
+
Expect(tmpManifest.Sections[0].Groups[0].Layout).to.equal('Tabular');
|
|
3791
|
+
Expect(tmpManifest.Sections[0].Groups[0].RecordManifest).to.equal('FruitEditor');
|
|
3792
|
+
Expect(tmpManifest.ReferenceManifests['FruitEditor']).to.be.an('object');
|
|
3793
|
+
}
|
|
3794
|
+
);
|
|
3795
|
+
test
|
|
3796
|
+
(
|
|
3797
|
+
'getFormStats should include ReferenceManifest and TabularColumn counts',
|
|
3798
|
+
function ()
|
|
3799
|
+
{
|
|
3800
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
3801
|
+
tmpPict.AppData = {};
|
|
3802
|
+
|
|
3803
|
+
let tmpView = tmpPict.addView('TestFormStatsTabular',
|
|
3804
|
+
{
|
|
3805
|
+
ViewIdentifier: 'TestFormStatsTabular',
|
|
3806
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
3807
|
+
}, libPictSectionFormEditor);
|
|
3808
|
+
|
|
3809
|
+
tmpView.initialize();
|
|
3810
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
3811
|
+
// addSection() already creates one default group, so use group index 0
|
|
3812
|
+
tmpView._ManifestOpsProvider.createAndBindReferenceManifest(0, 0);
|
|
3813
|
+
tmpView._ManifestOpsProvider.addSubmanifestColumn(0, 0);
|
|
3814
|
+
tmpView._ManifestOpsProvider.addSubmanifestColumn(0, 0);
|
|
3815
|
+
tmpView._ManifestOpsProvider.addSubmanifestColumn(0, 0);
|
|
3816
|
+
|
|
3817
|
+
let tmpStats = tmpView._UtilitiesProvider.getFormStats();
|
|
3818
|
+
Expect(tmpStats.ReferenceManifests).to.equal(1);
|
|
3819
|
+
Expect(tmpStats.TabularColumns).to.equal(3);
|
|
3820
|
+
Expect(tmpStats.Sections).to.equal(1);
|
|
3821
|
+
Expect(tmpStats.Groups).to.equal(1);
|
|
3822
|
+
}
|
|
3823
|
+
);
|
|
3824
|
+
test
|
|
3825
|
+
(
|
|
3826
|
+
'getAllInputEntries should include tabular columns with IsTabular marker',
|
|
3827
|
+
function ()
|
|
3828
|
+
{
|
|
3829
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
3830
|
+
tmpPict.AppData = {};
|
|
3831
|
+
|
|
3832
|
+
let tmpView = tmpPict.addView('TestGetAllTabular',
|
|
3833
|
+
{
|
|
3834
|
+
ViewIdentifier: 'TestGetAllTabular',
|
|
3835
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
3836
|
+
}, libPictSectionFormEditor);
|
|
3837
|
+
|
|
3838
|
+
tmpView.initialize();
|
|
3839
|
+
|
|
3840
|
+
// Add a Record group with one input
|
|
3841
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
3842
|
+
tmpView._ManifestOpsProvider.addGroup(0);
|
|
3843
|
+
tmpView._ManifestOpsProvider.addRow(0, 0);
|
|
3844
|
+
tmpView._ManifestOpsProvider.addInput(0, 0, 0);
|
|
3845
|
+
|
|
3846
|
+
// Add a Tabular group with columns
|
|
3847
|
+
tmpView._ManifestOpsProvider.addGroup(0);
|
|
3848
|
+
let tmpManifest = tmpView._resolveManifestData();
|
|
3849
|
+
tmpManifest.Sections[0].Groups[1].Layout = 'Tabular';
|
|
3850
|
+
tmpView._ManifestOpsProvider.createAndBindReferenceManifest(0, 1);
|
|
3851
|
+
tmpView._ManifestOpsProvider.addSubmanifestColumn(0, 1);
|
|
3852
|
+
tmpView._ManifestOpsProvider.addSubmanifestColumn(0, 1);
|
|
3853
|
+
|
|
3854
|
+
let tmpEntries = tmpView._UtilitiesProvider.getAllInputEntries();
|
|
3855
|
+
Expect(tmpEntries).to.be.an('array');
|
|
3856
|
+
|
|
3857
|
+
// Should have 1 record input + 2 tabular columns
|
|
3858
|
+
Expect(tmpEntries.length).to.equal(3);
|
|
3859
|
+
|
|
3860
|
+
let tmpTabularEntries = tmpEntries.filter(function(e) { return e.IsTabular; });
|
|
3861
|
+
Expect(tmpTabularEntries.length).to.equal(2);
|
|
3862
|
+
|
|
3863
|
+
let tmpRecordEntries = tmpEntries.filter(function(e) { return !e.IsTabular; });
|
|
3864
|
+
Expect(tmpRecordEntries.length).to.equal(1);
|
|
3865
|
+
}
|
|
3866
|
+
);
|
|
3867
|
+
test
|
|
3868
|
+
(
|
|
3869
|
+
'Layout dropdown should include RecordSet option',
|
|
3870
|
+
function ()
|
|
3871
|
+
{
|
|
3872
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
3873
|
+
tmpPict.AppData = {};
|
|
3874
|
+
|
|
3875
|
+
let tmpView = tmpPict.addView('TestLayoutDropdown',
|
|
3876
|
+
{
|
|
3877
|
+
ViewIdentifier: 'TestLayoutDropdown',
|
|
3878
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
3879
|
+
}, libPictSectionFormEditor);
|
|
3880
|
+
|
|
3881
|
+
tmpView.initialize();
|
|
3882
|
+
tmpView._ManifestOpsProvider.addSection();
|
|
3883
|
+
tmpView._ManifestOpsProvider.addGroup(0);
|
|
3884
|
+
|
|
3885
|
+
// The Layout property edit list should include RecordSet
|
|
3886
|
+
// We verify this by checking that the view accepts RecordSet as a valid layout
|
|
3887
|
+
let tmpManifest = tmpView._resolveManifestData();
|
|
3888
|
+
tmpManifest.Sections[0].Groups[0].Layout = 'RecordSet';
|
|
3889
|
+
|
|
3890
|
+
// Should not throw when accessing a RecordSet layout group
|
|
3891
|
+
Expect(tmpManifest.Sections[0].Groups[0].Layout).to.equal('RecordSet');
|
|
3892
|
+
}
|
|
3893
|
+
);
|
|
3894
|
+
test
|
|
3895
|
+
(
|
|
3896
|
+
'_createEmptyManifest should include ReferenceManifests property',
|
|
3897
|
+
function ()
|
|
3898
|
+
{
|
|
3899
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
3900
|
+
tmpPict.AppData = {};
|
|
3901
|
+
|
|
3902
|
+
let tmpView = tmpPict.addView('TestEmptyManifest',
|
|
3903
|
+
{
|
|
3904
|
+
ViewIdentifier: 'TestEmptyManifest',
|
|
3905
|
+
ManifestDataAddress: 'AppData.FormConfig'
|
|
3906
|
+
}, libPictSectionFormEditor);
|
|
3907
|
+
|
|
3908
|
+
tmpView.initialize();
|
|
3909
|
+
|
|
3910
|
+
let tmpManifest = tmpView._resolveManifestData();
|
|
3911
|
+
Expect(tmpManifest.ReferenceManifests).to.be.an('object');
|
|
3912
|
+
Expect(Object.keys(tmpManifest.ReferenceManifests).length).to.equal(0);
|
|
3913
|
+
}
|
|
3914
|
+
);
|
|
3915
|
+
}
|
|
3916
|
+
);
|
|
3917
|
+
suite
|
|
3918
|
+
(
|
|
3919
|
+
'Properties Panel Tabular Column Editing',
|
|
3920
|
+
function ()
|
|
3921
|
+
{
|
|
3922
|
+
test
|
|
3923
|
+
(
|
|
3924
|
+
'selectTabularColumn should set _SelectedTabularColumn on properties panel',
|
|
3925
|
+
function ()
|
|
3926
|
+
{
|
|
3927
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
3928
|
+
tmpPict.AppData = {};
|
|
3929
|
+
|
|
3930
|
+
let tmpPropertiesPanel = require('../source/views/PictView-FormEditor-PropertiesPanel.js');
|
|
3931
|
+
|
|
3932
|
+
let tmpView = tmpPict.addView('TestSelectTabCol',
|
|
3933
|
+
{
|
|
3934
|
+
ViewIdentifier: 'TestSelectTabCol'
|
|
3935
|
+
}, tmpPropertiesPanel);
|
|
3936
|
+
|
|
3937
|
+
let tmpFormEditor = tmpPict.addView('TestSelectTabColParent',
|
|
3938
|
+
{
|
|
3939
|
+
ViewIdentifier: 'TestSelectTabColParent',
|
|
3940
|
+
ManifestDataAddress: 'AppData.TestManifest'
|
|
3941
|
+
}, libPictSectionFormEditor);
|
|
3942
|
+
tmpFormEditor.initialize();
|
|
3943
|
+
|
|
3944
|
+
tmpView._ParentFormEditor = tmpFormEditor;
|
|
3945
|
+
|
|
3946
|
+
tmpView.selectTabularColumn(0, 1, 'my_column');
|
|
3947
|
+
|
|
3948
|
+
Expect(tmpView._SelectedTabularColumn).to.be.an('object');
|
|
3949
|
+
Expect(tmpView._SelectedTabularColumn.SectionIndex).to.equal(0);
|
|
3950
|
+
Expect(tmpView._SelectedTabularColumn.GroupIndex).to.equal(1);
|
|
3951
|
+
Expect(tmpView._SelectedTabularColumn.ColumnAddress).to.equal('my_column');
|
|
3952
|
+
Expect(tmpView._SelectedInput).to.equal(null);
|
|
3953
|
+
}
|
|
3954
|
+
);
|
|
3955
|
+
test
|
|
3956
|
+
(
|
|
3957
|
+
'deselectInput on properties panel should clear _SelectedTabularColumn',
|
|
3958
|
+
function ()
|
|
3959
|
+
{
|
|
3960
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
3961
|
+
tmpPict.AppData = {};
|
|
3962
|
+
|
|
3963
|
+
let tmpPropertiesPanel = require('../source/views/PictView-FormEditor-PropertiesPanel.js');
|
|
3964
|
+
|
|
3965
|
+
let tmpView = tmpPict.addView('TestDeselectTabCol',
|
|
3966
|
+
{
|
|
3967
|
+
ViewIdentifier: 'TestDeselectTabCol'
|
|
3968
|
+
}, tmpPropertiesPanel);
|
|
3969
|
+
|
|
3970
|
+
tmpView._SelectedTabularColumn = { SectionIndex: 0, GroupIndex: 0, ColumnAddress: 'test' };
|
|
3971
|
+
|
|
3972
|
+
tmpView.deselectInput();
|
|
3973
|
+
|
|
3974
|
+
Expect(tmpView._SelectedTabularColumn).to.equal(null);
|
|
3975
|
+
Expect(tmpView._SelectedInput).to.equal(null);
|
|
3976
|
+
}
|
|
3977
|
+
);
|
|
3978
|
+
test
|
|
3979
|
+
(
|
|
3980
|
+
'commitTabularPropertyChange should update Descriptor fields',
|
|
3981
|
+
function ()
|
|
3982
|
+
{
|
|
3983
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
3984
|
+
tmpPict.AppData = {};
|
|
3985
|
+
|
|
3986
|
+
let tmpPropertiesPanel = require('../source/views/PictView-FormEditor-PropertiesPanel.js');
|
|
3987
|
+
|
|
3988
|
+
let tmpView = tmpPict.addView('TestCommitTabProp',
|
|
3989
|
+
{
|
|
3990
|
+
ViewIdentifier: 'TestCommitTabProp'
|
|
3991
|
+
}, tmpPropertiesPanel);
|
|
3992
|
+
|
|
3993
|
+
let tmpFormEditor = tmpPict.addView('TestCommitTabPropParent',
|
|
3994
|
+
{
|
|
3995
|
+
ViewIdentifier: 'TestCommitTabPropParent',
|
|
3996
|
+
ManifestDataAddress: 'AppData.TestCommitTabManifest'
|
|
3997
|
+
}, libPictSectionFormEditor);
|
|
3998
|
+
tmpFormEditor.initialize();
|
|
3999
|
+
|
|
4000
|
+
tmpFormEditor._ManifestOpsProvider.addSection();
|
|
4001
|
+
tmpFormEditor._ManifestOpsProvider.addGroup(0);
|
|
4002
|
+
tmpFormEditor._ManifestOpsProvider.createAndBindReferenceManifest(0, 0);
|
|
4003
|
+
tmpFormEditor._ManifestOpsProvider.addSubmanifestColumn(0, 0);
|
|
4004
|
+
|
|
4005
|
+
let tmpManifest = tmpFormEditor._resolveManifestData();
|
|
4006
|
+
let tmpRefName = tmpManifest.Sections[0].Groups[0].RecordManifest;
|
|
4007
|
+
let tmpRef = tmpManifest.ReferenceManifests[tmpRefName];
|
|
4008
|
+
let tmpAddress = Object.keys(tmpRef.Descriptors)[0];
|
|
4009
|
+
|
|
4010
|
+
tmpView._ParentFormEditor = tmpFormEditor;
|
|
4011
|
+
tmpView.selectTabularColumn(0, 0, tmpAddress);
|
|
4012
|
+
|
|
4013
|
+
tmpView.commitTabularPropertyChange('Name', 'Updated Name');
|
|
4014
|
+
|
|
4015
|
+
let tmpDesc = tmpFormEditor._resolveManifestData().ReferenceManifests[tmpRefName].Descriptors[tmpAddress];
|
|
4016
|
+
Expect(tmpDesc.Name).to.equal('Updated Name');
|
|
4017
|
+
|
|
4018
|
+
tmpView.commitTabularPropertyChange('Hash', 'UpdatedHash');
|
|
4019
|
+
tmpDesc = tmpFormEditor._resolveManifestData().ReferenceManifests[tmpRefName].Descriptors[tmpAddress];
|
|
4020
|
+
Expect(tmpDesc.Hash).to.equal('UpdatedHash');
|
|
4021
|
+
|
|
4022
|
+
tmpView.commitTabularPropertyChange('DataType', 'Number');
|
|
4023
|
+
tmpDesc = tmpFormEditor._resolveManifestData().ReferenceManifests[tmpRefName].Descriptors[tmpAddress];
|
|
4024
|
+
Expect(tmpDesc.DataType).to.equal('Number');
|
|
4025
|
+
}
|
|
4026
|
+
);
|
|
4027
|
+
test
|
|
4028
|
+
(
|
|
4029
|
+
'onInputSelectorChange should handle T: prefix for tabular columns',
|
|
4030
|
+
function ()
|
|
4031
|
+
{
|
|
4032
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
4033
|
+
tmpPict.AppData = {};
|
|
4034
|
+
|
|
4035
|
+
let tmpPropertiesPanel = require('../source/views/PictView-FormEditor-PropertiesPanel.js');
|
|
4036
|
+
|
|
4037
|
+
let tmpView = tmpPict.addView('TestInputSelectorTab',
|
|
4038
|
+
{
|
|
4039
|
+
ViewIdentifier: 'TestInputSelectorTab'
|
|
4040
|
+
}, tmpPropertiesPanel);
|
|
4041
|
+
|
|
4042
|
+
let tmpFormEditor = tmpPict.addView('TestInputSelectorTabParent',
|
|
4043
|
+
{
|
|
4044
|
+
ViewIdentifier: 'TestInputSelectorTabParent',
|
|
4045
|
+
ManifestDataAddress: 'AppData.TestSelectorManifest'
|
|
4046
|
+
}, libPictSectionFormEditor);
|
|
4047
|
+
tmpFormEditor.initialize();
|
|
4048
|
+
|
|
4049
|
+
tmpFormEditor._ManifestOpsProvider.addSection();
|
|
4050
|
+
tmpFormEditor._ManifestOpsProvider.addGroup(0);
|
|
4051
|
+
tmpFormEditor._ManifestOpsProvider.createAndBindReferenceManifest(0, 0);
|
|
4052
|
+
tmpFormEditor._ManifestOpsProvider.addSubmanifestColumn(0, 0);
|
|
4053
|
+
|
|
4054
|
+
let tmpManifest = tmpFormEditor._resolveManifestData();
|
|
4055
|
+
let tmpRefName = tmpManifest.Sections[0].Groups[0].RecordManifest;
|
|
4056
|
+
let tmpRef = tmpManifest.ReferenceManifests[tmpRefName];
|
|
4057
|
+
let tmpAddress = Object.keys(tmpRef.Descriptors)[0];
|
|
4058
|
+
|
|
4059
|
+
tmpView._ParentFormEditor = tmpFormEditor;
|
|
4060
|
+
|
|
4061
|
+
// Select via T: prefix format
|
|
4062
|
+
tmpView.onInputSelectorChange('T:0,0,' + tmpAddress);
|
|
4063
|
+
|
|
4064
|
+
Expect(tmpFormEditor._SelectedTabularColumn).to.be.an('object');
|
|
4065
|
+
Expect(tmpFormEditor._SelectedTabularColumn.SectionIndex).to.equal(0);
|
|
4066
|
+
Expect(tmpFormEditor._SelectedTabularColumn.GroupIndex).to.equal(0);
|
|
4067
|
+
Expect(tmpFormEditor._SelectedTabularColumn.ColumnAddress).to.equal(tmpAddress);
|
|
4068
|
+
}
|
|
4069
|
+
);
|
|
4070
|
+
test
|
|
4071
|
+
(
|
|
4072
|
+
'onInputSelectorChange should handle empty value by deselecting',
|
|
4073
|
+
function ()
|
|
4074
|
+
{
|
|
4075
|
+
let tmpPict = new libPict({ Product: 'TestFormEditor' });
|
|
4076
|
+
tmpPict.AppData = {};
|
|
4077
|
+
|
|
4078
|
+
let tmpPropertiesPanel = require('../source/views/PictView-FormEditor-PropertiesPanel.js');
|
|
4079
|
+
|
|
4080
|
+
let tmpView = tmpPict.addView('TestInputSelectorEmpty',
|
|
4081
|
+
{
|
|
4082
|
+
ViewIdentifier: 'TestInputSelectorEmpty'
|
|
4083
|
+
}, tmpPropertiesPanel);
|
|
4084
|
+
|
|
4085
|
+
let tmpFormEditor = tmpPict.addView('TestInputSelectorEmptyParent',
|
|
4086
|
+
{
|
|
4087
|
+
ViewIdentifier: 'TestInputSelectorEmptyParent',
|
|
4088
|
+
ManifestDataAddress: 'AppData.TestSelectorEmptyManifest'
|
|
4089
|
+
}, libPictSectionFormEditor);
|
|
4090
|
+
tmpFormEditor.initialize();
|
|
4091
|
+
|
|
4092
|
+
tmpView._ParentFormEditor = tmpFormEditor;
|
|
4093
|
+
|
|
4094
|
+
// Should not throw when deselecting
|
|
4095
|
+
tmpView.onInputSelectorChange('');
|
|
4096
|
+
tmpView.onInputSelectorChange(null);
|
|
4097
|
+
}
|
|
4098
|
+
);
|
|
4099
|
+
}
|
|
4100
|
+
);
|
|
4101
|
+
}
|
|
4102
|
+
);
|