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

cypress-pipe

v2.0.0

Published

Create custom commands using plain-old functions

Downloads

343,566

Readme

Cypress Pipe

cy.pipe can be used as a simpler replacement for Cypress Custom Commands - you just write functions.

cy.pipe works very similarly to cy.then except for a few key differences:

  • pipe will try to document the function name in the Command log (only works on named functions)
  • pipe will create DOM snapshots to aid in debugging
  • If the function passed to pipe resolves synchronously (doesn't contain Cypress commands)
    • AND returns a jQuery element, pipe will retry until the jQuery element list is not empty (most Cypress commands do this)
    • AND is followed by a cy.should, the function will be retried until the assertion passes or times out (most Cypress commands do this)
const obj = { foo: 'bar' }
const getFoo = s => s.foo
setTimeout(() => { obj.foo = 'baz' }, 1000)

cy.wrap(obj)
  .pipe(getFoo)
  .should('equal', 'baz')

The above assertion will pass after 1 second. The Cypress Command Log will look like:

WRAP       {foo: bar}
 - PIPE    getFoo
 - ASSERT  expected bar to equal bar

If the pipe was using a then, it would fail immediately and wouldn't show the getFoo functions anywhere in the Cypress Command Log.

If you care even more about log output and you have more generic functions that curry other functions, you can use loggable. That sounds scary, but you might have a function like getTodoByName where the function takes the name of the Todo and returns a function that takes a container. For example:

import { loggable } from 'cypress-pipe'

const getProp = loggable('getProp', prop => obj => obj[prop])
// alternative
const getProp = loggable(prop => function getProp(obj) { return obj[prop] })

cy.wrap({ foo: 'bar' })
  .pipe(getProp('foo'))
  .should('equal', 'bar')

The loggable decorator function can either take a name as a string, or allow .pipe to get it from a named currried function.

The Cypress Log will look like:

WRAP       {foo: bar}
 - PIPE    getProp("foo")
 - ASSERT  expected bar to equal bar

This library is a proof of concept, but should be stable. The proposal can be found here: https://github.com/cypress-io/cypress/issues/1548

Best Practices

Use synchronous functions when possible

Synchronous functions can be retried, async functions cannot. Retrying allows implicit waiting which avoids confusing flaky failures where tests are dependant on timing.

// bad
// The `cy.*` command inside the function prevents automatic retries. The following will actually fail if the text `'foobar'` isn't immediately available in the DOM
const getFirst = $el => cy.wrap($el).find('#first')

cy.get('body')
  .pipe(getFirst)
  .should('contain', 'foobar')

// good
// synchronous resolution - pipe will retry `getFirst` until it returns a non-empty jQuery element list and contains the text 'foobar'
const getFirst = $el => $el.find('#first')

cy.get('body')
  .pipe(getFirst)
  .should('contain', 'foobar')

Use cy commands for actions

pipe detects the use of Cypress commands and assumes side effects. It will take a 'before' and 'after' snapshots. 'before' is taken before any code is run. 'after' is taken at the end after the function is complete. For action helpers, this makes for a nice before/after snapshots. pipe doesn't prevent logging of Cypress commands from within a function (which can be confusing). If Cypress supports Command Log Grouping, pipe could invoke to have perfect logging.

const submitForm = $el => cy.wrap($el).find('#submit').click()

cy.get('form')
  .pipe(submitForm) // has before/after of submitting form

// Command Log:
// GET        <form>
//  -PIPE     submitForm
//  -WRAP     <form>
//  -FIND     #submit
//  -CLICK

Name functions

Don't use anonymous functions and pick short and descriptive function names. The Command Log can be used as a tool for mapping the contents of a test to the screenshot/video. This is useful when finding out which step the test failed on.

// okay
cy.wrap({ foo: 'bar' })
  .pipe(s => s.foo)
  .should('equal', 'bar')

// Command Log:
// WRAP       {foo: bar}
//  -PIPE     function() {}
//  - ASSERT  expected 'bar' to equal 'bar'

// good
const getFoo = s => s.foo
cy.wrap({ foo: 'bar' })
  .pipe(getFoo)
  .should('equal', 'bar')

// Command Log:
// WRAP       {foo: bar}
//  -PIPE     getFoo
//  - ASSERT  expected 'bar' to equal 'bar'

If you have a function that returns another function (curried for extra input), name that.

// Name the returned curried function
const getProp = key => function getProp(s) {
  return s[key]
}

cy.wrap({ foo: 'bar' })
  .pipe(getProp('foo'))
  .should('equal', 'bar')

// Command Log:
// WRAP       {foo: bar}
//  -PIPE     getProp
//  - ASSERT  expected 'bar' to equal 'bar'

Here's a screenshot of a failure using cypress-pipe and loggable:

cypress-pipe failure

The code that produced this was:

const getFirst = $el => $el.find('#first')
const getSecond = loggable('getSecond', selector => $el => $el.find(selector))

cy.get('body')
  .pipe(getFirst)
  .pipe(getSecond('#second1'))
  .should('contain', 'foobar')

Pipe tries to add as much debugging information as possible.

Installation

npm install cypress-pipe -D

Add the following to your cypress/support/index file:

import 'cypress-pipe'