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

cavyy

v0.6.1

Published

An integration test framework for React Native.

Downloads

3

Readme

Cavy

npm version CircleCI

Cavy logo

Cavy is a cross-platform integration test framework for React Native, by Pixie Labs.

This README covers installing and setting up Cavy, writing Cavy tests and FAQs. For information on how to use Cavy's command line interface, check out cavy-cli.

Table of Contents

How does it work?

Cavy (ab)uses React ref generating functions to give you the ability to refer to, and simulate actions upon, deeply nested components within your application. Unlike a tool like enzyme which uses a simulated renderer, Cavy runs within your live application as it is running on a host device (e.g. your Android or iOS simulator).

CLI and continuous integration

By default, Cavy outputs test results to the console when your app runs. However, you can also run Cavy tests directly from the command line using Cavy's own command line interface - cavy-cli. Just set the sendReport prop on your <Tester> component to true (see below).

Further details on how you can use cavy-cli to fully automate your tests with continuous integration can be found in the cavy-cli README.

Where does it fit in?

We built Cavy because, at the time of writing, React Native had only a handful of testing approaches available:

  1. Unit testing components (Jest).
  2. Shallow-render testing components (enzyme).
  3. Testing within your native environment, using native JS hooks (Appium).
  4. Testing completely within your native environment (XCTest).

Cavy fits in between shallow-render testing and testing within your native environment.

Installation

To get started using Cavy, install it using yarn:

yarn add cavy --dev

or npm:

npm i --save-dev cavy

Usage

Check out the sample app for example usage. Here it is running:

Sample app running

1. Set up the Tester

Import Tester, TestHookStore and your specs in your top-level JS file (typically this is your index.{ios,android}.js files). Instantiate a new TestHookStore and render your app inside a Tester.

// index.ios.js

import React, { Component } from 'react';
import { Tester, TestHookStore } from 'cavy';
import AppSpec from './specs/AppSpec';
import App from './app';

const testHookStore = new TestHookStore();

export default class AppWrapper extends Component {
  render() {
    return (
      <Tester specs={[AppSpec]} store={testHookStore} waitTime={4000}>
        <App />
      </Tester>
    );
  }
}

Tester props

| Prop | Type | Description | Default | | :------------ |:---------------:| :--------------- | :---------------: | | specs (required) | Array | Your spec functions | - | | store (required) | TestHookStore | The newly instantiated TestHookStore component | - | | waitTime | Integer | Time in milliseconds that your tests should wait to find a component | 2000 | | startDelay | Integer | Time in milliseconds before test execution begins | 0 | | clearAsyncStorage | Boolean | If true, clears AsyncStorage between each test e.g. to remove a logged in user | false | | sendReport | Boolean | If true, Cavy sends a report to cavy-cli | false | | preventReRender | Boolean | If true, prevent Cavy from resetting between test cases | false |

2. Hook up components

Add a test hook to any components you want to test by adding a ref and using the generateTestHook function. Then export a hooked version of the parent component.

generateTestHook takes a string as its first argument - this is the identifier used in tests. It takes an optional second argument in case you also want to set your own ref generating function.

// src/Scene.js

import React, { Component } from 'react';
import { TextInput } from 'react-native';
import { hook } from 'cavy';

class Scene extends Component {
  render() {
    return (
      <View>
        <TextInput
          ref={this.props.generateTestHook('Scene.TextInput')}
          onChangeText={...}
        />
      </View>      
    );
  }
}

const TestableScene = hook(Scene);
export default TestableScene;

Note on functional components: Functional components cannot be assigned a ref since they don't have instances. We suggest using Recompose's toClass helper function to convert it to a class component first.

3. Write test cases

Write your spec functions referencing your hooked-up components. See below for a list of currently available spec helper functions.

// specs/AppSpec.js

export default function(spec) {
  spec.describe('My feature', function() {
    spec.it('works', async function() {
      await spec.fillIn('Scene.TextInput', 'some string')
      await spec.press('Scene.button');
      await spec.exists('NextScene');
    });
  });
}

Congratulations! You are now all set up to start testing your app with Cavy. Your tests will run automatically when you run your app.

Apps that use native code

If you're not using Create React Native App, you'll need to register your AppWrapper as the main entry point with AppRegistry instead of your current App component:

AppRegistry.registerComponent('AppWrapper', () => AppWrapper);

Available spec helpers

| Function | Description | | :------------ | :--------------- | | fillIn(identifier, str) | Fills in the identified component with the stringComponent must respond to onChangeText | | press(identifier) | Presses the identified componentComponent must respond to onPress | | pause(integer) | Pauses the test for this length of time (milliseconds)Useful if you need to allow time for a response to be received before progressing | | exists(identifier) | Returns true if the component can be identified (i.e. is currently on screen) | | notExists(identifier) | As above, but checks for the absence of the component | | findComponent(identifier) | Returns the identified componentCan be used if your component doesn't respond to either onChangeText or onPressFor example:const picker = await spec.findComponent('Scene.modalPicker');picker.open();|

Writing your own spec helpers

Want to test something not included above? Write your own spec helper function!

Your function will need to be asynchronous and should throw an error in situations where you want the test to fail. For example, the following tests whether a <Text> component displays the correct text.

// specs/helpers.js

export async function containsText(component, text) {
  if (!component.props.children.includes(text)) {
    throw new Error(`Could not find text ${text}`);
  };
}
// specs/AppSpec.js

import { containsText } from './helpers';

export default function(spec) {
  spec.describe('Changing the text', function() {
    spec.it('works', async function() {
      await spec.press('Scene.button');
      const text = await spec.findComponent('Scene.text');
      await containsText(text, 'you pressed the button');
    });
  });
}

FAQs

How does Cavy compare to Appium? What is the benefit?

Cavy is a comparable tool to Appium. The key difference is that Appium uses native hooks to access components (accessibility IDs), wheras Cavy uses React Native refs. This means that Cavy sits directly within your React Native environment (working identically with both Android and iOS builds), making it easy to integrate into your application very quickly, without much overhead.

What does this allow me to do that Jest does not?

Jest is a useful tool for unit testing individual React Native components, whereas Cavy is an integration testing tool allowing you to run end-to-end user interface tests.

How about supporting stateless components?

We'd love for Cavy to be better compatible with stateless functional components and would be more than happy to see its reliance on refs replaced with something better suited to the task... What that looks like specifically, we're not 100% sure yet. We're very happy to discuss possible alternatives!

Contributing

Before contributing, please read the code of conduct.

  • Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
  • Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
  • Fork the project.
  • Start a feature/bugfix branch.
  • Commit and push until you are happy with your contribution.
  • Please try not to mess with the package.json, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so we can cherry-pick around it.