Test Suite Overview
The plugin has two test suites — one for JavaScript and one for PHP. They only test pure logic functions: no browser, no WordPress install, no database required.
How to Run
# Run all JS tests (single pass)
npm run test:js
# Run JS tests in watch mode (re-runs on file save)
npm run test:js:watch
# Run all PHP tests
vendor/bin/phpunit
Structure
tests/
├── js/
│ └── unit/
│ ├── page-builder/
│ │ ├── buildCanvasLiveCss.test.js # Canvas live-preview CSS generation
│ │ ├── buildCarouselWrapperData.test.js # Carousel settings resolution per device
│ │ ├── buildWidgetShortcode.test.js # [sanilwb ...] shortcode string builder
│ │ ├── CanvasCarousel.test.jsx # Editor canvas Embla instance management
│ │ ├── dndDropEdge.test.js # Drag-and-drop drop-edge detection
│ │ ├── gridColumns.test.js # Grid column layout helper
│ │ ├── history.test.js # Undo/redo stack + debounced snapshots
│ │ ├── injectTargetStyles.test.js # Own-tag style injection helper
│ │ ├── loopChildGroup.test.jsx # Loop's per-item clone rendering
│ │ ├── loopContext.test.jsx # Loop's per-clone React context
│ │ ├── pageBuilderStore.test.js # Factory function shape (schema guard)
│ │ ├── renderWidgetPreview.test.js # JS-side widget HTML preview rendering
│ │ ├── serialization.test.js # Tree <-> PHP JSON format conversion
│ │ ├── splitRootStyle.test.js # Root-wrapper vs. container style split
│ │ ├── structuralDialogTabs.test.js # Div dialog tab construction, per context
│ │ ├── styleTabSections.test.js # Shared Style tab section assembly
│ │ ├── treeTraversal.test.js # Node lookup/breadcrumb helpers
│ │ ├── useLoopPreview.test.js # Loop's batched AJAX preview fetch
│ │ └── widgetTypes.test.js # Widget registry shape/contexts
│ └── shared/
│ ├── buildAppearanceStyle.test.js # Responsive field fallback + visibility
│ ├── buildElementStyles.test.js # Element style attribute builder
│ └── colorValue.test.js # Color value sanitization
└── php/
├── bootstrap.php # Defines constants, loads classes (no WP)
└── unit/
├── AjaxTest.php # Widget context validation, schema checks
├── BlueprintsApplierTest.php # Blueprint template-ref resolution
├── CssCompilerTest.php # Stateless CSS declaration builders
├── FontSyncTest.php # Font registry sync/dedup
├── FrontendRendererTest.php # Recursive div render loop (nesting, structure)
├── PublicAjaxTest.php # ajax_render_widget() post-context setup
├── ShortcodeHandlerTest.php # [sanilwb] shortcode dispatch by widget type
├── ShortcodeHelpersTest.php # Shared shortcode utility methods
├── SiteLayoutConditionTest.php # Site Layout assignment condition matching
├── SiteLayoutRendererTest.php # Site Layout archive/search loop rendering
├── StyleFieldTargetsTest.php # styleFieldTargets.json bucket-target reader
└── TemplateReferenceShortcodeTest.php # Dynamic Template live rendering, recursion guard, memo cache
Tools
| Suite | Tool | Notes |
|---|---|---|
| JavaScript | Vitest | Configured in vitest.config.js |
| PHP | PHPUnit + Brain\Monkey | Brain\Monkey stubs WP functions per-test |
PHP bootstrap — no WordPress needed
The PHP bootstrap (tests/php/bootstrap.php) does three things so the plugin classes load in isolation:
- Defines
ABSPATHto satisfy theif (! defined('ABSPATH')) exit;guard in every plugin file. - Defines the
SANILWB_BP_*breakpoint constants (these are normally set in the main plugin file). - Loads
vendor/autoload.php(PHPUnit + Brain\Monkey + Mockery) and the plugin classes under test (class-sanilwb-blueprints-applier.php,class-sanilwb-style-field-targets.php,class-sanilwb-css-compiler.php,class-sanilwb-frontend-renderer.php,shortcodes/class-sanilwb-template-reference-shortcode.php,class-sanilwb-ajax.php,shortcodes/class-sanilwb-shortcode-helpers.php,shortcodes/class-sanilwb-heading-shortcode.php,class-sanilwb-shortcode-handler.php,shortcodes/class-sanilwb-shortcodes-shortcode.php,class-sanilwb-font-sync.php,class-sanilwb-site-layout-renderer.php,public/class-sanil-website-builder-public.php).
Brain\Monkey is not initialised in the bootstrap. Each test class calls Monkey\setUp() in setUp() and Monkey\tearDown() in tearDown() so WP function stubs are always isolated between test classes.
What Is and Isn't Tested
These tests cover pure logic only — functions that take inputs and return outputs with no side effects.
They do not test:
- React component rendering or UI interactions
- WordPress database reads/writes
- AJAX handlers
- File system operations (font downloads, compiled CSS files)
- Frontend shortcode output
For those areas, manual testing is the primary verification method.
Test Pages
Only a subset of the test files above have a dedicated write-up page — the rest are covered by their own inline comments in the test file.
| File | What it tests |
|---|---|
| JS: pageBuilderStore | Factory function shapes (schema contract) |
| JS: buildAppearanceStyle | Responsive value fallback and visibility flags |
| PHP: BlueprintsApplier | Blueprint template-ref-to-db-id resolution |