npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

run-dom-tests

v2.0.1

Published

Run mocha tests on node.js using a virtual DOM.

Downloads

17

Readme

run-dom-tests

Run mocha + chai + chai-dom tests on node.js using a virtual DOM.

Install

npm install -g run-dom-tests
run-dom-tests test.json

JSON file format: { html, tests }

Test

npm test

Usage sample

Document testing

You can make assertions about the document, both based on its plain, static structure - _originalDocument_ - or its dynamic structure document. For example, given the following HTML...

<html>
  <head>
    <script>
      function insertSection() {
        const secondDiv = document.getElementById("second");
        const section = document.createElement("section");
        document.body.insertBefore(section, secondDiv);
      }
      document.getElementById("insert-section").addEventListener("click", insertSection);
      insertSection();
    </script>
  </head>
  <body>
    <p id="first">
    This is a paragraph
    </p>

    <button id="insert-section">Insert a new section</button>

    <p id="second">
    This is another paragraph
    </p>
  </body>
</html>

...you can write the following tests:

describe("DOM API", function() {
  // you can validate the static structure of the DOM...
  context("static dom", () => {

    // ...both using plain chai https://www.chaijs.com/ assertions...
    it("works with plain assertions", () => {
      _originalDocument_.getElementsByTagName("p").length.should.eql(2);
      document.getElementsByTagName("p").length.should.eql(2);
    })

    // ...or chai-dom https://www.chaijs.com/plugins/chai-dom/ assertions:
    it("works with mocha-chai assertions", () => {
      _originalDocument_.body.should.contain("p");
      _originalDocument_.body.should.not.contain("section");
      document.getElementsByTagName("p").should.have.length(2);
      document.getElementById("first").should.exist;
      document.getElementById("first").should.have.trimmed.text("This is a paragraph");
    })
  })

  // you can also validate the
  // dynamic structure of the DOM just after the initial script tags execution
  describe("script tags", () => {
    it("inserts dom elements", () => {
      _originalDocument_.getElementsByTagName("section").should.have.length(0);
      document.getElementsByTagName("section").should.have.length(1);
    });
  })

  // finally you can interact with the dynamic dom
  // through events and make assertions about them
  describe("event handlers", () => {
    beforeEach(() => {
      // if your test mutates the DOM
      // you will need to reset document to a fresh state
      // before each test
      _resetDocument_();
    });

    it("inserts dom elements after a single event", () => {
      const button = document.getElementById("insert-section");

      _dispatch_("click", button);

      document.getElementsByTagName("section").should.have.length(2);
    });

    it("inserts dom elements after multiple events", () => {
      const button = document.getElementById("insert-section");

      _dispatch_("click", button);
      _dispatch_("click", button);
      _dispatch_("click", button);

      document.getElementsByTagName("section").should.have.length(4);
    });
  });
});

User interactions testing

User interactions like alert and prompt can be tested by stubbing user responses using _stubXxxResponse_ and checking prompted messages with _shiftXxxMessage_.

For example given the following HTML document...

<html>
  <head>
    <title>events</title>
  </head>
  <body>
    <button id="prompt-and-alert">Prompt and Alert</button>
    <button id="confirm-and-alert">Confirm and Alert</button>
    <script>
      document.querySelector("#prompt-and-alert").addEventListener("click", () => {
        let name = prompt("Please tell us who you are");
        alert("Hello " + name);
      });
      document.querySelector("#confirm-and-alert").addEventListener("click", () => {
        let result = confirm("Are you really sure?");
        if (result) {
          alert("Yay");
        } else {
          alert("Boo");
        }
      });
    </script>
  </body>
</html>

...you can write the following user interaction tests:

describe("User interactions", () => {
  beforeEach(() => {
    // call before each test in
    // order to clear user interactions registered and tested
    // through _stubXxxResponse_ and _shiftXxxMessage_
    _resetUserInteractions_();

    // if you also need to reset the document state
    // you can call `_resetDocument_()`
  })

  it("allows stubbing sequential confirm interaction", function() {
    // stub responses before calling the code
    _stubConfirmResponse_(false);
    _stubConfirmResponse_(true);

    // fire the actual code
    // by simulating events
    _dispatch_("click", document.querySelector("#confirm-and-alert"));
    _dispatch_("click", document.querySelector("#confirm-and-alert"));

    // run assertions
    _alertMessagesCount_().should.eql(2);
    _confirmMessagesCount_().should.eql(2);

    "Are you really sure?".should.eql(_shiftConfirmMessage_());
    "Boo".should.eql(_shiftAlertMessage_());
    "Are you really sure?".should.eql(_shiftConfirmMessage_());
    "Yay".should.eql(_shiftAlertMessage_());

    _alertMessagesCount_().should.eql(0);
    _confirmMessagesCount_().should.eql(0);
  });

  it("allows stubbing sequential prompt interaction", function() {
    // stub responses before calling the code
    _stubPromptResponse_("Node");
    _stubPromptResponse_("Mumuki");
    _stubPromptResponse_("JS");

    // fire the actual code
    // by simulating events
    _dispatch_("click", document.querySelector("#prompt-and-alert"));
    _dispatch_("click", document.querySelector("#prompt-and-alert"));
    _dispatch_("click", document.querySelector("#prompt-and-alert"));

    // run assertions
    _alertMessagesCount_().should.eql(3);
    _promptMessagesCount_().should.eql(3);

    "Hello Node".should.eql(_shiftAlertMessage_());
    "Hello Mumuki".should.eql(_shiftAlertMessage_());
    "Hello JS".should.eql(_shiftAlertMessage_());

    _alertMessagesCount_().should.eql(0);
    _promptMessagesCount_().should.eql(3);
  });
});

HTTP interactions testing

HTTP Interaction tests are are built on top of nock, using the _nock_ object.

Given the following HTML document...

<html>
  <head>
    <title>ajax</title>
    <script>
      document.addEventListener("DOMContentLoaded", () => {
        document.querySelector("#get-data").addEventListener("click", () => {
          fetch("https://some-domain.com/some-data.json")
            .then((response) => {
              return response.json();
            })
            .then((data) => {
              document.querySelector("#data").innerHTML = data.content;
            });
        });
      });
    </script>
  </head>
  <body>
    <div>
      <button id="get-data">GET DATA NOW!</button>
    </div>

    <h1>Remote data:</h1>
    <pre id="data">Nothing yet...</pre>
  </body>
</html>

...you can write the following HTTP interaction tests:

describe("HTTP Interactions", function() {
  beforeEach(() => {
    // resets all user interactions,
    // dom state and http interactions
    _resetAll_();

    // if only http interactions need to be reseted,
    // call _resetHttpInteractions_() instead
  });

  it("shows the downloaded content when the button is clicked", function(done) {
    document.querySelector("#data").innerHTML.should.eql("Nothing yet...");

    const mockedGet = _nock_("https://some-domain.com/")
      .get("/some-data.json")
      .reply(200, { content: "Some remote data" });

    _dispatch_('click', document.querySelector("#get-data"));

    _waitFor_(() => mockedGet.isDone(), () => {
      document.querySelector("#data").innerHTML.should.eql("Some remote data");
      done();
    });
  });
});

Reference

Members

Constants

Functions

_nock_

nock object for mocking http interactions

Kind: global variable See: https://github.com/nock/nock

_waitFor_

Waits for a condition to occur, and then executes an action. This function will check for the condition with a period of WAIT_FOR_TIMEOUT.

Kind: global variable See: WAIT_FOR_TIMEOUT

| Param | Type | Description | | --- | --- | --- | | condition | function | the condition to wait | | action | function | the action to execute |

~~oldDocument~~

Deprecated

Kind: global variable

_originalDocument_ : HTMLDocument

The original HTML document, before any JavaScript actions are executed

Kind: global variable

WAIT_FOR_TIMEOUT : number

Polling period of _waitFor_

Kind: global constant

~~_wait_for_()~~

Deprecated

Kind: global function

_dispatch_(type, node)

Simulates the dispatch of an event of the given type to the given node

Kind: global function

| Param | Type | Description | | --- | --- | --- | | type | string | the event type, such as click or DOMContentLoaded | | node | HTMLElement | the simulated event target. document by default |

_stubConfirmResponse_(response)

Enqueues an stubbed confirm window response message.

This function must be called in order, before the first alert confirm is performed

Kind: global function

| Param | Type | Description | | --- | --- | --- | | response | string | the stubbed response of the confirm window |

_stubPromptResponse_(response)

Enqueues an stubbed a prompt window response message

This function must be called in order, before the first alert prompt is performed

Kind: global function

| Param | Type | Description | | --- | --- | --- | | response | string | the stubbed response of the prompt window |

_shiftAlertMessage_() ⇒ string

Dequeues the first pending alert message to check.

Subsequent calls to this function will produce different results. When there are no more alert messages to dequeue, undefined is returned

Kind: global function Returns: string - the first pending alert message

_shiftConfirmMessage_() ⇒ boolean

Dequeues the first pending confirm message to check.

Subsequent calls to this function will produce different results. When there are no more confirm messages to dequeue, undefined is returned

Kind: global function Returns: boolean - the first pending confirm message

_shiftPromptMessage_() ⇒ string

Dequeues the first pending prompt message to check.

Subsequent calls to this function will produce different results. When there are no more prompt messages to dequeue, undefined is returned

Kind: global function Returns: string - the first pending prompt message

_alertMessagesCount_() ⇒ number

Answers the number of the pending alert message to check

Kind: global function Returns: number - the pending messages count to check

_confirmMessagesCount_() ⇒ number

Answers the number of the pending confirm message to check

Kind: global function Returns: number - the pending messages count to check

_promptMessagesCount_() ⇒ number

Answers the number of the pending prompt message to check

Kind: global function Returns: number - the pending messages count to check

_resetUserInteractions_()

Reset all stubs and messages

Kind: global function

_resetHttpInteractions_()

Reset nock state

Kind: global function

_resetDocument_()

Resets the document to its original state, discarding every document polyfill and then runs its scripts again.

window is not cleared.

Kind: global function

_resetAll_()

Resets the document, interactions and nock state

Kind: global function