node package manager

ui-harness

ui-harness

Build Status npm version js-style

Isolate, test and document modular UI with React using familiar describe/it testing semantics.

http://uiharness.com

ScreenShot

Quick Start (1-minute)

With the UIHarness you can go from an empty NPM module, to cleanly building isolated React components using best-practices in well under a minute.

See the quick-start sample repo https://github.com/philcockfield/ui-harness-sample

git clone https://github.com/philcockfield/ui-harness-sample.git
cd ui-harness-sample
npm install
npm start

Manual Setup

The UIHarness is just a simple NPM module.

npm install --save-dev ui-harness

Simply add it to you package.json file, with a start script:

{
  "name": "my-components",
  "version": "1.0.0",
  "scripts": {
    "uih": "node ./node_modules/ui-harness/start --entry=./src/specs",
  },
  "devDependencies": {
    "ui-harness": "^3.3.0"
  },
  "engines": { "node": ">=5.5.0" }
}

If you are using TypeScript, you will also need to ensure you have type definitions for your dependencies, such as React and React-DOM.

From here you can start developing your React components. All the core dependencies for react and babel transpiling are made available to your module by virtue of the one ui-harness dependency.

Now simply run:

npm run uih

And navigate your browser to http://localhost:3030

Project Structure

The package.json above assumes a project structure like this:

my-components
|— src
  |— components       # React components here.
  |— specs            # Spec files here.
     |— index.js      # --entry to the "describe/it" visual spec files.

For a working example see the ui-harness-sample repo. To deviate from this typical structure simply organize your module folders as you wish and change the --entry path passed to the start script.


Conceptual Introduction

The UIHarness allows you to add a one-line startup script to your node module that provides a complete visual test and build harness for creating and bundling your components.

Creating

As a tool for crafting your components and their API's in isolation, the UIHarness dramatically improves the quality and reuse potential of your UI investment. You will be falling into the "pit of success" conforming to best-practices that also make your job faster and easier, and importantly - more fun.

Documentation

Creating components in this manner has the knock-on effect of providing a visual API and documentation explorer for your component system. Sharing and socializing code and API's, both within your team, and publicly to the world, is a big part of making software a success. Functional documentation is a by-product of building components in the UIHarness.

Publishing

If you are isolating your UI components into their own discreet modules (a very good idea!), you can add the UIHarness as a dev-dependency (--save-dev), create and test your components within it, and then publish your module to NPM with the UIHarness as the startup option (npm start).

This makes your components easy to explore, evaluate, and understand by other developers. The UIHarness adds no run-time overhead to your module, as consumers of the components will only be requiring the isolated component, not the UIHarness itself, so it never gets built (via Webpack) into the resulting application bundle.

Startup Arguments and Configuration

The following arguments can be passed to the UIHarness at startup as command-line arguments:

  • --entry Path to the specs files (comma separated if more than one).

  • --port The port to run the harness on. Default: 3030

For example:

"scripts"{
  "start": "node ./node_modules/ui-harness/start --entry=./src/specs --port=1234"
}

.uiharness.yml

These values can alternatively be declared in a .uiharness.yml configuration file in the root of your project, with the following additional values that can only be declared within a YAML configuration:

  • graphqlSchema A path to the GraphQL schema.js file. If not specified Relay will not be enabled.

  • proxy An object containing { path, host } mappings to proxy server requests to (reference).

  • images An object containing { baseUrl, dir } that declares where images are served from. Default image values are:

    • baseUrl: <package-name>
    • dir: ./images
entry: ./src/specs  # Path, comma-separated paths, or array of paths.
port: 3030
graphqlSchema: ./data/schema.js
proxy:
  /graphql: http://localhost:8080
images:
  baseUrl: /my-images
  dir: ./assets/images
css:
  baseUrl: /my-css
  dir: ./assets/css

CSS

By default the UIHarness supports the webpack css-loader for *.css files. If however you wish to use css-modules simply declare the file extension of your modules in the .uiharness.yml with a regular-expression like this:

cssModules: .css

If you wish to retain the default css-loader behavior but still want to use css-modules, you can specify css-modules to only work on certain extensions:

cssModules: .module.css

And if you wish to use several different extensions for css-modules you can specify a list:

cssModules:
  - .css
  - .module.css

You may need to pass in some external CSS <style> values to apply to the component:

this
  .style({
    color: 'white',
    '.MyComponent': {
      padding: 20,
      background: 'red',
    }
  })
  .component( <MyComponent /> );

Building

You can use the UIHarness to output your built JS bundles. You can also use this function to keep an eye on the size of your JS before it's too late to do anything about it.

Declare a build section within the .uiharness.yml with the following fields:

build:
  prod: true  # Minifies if true (default: false). 
  outputFolder: ./.build/my-folder
 
  modules:
    main: ./src/app.js
    single:
      - ./src/components/foo.jsx
      - ./src/util/bar.js
 
  vendor:
    - react
    - react-dom
 
Command Line

The build function can be invoked from the command line. For example, you might add these as scripts to your package.json:

  "scripts"{
    "bundle": "node ./node_modules/ui-harness/build",
  }

Producing the following output in the terminal window:

Terminal:Size

Building from the API

You can invoke a build via the API by passing an object of the same structure as the build settings within .uiharness.yml to the build function:

import uiharness from 'ui-harness';
 
uiharness.build({ settings }) // See YAML build settings above. 
  .then(result => { ... })
  .catch(err => { ... });
 

Environment

When running the __UIHARNESS__ environment variable is set to true. Use this as a switch if you wish to consolidate UIHarness specs with unit-tests such as Mocha or Jasmine, or BDD feature/step files.

if (__UIHARNESS__) {
  describe('My visual spec', function() {
    // This will load in the UIHarness 
  });
}
 
if (!__UIHARNESS__) {
  describe('My unit-tests', function() {
    // This will run within the server-side test runner. 
  });
}

Examples

Simple Example

From within the /ui-harness project folder, to see the core set of specs used to build the UIHarness itself, along with specs for associated component libraries, run:

npm start

Relay Example

To see an example of Relay/GraphQL working within UIHarness run:

node example relay

Based on the relay-starter-kit, this takes a command-line argument of --graphqlSchema, which is the path to the GraphQL schema.js file.

uiharness.start({
  entry: './example/relay/specs',
  proxy: { '/graphql': 'http://localhost:8080' },
  graphqlSchema: path.resolve('./example/relay/data/schema.js')
})

From there the UIHarness will build the schema.json output, and compile it into the Webpack output sent to the client using the babel-relay-plugin.

To rebuild the schema (when changes have been made to it), simply delete the generated schema.json file and restart the UIHarness.

Links


License: MIT