OTTODesign System

Code

Form

Storybook group: Tests · Sidebar path: Tests/Form · Extracted 28.09.2026

Form (Form.interactions.stories.ts)

Interaction test stories (automated tests, not usage patterns).

Simple Form Submit

Story: tests-form--simple-form-submit · tags: play-fn

<form>
  <oc-text-field-v1 name="name1">text field</oc-text-field-v1>
  <oc-text-area-v1 name="name2">text area</oc-text-area-v1>
  <oc-checkbox-v1 name="name3">checkbox</oc-checkbox-v1>
  <oc-radio-button-v1 name="name4">radio button</oc-radio-button-v1>
  <oc-dropdown-v1 name="name5" label="dropdown"></oc-dropdown-v1>
  <oc-button-v1 type="submit" formaction="/trigger-me">submit</oc-button-v1>
  <button type="submit">do not trigger me</button>
</form>
Story source (TypeScript, verbatim from Storybook)
{
  render() {
    return html` <form>
      <oc-text-field-v1 name="name1">text field</oc-text-field-v1>
      <oc-text-area-v1 name="name2">text area</oc-text-area-v1>
      <oc-checkbox-v1 name="name3">checkbox</oc-checkbox-v1>
      <oc-radio-button-v1 name="name4">radio button</oc-radio-button-v1>
      <oc-dropdown-v1 name="name5" label="dropdown"></oc-dropdown-v1>
      <oc-button-v1 type="submit" formaction="/trigger-me">submit</oc-button-v1>
      <button type="submit">do not trigger me</button>
    </form>`;
  },
  async play({
    canvasElement
  }) {
    const form = canvasElement.getElementsByTagName("form").item(0)!;
    const annoyingButton = canvasElement.getElementsByTagName("button").item(0)!;
    let lastSubmitter: HTMLElement | null = null;
    let submitCounter = 0;
    form.addEventListener("submit", event => {
      event.preventDefault();
      lastSubmitter = event.submitter;
      submitCounter += 1;
    });

    // oc-text-field-v1
    await userEvent.type(canvasElement.querySelector("oc-text-field-v1")!.shadowRoot!.querySelector("input")!, "{Enter}");
    await expect(submitCounter).toBe(1);
    await expect(lastSubmitter).not.toBe(annoyingButton);

    // oc-text-area-v1
    await userEvent.type(canvasElement.querySelector("oc-text-area-v1")!.shadowRoot!.querySelector("textarea")!, "{Enter}");
    await expect(submitCounter).toBe(1);
    await expect(lastSubmitter).not.toBe(annoyingButton);

    // oc-checkbox-v1
    canvasElement.querySelector("oc-checkbox-v1")!.shadowRoot!.querySelector("input")!.dispatchEvent(new KeyboardEvent("keydown", {
      key: "Enter"
    }));
    await expect(submitCounter).toBe(2);
    await expect(lastSubmitter).not.toBe(annoyingButton);

    // oc-radio-button-v1
    canvasElement.querySelector("oc-radio-button-v1")!.shadowRoot!.querySelector("input")!.dispatchEvent(new KeyboardEvent("keydown", {
      key: "Enter"
    }));
    await expect(submitCounter).toBe(3);
    await expect(lastSubmitter).not.toBe(annoyingButton);

    // oc-dropdown-v1
    await userEvent.type(canvasElement.querySelector("oc-dropdown-v1")!.shadowRoot!.querySelector("select")!, "{Enter}");
    await expect(submitCounter).toBe(4);
    await expect(lastSubmitter).not.toBe(annoyingButton);
  }
}

Form Submit

Story: tests-form--form-submit · tags: play-fn

<div id="form-association">
  <oc-button-v1 type="submit">no form</oc-button-v1>
  <oc-button-v1 type="submit" form="form-association-form" formaction="/bar"
    >referenced form
  </oc-button-v1>
  <form id="form-association-form" method="get" action="/foo">
    <oc-button-v1 type="submit" formmethod="post">within form</oc-button-v1>
  </form>
</div>
Story source (TypeScript, verbatim from Storybook)
{
  render() {
    return html` <div id="form-association">
      <oc-button-v1 type="submit">no form</oc-button-v1>
      <oc-button-v1 type="submit" form="form-association-form" formaction="/bar"
        >referenced form
      </oc-button-v1>
      <form id="form-association-form" method="get" action="/foo">
        <oc-button-v1 type="submit" formmethod="post">within form</oc-button-v1>
      </form>
    </div>`;
  },
  async play({
    canvasElement
  }) {
    const form = canvasElement.getElementsByTagName("form").item(0)!;
    let submitCounter = 0;
    form.addEventListener("submit", event => {
      event.preventDefault();
      submitCounter += 1;
    });
    const [button1, button2, button3] = Array.from(canvasElement.getElementsByTagName("oc-button-v1"));
    deepQuerySelector(button1, "button")!.click();
    await expect(submitCounter, "button 1 should not submit").toBe(0);
    deepQuerySelector(button2, "button")!.click();
    await expect(submitCounter, "button 2 should submit").toBe(1);
    deepQuerySelector(button3, "button")!.click();
    await expect(submitCounter, "button 3 should submit").toBe(2);
  }
}