gemini-core
Version:
Utility which contains common modules for gemini and hermione
396 lines (293 loc) • 9.62 kB
Markdown
# gemini-core
[](https://travis-ci.org/gemini-testing/gemini-core)
Utility which contains common modules for [gemini](https://github.com/gemini-testing/gemini) and [hermione](https://github.com/gemini-testing/hermione).
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents**
- [SetsBuilder](#setsbuilder)
- [Options](#options)
- [Sets](#sets)
- [BrowserPool](#browserpool)
- [events](#events)
- [AsyncEmitter](#asyncemitter)
- [utils](#utils)
- [promiseUtils](#promiseutils)
- [BrowserAgent](#browseragent)
- [Errors](#errors)
- [CancelledError](#cancellederror)
- [Image](#image)
- [Methods](#methods)
- [crop](#crop)
- [getSize](#getsize)
- [getRGBA](#getrgba)
- [save](#save)
- [clear](#clear)
- [join](#join)
- [Static methods](#static-methods)
- [fromBase64](#frombase64)
- [RGBToString](#rgbtostring)
- [compare](#compare)
- [buildDiff](#builddiff)
- [Temp](#temp)
- [init](#init)
- [path](#path)
- [serialize](#serialize)
- [attach](#attach)
- [clientBdridge](#clientbdridge)
- [coverageLevel](#coveragelevel)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
### SetsBuilder
Creates mapping of test files with browsers in which they should be run and vice versa.
Example of usage:
```js
const SetsBuilder = require('gemini-core').SetsBuilder;
const sets = {
desktop: {
files: ['desktop/tests/**.js'],
ignoreFiles: ['desktop/tests/fixtures/**'], // exclude directories from reading while test finding
browsers: ['bro1'],
},
touch-phone: {
files: ['touch-phone/tests'],
browsers: ['bro2']
}
};
SetsBuilder
.create(sets, {defaultDir: 'default/path'}) // creates setsBuilder using specified tests and options
.useSets(['desktop']) // use only the specified sets
.useBrowsers(['bro1']) // use only specified browsers
.useFiles(['desktop/tests/test.js']) // use only specified files if sets
// and files to use are not specified
.build('/root', globOpts, ['.js', '.ts']) // builds a collection of sets with paths expanded according
// to the project root, glob options and file extensions
.then((setCollection) => {
setCollection.groupByFile(); // groups all browsers of test-sets by file:
// {'desktop/tests/test.js': ['bro1']}
setCollection.groupByBrowser(); // groups all files of test-sets by browser:
// {'bro': ['desktop/tests/test.js']}
})
.done();
```
### Options
Returns an object with some options.
```js
const options = require('gemini-core').config.options;
```
#### Sets
```js
const sets = options.sets; // returns a section for configparser with two options – files and browsers.
// Default value is an empty set - all: {files: []}
```
### BrowserPool
Example:
```js
const BrowserPool = require('gemini-core').BrowserPool;
// Some browser realization
class Browser {
constructor(id) {
this.id = 'bro'; // required field
this.sessionId = null; // required field
}
launch() {
return doLaunch()
.then((sessionId) => this.sessionId = sessionId);
}
// required method
reset() {
return doSomeReset();
}
quit() {
return doQuit();
}
}
const BrowserManager = {
create: (id) => new Browser(id),
start: (browser) => browser.launch(),
onStart: (browser) => emitter.emitAndWait('sessionStart', browser),
onQuit: (browser) => emitter.emitAndWait('sessionEnd', browser),
quit: (browser) => browser.quit()
};
const config = {
forBrowser: (id) => {
return {
parallelLimit: 1, // maximum number of specific browser sessions executed in parallel
sessionUseLimit: 2 // maxiumu number of session reuse (test per session, for example)
};
},
getBrowserIds: () => config.getBrowserIds(),
system: {
parallelLimit: 10 // maximum number of browser sessions at all
}
};
const pool = BrowserPool.create(BrowserManager, {
logNamespace: 'gemini', // prefix for logger. log = require('debug')(`${logNamespace}:pool:...`)
config
});
return pool.getBrowser('bro'/*, {highPriority: true}*/)
.then((bro) => {
...
return pool.freeBrowser(bro);
});
```
### events
#### AsyncEmitter
Node.js event emitter with promises support.
Node.js builtin `EventEmitter` class executes all handlers synchronously without waiting for completion of any async operations that may happen inside.
`AsyncEmitter` is the subclass of `EventEmitter` which adds ability to return a promise from event handler and wait until it resolved. Just use `emitAndWait` instead of `emit`:
```js
const AsyncEmitter = require('gemini-core').events.AsyncEmitter;
const emitter = new AsyncEmitter();
emitter.on('event', function() {
return Promise.delay(1000);
});
emitter.emitAndWait('event')
.then(function() {
console.log('All handlers finished'); // Would be called after 1 second
});
```
`emitAndWait` returns promise.
#### utils
`passthroughEvent(from, to, event)`
Passes `event` from `from` to `to`. `event` can be an array of events.
### promiseUtils
`waitForResults(promises)`
Waits for all promises in array to be resolved or rejected.
If any promise is rejected - rejects with the first rejection error, otherwise resolves.
### BrowserAgent
Example:
```js
const BrowserAgent = require('gemini-core').BrowserAgent;
const BrowserPool = require('gemini-core').BrowserPool;
const pool = BrowserPool.create(/*BrowserManager, config*/);
const browserAgent = BrowserAgent.create('bro-id', pool);
return browserAgent.getBrowser(/*{highPriority: true}*/)
.then((bro) => {
...
return browserAgent.freeBrowser(bro/*, {force: true}*/);
});
```
### Errors
#### CancelledError
This error will be thrown on browser pool cancel:
```js
const BrowserPool = require('gemini-core').BrowserPool;
const CancelledError = require('gemini-core').errors.CancelledError;
...
pool.getBrowser('bro')
.then((bro) => ...)
.catch((e) => {
if (e instanceof CancelledError) {
console.log('cancelled')
}
});
pool.cancel();
```
### Image
API for working with images.
```js
const {Image} = require('gemini-core');
const imgBuffer = new Buffer('someBufferString', 'base64');
const image = new Image(imgBuffer);
const imageSize = image.getSize();
```
#### Methods
##### crop
Crop image to the passed sizes depending on scale factor. Modifies current image.
Returns Promise with image instance.
```js
const image = new Image(imgBuffer);
const cropArea = {
top: 10,
left: 10,
width: 100,
height: 100
};
image.crop(cropArea, 2); // will crop double sized image i.e width=200, heigth=200 etc.
```
##### getSize
Returns object with current image size e.g. `{width: 100, height: 100}`
##### getRGBA
Returns RGBA color of the passed image pixel in row.
Takes pixel number in row as first argument and row nomber as second.
Returns object with color.
```js
const image = new Image(imgBuffer);
const color = image.getRGBA(1, 2); // {r: 255, g: 0, b: 0, a:255}
```
##### save
Save image to the passed path. Asynchronous operation.
Returns Promise with current image instance.
##### clear
Fill image area with black color depending on scale factor.
```js
const image = new Image(imgBuffer);
const clearArea = {
top: 10,
left: 10,
width: 100,
height: 100
};
image.clear(clearArea, {scaleFactor: 1});
```
##### join
Append another image to current. Modifies current image.
```js
const image1 = new Image(imgBuffer);
const image2 = new Image(imgBuffer);
image1.join(image2);
```
#### Static methods
##### fromBase64
Returns new Image instance from base64 hash.
##### RGBToString
Convert object-like RGB color to string.
```js
const color = Image.RGBToString({r: 255, g: 0, b: 0}); // returns #ff0000
```
##### compare
Compare images with passed options. Asynchronous operation.
Returns compare result sa Boolean value.
```js
const opts = {
canHaveCaret: true,
pixelRatio: 1,
tolerance: 2,
antialiasingTolerance: 3
};
return Image.compare(path1, path2, opts)
.then((isEqual) => {
console.log(isEqual);
});
```
##### buildDiff
Save new diff image with passed options on the file system.
```js
const diffOpts = {
reference: '/ref/path/image.png',
current: '/curr/path/image.png',
diff: '/diff/path/image.png',
diffColor: '#f5f5f5',
tolerance: 2
};
return Image.buildDiff(diffOpts); // will save image with diff to /diff/path/image.png
```
### Temp
Class for creating temp direcroty for image save. Directory will be removed on process end.
#### init
Init temp directory.
#### path
Generate random path relative temp directory.
#### serialize
Serialize Temp instance.
#### attach
Attach passed directory to the current Temp instance.
### clientBdridge
```js
const {clientBridge} = require('gemini-core');
return clientBridge.build(browser, {calibration, coverage});
```
### coverageLevel
```js
const {coverage: {coverageLevel}} = require('gemini-core');
coverageLevel.merge(oldValue, newValue);
```