jsgui3-server 0.0.143 → 0.0.145
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/docs/comprehensive-documentation.md +25 -6
- package/docs/configuration-reference.md +46 -11
- package/docs/controls-development.md +54 -26
- package/docs/jsgui3-html-improvement-ideas.md +162 -0
- package/docs/jsgui3-html-improvement-ideas.svg +151 -0
- package/docs/troubleshooting.md +9 -8
- package/examples/controls/14d) window, canvas globe/EarthGlobeRenderer.js +19 -14
- package/examples/controls/14d) window, canvas globe/pipeline/TransformStage.js +5 -5
- package/examples/jsgui3-html/01) mvvm-counter/client.js +648 -0
- package/examples/jsgui3-html/01) mvvm-counter/server.js +21 -0
- package/examples/jsgui3-html/02) date-transform/client.js +764 -0
- package/examples/jsgui3-html/02) date-transform/server.js +21 -0
- package/examples/jsgui3-html/03) form-validation/client.js +1045 -0
- package/examples/jsgui3-html/03) form-validation/server.js +21 -0
- package/examples/jsgui3-html/04) data-grid/client.js +738 -0
- package/examples/jsgui3-html/04) data-grid/server.js +21 -0
- package/examples/jsgui3-html/05) master-detail/client.js +649 -0
- package/examples/jsgui3-html/05) master-detail/server.js +21 -0
- package/examples/jsgui3-html/06) theming/client.js +514 -0
- package/examples/jsgui3-html/06) theming/server.js +21 -0
- package/examples/jsgui3-html/07) mixins/client.js +465 -0
- package/examples/jsgui3-html/07) mixins/server.js +21 -0
- package/examples/jsgui3-html/08) router/client.js +372 -0
- package/examples/jsgui3-html/08) router/server.js +21 -0
- package/examples/jsgui3-html/09) resource-transform/client.js +692 -0
- package/examples/jsgui3-html/09) resource-transform/server.js +21 -0
- package/examples/jsgui3-html/10) binding-debugger/client.js +810 -0
- package/examples/jsgui3-html/10) binding-debugger/server.js +21 -0
- package/examples/jsgui3-html/README.md +48 -0
- package/http/responders/static/Static_Route_HTTP_Responder.js +25 -20
- package/lab/README.md +19 -0
- package/lab/experiments/window_examples_dom_audit.js +241 -0
- package/lab/results/window_examples_dom_audit.json +131 -0
- package/lab/results/window_examples_dom_audit.md +46 -0
- package/package.json +8 -3
- package/publishers/http-webpageorsite-publisher.js +8 -4
- package/resources/processors/bundlers/css-bundler.js +28 -173
- package/resources/processors/bundlers/js/esbuild/Advanced_JS_Bundler_Using_ESBuild.js +32 -20
- package/resources/processors/bundlers/style-bundler.js +288 -0
- package/resources/processors/compilers/SASS_Compiler.js +88 -0
- package/resources/processors/extractors/js/css_and_js/AST_Node/CSS_And_JS_From_JS_String_Using_AST_Node_Extractor.js +64 -68
- package/resources/website-css-resource.js +24 -20
- package/resources/website-javascript-resource-processor.js +17 -57
- package/resources/website-javascript-resource.js +17 -57
- package/serve-factory.js +38 -24
- package/server.js +116 -92
- package/tests/README.md +38 -3
- package/tests/bundlers.test.js +41 -32
- package/tests/content-analysis.test.js +19 -18
- package/tests/end-to-end.test.js +336 -365
- package/tests/error-handling.test.js +13 -11
- package/tests/examples-controls.e2e.test.js +13 -1
- package/tests/fixtures/end-to-end-client.js +54 -0
- package/tests/fixtures/jsgui3-html/binding_debugger_expectations.json +15 -0
- package/tests/fixtures/jsgui3-html/counter_expectations.json +31 -0
- package/tests/fixtures/jsgui3-html/data_grid_expectations.json +26 -0
- package/tests/fixtures/jsgui3-html/date_transform_expectations.json +26 -0
- package/tests/fixtures/jsgui3-html/form_validation_expectations.json +27 -0
- package/tests/fixtures/jsgui3-html/master_detail_expectations.json +15 -0
- package/tests/fixtures/jsgui3-html/mixins_expectations.json +10 -0
- package/tests/fixtures/jsgui3-html/resource_transform_expectations.json +11 -0
- package/tests/fixtures/jsgui3-html/router_expectations.json +10 -0
- package/tests/fixtures/jsgui3-html/theming_expectations.json +10 -0
- package/tests/jsgui3-html-examples.puppeteer.test.js +537 -0
- package/tests/sass-controls.e2e.test.js +327 -0
- package/tests/test-runner.js +4 -1
- package/tests/window-examples.puppeteer.test.js +455 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const jsgui = require('./client');
|
|
2
|
+
const Server = require('../../../server');
|
|
3
|
+
const { Demo_UI } = jsgui.controls;
|
|
4
|
+
|
|
5
|
+
if (require.main === module) {
|
|
6
|
+
const server_instance = new Server({
|
|
7
|
+
Ctrl: Demo_UI,
|
|
8
|
+
src_path_client_js: require.resolve('./client.js')
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
server_instance.allowed_addresses = ['127.0.0.1'];
|
|
12
|
+
|
|
13
|
+
server_instance.on('ready', () => {
|
|
14
|
+
server_instance.start(52000, (err) => {
|
|
15
|
+
if (err) {
|
|
16
|
+
throw err;
|
|
17
|
+
}
|
|
18
|
+
console.log('server started on port 52000');
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# JSGUI3-HTML Example Plans
|
|
2
|
+
|
|
3
|
+
This folder collects new jsgui3-html focused examples for the server repo.
|
|
4
|
+
|
|
5
|
+
## Outline plan (10 examples)
|
|
6
|
+
|
|
7
|
+
1. **01) mvvm-counter**
|
|
8
|
+
- Goal: MVVM binding, computed properties, watchers, transformations, validators.
|
|
9
|
+
- UI: counter display, step input, increment/decrement/reset buttons.
|
|
10
|
+
- Tests: Puppeteer click flows, class toggles, validation states.
|
|
11
|
+
|
|
12
|
+
2. **02) date-transform**
|
|
13
|
+
- Goal: date transformations, parsing, range validation, locale formatting.
|
|
14
|
+
- UI: ISO input + locale display, min/max validation, error state.
|
|
15
|
+
|
|
16
|
+
3. **03) form-validation**
|
|
17
|
+
- Goal: multi-field validation (required/email/url/length/pattern).
|
|
18
|
+
- UI: registration form with per-field errors and submit state.
|
|
19
|
+
|
|
20
|
+
4. **04) data-grid**
|
|
21
|
+
- Goal: collection binding, sorting, filtering, pagination.
|
|
22
|
+
- UI: simple data grid with search and page controls.
|
|
23
|
+
|
|
24
|
+
5. **05) master-detail**
|
|
25
|
+
- Goal: selection syncing, computed detail view, navigation.
|
|
26
|
+
- UI: list + detail panel with prev/next controls.
|
|
27
|
+
|
|
28
|
+
6. **06) theming**
|
|
29
|
+
- Goal: theme tokens, theme overrides, CSS variable application.
|
|
30
|
+
- UI: theme toggle with token changes shown in a small layout.
|
|
31
|
+
|
|
32
|
+
7. **07) mixins**
|
|
33
|
+
- Goal: dragable/resizable/selectable mixins.
|
|
34
|
+
- UI: cards with drag/resize handles and selection states.
|
|
35
|
+
|
|
36
|
+
8. **08) router**
|
|
37
|
+
- Goal: router contract + route switching.
|
|
38
|
+
- UI: simple nav that swaps controls per route.
|
|
39
|
+
|
|
40
|
+
9. **09) resource-transform**
|
|
41
|
+
- Goal: Resource + Data_Transform pipeline.
|
|
42
|
+
- UI: load data, transform it, render output with status.
|
|
43
|
+
|
|
44
|
+
10. **10) binding-debugger**
|
|
45
|
+
- Goal: BindingDebugger usage to inspect bindings and changes.
|
|
46
|
+
- UI: inspector panel showing tracked changes over time.
|
|
47
|
+
|
|
48
|
+
Examples 01-10 are fully implemented right now.
|
|
@@ -54,22 +54,27 @@ class Static_Route_HTTP_Responder extends HTTP_Responder {
|
|
|
54
54
|
if (typeof accept_encoding === 'string' && accept_encoding.includes('gzip')) supported_encodings.gzip = true;
|
|
55
55
|
|
|
56
56
|
if (typeof accept_encoding === 'string' && accept_encoding.includes('br')) supported_encodings.br = true;
|
|
57
|
+
|
|
58
|
+
const has_br = response_buffers && response_buffers.br;
|
|
59
|
+
const has_gzip = response_buffers && response_buffers.gzip;
|
|
60
|
+
const use_br = supported_encodings.br === true && has_br;
|
|
61
|
+
const use_gzip = supported_encodings.gzip === true && has_gzip;
|
|
57
62
|
|
|
58
63
|
//console.log('supported_encodings', supported_encodings);
|
|
59
64
|
|
|
60
|
-
if (
|
|
61
|
-
|
|
62
|
-
for (const key in response_headers.br) {
|
|
63
|
-
const value = response_headers.br[key];
|
|
64
|
-
//console.log('[key, value]', [key, value]);
|
|
65
|
-
res.setHeader(key, value);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
} else if (
|
|
69
|
-
//console.log('should write headers for gzipped buffer...');
|
|
70
|
-
|
|
71
|
-
for (const key in response_headers.gzip) {
|
|
72
|
-
const value = response_headers.gzip[key];
|
|
65
|
+
if (use_br) {
|
|
66
|
+
|
|
67
|
+
for (const key in response_headers.br) {
|
|
68
|
+
const value = response_headers.br[key];
|
|
69
|
+
//console.log('[key, value]', [key, value]);
|
|
70
|
+
res.setHeader(key, value);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
} else if (use_gzip) {
|
|
74
|
+
//console.log('should write headers for gzipped buffer...');
|
|
75
|
+
|
|
76
|
+
for (const key in response_headers.gzip) {
|
|
77
|
+
const value = response_headers.gzip[key];
|
|
73
78
|
//console.log('[key, value]', [key, value]);
|
|
74
79
|
res.setHeader(key, value);
|
|
75
80
|
}
|
|
@@ -83,13 +88,13 @@ class Static_Route_HTTP_Responder extends HTTP_Responder {
|
|
|
83
88
|
|
|
84
89
|
// Then write the (hopefully compressed) response bodies...
|
|
85
90
|
|
|
86
|
-
if (
|
|
87
|
-
|
|
88
|
-
res.write(response_buffers.br);
|
|
89
|
-
} else if (
|
|
90
|
-
//console.log('should write gzipped buffer...');
|
|
91
|
-
res.write(response_buffers.gzip);
|
|
92
|
-
} else {
|
|
91
|
+
if (use_br) {
|
|
92
|
+
|
|
93
|
+
res.write(response_buffers.br);
|
|
94
|
+
} else if (use_gzip) {
|
|
95
|
+
//console.log('should write gzipped buffer...');
|
|
96
|
+
res.write(response_buffers.gzip);
|
|
97
|
+
} else {
|
|
93
98
|
res.write(response_buffers.identity);
|
|
94
99
|
}
|
|
95
100
|
|
package/lab/README.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Lab Experiments
|
|
2
|
+
|
|
3
|
+
This directory collects small, targeted experiments that validate specific UI behaviors or markup assumptions.
|
|
4
|
+
|
|
5
|
+
## Experiments
|
|
6
|
+
|
|
7
|
+
- `lab/experiments/window_examples_dom_audit.js`
|
|
8
|
+
- Server-rendered DOM checks for selected window examples.
|
|
9
|
+
- Writes results to `lab/results/window_examples_dom_audit.json` and `.md`.
|
|
10
|
+
|
|
11
|
+
## Running
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
node lab/experiments/window_examples_dom_audit.js
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Results
|
|
18
|
+
|
|
19
|
+
Experiment outputs are stored under `lab/results/` for traceability and documentation updates.
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
const Server_Page_Context = require('../../page-context');
|
|
5
|
+
|
|
6
|
+
const repo_root_path = path.join(__dirname, '..', '..');
|
|
7
|
+
const examples_controls_root_path = path.join(repo_root_path, 'examples', 'controls');
|
|
8
|
+
const results_dir_path = path.join(repo_root_path, 'lab', 'results');
|
|
9
|
+
|
|
10
|
+
const count_occurrences = (haystack, needle) => {
|
|
11
|
+
let idx = 0;
|
|
12
|
+
let count = 0;
|
|
13
|
+
while (true) {
|
|
14
|
+
idx = haystack.indexOf(needle, idx);
|
|
15
|
+
if (idx === -1) return count;
|
|
16
|
+
count++;
|
|
17
|
+
idx += needle.length;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const count_class_occurrences = (html, class_name) => {
|
|
22
|
+
const class_regex = new RegExp(`class="[^"]*\\b${class_name}\\b`, 'g');
|
|
23
|
+
const matches = html.match(class_regex);
|
|
24
|
+
return matches ? matches.length : 0;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const count_regex_occurrences = (html, regex) => {
|
|
28
|
+
const matches = html.match(regex);
|
|
29
|
+
return matches ? matches.length : 0;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const render_example_html = ({ dir_name, ctrl_name }) => {
|
|
33
|
+
const example_dir_path = path.join(examples_controls_root_path, dir_name);
|
|
34
|
+
const example_client_path = path.join(example_dir_path, 'client.js');
|
|
35
|
+
|
|
36
|
+
const jsgui = require(example_client_path);
|
|
37
|
+
const ctrl = jsgui.controls && jsgui.controls[ctrl_name];
|
|
38
|
+
if (!ctrl) {
|
|
39
|
+
throw new Error(`Missing exported control jsgui.controls.${ctrl_name} in ${example_client_path}`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const context = new Server_Page_Context();
|
|
43
|
+
const ctrl_instance = new ctrl({ context });
|
|
44
|
+
if (typeof ctrl_instance.all_html_render === 'function') {
|
|
45
|
+
return ctrl_instance.all_html_render();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (typeof ctrl_instance.render === 'function') {
|
|
49
|
+
return ctrl_instance.render();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
throw new Error(`Control ${ctrl_name} does not expose render methods`);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const make_count_check = (html, id, description, needle, expected) => {
|
|
56
|
+
const actual = count_occurrences(html, needle);
|
|
57
|
+
return {
|
|
58
|
+
id,
|
|
59
|
+
description,
|
|
60
|
+
expected,
|
|
61
|
+
actual,
|
|
62
|
+
pass: actual === expected
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const make_class_count_check = (html, id, description, class_name, expected) => {
|
|
67
|
+
const actual = count_class_occurrences(html, class_name);
|
|
68
|
+
return {
|
|
69
|
+
id,
|
|
70
|
+
description,
|
|
71
|
+
expected,
|
|
72
|
+
actual,
|
|
73
|
+
pass: actual === expected
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const make_contains_check = (html, id, description, needle) => {
|
|
78
|
+
const actual = html.includes(needle);
|
|
79
|
+
return {
|
|
80
|
+
id,
|
|
81
|
+
description,
|
|
82
|
+
expected: true,
|
|
83
|
+
actual,
|
|
84
|
+
pass: actual === true
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const make_regex_count_check = (html, id, description, regex, expected) => {
|
|
89
|
+
const actual = count_regex_occurrences(html, regex);
|
|
90
|
+
return {
|
|
91
|
+
id,
|
|
92
|
+
description,
|
|
93
|
+
expected,
|
|
94
|
+
actual,
|
|
95
|
+
pass: actual === expected
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const examples = [
|
|
100
|
+
{
|
|
101
|
+
dir_name: '1) window',
|
|
102
|
+
ctrl_name: 'Demo_UI',
|
|
103
|
+
checks: (html) => [
|
|
104
|
+
make_count_check(html, 'window_count', 'Window control count', 'data-jsgui-type="window"', 1),
|
|
105
|
+
make_contains_check(html, 'window_title_text', 'Window title text present', 'jsgui3-html Window Control'),
|
|
106
|
+
make_count_check(html, 'window_button_count', 'Window button count', 'data-jsgui-type="button"', 3)
|
|
107
|
+
]
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
dir_name: '4) window, tabbed panel',
|
|
111
|
+
ctrl_name: 'Demo_UI',
|
|
112
|
+
checks: (html) => [
|
|
113
|
+
make_class_count_check(html, 'tab_label_count', 'Tab label count', 'tab-label', 2),
|
|
114
|
+
make_contains_check(html, 'tab_label_one', 'Tab 1 label text present', 'tab 1'),
|
|
115
|
+
make_contains_check(html, 'tab_label_two', 'Tab 2 label text present', 'tab 2'),
|
|
116
|
+
make_count_check(html, 'tab_input_checked', 'Default checked tab input count', 'checked="checked"', 1)
|
|
117
|
+
]
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
dir_name: '8) window, checkbox/a)',
|
|
121
|
+
ctrl_name: 'Demo_UI',
|
|
122
|
+
checks: (html) => [
|
|
123
|
+
make_regex_count_check(
|
|
124
|
+
html,
|
|
125
|
+
'checkbox_input_count',
|
|
126
|
+
'Checkbox input count',
|
|
127
|
+
/\stype="checkbox"/g,
|
|
128
|
+
1
|
|
129
|
+
),
|
|
130
|
+
make_contains_check(html, 'checkbox_label_text', 'Checkbox label text present', 'A checkbox')
|
|
131
|
+
]
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
dir_name: '9) window, date picker',
|
|
135
|
+
ctrl_name: 'Demo_UI',
|
|
136
|
+
checks: (html) => [
|
|
137
|
+
make_class_count_check(html, 'date_picker_present', 'Date picker container present', 'date-picker', 1),
|
|
138
|
+
make_regex_count_check(
|
|
139
|
+
html,
|
|
140
|
+
'date_input_count',
|
|
141
|
+
'Date input type count',
|
|
142
|
+
/\stype="date"/g,
|
|
143
|
+
1
|
|
144
|
+
)
|
|
145
|
+
]
|
|
146
|
+
}
|
|
147
|
+
];
|
|
148
|
+
|
|
149
|
+
const build_results = () => {
|
|
150
|
+
const results = {
|
|
151
|
+
generated_at: new Date().toISOString(),
|
|
152
|
+
examples: []
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
for (const example of examples) {
|
|
156
|
+
const html = render_example_html(example);
|
|
157
|
+
const checks = example.checks(html);
|
|
158
|
+
const passed = checks.filter((check) => check.pass).length;
|
|
159
|
+
const failed = checks.length - passed;
|
|
160
|
+
|
|
161
|
+
results.examples.push({
|
|
162
|
+
dir_name: example.dir_name,
|
|
163
|
+
ctrl_name: example.ctrl_name,
|
|
164
|
+
checks,
|
|
165
|
+
summary: {
|
|
166
|
+
total: checks.length,
|
|
167
|
+
passed,
|
|
168
|
+
failed
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
results.summary = results.examples.reduce(
|
|
174
|
+
(acc, example) => {
|
|
175
|
+
acc.total += example.summary.total;
|
|
176
|
+
acc.passed += example.summary.passed;
|
|
177
|
+
acc.failed += example.summary.failed;
|
|
178
|
+
return acc;
|
|
179
|
+
},
|
|
180
|
+
{ total: 0, passed: 0, failed: 0 }
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
return results;
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
const render_markdown = (results) => {
|
|
187
|
+
const lines = [];
|
|
188
|
+
lines.push('# Window Examples DOM Audit');
|
|
189
|
+
lines.push('');
|
|
190
|
+
lines.push(`Generated at: ${results.generated_at}`);
|
|
191
|
+
lines.push('');
|
|
192
|
+
lines.push(`Total checks: ${results.summary.total}`);
|
|
193
|
+
lines.push(`Passed: ${results.summary.passed}`);
|
|
194
|
+
lines.push(`Failed: ${results.summary.failed}`);
|
|
195
|
+
lines.push('');
|
|
196
|
+
|
|
197
|
+
for (const example of results.examples) {
|
|
198
|
+
lines.push(`## ${example.dir_name}`);
|
|
199
|
+
lines.push('');
|
|
200
|
+
lines.push(`Control: ${example.ctrl_name}`);
|
|
201
|
+
lines.push('');
|
|
202
|
+
lines.push('| Check | Expected | Actual | Pass |');
|
|
203
|
+
lines.push('| --- | --- | --- | --- |');
|
|
204
|
+
for (const check of example.checks) {
|
|
205
|
+
const expected = Array.isArray(check.expected) ? check.expected.join(', ') : String(check.expected);
|
|
206
|
+
const actual = Array.isArray(check.actual) ? check.actual.join(', ') : String(check.actual);
|
|
207
|
+
lines.push(`| ${check.description} | ${expected} | ${actual} | ${check.pass ? 'yes' : 'no'} |`);
|
|
208
|
+
}
|
|
209
|
+
lines.push('');
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return lines.join('\n');
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
const write_results = (results) => {
|
|
216
|
+
fs.mkdirSync(results_dir_path, { recursive: true });
|
|
217
|
+
const json_path = path.join(results_dir_path, 'window_examples_dom_audit.json');
|
|
218
|
+
const md_path = path.join(results_dir_path, 'window_examples_dom_audit.md');
|
|
219
|
+
|
|
220
|
+
fs.writeFileSync(json_path, JSON.stringify(results, null, 2));
|
|
221
|
+
fs.writeFileSync(md_path, render_markdown(results));
|
|
222
|
+
|
|
223
|
+
return { json_path, md_path };
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
const main = () => {
|
|
227
|
+
const results = build_results();
|
|
228
|
+
const { json_path, md_path } = write_results(results);
|
|
229
|
+
|
|
230
|
+
console.log('Window examples DOM audit complete.');
|
|
231
|
+
console.log(`JSON: ${json_path}`);
|
|
232
|
+
console.log(`Markdown: ${md_path}`);
|
|
233
|
+
|
|
234
|
+
if (results.summary.failed > 0) {
|
|
235
|
+
process.exitCode = 1;
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
if (require.main === module) {
|
|
240
|
+
main();
|
|
241
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
{
|
|
2
|
+
"generated_at": "2025-12-19T19:05:37.894Z",
|
|
3
|
+
"examples": [
|
|
4
|
+
{
|
|
5
|
+
"dir_name": "1) window",
|
|
6
|
+
"ctrl_name": "Demo_UI",
|
|
7
|
+
"checks": [
|
|
8
|
+
{
|
|
9
|
+
"id": "window_count",
|
|
10
|
+
"description": "Window control count",
|
|
11
|
+
"expected": 1,
|
|
12
|
+
"actual": 1,
|
|
13
|
+
"pass": true
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"id": "window_title_text",
|
|
17
|
+
"description": "Window title text present",
|
|
18
|
+
"expected": true,
|
|
19
|
+
"actual": true,
|
|
20
|
+
"pass": true
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"id": "window_button_count",
|
|
24
|
+
"description": "Window button count",
|
|
25
|
+
"expected": 3,
|
|
26
|
+
"actual": 3,
|
|
27
|
+
"pass": true
|
|
28
|
+
}
|
|
29
|
+
],
|
|
30
|
+
"summary": {
|
|
31
|
+
"total": 3,
|
|
32
|
+
"passed": 3,
|
|
33
|
+
"failed": 0
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"dir_name": "4) window, tabbed panel",
|
|
38
|
+
"ctrl_name": "Demo_UI",
|
|
39
|
+
"checks": [
|
|
40
|
+
{
|
|
41
|
+
"id": "tab_label_count",
|
|
42
|
+
"description": "Tab label count",
|
|
43
|
+
"expected": 2,
|
|
44
|
+
"actual": 2,
|
|
45
|
+
"pass": true
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"id": "tab_label_one",
|
|
49
|
+
"description": "Tab 1 label text present",
|
|
50
|
+
"expected": true,
|
|
51
|
+
"actual": true,
|
|
52
|
+
"pass": true
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"id": "tab_label_two",
|
|
56
|
+
"description": "Tab 2 label text present",
|
|
57
|
+
"expected": true,
|
|
58
|
+
"actual": true,
|
|
59
|
+
"pass": true
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"id": "tab_input_checked",
|
|
63
|
+
"description": "Default checked tab input count",
|
|
64
|
+
"expected": 1,
|
|
65
|
+
"actual": 1,
|
|
66
|
+
"pass": true
|
|
67
|
+
}
|
|
68
|
+
],
|
|
69
|
+
"summary": {
|
|
70
|
+
"total": 4,
|
|
71
|
+
"passed": 4,
|
|
72
|
+
"failed": 0
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"dir_name": "8) window, checkbox/a)",
|
|
77
|
+
"ctrl_name": "Demo_UI",
|
|
78
|
+
"checks": [
|
|
79
|
+
{
|
|
80
|
+
"id": "checkbox_input_count",
|
|
81
|
+
"description": "Checkbox input count",
|
|
82
|
+
"expected": 1,
|
|
83
|
+
"actual": 1,
|
|
84
|
+
"pass": true
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"id": "checkbox_label_text",
|
|
88
|
+
"description": "Checkbox label text present",
|
|
89
|
+
"expected": true,
|
|
90
|
+
"actual": true,
|
|
91
|
+
"pass": true
|
|
92
|
+
}
|
|
93
|
+
],
|
|
94
|
+
"summary": {
|
|
95
|
+
"total": 2,
|
|
96
|
+
"passed": 2,
|
|
97
|
+
"failed": 0
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"dir_name": "9) window, date picker",
|
|
102
|
+
"ctrl_name": "Demo_UI",
|
|
103
|
+
"checks": [
|
|
104
|
+
{
|
|
105
|
+
"id": "date_picker_present",
|
|
106
|
+
"description": "Date picker container present",
|
|
107
|
+
"expected": 1,
|
|
108
|
+
"actual": 1,
|
|
109
|
+
"pass": true
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"id": "date_input_count",
|
|
113
|
+
"description": "Date input type count",
|
|
114
|
+
"expected": 1,
|
|
115
|
+
"actual": 1,
|
|
116
|
+
"pass": true
|
|
117
|
+
}
|
|
118
|
+
],
|
|
119
|
+
"summary": {
|
|
120
|
+
"total": 2,
|
|
121
|
+
"passed": 2,
|
|
122
|
+
"failed": 0
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
],
|
|
126
|
+
"summary": {
|
|
127
|
+
"total": 11,
|
|
128
|
+
"passed": 11,
|
|
129
|
+
"failed": 0
|
|
130
|
+
}
|
|
131
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Window Examples DOM Audit
|
|
2
|
+
|
|
3
|
+
Generated at: 2025-12-19T19:05:37.894Z
|
|
4
|
+
|
|
5
|
+
Total checks: 11
|
|
6
|
+
Passed: 11
|
|
7
|
+
Failed: 0
|
|
8
|
+
|
|
9
|
+
## 1) window
|
|
10
|
+
|
|
11
|
+
Control: Demo_UI
|
|
12
|
+
|
|
13
|
+
| Check | Expected | Actual | Pass |
|
|
14
|
+
| --- | --- | --- | --- |
|
|
15
|
+
| Window control count | 1 | 1 | yes |
|
|
16
|
+
| Window title text present | true | true | yes |
|
|
17
|
+
| Window button count | 3 | 3 | yes |
|
|
18
|
+
|
|
19
|
+
## 4) window, tabbed panel
|
|
20
|
+
|
|
21
|
+
Control: Demo_UI
|
|
22
|
+
|
|
23
|
+
| Check | Expected | Actual | Pass |
|
|
24
|
+
| --- | --- | --- | --- |
|
|
25
|
+
| Tab label count | 2 | 2 | yes |
|
|
26
|
+
| Tab 1 label text present | true | true | yes |
|
|
27
|
+
| Tab 2 label text present | true | true | yes |
|
|
28
|
+
| Default checked tab input count | 1 | 1 | yes |
|
|
29
|
+
|
|
30
|
+
## 8) window, checkbox/a)
|
|
31
|
+
|
|
32
|
+
Control: Demo_UI
|
|
33
|
+
|
|
34
|
+
| Check | Expected | Actual | Pass |
|
|
35
|
+
| --- | --- | --- | --- |
|
|
36
|
+
| Checkbox input count | 1 | 1 | yes |
|
|
37
|
+
| Checkbox label text present | true | true | yes |
|
|
38
|
+
|
|
39
|
+
## 9) window, date picker
|
|
40
|
+
|
|
41
|
+
Control: Demo_UI
|
|
42
|
+
|
|
43
|
+
| Check | Expected | Actual | Pass |
|
|
44
|
+
| --- | --- | --- | --- |
|
|
45
|
+
| Date picker container present | 1 | 1 | yes |
|
|
46
|
+
| Date input type count | 1 | 1 | yes |
|
package/package.json
CHANGED
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
"esbuild": "^0.27.1",
|
|
11
11
|
"fnl": "^0.0.37",
|
|
12
12
|
"fnlfs": "^0.0.34",
|
|
13
|
-
"jsgui3-client": "^0.0.
|
|
14
|
-
"jsgui3-html": "^0.0.
|
|
13
|
+
"jsgui3-client": "^0.0.125",
|
|
14
|
+
"jsgui3-html": "^0.0.176",
|
|
15
15
|
"jsgui3-webpage": "^0.0.8",
|
|
16
16
|
"jsgui3-website": "^0.0.8",
|
|
17
17
|
"lang-tools": "^0.0.44",
|
|
@@ -20,9 +20,13 @@
|
|
|
20
20
|
"ncp": "^2.0.0",
|
|
21
21
|
"obext": "^0.0.33",
|
|
22
22
|
"rimraf": "^6.1.2",
|
|
23
|
+
"sass": "^1.77.6",
|
|
23
24
|
"stream-to-array": "^2.3.0",
|
|
24
25
|
"url-parse": "^1.5.10"
|
|
25
26
|
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"puppeteer": "^19.11.1"
|
|
29
|
+
},
|
|
26
30
|
"commentDeps": {
|
|
27
31
|
"babel-plugin-minify-dead-code-elimination": "^0.5.0",
|
|
28
32
|
"babel-plugin-remove-comments": "^2.0.0",
|
|
@@ -39,7 +43,7 @@
|
|
|
39
43
|
"type": "git",
|
|
40
44
|
"url": "https://github.com/metabench/jsgui3-server.git"
|
|
41
45
|
},
|
|
42
|
-
"version": "0.0.
|
|
46
|
+
"version": "0.0.145",
|
|
43
47
|
"scripts": {
|
|
44
48
|
"cli": "node cli.js",
|
|
45
49
|
"serve": "node cli.js serve",
|
|
@@ -54,6 +58,7 @@
|
|
|
54
58
|
"test:performance": "node tests/test-runner.js --test=performance.test.js",
|
|
55
59
|
"test:errors": "node tests/test-runner.js --test=error-handling.test.js",
|
|
56
60
|
"test:examples:controls": "node tests/test-runner.js --test=examples-controls.e2e.test.js",
|
|
61
|
+
"test:puppeteer:windows": "node tests/test-runner.js --test=window-examples.puppeteer.test.js",
|
|
57
62
|
"test:debug": "node tests/test-runner.js --debug",
|
|
58
63
|
"test:verbose": "node tests/test-runner.js --verbose"
|
|
59
64
|
}
|
|
@@ -97,7 +97,9 @@ class HTTP_Webpageorsite_Publisher extends HTTP_Publisher {
|
|
|
97
97
|
constructor(spec) {
|
|
98
98
|
super(spec);
|
|
99
99
|
|
|
100
|
-
if (spec.debug !== undefined) this.debug = spec.debug;
|
|
100
|
+
if (spec.debug !== undefined) this.debug = spec.debug;
|
|
101
|
+
this.style_config = spec.style || {};
|
|
102
|
+
this.bundler_config = spec.bundler || {};
|
|
101
103
|
|
|
102
104
|
// But then some properties to do with the js client(s?) file path.
|
|
103
105
|
|
|
@@ -126,9 +128,11 @@ class HTTP_Webpageorsite_Publisher extends HTTP_Publisher {
|
|
|
126
128
|
|
|
127
129
|
// Maybe need a get_ready (async or obs) function....
|
|
128
130
|
|
|
129
|
-
this.js_bundler = new JS_Bundler({
|
|
130
|
-
'debug': this.debug || false
|
|
131
|
-
|
|
131
|
+
this.js_bundler = new JS_Bundler({
|
|
132
|
+
'debug': this.debug || false,
|
|
133
|
+
'style': this.style_config,
|
|
134
|
+
'bundler': this.bundler_config
|
|
135
|
+
});
|
|
132
136
|
|
|
133
137
|
|
|
134
138
|
}
|