mosaic-headless 1.29.1 → 1.29.2

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.
@@ -53,6 +53,12 @@ def main():
53
53
  help="a loop-pagination-numbers whose children are page links")
54
54
  ap.add_argument("--paged-item", default="ct-arch-title",
55
55
  help="the repeated attrID whose text should change per page")
56
+ ap.add_argument("--navbar", default="nb",
57
+ help="a navbar; its toggle is <id>-toggle and its nav <id>-nav")
58
+ ap.add_argument("--media", default="md-img",
59
+ help="an image node; icons are looked for beside it")
60
+ ap.add_argument("--shortcode", default="wp-sc",
61
+ help="a wpShortcode node")
56
62
  ap.add_argument("--steps", default="ms-panel-%d:3",
57
63
  help="multi-step panel attrID pattern and how many")
58
64
  ap.add_argument("--instances", default="cs-card",
@@ -169,6 +175,83 @@ def main():
169
175
  check("FORM/required_blocks", bool(invalid),
170
176
  "empty form reports invalid: %s" % invalid[:4])
171
177
 
178
+ # ---- navbar: the toggle only exists below its breakpoint
179
+ if not present(a.navbar):
180
+ skip("NAVBAR", "not on this page")
181
+ else:
182
+ wide = p.evaluate("""(id) => {
183
+ const t = document.getElementById(id + '-toggle');
184
+ const n = document.getElementById(id + '-nav');
185
+ const vis = e => { const r = e.getBoundingClientRect(),
186
+ s = getComputedStyle(e);
187
+ return r.height > 2 && s.display !== 'none'
188
+ && s.visibility !== 'hidden'; };
189
+ return {toggle: vis(t), nav: vis(n),
190
+ links: n.querySelectorAll('a').length};
191
+ }""", a.navbar)
192
+ check("NAVBAR/wide", wide["nav"] and not wide["toggle"],
193
+ "at this width the links are shown and the toggle is not "
194
+ "(nav=%s toggle=%s, %d links)"
195
+ % (wide["nav"], wide["toggle"], wide["links"]))
196
+ p.set_viewport_size({"width": 900, "height": 900})
197
+ p.wait_for_timeout(900)
198
+ narrow = p.evaluate("""(id) => {
199
+ const t = document.getElementById(id + '-toggle');
200
+ const n = document.getElementById(id + '-nav');
201
+ const vis = e => { const r = e.getBoundingClientRect(),
202
+ s = getComputedStyle(e);
203
+ return r.height > 2 && s.display !== 'none'; };
204
+ return {toggle: vis(t), nav: vis(n),
205
+ mode: String(document.getElementById(id).className)
206
+ .includes('dropdown-mode')};
207
+ }""", a.navbar)
208
+ check("NAVBAR/narrow", narrow["toggle"] and not narrow["nav"]
209
+ and narrow["mode"],
210
+ "below buttonBreakpoint it collapses behind the toggle "
211
+ "(dropdown-mode=%s)" % narrow["mode"])
212
+ p.click("#%s-toggle" % a.navbar)
213
+ p.wait_for_timeout(800)
214
+ opened = p.evaluate("""(id) => {
215
+ const n = document.getElementById(id + '-nav');
216
+ const r = n.getBoundingClientRect();
217
+ return r.height > 2 && getComputedStyle(n).display !== 'none'; }""",
218
+ a.navbar)
219
+ check("NAVBAR/toggle_opens", opened, "clicking it reveals the links")
220
+ p.set_viewport_size({"width": 1280, "height": 900})
221
+ p.wait_for_timeout(700)
222
+
223
+ # ---- media: an attachment-protocol image and raw-SVG icons
224
+ if not present(a.media):
225
+ skip("MEDIA", "not on this page")
226
+ else:
227
+ img = p.evaluate("""(id) => {
228
+ const e = document.querySelector('#' + id + ' img, img#' + id);
229
+ if (!e) return null;
230
+ return {w: Math.round(e.getBoundingClientRect().width),
231
+ natural: e.naturalWidth, src: (e.currentSrc || e.src || '')};
232
+ }""", a.media)
233
+ # naturalWidth > 0 is the only proof the file actually loaded; a broken
234
+ # src renders an <img> of the right size and no picture
235
+ check("MEDIA/image_loaded",
236
+ bool(img) and img["natural"] > 0 and img["w"] > 0,
237
+ "%dpx wide, natural %spx" % (img["w"], img["natural"]) if img
238
+ else "no <img> rendered")
239
+ icons = p.evaluate("""() => [...document.querySelectorAll('svg')]
240
+ .filter(s => s.closest('[id^=md-i]')).length""")
241
+ check("MEDIA/icons_inline", icons > 0,
242
+ "%d inline <svg> - `icon` takes RAW SVG in its `svg` property, "
243
+ "not a URL or a library name" % icons)
244
+
245
+ # ---- WordPress interop
246
+ if not present(a.shortcode):
247
+ skip("WORDPRESS", "not on this page")
248
+ else:
249
+ n = p.evaluate("""(id) => document.querySelectorAll(
250
+ '#' + id + ' .product, #' + id + ' li').length""", a.shortcode)
251
+ check("WORDPRESS/shortcode_ran", n > 0,
252
+ "%d items from the shortcode - this is WooCommerce's own "
253
+ "output, not a reimplementation" % n)
254
+
172
255
  # ---- a multi-step form shows ONE step at a time
173
256
  step_pat, n_steps = a.steps.rsplit(":", 1)
174
257
  n_steps = int(n_steps)