npm package: @orcden/od-component-test-suite
Description: OrcDen Component Test Suite
Latest version: 2.1.8

# OD Component Test Suite

> A set of universal component tests in TestCafe. 

The OD Component Test Suite runs a series of tests on your agnostic components. Based on basic symantic HTML behaviours, it ensures your components behave as they should.

## Features
- Simple Configuration
- Easy Execution
- Built-In TestCafe Selectors and 'Custom DOM Properties'
- Automatically Tests:
  - Webcomponents Support
  - Shadow DOM Support
  - Property Types
  - Property Behaviours
  - Attribute Behaviours
  - More...


## Proposal
Creating Webcomponents comes with many challenges; especially so when designed to be agnostic of any particular framework. Some libraries attempt to alleviate these challenges by providing a stricter set of rules to adhere to and wider selection of basic features while developing said components; implementing the required behaviour behind the scenes. Many of these libraries offer simple patterns to allow for easy data-binding and DOM rendering.

The advantages of this appraoch cannot be denied; faster development, easier to read code, etc. However it also comes with some disadvantages for more complex components and ones designed to be agnostic of any given framework. Since web development tends to grow rapidly a need to support compatibility with older libraries could be required while transitioning to new technologies. The authors of said libraries may have moved on or dropped support entirely, forcing developers to find workarounds, find new solutions, or wait patiently for a fix. Additionally, the stricter set of rules may actually impose limitations on the devopler while attempting more complex features or DOM manipulation.

Given the balancing act of relying on external frameworks and dependencies many devolopers in the Webcomponents space have started opting to design completely agnostic components from the ground up. Built on the new Webcomponents spec, developers are able to extend HTMLElement directly and leave compatibility issues to a supported polyfill until browsers are fully up to date with the spec. The downside being the loss of many built in behaviours and ease-of-use development features.

Instead of creating a new framewwork 'flavour-of-the-month' we believe the solution lies in test-driven development. Frontend testing frameworks are quickly becoming more popular and in some cases neccessary. Cross-browser compatibility and behaviour are of the utmost importance, and for larger organizations consistency of code and stable build pipelines means that most have already implemented some form of frontend testing already.

This Component Test Suite for TestCafe is designed to execute a series of configurable tests on your components, agnostic or otherwise. The goal being that your custom components operate as close to semantic HTML elements as possible. This will empower developers to maintain complete control of their code and not have to rely on external component-building libraries if they do not desire, while targeting a consistent set of component behaviours and interoperability.

## Why Testcafe?
TestCafe is perfectly positioned at this time to provide cross-browser testing solutions and it is because of that this library uses testcafe first and foremost. As other frontend testing frameworks add support for more browser testing it is our hope to add that functionality here as well.

## Installation
- Install with [npm](https://www.npmjs.com/)

```
npm i @orcden/od-component-test-suite --save-dev
```
## Example Basic Usage
See TestCafe for setting up a set of tests, then in your testfile:
```
import { TestCafeComponentTestSuite } from '../../../node_modules/@orcden/od-component-test-suite';
```
```
const _config = {
    testServer: 'http://localhost:8079',
    name: 'OD Top Button',
    tag: 'od-top-button',
    componentSelector: '#top-button',
    hasShadow: true,
    shadowSelector: '#top-button',
    properties: [
        {
            name: 'active',
            type: Boolean,
            default: false,
            attributeName: 'active'
        },
        {
            name: 'offset',
            type: Number,
            default: 1,
            validValue: 5,
            attributeName: 'offset'
        }
    ]
}

const testSuite = new TestCafeComponentTestSuite( _config );
testSuite.runAllTests();
```

## Example with Custom Tests
```
...
const testSuite = new TestCafeComponentTestSuite( _config );
testSuite.runAllTests();

const model = testSuite.model;
const topButton = model.component;

fixture( 'OD-Top-Button Custom Tests' )
    .page( model.testServer );

test( 'Integration Tests - Properties - offset - behaviour', async t => {
    let selector = model.componentSelector
    await t.eval( () => { document.querySelector( selector ).offset = 2 }, {dependencies: { selector }} );

    let offsetValue = await topButton.offset;

    await t
        .expect( topButton.withAttribute( 'offset', offsetValue.toString() ).exists ).ok( 'Attribute "offset" updates with property' );
        
    await t.eval( () => { document.querySelector( selector ).offset = 1 }, {dependencies: { selector }} );
} );
```
    
## Configuration
| Field               | Type    | Description                                                   |
|---------------------|---------|---------------------------------------------------------------|
| `testServer`        | String  | The server/page that your Testcafe fixture runs tests against |
| `name`              | String  | The proper name for your component; Should be easy to read |
| `componentTag`      | String  | The tagName for your component when it is in the DOM |
| `componentSelector` | String  | The selector used to find your component in the DOM of your specified server/page; Should be an Id |
| `hasShadow`         | Boolean | Set to true if your component uses a shadow DOM |
| `shadowSelector`    | String  | The selector used to find the PARENT element inside your components shadow DOM; Can be excluded if hasShadow is set false |
| `properties`        | Array   | A set of properties that component exposes; See below for property Configuration |

### Property Configuration
| Field           | Description |                          |
|-----------------|-------------|--------------------------|
| `name`          | String      | The name of the property |
| `type`          | Primative   | The JS type that your property is; Supported Types: Boolean, String, Number, Object, Array |
| `default`       | Primative   | The default value that the property is set to upon initialization; Should be of type specified in 'type' field |
| `validValue`    | Primative   | A value that the given property can accept without issue; Should be of type specified in 'type' field; ONLY REQUIRED IN Number AND String 'type' |
| `attributeName` | Primative   | The name of the attribute that corresponds to the property; ONLY REQUIRED IN Number AND String AND Boolean 'type' |

## Development
### Run development server and show demo

```
npm run demo
```

### Run linter

```
npm run lint
```

### Fix linter errors

```
npm run fix
```

### Build for production

```
npm run build
```