bdd-tc
v0.0.11
Published
Codegen from Yadda features
Downloads
16
Maintainers
Readme
BDD-to-code
Transforms Yadda features into working Testcafé tests.
How it works?
First we need a feature-file, say ./e2e/features/demo.feature
:
Feature: Some description
Scenario: Perform a single action
Given one step
When I run another step
Then I test for something specific
Now we must define some steps to cover it, e.g. ./e2e/steps/demo.js
:
import { Selector } from 'testcafe';
export default {
'Given one step': () => async t => {
await t
.expect('body').ok();
},
'When I run another step': () => async t => {
await t
.click(Selector('button'));
},
'Then I test for $phrase': value => async t => {
await t
.expect(Selector('body').innerText)
.contains(value);
},
};
Finally we can generate the test-files and execute them:
$ bdd-tc e2e/features -- testcafe --color chrome:headless
Steps
Steps are labeled functions that receive arguments and return actual test functions.
Those calls are inlined on the generated tests, but its code is actually imported:
import $step0 from '../steps/demo.js';
fixture `Some description`;
test(`Perform a single action`, async t => {
await $step0[`Given one step`]()(t);
await $step0[`When I run another step`]()(t);
await $step0[`Then I test for \$phrase`]("something specific")(t);
});
Hooks
Before and after hooks for tests can be defined too.
They're are similar to step functions:
export default {
before: {
namedHook: () => async t => {
// do something
},
},
after: {
// etc.
},
// use @path as input
url(path = '/') {
return process.env.BASE_URL + path;
},
};
Now you can reference them with @before
and @after
annotations respectively:
@after=doSomething
Feature: Some description
@before=namedHook,somethingElse
Scenario: Perform a single action
Given one step
When I run another step
Then I test for something specific
Depending on the context,
beforeEach/afterEach
orbefore/after
is used automatically.
Matchers
Additional $matchers
can be defined within steps as follows:
export default {
matchers: {
test: '(foo|bar)',
noMatch: '(?:[^\\s]*)',
},
'When ask for $test': test => async t => {
console.log(test); // foo OR bar
},
'Then verify $noMatch': noMatch => async t => {
console.log(noMatch); // undefined
},
};
Captures made from matchers will be passed as arguments, non-matched placeholders will be captured as (.+?)
and passed too.
Use
(?:<PATTERN>)
to omit captured values from matched placeholders.
Annotations
Built-in annotations are:
@xsnapshot
— Unique for features, disables any@snapshot
from scenarios below@snapshot
— Unique for scenarios, it'll take snapshots after each step!@before
— Setupbefore/beforeEach
from features and scenarios@after
— Setupafter/afterEach
from features and scenarios@only
— Append.only
on generated fixture/test calls@skip
— Completely omit fixture/test from generated code@page
— Optional pathame, used only ifurl()
is setup@url
— Append.page
calls on generated fixture/test calls
Given @snapshost
value is passed as takeSnapshot
's selector option, so it can be an array, in which case will fallback until one selector matches/exists.
Any other annotation is keept as input-data and passed through invoked hooks.
Multiple values using [ ;,]
as separator will be treated as arrays, e.g.
@media=foo,bar
Complex values can be passed as JSON values, e.g.
@arr=["foo", "bar"]
@obj={"baz": "buzz"}
@str="Other value, with commas, etc."
Working with steps
In order to assist you during writing steps, you can leverage on:
takeSnapshot(...)
— Calls the same method from testcafe-blink-diffuseSelectors(obj)
— Object containingSelector(...)
definitions, can be nesteduseFixtures(obj)
— Object containing any values as fixtures, can be nestedgetVal(key)
— Validate and return value from registered fixtures, see abovegetEl(key)
— Validate and return selector from registered ones, see above$(...)
— Shortcut forSelector(...)
, same options as original call
Working with fixtures
Importing the bdd-tc/matchers
module you gain access to:
jsf(schema[, options])
— Generate one or many samples from given JSON-Schema1faker[...]
— Faker.js instance - see demochance[...]
— Chance.js instance - see docsgen([type[, schema]])
— Generate a sample based on any given type, additional JSON-Schema is applied if givendate([step])
— RandomDate
object, given optional step:seconds
,minutes
,hours
,days
,months
oryears
pick(dataset)
— Pick any value from given dataset, even work with strings!oneOf(dataset, whereField, fieldValue)
— Find any item on dataset that matches field/valuenumber([min[, max]])
— Returns a random number within min/max boundariesrandexp(regexp)
— Return a string generated from any givenRegExp
shuffle(dataset)
— Copy, randomize and returns any given dataset
1 We're using json-schema-faker under the hood to generate those.
Demo/dev
npm install
— Setup dependenciesnpm run e2e
— Run defined e2e testsnpm run test:ci
— To run all unit-tests
Inspect the generated results from E2E snapshots:
npm run report:ui
open generated/index.html