Package Exports
- fxmgr
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (fxmgr) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
fxmgr - fixture manager for e2e tests
installation
fxmgr is designed to be a test helper. Unless your project is a test suite by
itself, you should install it as a local dev-dependency.
npm i fxmgr --save-devUsage
1. Describe your data fixtures
`./test/fx/persons.js':
module.exports = require('fxmgr').fixture({
entity: 'person',
cases: {
noSuch: {
'~': { db: 'reseredEmpty', cache: 'reservedEmpty' },
id: 9900000,
},
johnDoe: {
'~': { db: 'testData', cache: 'reservedEmpty' },
id: 9000001
fname: 'John',
lname: 'Doe',
},
johnSnow: {
'~': { db: 'testData', cache: 'testData' },
id: 9000002,
fname: 'John',
lname: 'Snow',
},
saintJohn: {
'~': { db: 'mustExist', cache: 'ignore' },
id: 1,
fname: 'John',
lname: 'Cidade',
}
},
stores: {
db: {
type: 'mongo',
defaultCase: 'testData',
toStoredForm: ({fname, lname, id}) => ({ fname, lname, id}),
saveAs: 'doc',
},
cache: {
type: 'redis',
dataType: 'strings',
defaultCase: 'reservedEmpty',
toStoredForm: ({fname, lname, id}) => ({ key: `person:${id}`, value: JSON.stringify({id, fname, lname}),
saveAs: 'cache',
},
},
})What are case types?
reservedEmpty- ids that should be free in the DB
- either to test 404, or to test entity creations.
testData- entities that should be in the db for the test to work.
- used to be read or to be updated.
- created on setup and remove in the end.
mustExist- entitis that must be in the DB, but are owned by the environment.
- the state of these entries is not known to the fixture.
- does not try to set them up, nor to clean them up.
- instead - they are validated to be found on the db
mustEql- entities that must be in the DB, but are owned by the environment.
- the state of these entries is known to the fixture.
- does not tyr to set them up
- they are validated against the desired state specified in the fixture
2. Create your setup and teardown sequences
./test/fx/index.js, assuming the fixture above, and a config with entries
for redis and mongo.
This example uses the config package, however, you can do it anyhow you like.
const { redis, mongo } = require('fxmgr')
const redisConfig = require('config').redis
const mongoConfig = require('config').mongo
const persons = require('./persons')
const fxRedis = redis(redisConfig).useData({
persons: persons.stores.cache,
})
const fxMongo = mongo(mongoConfig).useData({
persons: persons.stores.db,
})
module.exports = {
mongo: fxMongo,
redis: fxRedis,
fx: { persons },
beforeAll: () => Promise.all( [fxMongo, fxRedis].map(fx => fx.beforeAll()),
afterAll: () => Promise.all( [fxMogno), fxRedis].map(fx => fx.afterAll()),
}
3. Use your setup in tests
This example assumes test/util.js which exposes setup and teardown that
run the target server in a child_process.
(e2e-helper is an example of a tool you can use to do it).
./test/my-cool-person-client.js
const Should = require('should')
const {
beforeAll,
afterAll,
//mongo: { collection }, // - if we were doing POST/PUT requests, we'd want to see how the DB is changed
redis: { client }, // but here we do want to see how the cache is affected
fx: { persons },
} = require('./fx')
const { setup: runSvr, teardown: stopSvr } = require('./util')
const request = require('mocha-ui-exports-request') //yes, I know, has become to be a bad name. will change in the future
const SUT = 'http://localhost:3000'
describe('my cool person server', () => {
before(async () => {
await beforeAll()
await runSvr()
})
after(async () => {
await stopSvr()
await afterAll()
})
describe('GET /person/:id', () => {
describe('when hit with an id that is not in the DB', () => {
request(`${SUT}/person/${persons.noSuch.id}`)
.responds({ status: 404, body: [/no such entity/] })
})
describe('when hit with an id that is is found in cache', () => {
request(`${SUT}/person/${persons.johnSnow.id}) //because everybody remembers John Snow...
.responds({
status: 200,
body: {
'should include lname and fname of the queried entity': body => {
Should(body).have.properties( persons.johnDoe.doc )
},
},
})
})
describe('when hit with an id that is in DB and not in cache', () => {
request(`${SUT}/person/${persons.johnDoe.id}) //because nobody remembers John Doe...
.responds({
status: 200,
body: {
'should include lname and fname of the queried entity': body => {
Should(body).have.properties( persons.johnDoe.doc )
},
},
and: {
'should update the entry in cache': done => {
client.get(persons.johnDoe.cache.key, (err, cached) => {
if (err) return done(err);
Should(cached).eql(persons.johnDoe.cache.value);
})
}
}
})
})
})
})Roadmap
[v] 0.6.x - This is the preliminary version. Tested manually. Works, however violent. Could be much more friendly. [ ] 0.8.x - will focus in adding tests, CI, linting, coverage. [ ] 1.0.x - will be released with focus on user-experience - i.e user-input validations and more friendly errors. API changes may occur up until this version.
Backlog
Anything from the backlog that will be ready for a version - will be released with it.
- a built-in cli tool that lets you run
fxmgr seed- to initiate an envfxmgr setup- to run setup, andfxmgr cleanup, to help you restore a desired state
- redis adapter implements only dataType
strings. Need to supporthashes,lists,sets, andsortedSets - add an sql adapter implementation, probably based on knex