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

cynic

v0.2.1

Published

async testing framework for es-modules

Downloads

545

Readme

🧐 cynic

async testing framework for es modules

  • cynic is designed to be dirt-simple, because i'm sick of overcomplicated testing frameworks
  • the test suites are just nested async functions
  • the whole framework is just simple es modules that run anywhere: node, browser, puppeteer, deno
  • no magic assumptions are made about or foisted onto the environment: the assertion library and everything else is just simply imported like from any other module
  • examples here are shown in typescript, but of course you can use vanilla js

let's get cynical, and make a damn test suite!

  1. install cynic into your project

    npm install --save-dev cynic
  2. write a test suite, example.test.ts

    import {Suite, assert, expect} from "cynic"
    
    export default <Suite>{
      "alpha system": {
        "can sum two numbers (boolean return)": async() => {
          const a = 1
          const b = 2
          // no assertion library required:
          // simply returning false, or throwing, will fail a test
          return (a + b) === 3
        },
        "can sum three numbers (assert)": async() => {
          const a = 1
          const b = 2
          const c = 3
          // benefits of 'assert'
          //  - you get a stack trace
          //  - you can provide a custom message for each failure
          assert((a + b + c) === 6, `sum is wrong`)
        }
      },
      "bravo system": {
        "can multiply numbers (expect)": async() => {
          const a = 2
          const b = 3
          // benefits of 'expect'
          //  - you get a stack trace
          //  - cynic tries to invent a message about the failure
          expect(a * b).equals(6)
          expect(a * b * a).equals(12)
        }
      }
    }

now run it!

  • you can run the suite file through the cynic cli

    # run your tests in node
    cynic node example.test.js
    
    # run your tests in browser
    cynic browser example.test.js
    
    # run your tests in puppeteer (headless browser)
    cynic puppeteer example.test.js
    
    # use node debugger
    node inspect node_modules/cynic/dist/cli.js node example.test.js

    cynic executes the default export as a test suite

    optional arguments for all runtimes:

    • --label="test suite" — the report title

    optional arguments for browser and puppeteer runtimes:

    • --open=false — true to prompt open your default browser
    • --port=8021 — run the server on a different port
    • --origin="http://localhost:8021" — connect to the server via an alternative url (mind the port number!)
    • --cynic-path=node_modules/cynic — use an alternative path to the cynic library's root
    • --importmap-path=./dist/importmap.json — provide an import map for your test suites

    if puppeteer isn't running properly, see puppeteer's troubleshooting.md

  • or you can just execute your test suite, manually, anywhere

    this should work anywhere you can import an es module

    import {test} from "cynic"
    import suite from "./example.test.js"
    
    ;(async() => {
    
      // run the test suite
      const {report, ...stats} = await test("example suite", suite)
    
      // emit the report text to console
      console.log(report)
    
      // handle results programmatically
      if (stats.failed === 0) console.log("done")
      else console.log("failed!")
    
      // returns stats about the test run results
      console.log(stats)
    
    })()

    see which stats are available in the Stats interface in types.ts

so what do the console reports look like?

  • report: successful run

    cynic example suite
      
      ▽ examples
        ▽ alpha system
          ✓ can sum two numbers (boolean return)
          ✓ can sum three numbers (assertion)
        ▽ bravo system
          ✓ can multiply numbers (expectation)
      
    0 failed tests
    0 thrown errors
    3 passed tests
    3 total tests
    0.00 seconds
  • report: a test returns false
    return false to indicate a failed test

    cynic example suite
      
      ▽ examples
        ▽ alpha system
      
    ═════ ✘ can sum two numbers (boolean return)
      
        ▽ bravo system
    
    ✘ can sum two numbers (boolean return) — failed
    
    1 FAILED tests
    0 thrown errors
    2 passed tests
    3 total tests
    0.00 seconds
  • report: a test throws
    a thrown string or error will be shown as the failure reason

    cynic example suite
    
      ▽ examples
        ▽ alpha system
    
    ═════ ✘ can sum two numbers (boolean return)
    ――――――― arithmetic failed for interesting reasons
    
        ▽ bravo system
    
    ✘ can sum two numbers (boolean return) — arithmetic failed for interesting reasons
    
    1 FAILED tests
    1 thrown errors
    2 passed tests
    3 total tests
    0.00 seconds
  • report: a test fails an assertion
    assertions will display a stack trace, and optional custom message

    cynic example suite
    
      ▽ examples
        ▽ alpha system
      
    ═════ ✘ can sum three numbers (assertion)
    ――――――― CynicBrokenAssertion: sum is wrong
              at assert (file:///work/cynic/dist/assert.js:7:15)
              at can sum three numbers (assertion) (file:///work/cynic/dist/internals/example.test.js:13:20)
              at execute (file:///work/cynic/dist/internals/execute.js:13:34)
              [...]
    
        ▽ bravo system
    
    ✘ can sum three numbers (assertion) — CynicBrokenAssertion: sum is wrong
    
    1 FAILED tests
    1 thrown errors
    2 passed tests
    3 total tests
    0.00 seconds
  • report: a test fails an expectation
    stack trace is provided, and a failure reason is generated automatically

    cynic example suite
      
      ▽ examples
        ▽ alpha system
        ▽ bravo system
    
    ═════ ✘ can multiply numbers (expectation)
    ――――――― CynicBrokenExpectation: expect(7).equals(6): not equal, should be
              at composite (file:///work/cynic/dist/expect.js:46:19)
              at Object.equals (file:///work/cynic/dist/expect.js:25:125)
              at can multiply numbers (expectation) (file:///work/cynic/dist/internals/example.test.js:20:39)
              at execute (file:///work/cynic/dist/internals/execute.js:13:34)
              [...]
    
    ✘ can multiply numbers (expectation) — CynicBrokenExpectation: expect(7).equals(6): not equal, should be
    
    1 FAILED tests
    1 thrown errors
    2 passed tests
    3 total tests
    0.00 seconds

hot tips for big brains

  • use object nesting to group and organize tests arbitrarily

    import {Suite} from "cynic"
    export default <Suite>{
      "nested tests": {
        "more nested": {
          "exceedingly nested": {
            "it works": async() => true
          }
        }
      }
    }
  • you can just throw strings as assertions

    import {Suite} from "cynic"
    export default <Suite>{
      "assertions and expectations": async() => {
        const example = "abc"
    
        // let's call it "the spartan assertion"
        if (!example.includes("b"))
          throw `expected example to include "b"`
    
        return true
      }
    }
  • or you can use the handy assert function to do that, you get stack traces

    import {Suite, assert} from "cynic"
    export default <Suite>{
      "using 'assert'": async() => {
        const example = "abc"
        assert(example === "abc", `example must equal "abc"`)
        assert(example.includes("b"), `example should include "b"`)
      }
    }
  • or you can also use the experimental new expect api, you get auto-generated messages and stack traces

    import {Suite, expect} from "cynic"
    export default <Suite>{
      "using 'expect'": async() => {
        const example = "abc"
        expect(example).defined()
        expect(example).equals("abc")
      }
    }
  • a suite or test can return another suite or test — easy setups!

    export default <Suite>(async() => {
    
      // doing some async setup
      const myFile = await loadFile("myfile.json")
    
      // returning more tests
      return {
        "group of tests": {
          "my file exists": async() => {
            return !!myFile
          }
        }
      }
    })

food for thought

  • 🥃 chase moskal made this with open source love. please contribute!