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

@marko/testing-library

v6.2.0

Published

Simple and complete Marko testing utilities that encourage good testing practices.

Downloads

1,657

Readme

Table of Contents

The problem

You want to write maintainable tests for your Marko components. As a part of this goal, you want your tests to avoid including implementation details of your components and rather focus on making your tests give you the confidence for which they are intended. As part of this, you want your testbase to be maintainable in the long run so refactors of your components (changes to implementation but not functionality) don't break your tests and slow you and your team down.

This solution

The @marko/testing-library is a very lightweight solution for testing Marko components. It provides light utility functions on top of @testing-library/dom in a way that encourages better testing practices. Its primary guiding principle is:

The more your tests resemble the way your software is used, the more confidence they can give you.

Installation

npm install --save-dev @marko/testing-library

You may also be interested in installing jest-dom so you can use the custom jest matchers. Or if using another test runner like mocha you could check out chai-dom.

API

Marko testing library exposes all of the same utilities for querying the dom, firing events and testing asynchronous behavior as @testing-library/dom. This module only exposes two additional APIs to make testing against your components easier.

render(template, input?, { container }?)

This funcition renders your template asynchronously and provides you with query helpers that are scoped to output DOM.

import { render, screen } from "@marko/testing-library";
import HelloTemplate from "./src/__test__/fixtures/hello-name.marko";

test("contains the text", async () => {
  const { rerender } = await render(HelloTemplate, {
    name: "World",
  });

  // Will find the element within the rendered result from the template.
  expect(screen.getByText("Hello World")).toBeInTheDocument();

  // You can also rerender the component if needed.
  await rerender({ name: "Marko" });

  expect(screen.getByText("Hello Marko")).toBeInTheDocument();
});

The render result will also provide you with a container HTMLElement. This acts as an escape hatch and allows you to test your components going against the guiding principles. With the container you can grab any element using querySelector or other means that mean nothing to your users.

test("not a great test", async () => {
  const { container } = await render(HelloTemplate, { name: "World" });

  expect(container.querySelector("div")).toBeInTheDocument();
});

The problem with the above test is that your user does not care about or see that there is a div element, the user only see's the text content of the div. Maybe it turns out that a div wasn't the best element and we should switch to an h1? Now your tests are broken, even though there is likely no perceptable change to the user.

cleanup()

With client side tests your components are rendered into a placeholder HTMLElement. You can call cleanup at any time to destroy any attached components and remove them from the DOM.

import { cleanup, screen } from "@marko/testing-library";
import HelloTemplate from "./src/__test__/fixtures/hello-name.marko";

test("contains the text", async () => {
  await render(HelloTemplate, { name: "World" });

  expect(screen.getByText("Hello World")).toBeInTheDocument();

  cleanup();

  expect(screen.queryByText("Hello Marko")).toBeNull();
});

By default if your testing framework exposes an afterEach hook (such as jest and mocha) then cleanup will be automatically invoked after each of your tests run.

If you'd like to disable the automatic cleanup behavior described above you can import @marko/testing-library/dont-cleanup-after-each.

import "@marko/testing-library/dont-cleanup-after-each";

With mocha you can use mocha -r @marko/testing-library/dont-cleanup-after-each as a shorthand.

If you are using Jest, you can include setupFilesAfterEnv: ["@marko/testing-library/dont-cleanup-after-each"] in your Jest config to avoid doing this in each file.

normalize()

Returns a clone of the passed DOM container with Marko's internal markers removed (data-marko, etc.), id's and whitespace are also normalized.

import { render, normalize } from "@marko/testing-library";
import HelloTemplate from "./src/__test__/fixtures/hello-name.marko";

test("snapshot", async () => {
  const { container } = await render(HelloTemplate, { name: "World" });

  expect(normalize(container)).toMatchSnapshot();
});

Setup

Marko testing library is not dependent on any test runner, however it is dependent on the test environment. These utilities work for testing both server side, and client side Marko templates and provide a slightly different implementation for each. This is done using a browser shim, just like in Marko.

The browser shim is picked up by many tools, including all bundlers and some test runners.

Below is some example configurations to test both server and browser components with some popular test runners.

Jest

For Jest to understand Marko templates you must first install the @marko/jest preset. This allows your Marko templates to be imported into your tests.

To test components rendered in the client side, be sure to use the @marko/jest/preset/browser jest preset and you are good to go!

jest.config.js

module.exports = {
  preset: "@marko/jest/preset/browser",
};

If you'd like to test components using server side rendering you can instead use the @marko/jest/preset/node jest preset.

jest.config.js

module.exports = {
  preset: "@marko/jest/preset/node",
};

A Jest configuration can also have multiple projects which we can use to create a combined configuration for server side tests, and browser side tests, like so:

jest.config.js

module.exports = {
  projects: [
    {
      displayName: "server",
      preset: "@marko/jest/preset/node",
      testRegex: "/__tests__/[^.]+\\.server\\.js$",
    },
    {
      displayName: "browser",
      preset: "@marko/jest/preset/browser",
      testRegex: "/__tests__/[^.]+\\.browser\\.js$",
    },
  ],
};

Mocha

Mocha also works great for testing Marko components. Mocha, however, has no understanding of browser shims which means out of the box it can only work with server side Marko components.

To run server side Marko tests with mocha you can simply run the following command:

mocha -r marko/node-require

This enables the Marko require hook and allows you to require server side Marko templates directly in your tests.

For client side testing of your components with Mocha often you will use a bundler to build your tests (this will properly resolve the browser shims mentioned above) and then you can load these tests in some kind of browser context.

Guiding Principles

[The more your tests resemble the way your software is used, the more confidence they can give you.][https://testing-library.com/docs/guiding-principles]

We try to only expose methods and utilities that encourage you to write tests that closely resemble how your Marko components are used.

Utilities are included in this project based on the following guiding principles:

  1. If it relates to rendering components, then it should deal with DOM nodes rather than component instances, and it should not encourage dealing with component instances.
  2. It should be generally useful for testing the application components in the way the user would use it. We are making some trade-offs here because we're using a computer and often a simulated browser environment, but in general, utilities should encourage tests that use the components the way they're intended to be used.
  3. Utility implementations and APIs should be simple and flexible.

At the end of the day, what we want is for this library to be pretty light-weight, simple, and understandable.

Docs

Read The Docs | Edit the docs

Code of Conduct

This project adheres to the eBay Code of Conduct. By participating in this project you agree to abide by its terms.