Test report – Midground 1.1.0
All figures come from real runs on 26 September 2026 against the local Docker environment (WordPress 7.1.2, PHP 8.3, MariaDB 11, WooCommerce 11.1.2) and, for the minimum versions, a fresh WordPress 6.6 on PHP 8.1. Browsers: Chromium, Firefox and WebKit from Playwright 1.63. Nothing is estimated. Raw data is in tests/results/ (not versioned) and can be recreated with the commands in each section.
Summary #
| Area | Result | Command |
|---|---|---|
| JavaScript unit tests | 12 / 12 passed | npm test |
| PHP integration tests | 98 / 98 passed, 1,399 checks | npm run test:php |
| Browser tests, 5 projects | 327 passed, 0 failed, 3 skipped on purpose (101 + 12 + 101 + 101 + 12) | npm run test:e2e |
| Accessibility (axe-core) | no serious or critical violations on 8 showcase pages, every page of the six starter sites and the editor, in all browsers | part of the browser tests |
| Clean install and life cycle | 45 / 45 (WordPress 7.1.2, PHP 8.3) and 46 / 46 (WordPress 6.6.2, PHP 8.1, with the PHP suite 98 / 98) | bash tests/install/clean-install.sh |
| Performance | every budget met for Midground's part; CLS at most 0.048, LCP on a throttled phone 1.31–1.70 s | node tools/perf.mjs |
| Translations | 2,596 / 2,596 strings in Norwegian (Bokmål) | bash tools/i18n.sh |
1. JavaScript unit tests (tests/js) #
The motion engine (interpolation per channel, combining effects, transform order, strength scaling), CSS value validation and the style compiler against shared test data, number formatting identical to PHP, document operations (insert, move, remove, style inheritance, allowed children).
2. PHP integration tests (tests/php) #
They run inside the real WordPress through WP-CLI; a PHP warning from Midground code turns a test red. Services of other companies are answered by local stand-ins (see status). Covered:
- Document model: invalid input, stable and duplicate ids, junk nodes, unknown element types kept safely, children that are not allowed, depth and size limits, sanitising per field type (inline HTML, rich text, links, numbers, dates, places, enums), scripts only for administrators, styles per screen size and injection attempts, attributes, effects, background video, SEO settings, migration from schema 1, JSON shape.
- Conditions and templates: matching, specificity before priority, priority and last change for equal rules (with a conflict), exceptions, facts from a real
WP_Query; header and footer created once on first run, retired when replaced, the Site information for the editor. - Storage: static copy and block structure, live rendering, revisions with the document and restore, original content stored once and restored exactly, edits made in another editor noticed and never overwritten, autosave, refresh without a revision.
- Motion: every built-in recipe (text reveal, hover and pointer included) gives valid data, strength 0 = rest, screen-size factors, custom keyframes, extensions.
- Media and fonts: 3D model validation, background video sources, the Google Fonts copy (only real font files, only from Google's font host, only administrators),
@font-faceserved from the site. - New elements: icon boxes (numbers however they are typed; a removed icon stays removed), reviews (rating and screen reader text; Google and Trustpilot through stand-ins, cleaned, cached, last good reviews kept), countdown (dates in the site's time zone), forms (the static copy keeps the shortcode), map (OpenStreetMap by default, Google only with a key, nothing loads by itself), background video (only safe settings, nothing before consent), API keys (checked, never exported). Slider, logo band, text band, popup, announcement bar, booking and language switcher are covered by the browser tests.
- Platform: SEO settings and cooperation with SEO plugins, WPML and Polylang, client mode (the server keeps layout and styles whatever is sent), export and import (images linked or copied, components re-linked), the licence layer with a stand-in shop, the AI assistant with a stand-in service, the move from Kulisse 1.0.
- Starter sites: every starter site imports without errors, takes over the front page, header and design, renders every page, updates instead of duplicating, and removing it restores the earlier design; fonts are copied when asked and fall back to a bundled font.
- Import, rendering, REST and life cycle: block and classic import, every element in editor, front-end and static mode, PHP/JS parity of the style compiler, the capability matrix for five roles, validation (400/404/413), a locked post gives 423, activation creates no content, uninstall keeps pages and documents, the documented extension example.
3. Browser tests (tests/e2e) #
Playwright, one worker, in five projects: desktop-chromium, desktop-firefox and desktop-webkit (1440×900) run every test; mobile-chromium (Pixel 7) and mobile-webkit (iPhone 14) run the tests marked @mobile.
| File | Test | Chromium | Pixel 7 | Firefox | WebKit | iPhone 14 |
|---|---|---|---|---|---|---|
01-vertical-slice | build, move, style, animate, publish and reload | passed | – | passed | passed | – |
02-library-motion | insert a page layout from the library, publish, and scroll-driven motion runs | passed | – | passed | passed | – |
02-library-motion | reduced motion: no transforms, scene unpinned, content visible | passed | – | passed | passed | – |
02-library-motion | pinned scene on a phone and a tablet: acts replace each other without overlapping | passed | – | passed | passed | – |
03-editor | layers: tree, keyboard moves and nesting, rename, hide, lock, drag | passed | – | passed | passed | – |
03-editor | undo/redo, duplicate, copy/paste, delete with undo, save and reload | passed | – | passed | passed | – |
03-editor | autosave keeps unsaved work and offers to restore it | passed | – | passed | passed | – |
03-editor | responsive overrides per device | passed | – | passed | passed | – |
03-editor | global design values update the canvas and are saved | passed | – | passed | passed | – |
03-editor | components: save as component, local override, publish | passed | – | passed | passed | – |
03-editor | revisions can be loaded back into the editor | passed | – | passed | passed | – |
03-editor | a failed save keeps the work and can be retried | passed | – | passed | passed | – |
03-editor | elements and library are searchable (also by Norwegian keywords) | passed | – | passed | passed | – |
04-templates | single-post template: create, preview with real content, conditions, priority and exclusions | passed | – | passed | passed | – |
04-templates | specificity beats priority; equal templates are resolved by date and reported | passed | – | passed | passed | – |
04-templates | 404 and search templates render on the frontend with real results | passed | – | passed | passed | – |
05-import | block content: report, preview, publish, then restore the original | passed | – | passed | passed | – |
05-import | classic content can be kept as one block | passed | – | passed | passed | – |
05-import | changes made in another editor are detected and can be imported | passed | – | passed | passed | – |
06-woocommerce | shop, product templates, cart and checkout with a simple and a variable product | passed | passed | passed | passed | passed |
07-security | subscriber › cannot open the editor or use any Midground endpoint | passed | – | passed | passed | – |
07-security | author › can build their own post, not others' pages, templates or site design | passed | – | passed | passed | – |
07-security | author › hostile content is cleaned before it is stored and rendered | passed | – | passed | passed | – |
07-security | administrator › invalid documents are repaired or rejected, never stored as-is | passed | – | passed | passed | – |
07-security | administrator › 3D model uploads are validated | passed | – | passed | passed | – |
08-fallbacks | 3D model loads and renders with WebGL | passed | – | passed | passed | – |
08-fallbacks | without WebGL the poster and a note are shown | passed | – | passed | passed | – |
08-fallbacks | a model that fails to load falls back to the poster | passed | – | passed | passed | – |
08-fallbacks | without JavaScript › all content is readable and the model poster is shown | passed | – | passed | passed | – |
08-fallbacks | when the motion runtime fails to load, content stays visible | passed | – | passed | passed | – |
08-fallbacks | phone: scroll motion runs, 3D or poster shows, nothing overflows | passed | passed | passed | passed | passed |
09-lifecycle | deactivating the builder leaves the content in place | passed | – | passed | passed | – |
09-lifecycle | another theme shows the same Midground content | passed | – | passed | passed | – |
09-lifecycle | turning WooCommerce off does not break pages with shop elements | passed | – | passed | passed | – |
10-mobile-editor | build a small page on a phone without drag and drop | skipped | passed | skipped | skipped | passed |
11-accessibility | no serious WCAG violations: / | passed | passed | passed | passed | passed |
11-accessibility | no serious WCAG violations: /myr/ | passed | passed | passed | passed | passed |
11-accessibility | no serious WCAG violations: /journal/ | passed | passed | passed | passed | passed |
11-accessibility | no serious WCAG violations: /shop/ | passed | passed | passed | passed | passed |
11-accessibility | no serious WCAG violations: /product/myr-pendel/ | passed | passed | passed | passed | passed |
11-accessibility | no serious WCAG violations: /cart/ | passed | passed | passed | passed | passed |
11-accessibility | no serious WCAG violations: /?s=lampe | passed | passed | passed | passed | passed |
11-accessibility | no serious WCAG violations: /finnes-ikke/ | passed | passed | passed | passed | passed |
11-accessibility | editor › the editor interface has no serious violations | passed | – | passed | passed | – |
11-accessibility | the site works with the keyboard alone | passed | – | passed | passed | – |
12-norwegian | editor in Norwegian › labels, notices and element names are Norwegian | passed | – | passed | passed | – |
12-norwegian | the site in Norwegian | passed | – | passed | passed | – |
13-richtext | settings panel: format text, color it, and turn a paragraph into a Heading element | passed | – | passed | passed | – |
13-richtext | HTML view: headings typed as HTML are split into Heading elements | passed | – | passed | passed | – |
13-richtext | on the page: floating toolbar formats text and makes headings | passed | – | passed | passed | – |
14-handles | resize and spacing handles write per-device styles | passed | – | passed | passed | – |
15-site-panels | design panel content fits the panel width (en_US) | passed | – | passed | passed | – |
15-site-panels | design panel content fits the panel width (nb_NO) | passed | – | passed | passed | – |
15-site-panels | header and footer are easy to reach › click the header on the page, edit it, and go back to the page | passed | – | passed | passed | – |
15-site-panels | header and footer are easy to reach › menu items open the header and footer; the toolbar on the site links to them | passed | – | passed | passed | – |
15-site-panels | header and footer are easy to reach › first run creates a header and footer; a demo import replaces them if untouched | passed | – | passed | passed | – |
16-background-video | background video › a file plays muted on screen, under the overlay; YouTube waits for consent | passed | – | passed | passed | – |
16-background-video | background video › "Not now" keeps YouTube away; consent handled elsewhere loads it without asking | passed | – | passed | passed | – |
16-background-video | background video › reduced motion and phones set to "poster" download no video | passed | – | passed | passed | – |
16-background-video | background video › set up in the editor from Style → Background | passed | – | passed | passed | – |
17-fonts | fonts › add a font, use it for headings, served from this site | passed | – | passed | passed | – |
17-fonts | fonts › a font in use cannot be removed until another is chosen | passed | – | passed | passed | – |
18-iconboxes | icon boxes › add a group, change its style and one box | passed | – | passed | passed | – |
18-iconboxes | icon boxes › numbers count up on the site, and just show with reduced motion | passed | – | passed | passed | – |
19-reviews | reviews: summary, cards, carousel and featured | passed | – | passed | passed | – |
20-slider | slider › add a slider with three slides and publish | passed | – | passed | passed | – |
20-slider | slider › arrows, dots, autoplay and pause on the site | passed | – | passed | passed | – |
20-slider | slider › no automatic change with reduced motion | passed | – | passed | passed | – |
21-countdown-marquee | countdowns: to a date, after the end, and per visitor | passed | – | passed | passed | – |
21-countdown-marquee | logo band moves, pauses, and stays calm with reduced motion | passed | – | passed | passed | – |
22-popup-announcement | popup: after a delay once, from links always, and it closes | passed | – | passed | passed | – |
22-popup-announcement | announcement bar: closing is remembered without a flash | passed | – | passed | passed | – |
22-popup-announcement | in the editor the popup sits in the page with its link address | passed | – | passed | passed | – |
23-map | map › find an address in the editor | passed | – | passed | passed | – |
23-map | map › on the site: nothing from the map service until the visitor asks | passed | – | passed | passed | – |
23-map | map › Google Maps with the owner’s own key | passed | – | passed | passed | – |
24-forms-booking | forms and booking › pick a form in the editor; styled like the site; the static copy keeps the shortcode | passed | – | passed | passed | – |
24-forms-booking | forms and booking › booking: in a window, on the page, in a new tab, or from a booking plugin | passed | – | passed | passed | – |
25-reveal-hover | text reveal: words and letters appear, whole text for screen readers | passed | – | passed | passed | – |
25-reveal-hover | text reveal is plain text with reduced motion | passed | – | passed | passed | – |
25-reveal-hover | hover: lifts while hovered and settles back | passed | – | passed | passed | – |
25-reveal-hover | moving text band slides with scrolling and never shows a gap | passed | – | passed | passed | – |
25-reveal-hover | page transitions are an opt-in design value, off with reduced motion | passed | – | passed | passed | – |
26-seo | search and sharing settings reach the page | passed | – | passed | passed | – |
26-seo | with an SEO plugin active Midground outputs nothing and says so | passed | – | passed | passed | – |
27-client-mode | client mode › the editor offers content only | passed | – | passed | passed | – |
27-client-mode | client mode › the server keeps layout and styles whatever is sent | passed | – | passed | passed | – |
28-export-import | export a page and import it again | passed | – | passed | passed | – |
29-woo-lean | pages without shop content load no WooCommerce scripts; shop pages do | passed | – | passed | passed | – |
30-assistant | AI assistant › no AI button while it is off | passed | – | passed | passed | – |
30-assistant | AI assistant › improve and shorten a text, accepting only when chosen | passed | – | passed | passed | – |
31-starter-sites | import a starter site from the admin, then remove it | passed | – | passed | passed | – |
31-starter-sites | no serious WCAG violations: agency | passed | – | passed | passed | – |
31-starter-sites | no serious WCAG violations: restaurant | passed | – | passed | passed | – |
31-starter-sites | no serious WCAG violations: shop | passed | – | passed | passed | – |
31-starter-sites | no serious WCAG violations: local | passed | – | passed | passed | – |
31-starter-sites | no serious WCAG violations: experience | passed | – | passed | passed | – |
31-starter-sites | no serious WCAG violations: saas | passed | – | passed | passed | – |
32-help-tour | the tour starts once, can be stepped through with the keyboard and taken again | passed | passed | passed | passed | passed |
32-help-tour | the Help menu opens the keyboard shortcuts | passed | – | passed | passed | – |
33-header | a sticky header stays at the top of the screen | passed | – | passed | passed | – |
33-header | header over the first section: see-through on the hero, solid after scrolling | passed | – | passed | passed | – |
- Chromium (
desktop-chromium): 101 passed, 0 failed, 1 skipped - Pixel 7 (
mobile-chromium): 12 passed, 0 failed - Firefox (
desktop-firefox): 101 passed, 0 failed, 1 skipped - WebKit (
desktop-webkit): 101 passed, 0 failed, 1 skipped - iPhone 14 (
mobile-webkit): 12 passed, 0 failed
The one skipped test on the desktop projects is the phone editor test, which runs on the phones. In total 327 passed, 0 failed, 3 skipped on purpose.
4. Accessibility #
axe-core 4.13 with the WCAG 2.0/2.1 level A and AA rules, at rest (reduced motion, so animations are not measured half-way):
| File | Test | Chromium | Pixel 7 | Firefox | WebKit | iPhone 14 |
|---|---|---|---|---|---|---|
11-accessibility | no serious WCAG violations: / | passed | passed | passed | passed | passed |
11-accessibility | no serious WCAG violations: /myr/ | passed | passed | passed | passed | passed |
11-accessibility | no serious WCAG violations: /journal/ | passed | passed | passed | passed | passed |
11-accessibility | no serious WCAG violations: /shop/ | passed | passed | passed | passed | passed |
11-accessibility | no serious WCAG violations: /product/myr-pendel/ | passed | passed | passed | passed | passed |
11-accessibility | no serious WCAG violations: /cart/ | passed | passed | passed | passed | passed |
11-accessibility | no serious WCAG violations: /?s=lampe | passed | passed | passed | passed | passed |
11-accessibility | no serious WCAG violations: /finnes-ikke/ | passed | passed | passed | passed | passed |
11-accessibility | editor › the editor interface has no serious violations | passed | – | passed | passed | – |
11-accessibility | the site works with the keyboard alone | passed | – | passed | passed | – |
31-starter-sites | no serious WCAG violations: agency | passed | – | passed | passed | – |
31-starter-sites | no serious WCAG violations: restaurant | passed | – | passed | passed | – |
31-starter-sites | no serious WCAG violations: shop | passed | – | passed | passed | – |
31-starter-sites | no serious WCAG violations: local | passed | – | passed | passed | – |
31-starter-sites | no serious WCAG violations: experience | passed | – | passed | passed | – |
31-starter-sites | no serious WCAG violations: saas | passed | – | passed | passed | – |
"passed" means no serious or critical violation. Each starter site row checks every page of that site (4, 3, 4, 4, 3 and 2 pages); those checks run on the desktop projects.
Also: a keyboard test (skip link, visible focus, every focused element visible, no focus trap), the editor tour (focus kept in the tour card, Escape closes, arrow keys step through), popups as real dialogs, reduced motion (no transforms, pinned scenes released), content readable without JavaScript, without WebGL and when the runtime fails. Not done: a manual test with a screen reader (see status).
5. Clean install and life cycle (tests/install/clean-install.sh) #
A new WordPress (its own database) on port 8089 with the packages from dist/:
- Install and activate the theme and plugin from the ZIP files; activation creates no content.
- First visit to the admin: a header and a footer are created once.
- Build a page: heading, text, effect and CSS show; the revision has the document.
- Update (reinstall over an older version number): the upgrade routine runs, the static copies are refreshed in the background, content is intact.
- Deactivate: heading and text still show, the theme's fallback styles load, no PHP errors.
- Uninstall (default): page, document, template and settings are kept; the plugin files go.
- Reinstall: the document can be edited again.
- Uninstall with "delete on uninstall": templates and settings are deleted, the page is kept and still readable.
- The Skumring showcase without WooCommerce: import and removal work, no shop is created.
- A starter site (Brightwater Plumbing): its front page, header and colours take over; removing it puts the earlier colours back.
| Environment | Result |
|---|---|
| WordPress 7.1.2, PHP 8.3.33 (latest) | 45 / 45 checks passed |
| WordPress 6.6.2, PHP 8.1.30 (web) and 8.1.34 (WP-CLI) – the minimum versions | 46 / 46 checks passed, including the whole PHP integration suite on these versions: 98 / 98 tests, 1,386 checks (without WooCommerce, whose current version needs a newer WordPress) |
All 100 PHP files of the theme and plugins also pass php -l on PHP 8.1.30.
The latest-version install was run three times on the final packages: twice 45 / 45, and once 44 / 45 – the check that reads the starter site's front page straight after the import did not find its heading in one run. It passed in the other two runs and on the minimum versions, and the cause was not found; it is noted here rather than hidden.
Commands:
python tools/package.py
bash tests/install/clean-install.sh
MG_WP_IMAGE=wordpress:6.6-php8.1-apache MG_CLI_IMAGE=wordpress:cli-php8.1 MG_PHP_TESTS=1 bash tests/install/clean-install.sh
6. Performance (tools/perf.mjs) #
Cold cache, median of 3 runs. Phone: Pixel 7, 4× CPU slowdown and a "Slow 4G"-like network (150 ms RTT, 1.6 Mbit/s). Desktop: 1440×900 without throttling. Measured locally; not Lighthouse.
| Page | Device | TTFB | FCP | LCP | CLS | TBT | Requests | JS Midground | JS WordPress/WooCommerce | CSS | Fonts | Images |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
Business page / | Phone (throttled) | 209 ms | 980 ms | 1.40 s | 0.001 | 0 ms | 13 | 12.5 KB | 7.5 KB | 17.3 KB | 151.1 KB | 104.9 KB |
Business page / | Desktop | 269 ms | 332 ms | 332 ms | 0 | 0 ms | 14 | 12.5 KB | 7.5 KB | 17.3 KB | 151.1 KB | 92.2 KB |
3D + parallax page /myr/ | Phone (throttled) | 213 ms | 1.67 s | 1.70 s | 0 | 0 ms | 28 | 12.5 KB | 52.5 KB | 34.6 KB | 151.1 KB | 86.8 KB |
3D + parallax page /myr/ | Desktop | 195 ms | 280 ms | 280 ms | 0 | 0 ms | 35 | 12.5 KB | 52.5 KB | 34.6 KB | 151.1 KB | 166.4 KB |
Shop /shop/ | Phone (throttled) | 218 ms | 1.64 s | 1.64 s | 0 | 0 ms | 24 | 12.5 KB | 52.5 KB | 34.6 KB | 151.1 KB | 82.5 KB |
Shop /shop/ | Desktop | 183 ms | 244 ms | 244 ms | 0 | 0 ms | 24 | 12.5 KB | 52.5 KB | 34.6 KB | 151.1 KB | 48.8 KB |
Product /product/myr-pendel/ | Phone (throttled) | 290 ms | 1.66 s | 1.66 s | 0.048 | 0 ms | 39 | 12.5 KB | 95.3 KB | 38.2 KB | 151.1 KB | 137.5 KB |
Product /product/myr-pendel/ | Desktop | 202 ms | 276 ms | 276 ms | 0 | 0 ms | 40 | 12.5 KB | 95.3 KB | 38.2 KB | 151.1 KB | 128.7 KB |
Starter site Ember & Oak / | Phone (throttled) | 217 ms | 1.02 s | 1.31 s | 0.003 | 0 ms | 13 | 12.5 KB | 7.5 KB | 17.3 KB | 151.1 KB | 127.1 KB |
Starter site Ember & Oak / | Desktop | 180 ms | 264 ms | 264 ms | 0 | 0 ms | 17 | 12.5 KB | 7.5 KB | 17.3 KB | 151.1 KB | 190.3 KB |
Starter site Loopwise / | Phone (throttled) | 200 ms | 1.01 s | 1.66 s | 0.003 | 16 ms | 17 | 12.5 KB | 7.5 KB | 17.3 KB | 57.5 KB | 150.1 KB |
Starter site Loopwise / | Desktop | 223 ms | 280 ms | 280 ms | 0 | 0 ms | 17 | 12.5 KB | 7.5 KB | 17.3 KB | 57.5 KB | 99.1 KB |
KB = compressed transfer (gzip) measured in the network layer. "JS Midground" is the runtime; on the 3D page the 3D viewer (166.1 KB, three.js) and the model (213.4 KB, GLB) load only when the model comes near the screen – not with the page. The two starter site rows are measured on their own after importing each starter site (design included, fonts not copied from Google, so the bundled fonts stand in) into the same installation. Motion runtime per scroll frame (desktop, every effect active): business page 11 elements, median 0 ms, 95th percentile 0.1 ms, max 0.2 ms; 3D page 12 elements, median 0 ms, 95th percentile 0.1 ms, max 0.3 ms; Loopwise 4 elements, max 0.4 ms.
Against the budgets in the plan:
| Budget (from the plan) | Simple page | Heavy 3D page | Measured | Status |
|---|---|---|---|---|
| JS before interaction (gzip), Midground | ≤ 20 KB | ≤ 30 KB | 12.5 KB on every page (1.0: 6.8 KB; the new elements are in the same runtime) | met |
| JS from WordPress/WooCommerce | – | – | 7.5 KB on pages without shop content (1.0: 52.5 KB – WooCommerce's scripts are now left out there); 52.5 KB on shop pages, 95.3 KB on the product page (jQuery, cart, gallery) | outside Midground's control |
| 3D module (gzip, on demand) | 0 | ≤ 200 KB | 0 on the simple page, 166.1 KB on the 3D page | met |
| CSS (gzip) | ≤ 30 KB | ≤ 35 KB | 17.3 KB on pages without shop content (1.0: 29.9 KB); 34.6 KB on the 3D page and the shop, 38.2 KB on the product page. Midground's and the theme's share is 17.1 KB everywhere; the rest is WooCommerce (16.7 KB, plus 2.9 KB for its image zoom on product pages) | met for Midground's part |
| Fonts | ≤ 2 variable woff2 | same | 2 files, 151.1 KB (the bundled fonts); Loopwise uses one of them, 57.5 KB | met |
| GLB per model | – | ≤ 1.5 MB (aim ≤ 600 KB) | 213.4 KB | met |
| CLS | < 0.05 | < 0.05 | at most 0.003 on normal pages; 0.048 on the product page on a phone | met |
| LCP (phone, local) | < 2.5 s | < 3.0 s | 1.31–1.70 s | met |
| Runtime per scroll frame (desktop) | < 2 ms | < 4 ms | max 0.4 ms | met |
7. Translations #
All 2,596 / 2,596 strings are translated to Norwegian (Bokmål): 1,846 for the builder, the theme and the showcase from before, plus 750 new ones – the editor tour and Help menu, the Starter sites screen and the content of the six starter sites (bash tools/i18n.sh). The user guide exists in English and Norwegian. The Norwegian editor and site are checked by 12-norwegian.
8. What was found and fixed during testing #
Found by the tests and fixed before delivery:
- iPhone and iPad: tapping an element in the editor did not select it. Safari only turns a tap into a click where a click listener sits below the document; the canvas now has one. The editor's bottom sheets also spilled under the bottom bar on short phones, and the top bar's buttons overlapped on narrow screens.
- Safari: a page with a background video file never finished loading while the video started; video files now start after the page has loaded (which also helps every browser's loading time).
- Contrast (axe-core on every starter site page): key figures in the accent colour, text on the accent-coloured call to action, countdown labels, a label on the sale band and WooCommerce's greyed-out "Add to cart" button had too little contrast; all fixed (icon box groups got a shared number colour for this).
- Layout: outlined text bands were invisible (the outline took the transparent text colour), hidden screen-reader texts in carousels widened the page, long e-mail addresses in footers pushed the page wider, review cards left an empty column, key figures sat one per row on phones, booking buttons could not take colours.
- Layout shift on phones (found by the performance measurements): a menu that folds into a button first showed as a list until the runtime had started, and the fonts the design uses were not all preloaded (CLS 0.09 on the restaurant starter site on a throttled phone). Pages are now marked as scripted before they are drawn (with a fallback if the runtime never starts), and the heading and body fonts – bundled or copied from Google Fonts – are preloaded.
- Product page on phones: WooCommerce's image gallery jumped while its slider started (CLS 0.44). The gallery now keeps the tallest image's proportions from the first paint: 0.048.
- Found while building the showcase sites (
showcase/): a header template's "Stick to the top" setting had no effect on the site, and a page's "Header over the first section" only worked with the theme's own header; both now work with Midground headers, and the header gets its own background back when the page scrolls (33-header). Titles in features, post lists, plans, questions and large quotes ignored the type settings (a one-weight serif was shown in a fake bold); "Remove icon" on icon boxes and features did not stick; captions, quote roles and archive descriptions were grey-on-dark on dark sections, and WooCommerce's stock text was too pale. All fixed. - Editor: the overlay around the selected element rewrote the page many times per second even when nothing changed; the tour now keeps the keyboard focus even while the editor settles; the showcase's colour names were saved in Norwegian on English sites.
Tests that were changed because a browser behaves differently (not because of a fault): Safari's Tab key skips links unless the visitor turns that on, so the keyboard test focuses the skip link directly in WebKit; mobile WebKit in the tests has no mouse wheel; four tests now wait for a save, a preview or the right settings panel instead of racing it.
Firefox under the test machine's app sandbox had to be started from its real installation folder (PLAYWRIGHT_BROWSERS_PATH); this is about the test machine, not the product.
9. Not tested and known limits #
See status: real devices and Safari on macOS/iOS, a manual screen reader test, multisite, other WooCommerce product types and payment methods, measurements over a real network, and the features that were verified only with stand-ins for other companies' services.