Repo docs

Per-repo documentation — each repo's docs/ and README, ingested and associated with the repo. Rendered through the <<<RepoDocs>>> tag.

← gitlab__testmonkeyalpha-group__repl docs · README.md

JSON-Control

A JavaScript UI control library and companion testing library.

lib/json-control is a vendored copy of dudezilla/JSON-Control, extended with two new controls. lib/control-testing provides instrumented spy controls, a test harness, and Jest-based integration tests for validating control behaviour.

---

Repository layout

lib/
  json-control/        # The control library (CommonJS, browser via Browserify)
    src/               # Control source files
    dist/              # Generated by `pnpm run generate` — do not edit by hand
    generate-demo.js   # Build script: bundles with Browserify and writes demo HTML
  control-testing/     # Testing library
    src/               # SpyControl, ControlHarness, EventSimulator, hooks
    tests/             # Jest integration tests (58 tests across 7 suites)

---

Requirements

| Tool | Version | |------|---------| | Node.js | 18 or later | | pnpm | 10 or later |

Install pnpm if you do not already have it:

npm install -g pnpm

---

Installation

Clone the repository and install all dependencies from the workspace root:

git clone https://gitlab.com/testmonkeyalpha-group/repl.git
cd repl
pnpm install

This installs dependencies for all packages in the monorepo in one step.

---

Running the tests

pnpm --filter @workspace/control-testing run test

Expected output: 58 tests, 7 suites, all passing.

Test files and what they cover:

| File | Controls under test | |------|-------------------| | construction.test.ts | Control construction and ID generation | | getElement.test.ts | DOM element creation | | setValue.test.ts | Value mutation and metrics | | bindings.test.ts | ControlRegistry registration | | eventLinkage.test.ts | Parent–child event propagation | | codeSnippet.test.ts | CodeSnippetControl rendering and escaping | | collapsibleCode.test.ts | CollapsibleCodeControl toggle and setCode |

---

Building the browser bundle and demo

The generator script bundles the library with Browserify and writes a live HTML demo:

pnpm --filter @workspace/json-control run generate

This produces two files inside lib/json-control/dist/:

| File | Description | |------|-------------| | Dudezilla.js | Browserify bundle — exposes the library via require('Dudezilla') | | CollapsibleCodeControl.html | Live demo page — open directly in a browser |

To view the demo, open lib/json-control/dist/CollapsibleCodeControl.html in any browser. No server is required.

---

Controls

Included from the upstream library

| Control | Description | |---------|-------------| | BooleanControl | Checkbox | | VerboseBooleanControl | Checkbox with verbose label | | RadioControl | Single radio button | | SelectionControl | Group of radio buttons (composite) | | ObservedSelectionControl | SelectionControl that reports changes | | ValueDisplayControl | Non-interactive label + value display |

Added in this repository

| Control | Description | |---------|-------------| | CodeSnippetControl | Renders code in a <figure><pre><code> block with HTML entity escaping | | CollapsibleCodeControl | Composite: clickable <h3> heading that toggles a CodeSnippetControl |

---

Using a control in a page

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>My Page</title>
    <script src="./Dudezilla.js"></script>
    <script>
      const dZilla = require('Dudezilla')
      const ControlRegistry = dZilla.ControlRegistry
      const ControlConfiguration = dZilla.ControlConfiguration
      const CollapsibleCodeControl = dZilla.CollapsibleCodeControl

      function init() {
        window.dudezilla = { bindings: new ControlRegistry() }

        const cfg = new ControlConfiguration({
          name: 'my_snippet',
          label: 'Click to collapse',
          state: 'const x = 42;',
          control_type: 'collapsible_code'
        })
        cfg.setRootID('root')

        const ctrl = new CollapsibleCodeControl(cfg)
        window.dudezilla.bindings.append(ctrl)
        document.getElementById('root').appendChild(ctrl.getElement())
        ctrl.applyHandlers()
      }

      window.addEventListener('load', init)
    </script>
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>

The pattern is the same for every control: create a ControlConfiguration, call setRootID, construct the control, append it to the DOM, call applyHandlers().

---

Using the testing library

import { useControlHarness } from '@workspace/control-testing'
import { SpyControl, makeSpyConfig } from '@workspace/control-testing'
import { EventSimulator } from '@workspace/control-testing'

const getHarness = useControlHarness()   // registers beforeEach / afterEach

test('records a setValue event', () => {
  const harness = getHarness()
  const ctrl = new SpyControl(makeSpyConfig('myControl', 'root'), harness.metrics)

  ctrl.setValue('hello')

  const events = harness.metrics.getEventsFor('root__myControl')
  expect(events.some(e => e.event === 'setValue')).toBe(true)
})

useControlHarness() sets up and tears down a jsdom environment around each test. SpyControl wraps any control and records construction, DOM rendering, value changes, and event linkage calls into harness.metrics.