// Auto-generated from _hyperscript upstream test suite
// Source: spec/tests/hyperscript-upstream-tests.json
// 378 tests (453 skipped)
//
// DO NOT EDIT — regenerate with: python3 tests/playwright/generate-hs-tests.py

module.exports = [
  {
    "category": "add",
    "name": "can add class ref on a single div",
    "html": "<div id=\"el\" _='on click add .foo'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": false
  },
  {
    "category": "add",
    "name": "can add class ref w/ double dash on a single div",
    "html": "<div id=\"el\" _='on click add .foo--bar'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").classList.contains(\"foo--bar\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": false
  },
  {
    "category": "add",
    "name": "can add class ref on a single form",
    "html": "<form id=\"el\" _='on click add .foo'></form>",
    "action": "qs(\"form\").click()",
    "checks": [
      {
        "expr": "qs(\"form\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": false
  },
  {
    "category": "add",
    "name": "can target another div for class ref",
    "html": "<div id='bar'></div><div _='on click add .foo to #bar'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "byId(\"bar\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "true"
      },
      {
        "expr": "qs(\"div\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "false"
      }
    ],
    "async": false
  },
  {
    "category": "add",
    "name": "can add to query in me",
    "html": "<div _='on click add .foo to <p/> in me'><p id='p1'></p></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "byId(\"p1\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "true"
      },
      {
        "expr": "qs(\"div\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "false"
      }
    ],
    "async": false
  },
  {
    "category": "add",
    "name": "can add to children",
    "html": "<div _='on click add .foo to my children'><p id='p1'></p></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "byId(\"p1\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "true"
      },
      {
        "expr": "qs(\"div\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "false"
      }
    ],
    "async": false
  },
  {
    "category": "add",
    "name": "can add multiple class refs",
    "html": "<div id=\"el\" _='on click add .foo .bar'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "true"
      },
      {
        "expr": "qs(\"div\").classList.contains(\"bar\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": false
  },
  {
    "category": "add",
    "name": "can add class refs w/ colons and dashes",
    "html": "<div id=\"el\" _='on click add .foo:bar-doh'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").classList.contains(\"foo:bar-doh\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": false
  },
  {
    "category": "add",
    "name": "can filter class addition via the when clause",
    "html": "<div id=\"el\" _='on click add .rey to .bar when it matches .doh'></div><div class='bar'></div><div class='bar doh'></div>",
    "action": "byId(\"div1\") && byId(\"div1\").click()",
    "checks": [
      {
        "expr": "byId(\"div2\").classList.contains(\"rey\")",
        "op": "==",
        "expected": "false"
      },
      {
        "expr": "byId(\"div3\").classList.contains(\"rey\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": false
  },
  {
    "category": "add",
    "name": "can filter property addition via the when clause",
    "html": "<div id=\"el\" _='on click add @rey to .bar when it matches .doh'></div><div class='bar'></div><div class='bar doh'></div>",
    "action": "byId(\"div1\") && byId(\"div1\").click()",
    "checks": [
      {
        "expr": "byId(\"div2\").hasAttribute(\"rey\")",
        "op": "==",
        "expected": "false"
      },
      {
        "expr": "byId(\"div3\").hasAttribute(\"rey\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": false
  },
  {
    "category": "add",
    "name": "can add to an HTMLCollection",
    "html": "<div _='on click add .foo to the children of #bar'></div><div id='bar'><div id='c1'></div><div id='c2'></div></div>",
    "action": "byId(\"div1\") && byId(\"div1\").click()",
    "checks": [
      {
        "expr": "byId(\"c1\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "true"
      },
      {
        "expr": "byId(\"c2\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": false
  },
  {
    "category": "remove",
    "name": "can remove class ref on a single div",
    "html": "<div id=\"el\" class='foo' _='on click remove .foo'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "false"
      }
    ],
    "async": false
  },
  {
    "category": "remove",
    "name": "can remove class ref on a single form",
    "html": "<form id=\"el\" class='foo' _='on click remove .foo'></form>",
    "action": "qs(\"form\").click()",
    "checks": [
      {
        "expr": "qs(\"form\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "false"
      }
    ],
    "async": false
  },
  {
    "category": "remove",
    "name": "can target another div for class ref",
    "html": "<div class='foo' id='bar'></div><div _='on click remove .foo from #bar'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "byId(\"bar\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "false"
      },
      {
        "expr": "qs(\"div\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "false"
      }
    ],
    "async": false
  },
  {
    "category": "remove",
    "name": "can remove elements",
    "html": "<div id=\"el\" _='on click remove me'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").parentElement",
        "op": "==",
        "expected": "null"
      }
    ],
    "async": false
  },
  {
    "category": "remove",
    "name": "can remove other elements",
    "html": "<div _='on click remove #that'></div><div id='that'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "byId(\"div2\").parentElement",
        "op": "==",
        "expected": "null"
      }
    ],
    "async": false
  },
  {
    "category": "remove",
    "name": "can remove parent element",
    "html": "<div id='p1'><button  id='b1' _=\"on click remove my.parentElement\"></button></div> ",
    "action": "btn.click()",
    "checks": [
      {
        "expr": "qs(\"div\").parentElement",
        "op": "==",
        "expected": "null"
      }
    ],
    "async": false
  },
  {
    "category": "remove",
    "name": "can remove multiple class refs",
    "html": "<div id=\"el\" class='foo bar doh' _='on click remove .foo .bar'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "false"
      },
      {
        "expr": "qs(\"div\").classList.contains(\"bar\")",
        "op": "==",
        "expected": "false"
      },
      {
        "expr": "qs(\"div\").classList.contains(\"doh\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": false
  },
  {
    "category": "remove",
    "name": "can remove query refs from specific things",
    "html": "<div><div id='d1' _='on click remove <p/> from me'><p>foo</p>bar</div><p>doh</p></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML.includes(\"foo\")",
        "op": "==",
        "expected": "false"
      },
      {
        "expr": "qs(\"div\").innerHTML.includes(\"bar\")",
        "op": "==",
        "expected": "true"
      },
      {
        "expr": "qs(\"div\").innerHTML.includes(\"doh\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": false
  },
  {
    "category": "toggle",
    "name": "can toggle class ref on a single div",
    "html": "<div id=\"el\" _='on click toggle .foo'></div>",
    "action": "qs(\"div\").click(); qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "false"
      }
    ],
    "async": false
  },
  {
    "category": "toggle",
    "name": "can toggle class ref on a single form",
    "html": "<form id=\"el\" _='on click toggle .foo'></form>",
    "action": "qs(\"form\").click(); qs(\"form\").click()",
    "checks": [
      {
        "expr": "qs(\"form\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "false"
      }
    ],
    "async": false
  },
  {
    "category": "toggle",
    "name": "can target another div for class ref toggle",
    "html": "<div id='bar'></div><div _='on click toggle .foo on #bar'></div>",
    "action": "qs(\"div\").click(); qs(\"div\").click()",
    "checks": [
      {
        "expr": "byId(\"bar\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "false"
      },
      {
        "expr": "qs(\"div\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "false"
      }
    ],
    "async": false
  },
  {
    "category": "toggle",
    "name": "can toggle for a fixed amount of time",
    "html": "<div id=\"el\" _='on click toggle .foo for 10ms'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "false"
      }
    ],
    "async": true
  },
  {
    "category": "toggle",
    "name": "can toggle until an event on another element",
    "html": "<div id='d1'></div><div _='on click toggle .foo until foo from #d1'></div>",
    "action": "qs(\"div\").click(); byId(\"d1\").dispatchEvent(new CustomEvent(\"foo\")",
    "checks": [
      {
        "expr": "qs(\"div\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "false"
      }
    ],
    "async": true
  },
  {
    "category": "toggle",
    "name": "can toggle between two classes",
    "html": "<div id=\"el\" class='foo' _='on click toggle between .foo and .bar'></div>",
    "action": "qs(\"div\").click(); qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "true"
      },
      {
        "expr": "qs(\"div\").classList.contains(\"bar\")",
        "op": "==",
        "expected": "false"
      }
    ],
    "async": false
  },
  {
    "category": "toggle",
    "name": "can toggle multiple class refs",
    "html": "<div id=\"el\" class='bar' _='on click toggle .foo .bar'></div>",
    "action": "qs(\"div\").click(); qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "false"
      },
      {
        "expr": "qs(\"div\").classList.contains(\"bar\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": false
  },
  {
    "category": "toggle",
    "name": "can toggle display",
    "html": "<div id=\"el\" _='on click toggle *display'></div>",
    "action": "qs(\"div\").click(); qs(\"div\").click()",
    "checks": [
      {
        "expr": "getComputedStyle(qs(\"div\")).display",
        "op": "==",
        "expected": "\"block\""
      }
    ],
    "async": false
  },
  {
    "category": "toggle",
    "name": "can toggle opacity",
    "html": "<div id=\"el\" _='on click toggle *opacity'></div>",
    "action": "qs(\"div\").click(); qs(\"div\").click()",
    "checks": [
      {
        "expr": "getComputedStyle(qs(\"div\")).opacity",
        "op": "==",
        "expected": "\"1\""
      }
    ],
    "async": false
  },
  {
    "category": "toggle",
    "name": "can toggle opacity",
    "html": "<div id=\"el\" _='on click toggle *visibility'></div>",
    "action": "qs(\"div\").click(); qs(\"div\").click()",
    "checks": [
      {
        "expr": "getComputedStyle(qs(\"div\")).visibility",
        "op": "==",
        "expected": "\"visible\""
      }
    ],
    "async": false
  },
  {
    "category": "toggle",
    "name": "can toggle display w/ my",
    "html": "<div id=\"el\" _='on click toggle my *display'></div>",
    "action": "qs(\"div\").click(); qs(\"div\").click()",
    "checks": [
      {
        "expr": "getComputedStyle(qs(\"div\")).display",
        "op": "==",
        "expected": "\"block\""
      }
    ],
    "async": false
  },
  {
    "category": "toggle",
    "name": "can toggle display w/ my",
    "html": "<div id=\"el\" _='on click toggle my *opacity'></div>",
    "action": "qs(\"div\").click(); qs(\"div\").click()",
    "checks": [
      {
        "expr": "getComputedStyle(qs(\"div\")).opacity",
        "op": "==",
        "expected": "\"1\""
      }
    ],
    "async": false
  },
  {
    "category": "toggle",
    "name": "can toggle display w/ my",
    "html": "<div id=\"el\" _='on click toggle my *visibility'></div>",
    "action": "qs(\"div\").click(); qs(\"div\").click()",
    "checks": [
      {
        "expr": "getComputedStyle(qs(\"div\")).visibility",
        "op": "==",
        "expected": "\"visible\""
      }
    ],
    "async": false
  },
  {
    "category": "toggle",
    "name": "can toggle display on other elt",
    "html": "<div _='on click toggle the *display of #d2'></div><div id='d2'></div>",
    "action": "qs(\"div\").click(); qs(\"div\").click()",
    "checks": [
      {
        "expr": "getComputedStyle(div2).display",
        "op": "==",
        "expected": "\"block\""
      }
    ],
    "async": false
  },
  {
    "category": "toggle",
    "name": "can toggle display on other elt",
    "html": "<div _='on click toggle the *opacity of #d2'></div><div id='d2'></div>",
    "action": "qs(\"div\").click(); qs(\"div\").click()",
    "checks": [
      {
        "expr": "getComputedStyle(div2).opacity",
        "op": "==",
        "expected": "\"1\""
      }
    ],
    "async": false
  },
  {
    "category": "toggle",
    "name": "can toggle display on other elt",
    "html": "<div _='on click toggle the *visibility of #d2'></div><div id='d2'></div>",
    "action": "qs(\"div\").click(); qs(\"div\").click()",
    "checks": [
      {
        "expr": "getComputedStyle(div2).visibility",
        "op": "==",
        "expected": "\"visible\""
      }
    ],
    "async": false
  },
  {
    "category": "set",
    "name": "can set properties",
    "html": "<div id='d1' _='on click set #d1.innerHTML to \"foo\"'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "set",
    "name": "can set indirect properties",
    "html": "<div id='d1' _='on click set innerHTML of #d1 to \"foo\"'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "set",
    "name": "can set complex indirect properties lhs",
    "html": "<div _='on click set parentNode.innerHTML of #d1 to \"foo\"'><div id='d1'></div></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "set",
    "name": "can set complex indirect properties rhs",
    "html": "<div _='on click set innerHTML of #d1.parentNode to \"foo\"'><div id='d1'></div></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "set",
    "name": "can set chained indirect properties",
    "html": "<div _='on click set the innerHTML of the parentNode of #d1 to \"foo\"'><div id='d1'></div></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "set",
    "name": "can set styles",
    "html": "<div id=\"el\" _='on click set my.style.color to \"red\"'>lolwat</div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").style.color",
        "op": "==",
        "expected": "\"red\""
      }
    ],
    "async": false
  },
  {
    "category": "set",
    "name": "can set javascript globals",
    "html": "<div id=\"el\" _='on click set window.temp to \"red\"'>lolwat</div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "window[\"temp\"]",
        "op": "==",
        "expected": "\"red\""
      }
    ],
    "async": false
  },
  {
    "category": "set",
    "name": "can set local variables",
    "html": "<div id='d1' _='on click set newVar to \"foo\" then                                    put newVar into #d1.innerHTML'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "set",
    "name": "can set into id ref",
    "html": "<div id='d1' _='on click set #d1.innerHTML to \"foo\"'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "set",
    "name": "can set into class ref",
    "html": "<div id=\"el\" class='divs' _='on click set .divs.innerHTML to \"foo\"'></div><div class='divs''></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"foo\""
      },
      {
        "expr": "byId(\"d2\").innerHTML",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "set",
    "name": "can set into attribute ref",
    "html": "<div id=\"el\" class='divs' _='on click set @bar to \"foo\"'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").getAttribute(\"bar\")",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "set",
    "name": "can set into indirect attribute ref",
    "html": "<div class='divs' _=\"on click set #div2's @bar to 'foo'\"></div><div id='div2'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d2\").getAttribute(\"bar\")",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "set",
    "name": "can set into indirect attribute ref 2",
    "html": "<div class='divs' _=\"on click set #div2's @bar to 'foo'\"></div><div id='div2'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d2\").getAttribute(\"bar\")",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "set",
    "name": "can set into indirect attribute ref 3",
    "html": "<div class='divs' _=\"on click set @bar of #div2 to 'foo'\"></div><div id='div2'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d2\").getAttribute(\"bar\")",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "set",
    "name": "can set into style ref",
    "html": "<div id=\"el\" class='divs' _='on click set *color to \"red\"'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").style[\"color\"]",
        "op": "==",
        "expected": "\"red\""
      }
    ],
    "async": false
  },
  {
    "category": "set",
    "name": "can set into indirect style ref",
    "html": "<div class='divs' _=\"on click set #div2's *color to 'red'\"></div><div id='div2'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d2\").style[\"color\"]",
        "op": "==",
        "expected": "\"red\""
      }
    ],
    "async": false
  },
  {
    "category": "set",
    "name": "can set into indirect style ref 2",
    "html": "<div class='divs' _=\"on click set #div2's *color to 'red'\"></div><div id='div2'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d2\").style[\"color\"]",
        "op": "==",
        "expected": "\"red\""
      }
    ],
    "async": false
  },
  {
    "category": "set",
    "name": "can set into indirect style ref 3",
    "html": "<div class='divs' _=\"on click set *color of #div2 to 'red'\"></div><div id='div2'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d2\").style[\"color\"]",
        "op": "==",
        "expected": "\"red\""
      }
    ],
    "async": false
  },
  {
    "category": "set",
    "name": "can set many properties at once with object literal",
    "html": "<div id=\"el\" _='on click set {bar: 2, baz: 3} on obj'></div>",
    "action": "",
    "checks": [
      {
        "expr": "obj",
        "op": "deep==",
        "expected": "{ foo: 1, bar: 2, baz: 3 }"
      }
    ],
    "async": false
  },
  {
    "category": "set",
    "name": "can set props w/ array access syntax",
    "html": "<div id=\"el\" _='on click set my style[\"color\"] to \"red\"'>lolwat</div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").style.color",
        "op": "==",
        "expected": "\"red\""
      }
    ],
    "async": false
  },
  {
    "category": "set",
    "name": "can set props w/ array access syntax and var",
    "html": "<div id=\"el\" _='on click set foo to \"color\" then set my style[foo] to \"red\"'>lolwat</div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").style.color",
        "op": "==",
        "expected": "\"red\""
      }
    ],
    "async": false
  },
  {
    "category": "set",
    "name": "can set arrays w/ array access syntax",
    "html": "<div id=\"el\" _='on click set arr to [1, 2, 3] set arr[0] to \"red\" set my *color to arr[0]'>lolwat</div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").style.color",
        "op": "==",
        "expected": "\"red\""
      }
    ],
    "async": false
  },
  {
    "category": "set",
    "name": "can set arrays w/ array access syntax and var",
    "html": "<div id=\"el\" _='on click set arr to [1, 2, 3] set idx to 0 set arr[idx] to \"red\" set my *color to arr[0]'>lolwat</div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").style.color",
        "op": "==",
        "expected": "\"red\""
      }
    ],
    "async": false
  },
  {
    "category": "put",
    "name": "can set properties",
    "html": "<div id='d1' _='on click put \"foo\" into #d1.innerHTML'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "put",
    "name": "can put directly into nodes",
    "html": "<div id='d1' _='on click put \"foo\" into #d1'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").textContent",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "put",
    "name": "can put nodes into nodes",
    "html": "<div id='d1'></div><div id='d2' _='on click put #d1 into #d2'></div>",
    "action": "byId(\"d2\").click()",
    "checks": [
      {
        "expr": "byId(\"d2\").firstChild",
        "op": "==",
        "expected": "d1"
      }
    ],
    "async": false
  },
  {
    "category": "put",
    "name": "can put directly into symbols",
    "html": "<div id=\"el\" _='on click put \"foo\" into me'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "put",
    "name": "me symbol doesn't get stomped on direct write",
    "html": "<div id=\"el\" _='on click put \"foo\" into me then put \"bar\" into me'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"bar\""
      }
    ],
    "async": false
  },
  {
    "category": "put",
    "name": "can set styles",
    "html": "<div id=\"el\" _='on click put \"red\" into my.style.color'>lolwat</div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").style.color",
        "op": "==",
        "expected": "\"red\""
      }
    ],
    "async": false
  },
  {
    "category": "put",
    "name": "can set javascript globals",
    "html": "<div id=\"el\" _='on click put \"red\" into window.temp'>lolwat</div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "window[\"temp\"]",
        "op": "==",
        "expected": "\"red\""
      }
    ],
    "async": false
  },
  {
    "category": "put",
    "name": "can set into class ref w/ flatmapped property",
    "html": "<div _='on click put \"foo\" into .divs.parentElement.innerHTML'></div><div id='d1'><div class='divs'></div></div><div id='d2'><div class='divs'></div></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").textContent",
        "op": "==",
        "expected": "\"foo\""
      },
      {
        "expr": "byId(\"d2\").textContent",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "put",
    "name": "can set into class ref w/ flatmapped property using of",
    "html": "<div _='on click put \"foo\" into innerHTML of parentElement of .divs'></div><div id='d1'><div class='divs'></div></div><div id='d2'><div class='divs'></div></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").textContent",
        "op": "==",
        "expected": "\"foo\""
      },
      {
        "expr": "byId(\"d2\").textContent",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "put",
    "name": "can set local variables",
    "html": "<div id='d1' _='on click put \"foo\" into newVar then                                    put newVar into #d1.innerHTML'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "put",
    "name": "can set into id ref",
    "html": "<div id='d1' _='on click put \"foo\" into #d1.innerHTML'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "put",
    "name": "can insert before",
    "html": "<div id='d2' _='on click put #d1 before #d2'></div><div id='d1'>foo</div>",
    "action": "byId(\"d2\").click()",
    "checks": [
      {
        "expr": "byId(\"d2\").byId(\"previousSibling\").textContent",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "put",
    "name": "can insert after",
    "html": "<div id='d1'>foo</div><div id='d2' _='on click put #d1 after #d2'></div>",
    "action": "byId(\"d2\").click()",
    "checks": [
      {
        "expr": "byId(\"d2\").byId(\"nextSibling\").textContent",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "put",
    "name": "can insert after beginning",
    "html": "<div id='d1' _='on click put \"foo\" at start of #d1'>*</div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").textContent",
        "op": "==",
        "expected": "\"foo*\""
      }
    ],
    "async": false
  },
  {
    "category": "put",
    "name": "can insert before end",
    "html": "<div id='d1' _='on click put \"foo\" at end of #d1'>*</div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").textContent",
        "op": "==",
        "expected": "\"*foo\""
      }
    ],
    "async": false
  },
  {
    "category": "put",
    "name": "can set into attribute ref",
    "html": "<div id=\"el\" class='divs' _='on click put \"foo\" into @bar'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").getAttribute(\"bar\")",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "put",
    "name": "can set into indirect attribute ref",
    "html": "<div id=\"el\" class='divs' _='on click put \"foo\" into my @bar'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").getAttribute(\"bar\")",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "put",
    "name": "can set into indirect attribute ref 2",
    "html": "<div class='divs' _=\"on click put 'foo' into #div2's @bar\"></div><div id='div2'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d2\").getAttribute(\"bar\")",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "put",
    "name": "can set into indirect attribute ref 3",
    "html": "<div class='divs' _=\"on click put 'foo' into @bar of #div2\"></div><div id='div2'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d2\").getAttribute(\"bar\")",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "put",
    "name": "can set into style ref",
    "html": "<div id=\"el\" class='divs' _='on click put \"red\" into *color'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").style[\"color\"]",
        "op": "==",
        "expected": "\"red\""
      }
    ],
    "async": false
  },
  {
    "category": "put",
    "name": "can set into indirect style ref",
    "html": "<div id=\"el\" class='divs' _='on click put \"red\" into my *color'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").style[\"color\"]",
        "op": "==",
        "expected": "\"red\""
      }
    ],
    "async": false
  },
  {
    "category": "put",
    "name": "can set into indirect style ref 2",
    "html": "<div class='divs' _=\"on click put 'red' into #div2's *color\"></div><div id='div2'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d2\").style[\"color\"]",
        "op": "==",
        "expected": "\"red\""
      }
    ],
    "async": false
  },
  {
    "category": "put",
    "name": "can set into indirect style ref 3",
    "html": "<div class='divs' _=\"on click put 'red' into the *color of #div2\"></div><div id='div2'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d2\").style[\"color\"]",
        "op": "==",
        "expected": "\"red\""
      }
    ],
    "async": false
  },
  {
    "category": "put",
    "name": "can put properties w/ array access syntax",
    "html": "<div id=\"el\" _='on click put \"red\" into my style[\"color\"]'>lolwat</div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").style.color",
        "op": "==",
        "expected": "\"red\""
      }
    ],
    "async": false
  },
  {
    "category": "put",
    "name": "can put properties w/ array access syntax and var",
    "html": "<div id=\"el\" _='on click set foo to \"color\" then put \"red\" into my style[foo]'>lolwat</div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").style.color",
        "op": "==",
        "expected": "\"red\""
      }
    ],
    "async": false
  },
  {
    "category": "put",
    "name": "can put array vals w/ array access syntax",
    "html": "<div id=\"el\" _='on click set arr to [1, 2, 3] put \"red\" into arr[0] put arr[0] into my *color'>lolwat</div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").style.color",
        "op": "==",
        "expected": "\"red\""
      }
    ],
    "async": false
  },
  {
    "category": "put",
    "name": "can put array vals w/ array access syntax and var",
    "html": "<div id=\"el\" _='on click set arr to [1, 2, 3] set idx to 0 put \"red\" into arr[idx] put arr[0] into my *color'>lolwat</div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").style.color",
        "op": "==",
        "expected": "\"red\""
      }
    ],
    "async": false
  },
  {
    "category": "put",
    "name": "is null tolerant",
    "html": "<div id=\"el\" class='divs' _='on click put \"red\" into #a-bad-id-that-does-not-exist'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [],
    "async": false
  },
  {
    "category": "hide",
    "name": "can hide element with no target",
    "html": "<div id=\"el\" _='on click hide'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "getComputedStyle(qs(\"div\")).display",
        "op": "==",
        "expected": "\"none\""
      }
    ],
    "async": false
  },
  {
    "category": "hide",
    "name": "hide element then show element retains original display",
    "html": "<div id=\"el\" _='on click 1 hide                          on click 2 show'></div>",
    "action": "qs(\"div\").click(); qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").style.display",
        "op": "==",
        "expected": "\"\""
      },
      {
        "expr": "getComputedStyle(qs(\"div\")).display",
        "op": "==",
        "expected": "\"block\""
      }
    ],
    "async": false
  },
  {
    "category": "hide",
    "name": "can hide element with no target followed by command",
    "html": "<div id=\"el\" _='on click hide add .foo'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "getComputedStyle(qs(\"div\")).display",
        "op": "==",
        "expected": "\"none\""
      },
      {
        "expr": "qs(\"div\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": false
  },
  {
    "category": "hide",
    "name": "can hide element with no target followed by then",
    "html": "<div id=\"el\" _='on click hide then add .foo'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "getComputedStyle(qs(\"div\")).display",
        "op": "==",
        "expected": "\"none\""
      },
      {
        "expr": "qs(\"div\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": false
  },
  {
    "category": "hide",
    "name": "can hide element with no target with a with",
    "html": "<div id=\"el\" _='on click hide with display then add .foo'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "getComputedStyle(qs(\"div\")).display",
        "op": "==",
        "expected": "\"none\""
      },
      {
        "expr": "qs(\"div\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": false
  },
  {
    "category": "hide",
    "name": "can hide element, with display:none by default",
    "html": "<div id=\"el\" _='on click hide me'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "getComputedStyle(qs(\"div\")).display",
        "op": "==",
        "expected": "\"none\""
      }
    ],
    "async": false
  },
  {
    "category": "hide",
    "name": "can hide element with display:none explicitly",
    "html": "<div id=\"el\" _='on click hide me with display'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "getComputedStyle(qs(\"div\")).display",
        "op": "==",
        "expected": "\"none\""
      }
    ],
    "async": false
  },
  {
    "category": "hide",
    "name": "can hide element with opacity:0",
    "html": "<div id=\"el\" _='on click hide me with opacity'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "getComputedStyle(qs(\"div\")).opacity",
        "op": "==",
        "expected": "\"0\""
      }
    ],
    "async": false
  },
  {
    "category": "hide",
    "name": "can hide element with opacity style literal",
    "html": "<div id=\"el\" _='on click hide me with *opacity'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "getComputedStyle(qs(\"div\")).opacity",
        "op": "==",
        "expected": "\"0\""
      }
    ],
    "async": false
  },
  {
    "category": "hide",
    "name": "can hide element, with visibility:hidden",
    "html": "<div id=\"el\" _='on click hide me with visibility'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "getComputedStyle(qs(\"div\")).visibility",
        "op": "==",
        "expected": "\"hidden\""
      }
    ],
    "async": false
  },
  {
    "category": "hide",
    "name": "can hide other elements",
    "html": "<div id=\"el\" class=hideme></div><div _='on click hide .hideme'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "getComputedStyle(hideme).display",
        "op": "==",
        "expected": "\"none\""
      }
    ],
    "async": false
  },
  {
    "category": "hide",
    "name": "can hide with custom strategy",
    "html": "<div id=\"el\" _='on click hide with myHide'></div>",
    "action": "classList.remove(\"foo\"); qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": false
  },
  {
    "category": "hide",
    "name": "can set default to custom strategy",
    "html": "<div id=\"el\" _='on click hide'></div>",
    "action": "classList.remove(\"foo\"); qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": false
  },
  {
    "category": "if",
    "name": "basic true branch works",
    "html": "<div id=\"el\" _='on click if true put \"foo\" into me.innerHTML'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "if",
    "name": "basic true branch works with multiple commands",
    "html": "<div id=\"el\" _='on click if true log me then                                   put \"foo\" into me.innerHTML'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "if",
    "name": "basic true branch works with end",
    "html": "<div id=\"el\" _='on click if true put \"foo\" into me.innerHTML end'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "if",
    "name": "basic true branch works with naked else",
    "html": "<div id=\"el\" _='on click if true put \"foo\" into me.innerHTML else'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "if",
    "name": "basic true branch works with naked else end",
    "html": "<div id=\"el\" _='on click if true put \"foo\" into me.innerHTML else end'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "if",
    "name": "basic else branch works",
    "html": "<div id=\"el\" _='on click if false else put \"foo\" into me.innerHTML'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "if",
    "name": "basic else branch works with end",
    "html": "<div id=\"el\" _='on click if false else put \"foo\" into me.innerHTML end'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "if",
    "name": "basic else if branch works",
    "html": "<div id=\"el\" _='on click if false else if true put \"foo\" into me.innerHTML'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "if",
    "name": "basic else if branch works with end",
    "html": "<div id=\"el\" _='on click if false                                   else if true put \"foo\" into me.innerHTML end'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "if",
    "name": "otherwise alias works",
    "html": "<div id=\"el\" _='on click if false otherwise put \"foo\" into me.innerHTML'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "if",
    "name": "triple else if branch works",
    "html": "<div id=\"el\" _='on click if false else if false else put \"foo\" into me.innerHTML'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "if",
    "name": "triple else if branch works with end",
    "html": "<div id=\"el\" _='on click if false                                   else if false                                  else put \"foo\" into me.innerHTML end'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "if",
    "name": "basic else branch works with multiple commands",
    "html": "<div id=\"el\" _='on click if false put \"bar\" into me.innerHTML                                  else log me then                                       put \"foo\" into me.innerHTML'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "if",
    "name": "true branch with a wait works",
    "html": "<div id=\"el\" _='on click if true wait 10 ms then put \"foo\" into me.innerHTML'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": true
  },
  {
    "category": "if",
    "name": "false branch with a wait works",
    "html": "<div id=\"el\" _='on click if false else wait 10 ms then put \"foo\" into me.innerHTML'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": true
  },
  {
    "category": "if",
    "name": "if properly passes execution along if child is not executed",
    "html": "<div id=\"el\" _='on click if false end put \"foo\" into me.innerHTML'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "if",
    "name": "if properly supports nested if statements and end block",
    "html": "<div id=\"el\" _='on click \\n                      if window.tmp then\\n                        put \"foo\" into me\\n                      else if not window.tmp then\\n                        // do nothing\\n                      end\\n                  catch e\\n                      // just here for the parsing...\\n'</div>",
    "action": "byId(\"d1\").click(); byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "if",
    "name": "if on new line does not join w/ else",
    "html": "<div id=\"el\" _='on click \\n                      if window.tmp then\\n                      else\\n                        if window.tmp then                        end\\n                        put \"foo\" into me\\n                      end\\n                  '</div>",
    "action": "byId(\"d1\").click(); byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"\""
      }
    ],
    "async": false
  },
  {
    "category": "repeat",
    "name": "basic for loop works",
    "html": "<div id=\"el\" _='on click repeat for x in [1, 2, 3]                                    put x at end of me                                  end'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"123\""
      }
    ],
    "async": false
  },
  {
    "category": "repeat",
    "name": "basic for loop with null works",
    "html": "<div id=\"el\" _='on click repeat for x in null                                    put x at end of me                                  end'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"\""
      }
    ],
    "async": false
  },
  {
    "category": "repeat",
    "name": "waiting in for loop works",
    "html": "<div id=\"el\" _='on click repeat for x in [1, 2, 3]\\n                                    log me                                     put x at end of me\\n                                    wait 1ms\\n                                  end'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"123\""
      }
    ],
    "async": true
  },
  {
    "category": "repeat",
    "name": "basic raw for loop works",
    "html": "<div id=\"el\" _='on click for x in [1, 2, 3]                                    put x at end of me                                  end'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"123\""
      }
    ],
    "async": false
  },
  {
    "category": "repeat",
    "name": "basic raw for loop works",
    "html": "<div id=\"el\" _='on click for x in null                                    put x at end of me                                  end'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"\""
      }
    ],
    "async": false
  },
  {
    "category": "repeat",
    "name": "waiting in raw for loop works",
    "html": "<div id=\"el\" _='on click for x in [1, 2, 3]\\n                                    put x at end of me\\n                                    wait 1ms\\n                                  end'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"123\""
      }
    ],
    "async": true
  },
  {
    "category": "repeat",
    "name": "basic in loop works",
    "html": "<div id=\"el\" _='on click repeat in [1, 2, 3]                                    put it at end of me                                  end'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"123\""
      }
    ],
    "async": false
  },
  {
    "category": "repeat",
    "name": "index syntax works",
    "html": "<div id=\"el\" _='on click repeat for x in [\"a\", \"ab\", \"abc\"] index i                                    put x + i at end of me                                  end'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"a0ab1abc2\""
      }
    ],
    "async": false
  },
  {
    "category": "repeat",
    "name": "indexed by syntax works",
    "html": "<div id=\"el\" _='on click repeat for x in [\"a\", \"ab\", \"abc\"] indexed by i                                    put x + i at end of me                                  end'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"a0ab1abc2\""
      }
    ],
    "async": false
  },
  {
    "category": "repeat",
    "name": "basic times loop works",
    "html": "<div id=\"el\" _='on click repeat 3 times                                    put \"a\" at end of me                                  end'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"aaa\""
      }
    ],
    "async": false
  },
  {
    "category": "repeat",
    "name": "times loop with expression works",
    "html": "<div id=\"el\" _='on click repeat 3 + 3 times                                    put \"a\" at end of me                                  end'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"aaaaaa\""
      }
    ],
    "async": false
  },
  {
    "category": "repeat",
    "name": "loop continue works",
    "html": "<div id=\"el\" _=\"on click\n\t\t\t\trepeat 2 times\n\t\t\t\t\tfor x in ['A', 'B', 'C', 'D']\n\t\t\t\t\t\tif (x != 'D') then\n\t\t\t\t\t\t\tput 'success ' + x  + '. ' at end of me\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t\tput 'FAIL!!. ' at end of me\n\t\t\t\t\t\tend\n\t\t\t\t\t\tput 'expected D. ' at end of me\n\t\t\t\t\tend\n\t\t\t\tend\n\t\t\t\"></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"success A. success B. success C. expected D. success A. success B. success C. expected D. \""
      }
    ],
    "async": false
  },
  {
    "category": "repeat",
    "name": "loop break works",
    "html": "<div id=\"el\" _=\"on click\n\t\t\t\trepeat 2 times\n\t\t\t\t\tfor x in ['A', 'B', 'C', 'D']\n\t\t\t\t\t\tif x is 'C'\n\t\t\t\t\t\t  break\n\t\t\t\t\t\tend\n\t\t\t\t\t\tput x at end of me\n\t\t\t\t\tend\n\t\t\t\tend\n\t\t\t\"></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerHTML",
        "op": "==",
        "expected": "\"ABAB\""
      }
    ],
    "async": false
  },
  {
    "category": "wait",
    "name": "can wait on time",
    "html": "<div id=\"el\" _='on click                              add .foo then                              wait 20ms then                              add .bar'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "true"
      },
      {
        "expr": "qs(\"div\").classList.contains(\"bar\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": true
  },
  {
    "category": "wait",
    "name": "can wait on event",
    "html": "<div id=\"el\" _='on click                              add .foo then                              wait for foo then                              add .bar'></div>",
    "action": "qs(\"div\").click(); qs(\"div\").dispatchEvent(new CustomEvent(\"foo\")",
    "checks": [
      {
        "expr": "qs(\"div\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "true"
      },
      {
        "expr": "qs(\"div\").classList.contains(\"bar\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": true
  },
  {
    "category": "wait",
    "name": "waiting on an event sets 'it' to the event",
    "html": "<div id=\"el\" _='on click wait for foo         then put its.detail into me'></div>",
    "action": "qs(\"div\").click(); qs(\"div\").dispatchEvent(new CustomEvent(\"foo\", { detail: \"hyperscript is hyper cool\" })",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"hyperscript is hyper cool\""
      }
    ],
    "async": true
  },
  {
    "category": "wait",
    "name": "can destructure properties in a wait",
    "html": "<div id=\"el\" _='on click wait for foo(bar)         then put bar into me'></div>",
    "action": "qs(\"div\").click(); qs(\"div\").dispatchEvent(new CustomEvent(\"foo\", { detail: { bar: \"bar\" } })",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"bar\""
      }
    ],
    "async": true
  },
  {
    "category": "wait",
    "name": "can wait on event on another element",
    "html": "<div id='d2'></div><div _='on click                              add .foo then                              wait for foo from #d2 then                              add .bar'></div>",
    "action": "qs(\"div\").click(); byId(\"div2\") && byId(\"div2\").dispatchEvent(new CustomEvent(\"foo\")",
    "checks": [
      {
        "expr": "qs(\"div\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "true"
      },
      {
        "expr": "qs(\"div\").classList.contains(\"bar\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": true
  },
  {
    "category": "wait",
    "name": "can wait on event or timeout 1",
    "html": "<div id='d2'></div><div _='on click                              add .foo then                              wait for foo or 0ms then                              add .bar'></div>",
    "action": "qs(\"div\").click(); byId(\"div2\") && byId(\"div2\").dispatchEvent(new CustomEvent(\"foo\")",
    "checks": [
      {
        "expr": "qs(\"div\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "true"
      },
      {
        "expr": "qs(\"div\").classList.contains(\"bar\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": true
  },
  {
    "category": "wait",
    "name": "can wait on event or timeout 2",
    "html": "<div id='d2'></div><div _='on click                              add .foo then                              wait for foo or 0ms then                              add .bar'></div>",
    "action": "qs(\"div\").click(); byId(\"div2\") && byId(\"div2\").dispatchEvent(new CustomEvent(\"foo\")",
    "checks": [
      {
        "expr": "qs(\"div\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "true"
      },
      {
        "expr": "qs(\"div\").classList.contains(\"bar\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": true
  },
  {
    "category": "send",
    "name": "can send events",
    "html": "<div _='on click send foo to #bar'></div><div id='bar' _='on foo add .foo-sent'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "byId(\"bar\").classList.contains(\"foo-sent\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": false
  },
  {
    "category": "send",
    "name": "can reference sender in events",
    "html": "<div _='on click log 0 send foo to #bar log 3'></div><div id='bar' _='on foo add .foo-sent to sender log 1, me, sender'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").classList.contains(\"foo-sent\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": false
  },
  {
    "category": "send",
    "name": "can send events with args",
    "html": "<div _='on click send foo(x:42) to #bar'></div><div id='bar' _='on foo put event.detail.x into my.innerHTML'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "byId(\"bar\").classList.contains(\"foo-sent\")",
        "op": "==",
        "expected": "false"
      },
      {
        "expr": "byId(\"bar\").innerHTML",
        "op": "==",
        "expected": "\"42\""
      }
    ],
    "async": false
  },
  {
    "category": "send",
    "name": "can send events with dots",
    "html": "<div _='on click send foo.bar to #bar'></div><div id='bar' _='on foo.bar add .foo-sent'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "byId(\"bar\").classList.contains(\"foo-sent\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": false
  },
  {
    "category": "send",
    "name": "can send events with dots with args",
    "html": "<div _='on click send foo.bar(x:42) to #bar'></div><div id='bar' _='on foo.bar put event.detail.x into my.innerHTML'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "byId(\"bar\").classList.contains(\"foo-sent\")",
        "op": "==",
        "expected": "false"
      },
      {
        "expr": "byId(\"bar\").innerHTML",
        "op": "==",
        "expected": "\"42\""
      }
    ],
    "async": false
  },
  {
    "category": "send",
    "name": "can send events with colons",
    "html": "<div _='on click send foo:bar to #bar'></div><div id='bar' _='on foo:bar add .foo-sent'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "byId(\"bar\").classList.contains(\"foo-sent\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": false
  },
  {
    "category": "send",
    "name": "can send events with colons with args",
    "html": "<div _='on click send foo:bar(x:42) to #bar'></div><div id='bar' _='on foo:bar put event.detail.x into my.innerHTML'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "byId(\"bar\").classList.contains(\"foo-sent\")",
        "op": "==",
        "expected": "false"
      },
      {
        "expr": "byId(\"bar\").innerHTML",
        "op": "==",
        "expected": "\"42\""
      }
    ],
    "async": false
  },
  {
    "category": "send",
    "name": "can send events to any expression",
    "html": "<div _='def bar return #bar on click send foo to bar()'></div><div id='bar' _='on foo add .foo-sent'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "byId(\"bar\").classList.contains(\"foo-sent\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": false
  },
  {
    "category": "take",
    "name": "can take a class from other elements",
    "html": "<div id=\"el\" class='div foo'></div><div class='div' _='on click take .foo from .div'></div><div class='div'></div>",
    "action": "byId(\"d2\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "false"
      },
      {
        "expr": "byId(\"d2\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "true"
      },
      {
        "expr": "byId(\"d3\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "false"
      }
    ],
    "async": false
  },
  {
    "category": "take",
    "name": "can take a class from other forms",
    "html": "<form id=\"el\" class='div foo'></form><form class='div' _='on click take .foo from .div'></form><form class='div'></form>",
    "action": "byId(\"f2\").click()",
    "checks": [
      {
        "expr": "byId(\"f1\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "false"
      },
      {
        "expr": "byId(\"f2\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "true"
      },
      {
        "expr": "byId(\"f3\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "false"
      }
    ],
    "async": false
  },
  {
    "category": "take",
    "name": "can take a class for other elements",
    "html": "<div class='div foo'></div><div class='div' _='on click take .foo from .div for #d3'></div><div id='d3' class='div'></div>",
    "action": "byId(\"d2\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "false"
      },
      {
        "expr": "byId(\"d2\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "false"
      },
      {
        "expr": "byId(\"d3\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": false
  },
  {
    "category": "take",
    "name": "a parent can take a class for other elements",
    "html": "<div _='on click take .foo from .div for event.target'><div id='d1' class='div foo'></div><div id='d2' class='div'></div><div id='d3' class='div'></div></div>",
    "action": "byId(\"d2\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "false"
      },
      {
        "expr": "byId(\"d2\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "true"
      },
      {
        "expr": "byId(\"d3\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "false"
      }
    ],
    "async": false
  },
  {
    "category": "take",
    "name": "can take an attribute from other elements",
    "html": "<div id=\"el\" class='div' data-foo='bar'></div><div class='div' _='on click take @data-foo from .div'></div><div class='div'></div>",
    "action": "byId(\"d2\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").getAttribute(\"data-foo\")",
        "op": "==",
        "expected": "\"bar\""
      },
      {
        "expr": "byId(\"d2\").getAttribute(\"data-foo\")",
        "op": "==",
        "expected": "\"\""
      },
      {
        "expr": "byId(\"d2\").getAttribute(\"data-foo\"",
        "op": "==",
        "expected": "null"
      },
      {
        "expr": "byId(\"d3\").getAttribute(\"data-foo\"",
        "op": "==",
        "expected": "null"
      },
      {
        "expr": "byId(\"d1\").getAttribute(\"data-foo\"",
        "op": "==",
        "expected": "null"
      }
    ],
    "async": false
  },
  {
    "category": "take",
    "name": "can take an attribute with specific value from other elements",
    "html": "<div id=\"el\" class='div' data-foo='bar'></div><div class='div' _='on click take @data-foo=baz from .div'></div><div class='div'></div>",
    "action": "byId(\"d2\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").getAttribute(\"data-foo\")",
        "op": "==",
        "expected": "\"bar\""
      },
      {
        "expr": "byId(\"d2\").getAttribute(\"data-foo\")",
        "op": "==",
        "expected": "\"baz\""
      },
      {
        "expr": "byId(\"d2\").getAttribute(\"data-foo\"",
        "op": "==",
        "expected": "null"
      },
      {
        "expr": "byId(\"d3\").getAttribute(\"data-foo\"",
        "op": "==",
        "expected": "null"
      },
      {
        "expr": "byId(\"d1\").getAttribute(\"data-foo\"",
        "op": "==",
        "expected": "null"
      }
    ],
    "async": false
  },
  {
    "category": "take",
    "name": "can take an attribute value from other elements and set specific values instead",
    "html": "<div id=\"el\" class='div' data-foo='bar'></div><div class='div' _='on click take @data-foo=baz with \"qux\" from .div'></div><div class='div'></div>",
    "action": "byId(\"d2\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").getAttribute(\"data-foo\")",
        "op": "==",
        "expected": "\"qux\""
      },
      {
        "expr": "byId(\"d2\").getAttribute(\"data-foo\")",
        "op": "==",
        "expected": "\"baz\""
      },
      {
        "expr": "byId(\"d3\").getAttribute(\"data-foo\")",
        "op": "==",
        "expected": "\"qux\""
      },
      {
        "expr": "byId(\"d2\").getAttribute(\"data-foo\"",
        "op": "==",
        "expected": "null"
      },
      {
        "expr": "byId(\"d3\").getAttribute(\"data-foo\"",
        "op": "==",
        "expected": "null"
      }
    ],
    "async": false
  },
  {
    "category": "take",
    "name": "can take an attribute value from other elements and set value from an expression instead",
    "html": "<div id=\"el\" class='div' data-foo='bar'></div><div class='div' data-foo='qux' _='on click take @data-foo=baz with my @data-foo from .div'></div><div class='div'></div>",
    "action": "byId(\"d2\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").getAttribute(\"data-foo\")",
        "op": "==",
        "expected": "\"qux\""
      },
      {
        "expr": "byId(\"d2\").getAttribute(\"data-foo\")",
        "op": "==",
        "expected": "\"baz\""
      },
      {
        "expr": "byId(\"d3\").getAttribute(\"data-foo\")",
        "op": "==",
        "expected": "\"qux\""
      },
      {
        "expr": "byId(\"d3\").getAttribute(\"data-foo\"",
        "op": "==",
        "expected": "null"
      }
    ],
    "async": false
  },
  {
    "category": "take",
    "name": "can take an attribute for other elements",
    "html": "<div class='div' data-foo='bar'></div><div class='div' _='on click take @data-foo from .div for #d3'></div><div id='d3' class='div'></div>",
    "action": "byId(\"d2\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").getAttribute(\"data-foo\")",
        "op": "==",
        "expected": "\"bar\""
      },
      {
        "expr": "byId(\"d3\").getAttribute(\"data-foo\")",
        "op": "==",
        "expected": "\"\""
      },
      {
        "expr": "byId(\"d2\").getAttribute(\"data-foo\"",
        "op": "==",
        "expected": "null"
      },
      {
        "expr": "byId(\"d3\").getAttribute(\"data-foo\"",
        "op": "==",
        "expected": "null"
      },
      {
        "expr": "byId(\"d1\").getAttribute(\"data-foo\"",
        "op": "==",
        "expected": "null"
      }
    ],
    "async": false
  },
  {
    "category": "take",
    "name": "a parent can take an attribute for other elements",
    "html": "<div _='on click take @data-foo from .div for event.target'><div id='d1' class='div' data-foo='bar'></div><div id='d2' class='div'></div><div id='d3' class='div'></div></div>",
    "action": "byId(\"d2\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").getAttribute(\"data-foo\")",
        "op": "==",
        "expected": "\"bar\""
      },
      {
        "expr": "byId(\"d2\").getAttribute(\"data-foo\")",
        "op": "==",
        "expected": "\"\""
      },
      {
        "expr": "byId(\"d2\").getAttribute(\"data-foo\"",
        "op": "==",
        "expected": "null"
      },
      {
        "expr": "byId(\"d3\").getAttribute(\"data-foo\"",
        "op": "==",
        "expected": "null"
      },
      {
        "expr": "byId(\"d1\").getAttribute(\"data-foo\"",
        "op": "==",
        "expected": "null"
      }
    ],
    "async": false
  },
  {
    "category": "take",
    "name": "can take multiple classes from other elements",
    "html": "<div id=\"el\" class='div foo'></div><div class='div' _='on click take .foo .bar'></div><div class='div bar'></div>",
    "action": "byId(\"d2\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "false"
      },
      {
        "expr": "byId(\"d2\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "true"
      },
      {
        "expr": "byId(\"d3\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "false"
      },
      {
        "expr": "byId(\"d1\").classList.contains(\"bar\")",
        "op": "==",
        "expected": "false"
      },
      {
        "expr": "byId(\"d2\").classList.contains(\"bar\")",
        "op": "==",
        "expected": "true"
      },
      {
        "expr": "byId(\"d3\").classList.contains(\"bar\")",
        "op": "==",
        "expected": "false"
      }
    ],
    "async": false
  },
  {
    "category": "take",
    "name": "can take multiple classes from specific element",
    "html": "<div id=\"el\" class='div1 foo bar'></div><div class='div' _='on click take .foo .bar from .div1'></div><div class='div bar'></div>",
    "action": "byId(\"d2\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "false"
      },
      {
        "expr": "byId(\"d2\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "true"
      },
      {
        "expr": "byId(\"d3\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "false"
      },
      {
        "expr": "byId(\"d1\").classList.contains(\"bar\")",
        "op": "==",
        "expected": "false"
      },
      {
        "expr": "byId(\"d2\").classList.contains(\"bar\")",
        "op": "==",
        "expected": "true"
      },
      {
        "expr": "byId(\"d3\").classList.contains(\"bar\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": false
  },
  {
    "category": "log",
    "name": "can log single item",
    "html": "<div id=\"el\" _='on click log me'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [],
    "async": false
  },
  {
    "category": "log",
    "name": "can log multiple items",
    "html": "<div id=\"el\" _='on click log me, my'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [],
    "async": false
  },
  {
    "category": "log",
    "name": "can log multiple items with debug",
    "html": "<div id=\"el\" _='on click log me, my with console.debug'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [],
    "async": false
  },
  {
    "category": "log",
    "name": "can log multiple items with error",
    "html": "<div id=\"el\" _='on click log me, my with console.error'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [],
    "async": false
  },
  {
    "category": "call",
    "name": "can call javascript instance functions",
    "html": "<div id='d1' _='on click call document.getElementById(\"d1\") then                                          put it into window.results'></div>",
    "action": "byId(\"d1\").click()",
    "checks": [
      {
        "expr": "value",
        "op": "==",
        "expected": "d1"
      }
    ],
    "async": false
  },
  {
    "category": "call",
    "name": "can call global javascript functions",
    "html": "<div id=\"el\" _='on click call globalFunction(\"foo\")'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "\"foo\"",
        "op": "==",
        "expected": "calledWith"
      }
    ],
    "async": false
  },
  {
    "category": "call",
    "name": "can call no argument functions",
    "html": "<div id=\"el\" _='on click call globalFunction()'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "called",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": false
  },
  {
    "category": "call",
    "name": "can call functions w/ underscores",
    "html": "<div id=\"el\" _='on click call global_function()'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "called",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": false
  },
  {
    "category": "call",
    "name": "can call functions w/ dollar signs",
    "html": "<div id=\"el\" _='on click call $()'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "called",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": false
  },
  {
    "category": "increment",
    "name": "can increment an empty variable",
    "html": "<div id=\"el\" _=\"on click increment value then put value into me\"></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"1\""
      }
    ],
    "async": false
  },
  {
    "category": "increment",
    "name": "can increment a variable",
    "html": "<div id=\"el\" _=\"on click set value to 20 then increment value by 2 then put value into me\"></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"22\""
      }
    ],
    "async": false
  },
  {
    "category": "increment",
    "name": "can increment refer to result",
    "html": "<div id=\"el\" _=\"on click increment value by 2 then put it into me\"></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"2\""
      }
    ],
    "async": false
  },
  {
    "category": "increment",
    "name": "can increment an attribute",
    "html": "<div id=\"el\" value=\"5\" _=\"on click increment @value then put @value into me\"></div>",
    "action": "qs(\"div\").click(); qs(\"div\").click(); qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"8\""
      }
    ],
    "async": false
  },
  {
    "category": "increment",
    "name": "can increment an floating point numbers",
    "html": "<div id=\"el\" value=\"5\" _=\"on click set value to 5.2 then increment value by 6.1 then put value into me\"></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"11.3\""
      }
    ],
    "async": false
  },
  {
    "category": "increment",
    "name": "can increment a property",
    "html": "<div id=\"el\" _=\"on click increment my.innerHTML\">3</div>",
    "action": "qs(\"div\").click(); qs(\"div\").click(); qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"6\""
      }
    ],
    "async": false
  },
  {
    "category": "increment",
    "name": "can increment by zero",
    "html": "<div id=\"el\" _=\"on click set value to 20 then increment value by 0 then put value into me\"></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"20\""
      }
    ],
    "async": false
  },
  {
    "category": "increment",
    "name": "can increment a value multiple times",
    "html": "<div id=\"el\" _=\"on click increment my.innerHTML\"></div>",
    "action": "qs(\"div\").click(); qs(\"div\").click(); qs(\"div\").click(); qs(\"div\").click(); qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"5\""
      }
    ],
    "async": false
  },
  {
    "category": "increment",
    "name": "can decrement an empty variable",
    "html": "<div id=\"el\" _=\"on click decrement value then put value into me\"></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"-1\""
      }
    ],
    "async": false
  },
  {
    "category": "increment",
    "name": "can decrement a variable",
    "html": "<div id=\"el\" _=\"on click set value to 20 then decrement value by 2 then put value into me\"></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"18\""
      }
    ],
    "async": false
  },
  {
    "category": "increment",
    "name": "can decrement an attribute",
    "html": "<div id=\"el\" value=\"5\" _=\"on click decrement @value then put @value into me\"></div>",
    "action": "qs(\"div\").click(); qs(\"div\").click(); qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"2\""
      }
    ],
    "async": false
  },
  {
    "category": "increment",
    "name": "can decrement an floating point numbers",
    "html": "<div id=\"el\" value=\"5\" _=\"on click set value to 6.1 then decrement value by 5.1 then put value into me\"></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"1\""
      }
    ],
    "async": false
  },
  {
    "category": "increment",
    "name": "can decrement a property",
    "html": "<div id=\"el\" _=\"on click decrement my.innerHTML\">3</div>",
    "action": "qs(\"div\").click(); qs(\"div\").click(); qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"0\""
      }
    ],
    "async": false
  },
  {
    "category": "increment",
    "name": "can decrement a value multiple times",
    "html": "<div id=\"el\" _=\"on click decrement my.innerHTML\"></div>",
    "action": "qs(\"div\").click(); qs(\"div\").click(); qs(\"div\").click(); qs(\"div\").click(); qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"-5\""
      }
    ],
    "async": false
  },
  {
    "category": "increment",
    "name": "can decrement by zero",
    "html": "<div id=\"el\" _=\"on click set value to 20 then decrement value by 0 then put value into me\"></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"20\""
      }
    ],
    "async": false
  },
  {
    "category": "append",
    "name": "can append a string to another string",
    "html": "<div id=\"el\" _=\"on click\n                            set value to 'Hello there.' then\n                            append ' General Kenobi.' to value then\n                            set my.innerHTML to value\"></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"Hello there. General Kenobi.\""
      }
    ],
    "async": false
  },
  {
    "category": "append",
    "name": "can append a value to a DOM node",
    "html": "<div id=\"el\" _=\"on click\n                            append '<span>This is my inner HTML</span>' to me\n                            append '<b>With Tags</b>' to me\"></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"<span>This is my inner HTML</span><b>With Tags</b>\""
      }
    ],
    "async": false
  },
  {
    "category": "append",
    "name": "can append a value to a DOM element",
    "html": "<div id=\"content\" _=\"on click\n                            append 'Content' to #content\"></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"Content\""
      }
    ],
    "async": false
  },
  {
    "category": "append",
    "name": "can append a value to I",
    "html": "<div id=\"el\" _=\"on click \n                            append 'Content' to I\"></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"Content\""
      }
    ],
    "async": false
  },
  {
    "category": "append",
    "name": "can append a value to an object property",
    "html": "<div id=\"id\" _=\"on click append '_new' to my id\"></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").id",
        "op": "==",
        "expected": "\"id_new\""
      }
    ],
    "async": false
  },
  {
    "category": "append",
    "name": "multiple appends work",
    "html": "<div id=\"id\" _=\"on click get 'foo' then append 'bar' then append 'doh' then append it to me\"></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"foobardoh\""
      }
    ],
    "async": false
  },
  {
    "category": "append",
    "name": "append to undefined ignores the undefined",
    "html": "<div id=\"id\" _=\"on click append 'bar' then append it to me\"></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"bar\""
      }
    ],
    "async": false
  },
  {
    "category": "append",
    "name": "append preserves existing content rather than overwriting it",
    "html": "<div _=\"on click append '<a>New Content</a>' to me\"><button id=\"btn1\">Click Me</button></div>",
    "action": "btn.click(); qs(\"div\").click(); btn.click()",
    "checks": [
      {
        "expr": "clicks",
        "op": "==",
        "expected": "1"
      },
      {
        "expr": "btn.parentNode",
        "op": "==",
        "expected": "div"
      }
    ],
    "async": false
  },
  {
    "category": "append",
    "name": "new content added by append will be live",
    "html": "<div _=\"on click append \\`<button id='b1' _='on click increment window.temp'>Test</button>\\` to me\"></div>",
    "action": "qs(\"div\").click(); btn.click()",
    "checks": [
      {
        "expr": "window.temp",
        "op": "==",
        "expected": "1"
      }
    ],
    "async": false
  },
  {
    "category": "tell",
    "name": "establishes a proper beingTold symbol",
    "html": "<div id='d1' _='on click                           add .foo                           tell #d2                            add .bar'></div><div id='d2'></div>",
    "action": "byId(\"div1\") && byId(\"div1\").click()",
    "checks": [
      {
        "expr": "byId(\"div1\").classList.contains(\"bar\")",
        "op": "==",
        "expected": "false"
      },
      {
        "expr": "byId(\"div1\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "true"
      },
      {
        "expr": "byId(\"div2\").classList.contains(\"bar\")",
        "op": "==",
        "expected": "true"
      },
      {
        "expr": "byId(\"div2\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "false"
      }
    ],
    "async": false
  },
  {
    "category": "tell",
    "name": "does not overwrite the me symbol",
    "html": "<div id='d1' _='on click                           add .foo                           tell #d2                            add .bar to me'></div><div id='d2'></div>",
    "action": "byId(\"div1\") && byId(\"div1\").click()",
    "checks": [
      {
        "expr": "byId(\"div1\").classList.contains(\"bar\")",
        "op": "==",
        "expected": "true"
      },
      {
        "expr": "byId(\"div1\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "true"
      },
      {
        "expr": "byId(\"div2\").classList.contains(\"bar\")",
        "op": "==",
        "expected": "false"
      },
      {
        "expr": "byId(\"div2\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "false"
      }
    ],
    "async": false
  },
  {
    "category": "tell",
    "name": "works with an array",
    "html": "<div id='d1' _='on click                           add .foo                           tell <p/> in me                            add .bar'><p id='p1'></p><p id='p2'></p><div id='d2'></div></div>",
    "action": "byId(\"div1\") && byId(\"div1\").click()",
    "checks": [
      {
        "expr": "byId(\"div1\").classList.contains(\"bar\")",
        "op": "==",
        "expected": "false"
      },
      {
        "expr": "byId(\"div1\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "true"
      },
      {
        "expr": "byId(\"div2\").classList.contains(\"bar\")",
        "op": "==",
        "expected": "false"
      },
      {
        "expr": "byId(\"div2\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "false"
      },
      {
        "expr": "byId(\"p1\").classList.contains(\"bar\")",
        "op": "==",
        "expected": "true"
      },
      {
        "expr": "byId(\"p1\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "false"
      },
      {
        "expr": "byId(\"p2\").classList.contains(\"bar\")",
        "op": "==",
        "expected": "true"
      },
      {
        "expr": "byId(\"p2\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "false"
      }
    ],
    "async": false
  },
  {
    "category": "tell",
    "name": "restores a proper implicit me symbol",
    "html": "<div id='d1' _='on click                           tell #d2                            add .bar                          end                          add .foo'></div><div id='d2'></div>",
    "action": "byId(\"div1\") && byId(\"div1\").click()",
    "checks": [
      {
        "expr": "byId(\"div1\").classList.contains(\"bar\")",
        "op": "==",
        "expected": "false"
      },
      {
        "expr": "byId(\"div1\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "true"
      },
      {
        "expr": "byId(\"div2\").classList.contains(\"bar\")",
        "op": "==",
        "expected": "true"
      },
      {
        "expr": "byId(\"div2\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "false"
      }
    ],
    "async": false
  },
  {
    "category": "tell",
    "name": "ignores null",
    "html": "<div id='d1' _='on click                           tell null                            add .bar                          end                          add .foo'></div><div id='d2'></div>",
    "action": "byId(\"div1\") && byId(\"div1\").click()",
    "checks": [
      {
        "expr": "byId(\"div1\").classList.contains(\"bar\")",
        "op": "==",
        "expected": "false"
      },
      {
        "expr": "byId(\"div1\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "true"
      },
      {
        "expr": "byId(\"div2\").classList.contains(\"bar\")",
        "op": "==",
        "expected": "false"
      },
      {
        "expr": "byId(\"div2\").classList.contains(\"foo\")",
        "op": "==",
        "expected": "false"
      }
    ],
    "async": false
  },
  {
    "category": "tell",
    "name": "you symbol represents the thing being told",
    "html": "<div id='d1' _='on click                           tell #d2                            add .bar to you'></div><div id='d2'></div>",
    "action": "byId(\"div1\") && byId(\"div1\").click()",
    "checks": [
      {
        "expr": "byId(\"div1\").classList.contains(\"bar\")",
        "op": "==",
        "expected": "false"
      },
      {
        "expr": "byId(\"div2\").classList.contains(\"bar\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": false
  },
  {
    "category": "tell",
    "name": "your symbol represents the thing being told",
    "html": "<div id='d1' _='on click                           tell #d2                            put your innerText into me'></div><div id='d2'>foo</div>",
    "action": "byId(\"div1\") && byId(\"div1\").click()",
    "checks": [
      {
        "expr": "byId(\"div1\").innerText",
        "op": "==",
        "expected": "\"foo\""
      },
      {
        "expr": "byId(\"div2\").innerText",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "tell",
    "name": "attributes refer to the thing being told",
    "html": "<div id='d1' _='on click                           tell #d2                            put @foo into me'></div><div foo='bar' id='d2'></div>",
    "action": "byId(\"div1\") && byId(\"div1\").click()",
    "checks": [
      {
        "expr": "byId(\"div1\").innerText",
        "op": "==",
        "expected": "\"bar\""
      },
      {
        "expr": "byId(\"div2\").innerText",
        "op": "==",
        "expected": "\"\""
      }
    ],
    "async": false
  },
  {
    "category": "tell",
    "name": "yourself attribute also works",
    "html": "<div id=\"d1\" _=\"on click tell #d2 remove yourself\"><div id=\"d2\"></div></div>",
    "action": "byId(\"div1\") && byId(\"div1\").click()",
    "checks": [
      {
        "expr": "byId(\"div1\").innerHTML",
        "op": "==",
        "expected": "\"\""
      }
    ],
    "async": false
  },
  {
    "category": "tell",
    "name": "tell terminates with a feature",
    "html": "<div id=\"d1\" _=\"on click tell #d2 remove yourself on click tell #d3 remove yourself\"><div id=\"d2\"></div><div id=\"d3\"></div></div>",
    "action": "byId(\"div1\") && byId(\"div1\").click()",
    "checks": [
      {
        "expr": "byId(\"div1\").innerHTML",
        "op": "==",
        "expected": "\"\""
      }
    ],
    "async": false
  },
  {
    "category": "on",
    "name": "can respond to events with dots in names",
    "html": "<div _='on click send example.event to #d1'></div><div id='d1' _='on example.event add .called'></div>",
    "action": "bar.click()",
    "checks": [
      {
        "expr": "qs(\"div\").classList.contains(\"called\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": false
  },
  {
    "category": "on",
    "name": "can respond to events with colons in names",
    "html": "<div _='on click send example:event to #d1'></div><div id='d1' _='on example:event add .called'></div>",
    "action": "bar.click()",
    "checks": [
      {
        "expr": "qs(\"div\").classList.contains(\"called\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": false
  },
  {
    "category": "on",
    "name": "can respond to events with minus in names",
    "html": "<div _='on click send \"a-b\" to #d1'></div><div id='d1' _='on \"a-b\" add .called'></div>",
    "action": "bar.click()",
    "checks": [
      {
        "expr": "qs(\"div\").classList.contains(\"called\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": false
  },
  {
    "category": "on",
    "name": "can respond to events on other elements",
    "html": "<div id='bar'></div><div _='on click from #bar add .clicked'></div>",
    "action": "bar.click()",
    "checks": [
      {
        "expr": "qs(\"div\").classList.contains(\"clicked\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": false
  },
  {
    "category": "on",
    "name": "listeners on other elements are removed when the registering element is removed",
    "html": "<div id='bar'></div><div _='on click from #bar set #bar.innerHTML to #bar.innerHTML + \"a\"'></div>",
    "action": "bar.click(); bar.click()",
    "checks": [
      {
        "expr": "byId(\"bar\").innerHTML",
        "op": "==",
        "expected": "\"a\""
      }
    ],
    "async": false
  },
  {
    "category": "on",
    "name": "listeners on self are not removed when the element is removed",
    "html": "<div id=\"el\" _='on someCustomEvent put 1 into me'></div>",
    "action": "qs(\"div\").remove(); qs(\"div\").dispatchEvent(new Event(\"someCustomEvent\")",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"1\""
      }
    ],
    "async": false
  },
  {
    "category": "on",
    "name": "supports \"elsewhere\" modifier",
    "html": "<div id=\"el\" _='on click elsewhere add .clicked'></div>",
    "action": "qs(\"div\").click(); body.click()",
    "checks": [
      {
        "expr": "qs(\"div\").classList.contains(\"clicked\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": false
  },
  {
    "category": "on",
    "name": "supports \"from elsewhere\" modifier",
    "html": "<div id=\"el\" _='on click from elsewhere add .clicked'></div>",
    "action": "qs(\"div\").click(); body.click()",
    "checks": [
      {
        "expr": "qs(\"div\").classList.contains(\"clicked\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": false
  },
  {
    "category": "on",
    "name": "can pick detail fields out by name",
    "html": "<div id='d1' _='on click send custom(foo:\"fromBar\") to #d2'></div><div id='d2' _='on custom(foo) call me.classList.add(foo)'></div>",
    "action": "bar.click()",
    "checks": [
      {
        "expr": "qs(\"div\").classList.contains(\"fromBar\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": false
  },
  {
    "category": "on",
    "name": "can pick event properties out by name",
    "html": "<div id='d1' _='on click send fromBar to #d2'></div><div id='d2' _='on fromBar(type) call me.classList.add(type)'></div>",
    "action": "bar.click()",
    "checks": [
      {
        "expr": "qs(\"div\").classList.contains(\"fromBar\")",
        "op": "==",
        "expected": "true"
      }
    ],
    "async": false
  },
  {
    "category": "on",
    "name": "can fire an event on load",
    "html": "<div id='d1' _='on load put \"Loaded\" into my.innerHTML'></div>",
    "action": "",
    "checks": [
      {
        "expr": "qs(\"div\").innerText",
        "op": "==",
        "expected": "\"Loaded\""
      }
    ],
    "async": true
  },
  {
    "category": "on",
    "name": "can have a simple event filter",
    "html": "<div id='d1' _='on click[false] log event then put \"Clicked\" into my.innerHTML'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "byId(\"d1\").innerText",
        "op": "==",
        "expected": "\"\""
      }
    ],
    "async": false
  },
  {
    "category": "on",
    "name": "can refer to event properties directly in filter",
    "html": "<div id=\"el\" _='on click[buttons==0] log event then put \"Clicked\" into my.innerHTML'></div><div _='on click[buttons==1] log event then put \"Clicked\" into my.innerHTML'></div><div _='on click[buttons==1 and buttons==0] log event then put \"Clicked\" into my.innerHTML'></div>",
    "action": "qs(\"div\").click(); qs(\"div\").click(); qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").innerText",
        "op": "==",
        "expected": "\"\""
      }
    ],
    "async": false
  },
  {
    "category": "on",
    "name": "can refer to event detail properties directly in filter",
    "html": "<div id=\"el\" _='on example[foo] increment @count then put it into me'></div>",
    "action": "qs(\"div\").dispatchEvent(event); qs(\"div\").dispatchEvent(event); qs(\"div\").dispatchEvent(event)",
    "checks": [
      {
        "expr": "qs(\"div\").innerText",
        "op": "==",
        "expected": "\"2\""
      }
    ],
    "async": false
  },
  {
    "category": "on",
    "name": "can click after a positive event filter",
    "html": "<div id=\"el\" _='on foo(bar)[bar] put \"triggered\" into my.innerHTML'></div>",
    "action": "qs(\"div\").dispatchEvent(new CustomEvent(\"foo\", { detail: { bar: false } }); qs(\"div\").dispatchEvent(new CustomEvent(\"foo\", { detail: { bar: true } })",
    "checks": [
      {
        "expr": "qs(\"div\").innerText",
        "op": "==",
        "expected": "\"triggered\""
      }
    ],
    "async": false
  },
  {
    "category": "on",
    "name": "multiple event handlers at a time are allowed to execute with the every keyword",
    "html": "<div id=\"el\" _='on every click put increment() into my.innerHTML then wait for a customEvent'></div>",
    "action": "qs(\"div\").click(); qs(\"div\").click(); qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").innerText",
        "op": "==",
        "expected": "\"3\""
      }
    ],
    "async": false
  },
  {
    "category": "on",
    "name": "can have multiple event handlers",
    "html": "<div id=\"el\" _='on foo put increment() into my.innerHTML end                          on bar put increment() into my.innerHTML'></div>",
    "action": "qs(\"div\").dispatchEvent(new CustomEvent(\"foo\"); qs(\"div\").dispatchEvent(new CustomEvent(\"bar\"); qs(\"div\").dispatchEvent(new CustomEvent(\"foo\")",
    "checks": [
      {
        "expr": "qs(\"div\").innerText",
        "op": "==",
        "expected": "\"3\""
      }
    ],
    "async": false
  },
  {
    "category": "on",
    "name": "can have multiple event handlers, no end",
    "html": "<div id=\"el\" _='on foo put increment() into my.innerHTML                          on bar put increment() into my.innerHTML'></div>",
    "action": "qs(\"div\").dispatchEvent(new CustomEvent(\"foo\"); qs(\"div\").dispatchEvent(new CustomEvent(\"bar\"); qs(\"div\").dispatchEvent(new CustomEvent(\"foo\")",
    "checks": [
      {
        "expr": "qs(\"div\").innerText",
        "op": "==",
        "expected": "\"3\""
      }
    ],
    "async": false
  },
  {
    "category": "on",
    "name": "can queue events",
    "html": "<div id=\"el\" _='on foo wait for bar then call increment()'></div>",
    "action": "qs(\"div\").dispatchEvent(new CustomEvent(\"foo\"); qs(\"div\").dispatchEvent(new CustomEvent(\"foo\"); qs(\"div\").dispatchEvent(new CustomEvent(\"foo\"); qs(\"div\").dispatchEvent(new CustomEvent(\"bar\"); qs(\"div\").dispatchEvent(new CustomEvent(\"bar\"); qs(\"div\").dispatchEvent(new CustomEvent(\"bar\")",
    "checks": [
      {
        "expr": "i",
        "op": "==",
        "expected": "2"
      }
    ],
    "async": true
  },
  {
    "category": "on",
    "name": "can queue first event",
    "html": "<div id=\"el\" _='on foo queue first wait for bar then call increment()'></div>",
    "action": "qs(\"div\").dispatchEvent(new CustomEvent(\"foo\"); qs(\"div\").dispatchEvent(new CustomEvent(\"foo\"); qs(\"div\").dispatchEvent(new CustomEvent(\"foo\"); qs(\"div\").dispatchEvent(new CustomEvent(\"bar\"); qs(\"div\").dispatchEvent(new CustomEvent(\"bar\"); qs(\"div\").dispatchEvent(new CustomEvent(\"bar\")",
    "checks": [
      {
        "expr": "i",
        "op": "==",
        "expected": "2"
      }
    ],
    "async": true
  },
  {
    "category": "on",
    "name": "can queue last event",
    "html": "<div id=\"el\" _='on foo queue last wait for bar then call increment()'></div>",
    "action": "qs(\"div\").dispatchEvent(new CustomEvent(\"foo\"); qs(\"div\").dispatchEvent(new CustomEvent(\"foo\"); qs(\"div\").dispatchEvent(new CustomEvent(\"foo\"); qs(\"div\").dispatchEvent(new CustomEvent(\"bar\"); qs(\"div\").dispatchEvent(new CustomEvent(\"bar\"); qs(\"div\").dispatchEvent(new CustomEvent(\"bar\")",
    "checks": [
      {
        "expr": "i",
        "op": "==",
        "expected": "2"
      }
    ],
    "async": true
  },
  {
    "category": "on",
    "name": "can queue all events",
    "html": "<div id=\"el\" _='on foo queue all wait for bar then call increment()'></div>",
    "action": "qs(\"div\").dispatchEvent(new CustomEvent(\"foo\"); qs(\"div\").dispatchEvent(new CustomEvent(\"foo\"); qs(\"div\").dispatchEvent(new CustomEvent(\"foo\"); qs(\"div\").dispatchEvent(new CustomEvent(\"bar\"); qs(\"div\").dispatchEvent(new CustomEvent(\"bar\"); qs(\"div\").dispatchEvent(new CustomEvent(\"bar\")",
    "checks": [
      {
        "expr": "i",
        "op": "==",
        "expected": "3"
      }
    ],
    "async": true
  },
  {
    "category": "on",
    "name": "queue none does not allow future queued events",
    "html": "<div id=\"el\" _='on click queue none put increment() into my.innerHTML then wait for a customEvent'></div>",
    "action": "qs(\"div\").click(); qs(\"div\").click(); qs(\"div\").dispatchEvent(new CustomEvent(\"customEvent\"); qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").innerText",
        "op": "==",
        "expected": "\"2\""
      }
    ],
    "async": true
  },
  {
    "category": "on",
    "name": "can invoke on multiple events",
    "html": "<div id=\"el\" _='on click or foo call increment()'></div>",
    "action": "qs(\"div\").click(); qs(\"div\").dispatchEvent(new CustomEvent(\"foo\")",
    "checks": [
      {
        "expr": "i",
        "op": "==",
        "expected": "2"
      }
    ],
    "async": false
  },
  {
    "category": "on",
    "name": "can listen for events in another element (lazy)",
    "html": "<div _='on click in #d1 put it into window.tmp'>                    <div id='d1'></div>                    <div id='d2'></div>               </div>",
    "action": "byId(\"div1\") && byId(\"div1\").click()",
    "checks": [
      {
        "expr": "div1",
        "op": "==",
        "expected": "window.tmp"
      }
    ],
    "async": false
  },
  {
    "category": "on",
    "name": "can mix ranges",
    "html": "<div id=\"el\" _='on click 1 put \"one\" into my.innerHTML                           on click 3 put \"three\" into my.innerHTML                           on click 2 put \"two\" into my.innerHTML '>0</div>",
    "action": "qs(\"div\").click(); qs(\"div\").click(); qs(\"div\").click(); qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"three\""
      }
    ],
    "async": false
  },
  {
    "category": "on",
    "name": "can listen for general mutations",
    "html": "<div id=\"el\" _='on mutation put \"Mutated\" into me then wait for hyperscript:mutation'></div>",
    "action": "qs(\"div\").setAttribute(\"foo\", \"bar\")",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"Mutated\""
      }
    ],
    "async": true
  },
  {
    "category": "on",
    "name": "can listen for attribute mutations",
    "html": "<div id=\"el\" _='on mutation of attributes put \"Mutated\" into me'></div>",
    "action": "qs(\"div\").setAttribute(\"foo\", \"bar\")",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"Mutated\""
      }
    ],
    "async": true
  },
  {
    "category": "on",
    "name": "can listen for specific attribute mutations",
    "html": "<div id=\"el\" _='on mutation of @foo put \"Mutated\" into me'></div>",
    "action": "qs(\"div\").setAttribute(\"foo\", \"bar\")",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"Mutated\""
      }
    ],
    "async": true
  },
  {
    "category": "on",
    "name": "can listen for specific attribute mutations and filter out other attribute mutations",
    "html": "<div id=\"el\" _='on mutation of @bar put \"Mutated\" into me'></div>",
    "action": "qs(\"div\").setAttribute(\"foo\", \"bar\")",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"\""
      }
    ],
    "async": true
  },
  {
    "category": "on",
    "name": "can listen for childList mutations",
    "html": "<div id=\"el\" _='on mutation of childList put \"Mutated\" into me then wait for hyperscript:mutation'></div>",
    "action": "qs(\"div\").appendChild(document.createElement(\"P\")",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"Mutated\""
      }
    ],
    "async": true
  },
  {
    "category": "on",
    "name": "can listen for childList mutation filter out other mutations",
    "html": "<div id=\"el\" _='on mutation of childList put \"Mutated\" into me'></div>",
    "action": "qs(\"div\").setAttribute(\"foo\", \"bar\")",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"\""
      }
    ],
    "async": true
  },
  {
    "category": "on",
    "name": "can listen for characterData mutation filter out other mutations",
    "html": "<div id=\"el\" _='on mutation of characterData put \"Mutated\" into me'></div>",
    "action": "qs(\"div\").setAttribute(\"foo\", \"bar\")",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"\""
      }
    ],
    "async": true
  },
  {
    "category": "on",
    "name": "can listen for multiple mutations",
    "html": "<div id=\"el\" _='on mutation of @foo or @bar put \"Mutated\" into me'></div>",
    "action": "qs(\"div\").setAttribute(\"foo\", \"bar\")",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"Mutated\""
      }
    ],
    "async": true
  },
  {
    "category": "on",
    "name": "can listen for multiple mutations 2",
    "html": "<div id=\"el\" _='on mutation of @foo or @bar put \"Mutated\" into me'></div>",
    "action": "qs(\"div\").setAttribute(\"bar\", \"bar\")",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"Mutated\""
      }
    ],
    "async": true
  },
  {
    "category": "on",
    "name": "can listen for attribute mutations on other elements",
    "html": "<div id='d1'></div><div _='on mutation of attributes from #d1 put \"Mutated\" into me'></div>",
    "action": "byId(\"div1\") && byId(\"div1\").setAttribute(\"foo\", \"bar\")",
    "checks": [
      {
        "expr": "byId(\"div2\").innerHTML",
        "op": "==",
        "expected": "\"Mutated\""
      }
    ],
    "async": true
  },
  {
    "category": "on",
    "name": "can catch exceptions thrown in js functions",
    "html": "<button id=\"el\" _='on click throwBar() catch e put e into me'></button>",
    "action": "btn.click()",
    "checks": [
      {
        "expr": "byId(\"btn\").innerHTML",
        "op": "==",
        "expected": "\"bar\""
      }
    ],
    "async": false
  },
  {
    "category": "on",
    "name": "can catch top-level exceptions",
    "html": "<button id=\"el\" _='on click throw \"bar\" catch e put e into me'></button>",
    "action": "btn.click()",
    "checks": [
      {
        "expr": "byId(\"btn\").innerHTML",
        "op": "==",
        "expected": "\"bar\""
      }
    ],
    "async": false
  },
  {
    "category": "on",
    "name": "can catch async top-level exceptions",
    "html": "<button id=\"el\" _='on click wait 1ms then throw \"bar\" catch e put e into me'></button>",
    "action": "btn.click()",
    "checks": [
      {
        "expr": "byId(\"btn\").innerHTML",
        "op": "==",
        "expected": "\"bar\""
      }
    ],
    "async": true
  },
  {
    "category": "on",
    "name": "async exceptions don't kill the event queue",
    "html": "<button id=\"el\" _='on click                     increment :x                      if :x is 1                       wait 1ms then throw \"bar\"                     otherwise                       put \"success\" into me                    end                     catch e                       put e into me'></button>",
    "action": "btn.click(); btn.click()",
    "checks": [
      {
        "expr": "byId(\"btn\").innerHTML",
        "op": "==",
        "expected": "\"success\""
      }
    ],
    "async": true
  },
  {
    "category": "on",
    "name": "exceptions in catch block don't kill the event queue",
    "html": "<button id=\"el\" _='on click                     increment :x                      if :x is 1                       throw \"bar\"                     otherwise                       put \"success\" into me                    end                   catch e                       put e into me then throw e'></button>",
    "action": "btn.click(); btn.click()",
    "checks": [
      {
        "expr": "byId(\"btn\").innerHTML",
        "op": "==",
        "expected": "\"success\""
      }
    ],
    "async": false
  },
  {
    "category": "on",
    "name": "uncaught exceptions trigger 'exception' event",
    "html": "<button id=\"el\" _='on click put \"foo\" into me then throw \"bar\"                  on exception(error) put error into me'></button>",
    "action": "btn.click()",
    "checks": [
      {
        "expr": "byId(\"btn\").innerHTML",
        "op": "==",
        "expected": "\"bar\""
      }
    ],
    "async": false
  },
  {
    "category": "on",
    "name": "caught exceptions do not trigger 'exception'  event",
    "html": "<button id=\"el\" _='on click put \"foo\" into me then throw \"bar\"                     catch e log e                  on exception(error) put error into me'></button>",
    "action": "btn.click()",
    "checks": [
      {
        "expr": "byId(\"btn\").innerHTML",
        "op": "==",
        "expected": "\"foo\""
      }
    ],
    "async": false
  },
  {
    "category": "on",
    "name": "rethrown exceptions trigger 'exception'  event",
    "html": "<button id=\"el\" _='on click put \"foo\" into me then throw \"bar\"                     catch e throw e                  on exception(error) put error into me'></button>",
    "action": "btn.click()",
    "checks": [
      {
        "expr": "byId(\"btn\").innerHTML",
        "op": "==",
        "expected": "\"bar\""
      }
    ],
    "async": false
  },
  {
    "category": "on",
    "name": "basic finally blocks work",
    "html": "<button id=\"el\" _='on click throw \"bar\"             finally put \"bar\" into me'></button>",
    "action": "btn.click()",
    "checks": [
      {
        "expr": "byId(\"btn\").innerHTML",
        "op": "==",
        "expected": "\"bar\""
      }
    ],
    "async": false
  },
  {
    "category": "on",
    "name": "finally blocks work when exception thrown in catch",
    "html": "<button id=\"el\" _='on click throw \"bar\"            catch e throw e            finally put \"bar\" into me'></button>",
    "action": "btn.click()",
    "checks": [
      {
        "expr": "byId(\"btn\").innerHTML",
        "op": "==",
        "expected": "\"bar\""
      }
    ],
    "async": false
  },
  {
    "category": "on",
    "name": "async basic finally blocks work",
    "html": "<button id=\"el\" _='on click wait a tick then throw \"bar\"             finally put \"bar\" into me'></button>",
    "action": "btn.click()",
    "checks": [
      {
        "expr": "byId(\"btn\").innerHTML",
        "op": "==",
        "expected": "\"bar\""
      }
    ],
    "async": true
  },
  {
    "category": "on",
    "name": "async finally blocks work when exception thrown in catch",
    "html": "<button id=\"el\" _='on click wait a tick then throw \"bar\"            catch e set :foo to \"foo\" then throw e            finally put :foo + \"bar\" into me'></button>",
    "action": "btn.click()",
    "checks": [
      {
        "expr": "byId(\"btn\").innerHTML",
        "op": "==",
        "expected": "\"foobar\""
      }
    ],
    "async": true
  },
  {
    "category": "on",
    "name": "async exceptions in finally block don't kill the event queue",
    "html": "<button id=\"el\" _='on click                     increment :x                  finally                      if :x is 1                       wait 1ms then throw \"bar\"                     otherwise                       put \"success\" into me                    end                     '></button>",
    "action": "btn.click(); btn.click()",
    "checks": [
      {
        "expr": "byId(\"btn\").innerHTML",
        "op": "==",
        "expected": "\"success\""
      }
    ],
    "async": true
  },
  {
    "category": "on",
    "name": "exceptions in finally block don't kill the event queue",
    "html": "<button id=\"el\" _='on click                     increment :x                    finally                      if :x is 1                       throw \"bar\"                     otherwise                       put \"success\" into me                    end                   '></button>",
    "action": "btn.click(); btn.click()",
    "checks": [
      {
        "expr": "byId(\"btn\").innerHTML",
        "op": "==",
        "expected": "\"success\""
      }
    ],
    "async": false
  },
  {
    "category": "on",
    "name": "can ignore when target doesn't exist",
    "html": "<div id='#d1' _=' \ton click from #doesntExist \t\tthrow \"bar\" \ton click \t\tput \"clicked\" into me\t'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"clicked\""
      }
    ],
    "async": false
  },
  {
    "category": "on",
    "name": "can handle an or after a from clause",
    "html": "<div id='d1'></div><div id='d2'></div><div _=' \ton click from #d1 or click from #d2 \t\t increment @count then put @count into me\t'></div>",
    "action": "byId(\"d1\").click(); byId(\"d2\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"2\""
      }
    ],
    "async": false
  },
  {
    "category": "init",
    "name": "can define an init block inline",
    "html": "<div id=\"el\" _='init                  set my.foo to 42                end               on click put my.foo into my.innerHTML'></div>",
    "action": "qs(\"div\").click()",
    "checks": [
      {
        "expr": "qs(\"div\").innerHTML",
        "op": "==",
        "expected": "\"42\""
      }
    ],
    "async": true
  },
  {
    "category": "def",
    "name": "can install a function on an element and use in children w/ no leak",
    "html": "<div _='def func() put 42 into #d3'><div id='d1' _='on click call func()'></div><div id='d2'></div><div id='d3'></div> </div>",
    "action": "",
    "checks": [
      {
        "expr": "byId(\"d3\").innerText",
        "op": "==",
        "expected": "\"42\""
      }
    ],
    "async": false
  },
  {
    "category": "def",
    "name": "can install a function on an element and use in children w/ return value",
    "html": "<div _='def func() return 42'><div id='d1' _='on click put func() into me'></div><div id='d2'></div><div id='d3'></div> </div>",
    "action": "",
    "checks": [
      {
        "expr": "byId(\"d1\").innerText",
        "op": "==",
        "expected": "\"42\""
      }
    ],
    "async": false
  },
  {
    "category": "def",
    "name": "can install a function on an element and use me symbol correctly",
    "html": "<div _='def func() put 42 into me'><div id='d1' _='on click call func()'></div><div id='d2'></div><div id='d3'></div> </div>",
    "action": "",
    "checks": [
      {
        "expr": "qs(\"div\").innerText",
        "op": "==",
        "expected": "\"42\""
      }
    ],
    "async": false
  },
  {
    "category": "dialog",
    "name": "show opens a dialog as modal",
    "html": "<dialog id='d'><p>Hello</p></dialog><button _='on click show #d'>Open</button>",
    "action": "find('button').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "dialog",
    "name": "open opens a dialog",
    "html": "<dialog id='d'><p>Hello</p></dialog><button _='on click open #d'>Open</button>",
    "action": "find('button').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "dialog",
    "name": "open opens a details element",
    "html": "<details id='d'><summary>More</summary><p>Content</p></details><button _='on click open #d'>Open</button>",
    "action": "find('button').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "dialog",
    "name": "close closes a details element",
    "html": "<details id='d' open><summary>More</summary><p>Content</p></details><button _='on click close #d'>Close</button>",
    "action": "find('button').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "dialog",
    "name": "open on implicit me",
    "html": "<dialog id='d' _='on myOpen open'></dialog><button _='on click send myOpen to #d'>Open</button>",
    "action": "find('button').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "empty",
    "name": "can empty an element",
    "html": "<div id='d1'><p>hello</p><p>world</p></div><button _='on click empty #d1'></button>",
    "action": "find('button').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "empty",
    "name": "empty with no target empties me",
    "html": "<div id=\"el\" _='on click empty'>content</div>",
    "action": "find('div').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "empty",
    "name": "can empty multiple elements",
    "html": "<div id=\"el\" class='clearme'><p>a</p></div><div class='clearme'><p>b</p></div><button _='on click empty .clearme'></button>",
    "action": "find('button').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "empty",
    "name": "can empty an array",
    "html": "<div id=\"el\" _=\"on click\n\t\t                      set :arr to [1,2,3]\n\t\t                      empty :arr\n\t\t                      put :arr.length into me\"></div>",
    "action": "find('div').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "empty",
    "name": "can empty a text input",
    "html": "\n\t\t\t<input type=\"text\" id=\"t1\" value=\"hello\" />\n\t\t\t<button _=\"on click empty #t1\">Empty</button>\n\t\t",
    "action": "find('button').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "empty",
    "name": "can empty a textarea",
    "html": "\n\t\t\t<textarea id=\"ta1\">some text</textarea>\n\t\t\t<button _=\"on click empty #ta1\">Empty</button>\n\t\t",
    "action": "find('button').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "empty",
    "name": "can empty a checkbox",
    "html": "\n\t\t\t<input type=\"checkbox\" id=\"cb1\" checked />\n\t\t\t<button _=\"on click empty #cb1\">Empty</button>\n\t\t",
    "action": "find('button').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "empty",
    "name": "can empty a form (clears all inputs)",
    "html": "\n\t\t\t<form id=\"f1\">\n\t\t\t\t<input type=\"text\" id=\"t2\" value=\"val\" />\n\t\t\t\t<textarea id=\"ta2\">text</textarea>\n\t\t\t\t<input type=\"checkbox\" id=\"cb2\" checked />\n\t\t\t</form>\n\t\t\t<button _=\"on click empty #f1\">Empty</button>\n\t\t",
    "action": "find('button').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "empty",
    "name": "clear is an alias for empty",
    "html": "\n\t\t\t<input type=\"text\" id=\"t3\" value=\"hello\" />\n\t\t\t<button _=\"on click clear #t3\">Clear</button>\n\t\t",
    "action": "find('button').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "empty",
    "name": "clear works on elements",
    "html": "<div id='d2'><p>content</p></div><button _='on click clear #d2'></button>",
    "action": "find('button').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "halt",
    "name": "halts event propagation and default",
    "html": "<div id='outer' _='on click add .outer-clicked'>  <a id='inner' href='#shouldnot' _='on click halt'>click me</a></div>",
    "action": "find('#inner').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "halt",
    "name": "halt stops execution after the halt",
    "html": "<div id=\"el\" _='on click halt then add .should-not-happen'>test</div>",
    "action": "find('div').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "halt",
    "name": "halt the event stops propagation but continues execution",
    "html": "<div id='outer' _='on click add .outer-clicked'>  <div id='inner' _='on click halt the event then add .continued'>click me</div></div>",
    "action": "find('#inner').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "halt",
    "name": "halt the event's stops propagation but continues execution",
    "html": "<div id='outer' _='on click add .outer-clicked'>  <div id='inner' _=\\\"on click halt the event's then add .continued\\\">click me</div></div>",
    "action": "find('#inner').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "halt",
    "name": "halt bubbling only stops propagation, not default",
    "html": "<div id='outer' _='on click add .outer-clicked'>  <div id='inner' _='on click halt bubbling then add .continued'>click me</div></div>",
    "action": "find('#inner').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "halt",
    "name": "halt default only prevents default, not propagation",
    "html": "<div id='outer' _='on click add .outer-clicked'>  <div id='inner' _='on click halt default'>click me</div></div>",
    "action": "find('#inner').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "morph",
    "name": "basic morph updates content",
    "html": "<div id='target'>old</div><button _='on click morph #target to \\\"<div id=target>new</div>\\\"'>go</button>",
    "action": "find('button').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "morph",
    "name": "morph updates attributes",
    "html": "<div id='target' class='old'>content</div><button _='on click morph #target to \\\"<div id=target class=new>content</div>\\\"'>go</button>",
    "action": "find('button').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "morph",
    "name": "morph initializes hyperscript on new elements",
    "html": "<div id='target'><p>old</p></div><button id='go' _=\\\"on click morph #target to '<div id=target><p id=inner _=&#34;on click put `clicked` into me&#34;>new</p></div>'\\\">go</button>",
    "action": "find('#go').dispatchEvent('click'); find('#inner').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "morph",
    "name": "morph with variable content",
    "html": "<div id='target'>original</div><button id='go' _='on click set content to \\\"<div id=target>morphed</div>\\\" then morph #target to content'>go</button>",
    "action": "find('#go').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "reset",
    "name": "can reset a form",
    "html": "\n\t\t\t<form id=\"f1\">\n\t\t\t\t<input type=\"text\" id=\"t1\" value=\"original\" />\n\t\t\t\t<button type=\"button\" _=\"on click set #t1's value to 'changed'\">Change</button>\n\t\t\t\t<button type=\"button\" id=\"rst\" _=\"on click reset #f1\">Reset</button>\n\t\t\t</form>\n\t\t",
    "action": "find('#t1').fill('changed'); find('#rst').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "reset",
    "name": "reset with no target resets me (form)",
    "html": "\n\t\t\t<form _=\"on custom reset\">\n\t\t\t\t<input type=\"text\" id=\"t2\" value=\"default\" />\n\t\t\t</form>\n\t\t",
    "action": "find('#t2').fill('modified'); find('form').dispatchEvent('custom')",
    "checks": [],
    "async": true
  },
  {
    "category": "reset",
    "name": "can reset a text input to defaultValue",
    "html": "\n\t\t\t<input type=\"text\" id=\"t3\" value=\"hello\" />\n\t\t\t<button _=\"on click reset #t3\">Reset</button>\n\t\t",
    "action": "find('#t3').fill('goodbye'); find('button').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "reset",
    "name": "can reset a checkbox",
    "html": "\n\t\t\t<input type=\"checkbox\" id=\"cb1\" checked />\n\t\t\t<button _=\"on click reset #cb1\">Reset</button>\n\t\t",
    "action": "find('button').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "reset",
    "name": "can reset an unchecked checkbox",
    "html": "\n\t\t\t<input type=\"checkbox\" id=\"cb2\" />\n\t\t\t<button _=\"on click reset #cb2\">Reset</button>\n\t\t",
    "action": "find('button').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "reset",
    "name": "can reset a textarea",
    "html": "\n\t\t\t<textarea id=\"ta1\">original text</textarea>\n\t\t\t<button _=\"on click reset #ta1\">Reset</button>\n\t\t",
    "action": "find('#ta1').fill('new text'); find('button').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "reset",
    "name": "can reset a select",
    "html": "\n\t\t\t<select id=\"sel1\">\n\t\t\t\t<option value=\"a\">A</option>\n\t\t\t\t<option value=\"b\" selected>B</option>\n\t\t\t\t<option value=\"c\">C</option>\n\t\t\t</select>\n\t\t\t<button _=\"on click reset #sel1\">Reset</button>\n\t\t",
    "action": "find('button').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "reset",
    "name": "can reset multiple inputs",
    "html": "\n\t\t\t<input type=\"text\" class=\"resettable\" value=\"one\" />\n\t\t\t<input type=\"text\" class=\"resettable\" value=\"two\" />\n\t\t\t<button _=\"on click reset .resettable\">Reset</button>\n\t\t",
    "action": "find('button').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "swap",
    "name": "can swap two variables",
    "html": "<div id='d1' _='on click set x to \"a\" then set y to \"b\" then swap x with y then put x + y into me'></div>",
    "action": "find('#d1').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "swap",
    "name": "can swap two properties",
    "html": "<div id='d1' _='on click set #a.textContent to \"hello\" then set #b.textContent to \"world\" then swap #a.textContent with #b.textContent'></div>\n\t\t\t<span id='a'>x</span><span id='b'>y</span>",
    "action": "find('#d1').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "swap",
    "name": "can swap a variable with a property",
    "html": "<div id='d1' _='on click set x to \"old\" then set #target.dataset.val to \"new\" then swap x with #target.dataset.val then put x into me'></div>\n\t\t\t<span id='target' data-val='x'></span>",
    "action": "find('#d1').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "bind",
    "name": "attribute bound to another element input value",
    "html": "<input type=\"text\" id=\"title-input\" value=\"Hello\" /><h1 _=\"bind @data-title and #title-input's value\"></h1>",
    "action": "find('#title-input').fill('World')",
    "checks": [],
    "async": true
  },
  {
    "category": "when",
    "name": "detects changes from :element variable",
    "html": "<div id=\"el\" _=\"init set :count to 0 end\n\t\t\t         when :count changes put it into me end\n\t\t\t         on click increment :count\">0</div>",
    "action": "find('div').click(); find('div').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "when",
    "name": "works with on handlers that modify the watched variable",
    "html": "<div id=\"el\" _=\"init set :label to 'initial' end\n\t\t\t         when :label changes put it into me end\n\t\t\t         on click set :label to 'clicked'\">initial</div>",
    "action": "find('div').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "when",
    "name": "isolates element-scoped variables between elements",
    "html": "<div id=\"d1\" _=\"init set :value to 'A' end\n\t\t\t               when :value changes put it into me end\n\t\t\t               on click set :value to 'A-clicked'\">A</div><div id=\"d2\" _=\"init set :value to 'B' end\n\t\t\t               when :value changes put it into me end\n\t\t\t               on click set :value to 'B-clicked'\">B</div>",
    "action": "find('#d1').click(); find('#d2').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "when",
    "name": "value of #element is tracked",
    "html": "<input type=\"text\" id=\"of-input\" value=\"init\" /><span _=\"when (value of #of-input) changes put it into me\"></span>",
    "action": "find('#of-input').fill('changed')",
    "checks": [],
    "async": true
  },
  {
    "category": "liveTemplate",
    "name": "processes hyperscript on inner elements",
    "html": "\n\t\t\t<template live _=\"init set ^val to 0\">\n\t\t\t\t<button _=\"on click increment ^val then put ^val into the next <output/>\">+</button>\n\t\t\t\t<output>0</output>\n\t\t\t</template>\n\t\t",
    "action": "find('[data-live-template] button').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "assignableElements",
    "name": "set closest replaces ancestor",
    "html": "<div id=\"el\" class='wrapper'><button _='on click set (closest <div/>) to \\\"<div class=wrapper>replaced</div>\\\"'>go</button></div>",
    "action": "find('button').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "assignableElements",
    "name": "hyperscript in replacement content is initialized",
    "html": "<div id='target'>old</div><button id='go' _=\\\"on click set #target to '<div id=target _=&#34;on click put `clicked` into me&#34;>new</div>'\\\">go</button>",
    "action": "find('#go').dispatchEvent('click'); find('#target').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "assignableElements",
    "name": "put into still works as innerHTML",
    "html": "<div id='target'>old</div><button _='on click put \\\"new\\\" into #target'>go</button>",
    "action": "find('button').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "collectionExpressions",
    "name": "works with DOM elements",
    "html": "<ul id='list'><li class='yes'>A</li><li>B</li><li class='yes'>C</li></ul><button _='on click set items to <li/> in #list then set matches to items where it matches .yes then put matches mapped to its textContent into #out'>Go</button><div id='out'></div>",
    "action": "find('button').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "collectionExpressions",
    "name": "where binds after in on closest",
    "html": "<div id='box'><span class='a'>A</span><span class='b'>B</span><span class='a'>C</span></div><button _=\\\"on click set result to (<span/> in #box) where it matches .a then put result.length into me\\\">go (parens)</button><button id='b2' _=\\\"on click set result to <span/> in #box where it matches .a then put result.length into me\\\">go</button>",
    "action": "find('#b2').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "collectionExpressions",
    "name": "where in init followed by on feature",
    "html": "<div id='box'><span class='a'>A</span><span class='b'>B</span></div><button _=\\\"set :items to <span/> in #box where it matches .a on click put :items.length into me\\\">go</button>",
    "action": "find('button').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "collectionExpressions",
    "name": "where in component init followed by on feature",
    "html": "\n\t\t\t<div id='box'><span class='a'>A</span><span class='b'>B</span></div>\n\t\t\t<template component=\"test-where-comp\"\n\t\t\t\t_=\"set :items to <span/> in #box where it matches .a\n\t\t\t\t   on click put :items.length into me\">\n\t\t\t\t<slot/>\n\t\t\t</template>\n\t\t\t<test-where-comp>go</test-where-comp>\n\t\t",
    "action": "find('test-where-comp').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "collectionExpressions",
    "name": "where with is not me followed by on feature",
    "html": "\n\t\t\t<table>\n\t\t\t<tr><td><input type=\"checkbox\" class=\"cb\" checked></td></tr>\n\t\t\t<tr><td><input type=\"checkbox\" class=\"cb\"></td></tr>\n\t\t\t<tr><td><input type=\"checkbox\" class=\"cb\" checked></td></tr>\n\t\t\t<tr><td><input id=\"master\" type=\"checkbox\"\n\t\t\t\t_=\"set :checkboxes to <input[type=checkbox]/> in the closest <table/> where it is not me\n\t\t\t\t   on change set checked of the :checkboxes to my checked\"></td></tr>\n\t\t\t</table>\n\t\t",
    "action": "find('#master').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "dom-scope",
    "name": "child reads ^var set by parent",
    "html": "<div id=\"el\" _=\"init set ^count to 42\">  <span _=\"on click put ^count into me\">0</span></div>",
    "action": "find('span').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "dom-scope",
    "name": "child writes ^var and parent sees it",
    "html": "<div id=\"el\" _=\"init set ^count to 0\">  <button _=\"on click set ^count to 99\">set</button>  <span _=\"on click put ^count into me\">0</span></div>",
    "action": "find('button').click(); find('span').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "dom-scope",
    "name": "deeply nested child reads ^var from grandparent",
    "html": "<div id=\"el\" _=\"init set ^name to 'alice'\">  <div>    <div>      <span _=\"on click put ^name into me\">empty</span>    </div>  </div></div>",
    "action": "find('span').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "dom-scope",
    "name": "closest ancestor wins (shadowing)",
    "html": "<div id=\"el\" _=\"init set ^color to 'red'\">  <div _=\"init set ^color to 'blue'\">    <span _=\"on click put ^color into me\">empty</span>  </div></div>",
    "action": "find('span').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "dom-scope",
    "name": "sibling subtrees have independent ^vars",
    "html": "<div id=\"a\" _=\"init set ^val to 'A'\">  <span _=\"on click put ^val into me\">empty</span></div><div id=\"b\" _=\"init set ^val to 'B'\">  <span _=\"on click put ^val into me\">empty</span></div>",
    "action": "find('#a span').click(); find('#b span').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "dom-scope",
    "name": "write to ^var not found anywhere creates on current element",
    "html": "<div id=\"el\">  <button _=\"on click set ^newvar to 'created' then put ^newvar into next <span/>\">go</button>  <span>empty</span></div>",
    "action": "find('button').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "dom-scope",
    "name": "child write updates the ancestor, not a local copy",
    "html": "<div id=\"el\" _=\"init set ^shared to 0\">  <button _=\"on click set ^shared to 10\">set</button>  <span _=\"on click put ^shared into me\">0</span></div>",
    "action": "find('button').click(); find('span').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "dom-scope",
    "name": "increment works on inherited var",
    "html": "<div id=\"el\" _=\"init set ^count to 0\">  <button _=\"on click increment ^count\"  <span _=\"on click put ^count into me\">0</span></div>",
    "action": "find('button').click(); find('button').click(); find('button').click(); find('span').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "dom-scope",
    "name": "dom keyword works as scope modifier",
    "html": "<div id=\"el\" _=\"init set dom count to 42\">  <span _=\"on click put dom count into me\">0</span></div>",
    "action": "find('span').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "dom-scope",
    "name": "set ^var on explicit element",
    "html": "<div id=\"el\" class=\"store\">  <button _=\"on click set ^data on closest .store to 'hello'\">set</button>  <span _=\"on click put ^data on closest .store into me\">read</span></div>",
    "action": "find('button').click(); find('span').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "dom-scope",
    "name": "on clause targets a specific ancestor",
    "html": "<div id=\"el\" class=\"outer\" _=\"init set ^outerVal to 'outer'\">  <div class=\"inner\" _=\"init set ^innerVal to 'inner'\">    <span _=\"on click put ^outerVal on closest .outer into me\">read</span>  </div></div>",
    "action": "find('span').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "dom-scope",
    "name": "on clause with id reference",
    "html": "<div id=\"state-holder\"></div><button _=\"on click set ^count on #state-holder to 99\">set</button><span _=\"on click put ^count on #state-holder into me\">read</span>",
    "action": "find('button').click(); find('span').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "dom-scope",
    "name": "when reacts to ^var changes",
    "html": "<div id=\"el\" _=\"init set ^count to 0\">  <button _=\"on click increment ^count\"  <output _=\"when ^count changes put it into me\">0</output></div>",
    "action": "find('button').click(); find('button').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "dom-scope",
    "name": "always reacts to ^var changes",
    "html": "<div id=\"el\" _=\"init set ^name to 'alice'\">  <button _=\"on click set ^name to 'bob'\">rename</button>  <output _=\"live put 'Hello </div>",
    "action": "find('button').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "dom-scope",
    "name": "multiple children react to same ^var",
    "html": "<div _=\"init set ^color to 'red'\">  <button _=\"on click set ^color to 'blue'\">change</button>  <span id=\"a\" _=\"when ^color changes put it into me\"></span>  <span id=\"b\" _=\"when ^color changes put it into me\"></span></div>",
    "action": "find('button').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "dom-scope",
    "name": "sibling subtrees react independently with ^var",
    "html": "<div id=\"a\" _=\"init set ^val to 0\">  <button _=\"on click increment ^val\"  <output _=\"when ^val changes put it into me\">0</output></div><div id=\"b\" _=\"init set ^val to 0\">  <button _=\"on click increment ^val\"  <output _=\"when ^val changes put it into me\">0</output></div>",
    "action": "find('#a button').click(); find('#a button').click(); find('#b button').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "dom-scope",
    "name": "bind works with ^var",
    "html": "<div id=\"el\" _=\"init set ^search to ''\">  <input type=\"text\" _=\"bind ^search and my value\" />  <output _=\"when ^search changes put it into me\"></output></div>",
    "action": "find('input').fill('hello')",
    "checks": [],
    "async": true
  },
  {
    "category": "dom-scope",
    "name": "derived ^var chains reactively",
    "html": "<div _=\"init set ^price to 10 then set ^qty to 2 then set ^total to 20\">  <span _=\"when ^price changes set ^total to (^price * ^qty)\"></span>  <span _=\"when ^qty changes set ^total to (^price * ^qty)\"></span>  <output _=\"when ^total changes put it into me\"></output>  <button id=\"price-btn\" _=\"on click set ^price to 25\">set price</button>  <button id=\"qty-btn\" _=\"on click set ^qty to 5\">set qty</button></div>",
    "action": "find('#price-btn').click(); find('#qty-btn').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "component",
    "name": "processes _ on inner elements",
    "html": "\n\t\t\t<template component=\"test-inner\" _=\"init set ^count to 0\">\n\t\t\t\t<button _=\"on click increment ^count then put ^count into the next <span/>\">+</button>\n\t\t\t\t<span>0</span>\n\t\t\t</template>\n\t\t\t<test-inner></test-inner>\n\t\t",
    "action": "find('test-inner button').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "component",
    "name": "supports multiple independent instances",
    "html": "\n\t\t\t<template component=\"test-multi\" _=\"init set ^count to 0\">\n\t\t\t\t<button _=\"on click increment ^count then put ^count into the next <span/>\">+</button>\n\t\t\t\t<span>0</span>\n\t\t\t</template>\n\t\t\t<test-multi id=\"a\"></test-multi>\n\t\t\t<test-multi id=\"b\"></test-multi>\n\t\t",
    "action": "find('#a button').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "component",
    "name": "blocks processing of inner hyperscript until render",
    "html": "\n\t\t\t<template component=\"test-block\" _=\"init set ^msg to 'ready'\">\n\t\t\t\t<span _=\"on click put ^msg into me\">click me</span>\n\t\t\t</template>\n\t\t\t<test-block></test-block>\n\t\t",
    "action": "find('test-block span').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "component",
    "name": "does not process slotted _ attributes prematurely",
    "html": "\n\t\t\t<div _=\"init set ^x to 42\">\n\t\t\t\t<template component=\"test-slot-hs\">\n\t\t\t\t\t<div class=\"wrap\"><slot/></div>\n\t\t\t\t</template>\n\t\t\t\t<test-slot-hs>\n\t\t\t\t\t<span _=\"on click put ^x into me\">before</span>\n\t\t\t\t</test-slot-hs>\n\t\t\t</div>\n\t\t",
    "action": "find('test-slot-hs span').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "add",
    "name": "when clause sets result to matched elements",
    "html": "<div id='trigger' _='on click add .foo to .item when it matches .yes then if the result is empty show #none else hide #none'></div><div id='d1' class='item yes'></div><div id='d2' class='item'></div><div id='none' style='display:none'></div>",
    "action": "find('#trigger').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "add",
    "name": "when clause result is empty when nothing matches",
    "html": "<div id='trigger' _='on click add .foo to .item when it matches .nope then if the result is empty remove @hidden from #none'></div><div id='d1' class='item'></div><div id='none' hidden></div>",
    "action": "find('#trigger').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "default",
    "name": "can default possessive properties",
    "html": "<div id='d1' _=\\\"on click default #d1's foo to 'bar' then put #d1's foo into me\\\"></div>",
    "action": "find('#d1').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "default",
    "name": "can default of-expression properties",
    "html": "<div id='d1' _=\\\"on click default foo of me to 'bar' then put my foo into me\\\"></div>",
    "action": "find('#d1').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "default",
    "name": "can default array elements",
    "html": "<div id=\"el\" _=\"on click set arr to [null, null] then default arr[0] to 'yes' then put arr[0] into me\"></div>",
    "action": "find('div').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "default",
    "name": "default array element respects existing value",
    "html": "<div id=\"el\" _=\"on click set arr to ['existing', null] then default arr[0] to 'new' then put arr[0] into me\"></div>",
    "action": "find('div').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "default",
    "name": "default preserves zero",
    "html": "<div id=\"el\" _='on click set x to 0 then default x to 10 then put x into me'></div>",
    "action": "find('div').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "default",
    "name": "default overwrites empty string",
    "html": "<div id=\"el\" _='on click set x to \"\" then default x to \"fallback\" then put x into me'></div>",
    "action": "find('div').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "default",
    "name": "default preserves false",
    "html": "<div id=\"el\" _='on click set x to false then default x to true then put x into me'></div>",
    "action": "find('div').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "default",
    "name": "can default style ref when unset",
    "html": "<div id=\"el\" _=\"on click default *background-color to 'red'\"></div>",
    "action": "find('div').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "default",
    "name": "default style ref preserves existing value",
    "html": "<div id=\"el\" style=\"color: blue\" _=\"on click default *color to 'red'\"></div>",
    "action": "find('div').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "hide",
    "name": "can filter hide via the when clause",
    "html": "<div id='trigger' _='on click hide <div/> in me when it matches .hideable'>  <div id='d1' class='hideable'></div>  <div id='d2'></div></div>",
    "action": "find('#trigger').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "increment",
    "name": "can increment an array element",
    "html": "<div id=\"el\" _=\"on click set arr to [10, 20, 30] then increment arr[1] then put arr[1] into me\"></div>",
    "action": "find('div').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "increment",
    "name": "can decrement an array element",
    "html": "<div id=\"el\" _=\"on click set arr to [10, 20, 30] then decrement arr[1] then put arr[1] into me\"></div>",
    "action": "find('div').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "increment",
    "name": "can increment a possessive property",
    "html": "<div id=\"d1\" _=\"on click increment #d1's innerHTML\">5</div>",
    "action": "find('#d1').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "increment",
    "name": "can increment a property of expression",
    "html": "<div id=\"d1\" _=\"on click increment innerHTML of #d1\">5</div>",
    "action": "find('#d1').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "increment",
    "name": "can increment a style ref",
    "html": "<div id=\"el\" _=\"on click set my *opacity to 0.5 then increment *opacity by 0.25 then put *opacity into me\"></div>",
    "action": "find('div').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "js",
    "name": "handles rejected promises without hanging",
    "html": "<div id=\"el\" _='on click js return Promise.reject(\\\"boom\\\") end catch e put e into my.innerHTML'></div>",
    "action": "find('div').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "put",
    "name": "put null into attribute removes it",
    "html": "<div id='d1' foo='bar' _='on click put null into @foo'></div>",
    "action": "find('#d1').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "remove",
    "name": "can filter class removal via the when clause",
    "html": "<div id='trigger' _='on click remove .highlight from .item when it matches .old'></div><div id='d1' class='item old highlight'></div><div id='d2' class='item highlight'></div>",
    "action": "find('#trigger').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "repeat",
    "name": "basic raw for loop with null works",
    "html": "<div id=\"el\" _='on click for x in null                                    put x at end of me                                  end'></div>",
    "action": "find('div').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "repeat",
    "name": "basic property for loop works",
    "html": "<div id=\"el\" _='on click set x to {foo:1, bar:2, baz:3}                 for prop in x                    put x[prop] at end of me                 end'></div>",
    "action": "find('div').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "repeat",
    "name": "bottom-tested repeat until",
    "html": "<div id=\"el\" _='on click set x to 0                  repeat                    set x to                  until x is 3 end                  put x into me'></div>",
    "action": "find('div').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "repeat",
    "name": "bottom-tested repeat while",
    "html": "<div id=\"el\" _='on click set x to 0                  repeat                    set x to                  while x < 3 end                  put x into me'></div>",
    "action": "find('div').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "repeat",
    "name": "bottom-tested loop always runs at least once",
    "html": "<div id=\"el\" _='on click set x to 0                  repeat                    set x to                  until true end                  put x into me'></div>",
    "action": "find('div').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "repeat",
    "name": "break exits a simple repeat loop",
    "html": "<div id=\"el\" _=\"on click\n\t\t\t\tset x to 0\n\t\t\t\trepeat 10 times\n\t\t\t\t\tset x to x + 1\n\t\t\t\t\tif x is 3 break end\n\t\t\t\tend\n\t\t\t\tput x into me\n\t\t\t\"></div>",
    "action": "find('div').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "repeat",
    "name": "continue skips rest of iteration in simple repeat loop",
    "html": "<div id=\"el\" _=\"on click\n\t\t\t\trepeat for x in [1, 2, 3, 4, 5]\n\t\t\t\t\tif x is 3 continue end\n\t\t\t\t\tput x at end of me\n\t\t\t\tend\n\t\t\t\"></div>",
    "action": "find('div').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "repeat",
    "name": "break exits a for-in loop",
    "html": "<div id=\"el\" _=\"on click\n\t\t\t\trepeat for x in [1, 2, 3, 4, 5]\n\t\t\t\t\tif x is 4 break end\n\t\t\t\t\tput x at end of me\n\t\t\t\tend\n\t\t\t\"></div>",
    "action": "find('div').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "repeat",
    "name": "break exits a while loop",
    "html": "<div id=\"el\" _=\"on click\n\t\t\t\tset x to 0\n\t\t\t\trepeat while x < 100\n\t\t\t\t\tset x to x + 1\n\t\t\t\t\tif x is 5 break end\n\t\t\t\tend\n\t\t\t\tput x into me\n\t\t\t\"></div>",
    "action": "find('div').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "repeat",
    "name": "for loop over undefined skips without error",
    "html": "<div id=\"el\" _='on click repeat for x in doesNotExist put x at end of me end then put \\\"done\\\" into me'></div>",
    "action": "find('div').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "settle",
    "name": "can settle a collection of elements",
    "html": "<div class='item'></div><div class='item'></div><div id='trigger' _='on click settle <.item/> then add .done to <.item/>'></div>",
    "action": "find('#trigger').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "show",
    "name": "the result in a when clause refers to previous command result, not element being tested",
    "html": "<div _=\\\"on click   get 'found'   show <span/> in me when the result is 'found'\\\"><span id='s1' style='display:none'>A</span><span id='s2' style='display:none'>B</span></div>",
    "action": "find('div').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "show",
    "name": "the result after show...when is the matched elements",
    "html": "<div _=\\\"on click   show <p/> in me when its textContent is 'yes'   if the result is empty put 'none' into #out   else put 'some' into #out\\\"><p style='display:none'>yes</p><p style='display:none'>no</p><span id='out'>--</span></div>",
    "action": "find('div').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "toggle",
    "name": "can toggle visibility",
    "html": "<div id=\"el\" _='on click toggle *visibility'></div>",
    "action": "find('div').dispatchEvent('click'); find('div').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "toggle",
    "name": "can toggle opacity w/ my",
    "html": "<div id=\"el\" _='on click toggle my *opacity'></div>",
    "action": "find('div').dispatchEvent('click'); find('div').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "toggle",
    "name": "can toggle visibility w/ my",
    "html": "<div id=\"el\" _='on click toggle my *visibility'></div>",
    "action": "find('div').dispatchEvent('click'); find('div').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "toggle",
    "name": "can toggle *display between two values",
    "html": "<div id=\"el\" style='display:none' _=\\\"on click toggle *display of me between 'none' and 'flex'\\\"></div>",
    "action": "find('div').dispatchEvent('click'); find('div').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "toggle",
    "name": "can toggle *opacity between three values",
    "html": "<div id=\"el\" style='opacity:0' _=\\\"on click toggle *opacity of me between '0', '0.5' and '1'\\\"></div>",
    "action": "find('div').dispatchEvent('click'); find('div').dispatchEvent('click'); find('div').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "on",
    "name": "caught exceptions do not trigger 'exception' event",
    "html": "<button id=\"el\" _='on click put \\\"foo\\\" into me then throw \\\"bar\\\"                     catch e log e                  on exception(error) put error into me'></button>",
    "action": "find('button').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "on",
    "name": "rethrown exceptions trigger 'exception' event",
    "html": "<button id=\"el\" _='on click put \\\"foo\\\" into me then throw \\\"bar\\\"                     catch e throw e                  on exception(error) put error into me'></button>",
    "action": "find('button').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "on",
    "name": "can ignore when target doesn\\'t exist",
    "html": "<div id=\"el\" _=' \ton click from #doesntExist \t\tthrow \\\"bar\\\" \ton click \t\tput \\\"clicked\\\" into me\t'></div>",
    "action": "find('div').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "parser",
    "name": "can have comments in attributes (triple dash)",
    "html": "<div id=\"el\" _='on click put \\\"clicked\\\" into my.innerHTML ---put some content into the div...'></div>",
    "action": "find('div').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "parser",
    "name": "element-level isolation still works with error recovery",
    "html": "<div><div id='d1' _='on click blargh end on mouseenter also_bad'></div><div id='d2' _='on click put \\\"clicked\\\" into my.innerHTML'></div></div>",
    "action": "find('#d2').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "scoping",
    "name": "element scoped variables span features w/short syntax",
    "html": "<div id='d1' _='on click 1 set :x to 10                        on click 2 set @out to :x'></div>",
    "action": "find('#d1').dispatchEvent('click'); find('#d1').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "closest",
    "name": "closest does not consume a following where clause",
    "html": "<table><tr><td><input type='checkbox' class='cb'><input type='checkbox' class='cb'><input id='master' type='checkbox' _=\\\"set :others to <input[type=checkbox]/> in the closest <table/> where it is not me on click put :others.length into #out\\\"></td></tr></table><div id='out'></div>",
    "action": "find('#master').click()",
    "checks": [],
    "async": true
  },
  {
    "category": "comparisonOperator",
    "name": "is a works with instanceof fallback",
    "html": "<div id='d1' _='on click if I am a Element put \\\"yes\\\" into me'></div>",
    "action": "find('#d1').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "comparisonOperator",
    "name": "is a Node works via instanceof",
    "html": "<div id='d1' _='on click if I am a Node put \\\"yes\\\" into me'></div>",
    "action": "find('#d1').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "comparisonOperator",
    "name": "is not a works with instanceof fallback",
    "html": "<div id='d1' _='on click if \\\"hello\\\" is not a Element put \\\"yes\\\" into me'></div>",
    "action": "find('#d1').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "comparisonOperator",
    "name": "I precede works",
    "html": "<div id='a' _=\\\"on click if I precede #b put 'yes' into me\\\"></div><div id='b'></div>",
    "action": "find('#a').dispatchEvent('click')",
    "checks": [],
    "async": true
  },
  {
    "category": "no",
    "name": "no with where on DOM elements",
    "html": "<div id='box'><span class='a'>A</span><span class='b'>B</span></div><button _=\\\"on click if no <span/> in #box where it matches .c then put 'none' into #out else put 'found' into #out\\\">go</button><div id='out'></div>",
    "action": "find('button').click()",
    "checks": [],
    "async": true
  }
];
