diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index a26a5d4..0a53cd4 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -13,7 +13,7 @@ jobs: strategy: matrix: - node-version: [14.x, 16.x, 18.x] + node-version: [18.x, 20.x] steps: - uses: actions/checkout@v3 diff --git a/README.md b/README.md index 5318d10..3c07e61 100644 --- a/README.md +++ b/README.md @@ -5,13 +5,11 @@ Common plugin for: -* [gemini](https://github.com/gemini-testing/gemini) * [hermione](https://github.com/gemini-testing/hermione) which is intended to aggregate the results of tests running. -You can read more about gemini plugins [here](https://github.com/gemini-testing/gemini/blob/master/doc/plugins.md) -and hermione plugins [here](https://github.com/gemini-testing/hermione#plugins). +You can read more about hermione plugins [here](https://github.com/gemini-testing/hermione#plugins). ## Installation @@ -29,23 +27,6 @@ Plugin has following configuration: Also there is ability to override plugin parameters by CLI options or environment variables (see [configparser](https://github.com/gemini-testing/configparser)). -### Gemini usage - -Add plugin to your `gemini` config file: - -```js -module.exports = { - // ... - plugins: { - 'json-reporter/gemini': { - enabled: true, - path: 'my/custom/report.json' - } - }, - //... -} -``` - ### Hermione usage Add plugin to your `hermione` config file: diff --git a/gemini.js b/gemini.js deleted file mode 100644 index e455dbd..0000000 --- a/gemini.js +++ /dev/null @@ -1,29 +0,0 @@ -'use strict'; - -const GeminiCollector = require('./lib/collector/gemini'); -const geminiToolCollector = require('./lib/collector/tool/gemini'); -const parseConfig = require('./lib/config'); - -module.exports = (gemini, opts) => { - const config = parseConfig(opts); - - if (!config.enabled) { - return; - } - - const collector = GeminiCollector.create(geminiToolCollector, config); - - gemini.on(gemini.events.BEGIN_STATE, (data) => collector.markTestStart(data)); - - gemini.on(gemini.events.TEST_RESULT, (data) => { - data.equal ? collector.addSuccess(data) : collector.addFail(data); - }); - - gemini.on(gemini.events.SKIP_STATE, (data) => collector.addSkipped(data)); - - gemini.on(gemini.events.RETRY, (data) => collector.addRetry(data)); - - gemini.on(gemini.events.ERROR, (data) => collector.addError(data)); - - gemini.on(gemini.events.END_RUNNER, () => collector.saveFile()); -}; diff --git a/lib/collector/data-collector/gemini.js b/lib/collector/data-collector/gemini.js deleted file mode 100644 index 7e7eb51..0000000 --- a/lib/collector/data-collector/gemini.js +++ /dev/null @@ -1,28 +0,0 @@ -'use strict'; - -const DataCollector = require('./'); - -module.exports = class GeminiDataCollector extends DataCollector { - static create() { - return new GeminiDataCollector(); - } - - constructor() { - super(); - this._startTime = {}; - } - - saveStartTime(test) { - const id = this._generateId(test); - this._startTime[id] = Date.now(); - } - - append(test) { - const id = this._generateId(test); - - test.duration = Date.now() - this._startTime[id]; - delete this._startTime[id]; - - super.append(test); - } -}; diff --git a/lib/collector/gemini.js b/lib/collector/gemini.js deleted file mode 100644 index a601c4a..0000000 --- a/lib/collector/gemini.js +++ /dev/null @@ -1,34 +0,0 @@ -'use strict'; - -const Collector = require('./'); -const GeminiDataCollector = require('./data-collector/gemini'); - -module.exports = class GeminiCollector extends Collector { - static create(toolCollector, config) { - return new GeminiCollector(toolCollector, config); - } - - constructor(toolCollector, config) { - super(toolCollector, config); - this._dataCollector = GeminiDataCollector.create(); - } - - markTestStart(result) { - const test = this._toolCollector.configureTestResult(result); - this._dataCollector.saveStartTime(test); - } - - addRetry(result) { - this._toolCollector.isFailedTest(result) - ? this.addFail(result) - : this.addError(result); - } - - addFail(result) { - if (!result.hasOwnProperty('err') && result.hasOwnProperty('equal')) { - result.err = new Error('Images are not equal'); - } - - super.addFail(result); - } -}; diff --git a/lib/collector/tool/gemini.js b/lib/collector/tool/gemini.js deleted file mode 100644 index 396b384..0000000 --- a/lib/collector/tool/gemini.js +++ /dev/null @@ -1,23 +0,0 @@ -'use strict'; - -const _ = require('lodash'); -const utils = require('../utils'); - -exports.configureTestResult = (result) => { - return { - fullName: result.state.fullName, - suiteFullName: result.suite.fullName, - browserId: result.browserId, - file: result.suite.file, - referencePath: utils.getRelativePath(_.get(result, 'refImg.path')), - url: result.suite.url - }; -}; - -exports.isFailedTest = (result) => { - return result.hasOwnProperty('equal'); -}; - -exports.getSkipReason = (result) => { - return _.get(result, 'suite.skipComment', 'No skip reason'); -}; diff --git a/package.json b/package.json index 0be89c4..d7cc0eb 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "json-reporter", "version": "2.2.0", "description": "Common plugin for gemini and hermione which is intended to aggregate the results of tests running", - "main": "gemini.js", + "main": "hermione.js", "scripts": { "lint": "eslint .", "test": "npm run lint && npm run test-unit", @@ -19,10 +19,9 @@ "url": "https://github.com/gemini-testing/json-reporter/issues" }, "engines": { - "node": ">= 6" + "node": ">= 18" }, "keywords": [ - "gemini", "hermione", "plugin", "json-reporter" diff --git a/test/gemini.js b/test/gemini.js deleted file mode 100644 index 6f64a6f..0000000 --- a/test/gemini.js +++ /dev/null @@ -1,145 +0,0 @@ -'use strict'; - -const _ = require('lodash'); -const EventEmitter = require('events').EventEmitter; -const proxyquire = require('proxyquire'); - -const GeminiCollector = require('../lib/collector/gemini'); -const geminiToolCollector = require('../lib/collector/tool/gemini'); - -describe('json-reporter/gemini', () => { - const sandbox = sinon.sandbox.create(); - - let gemini; - let parseConfig; - - const mkGemini_ = () => { - const emitter = new EventEmitter(); - - emitter.events = { - TEST_RESULT: 'testResult', - SKIP_STATE: 'skipState', - RETRY: 'retry', - ERROR: 'err', - END_RUNNER: 'endRunner', - BEGIN_STATE: 'beginState', - END_STATE: 'endState' - }; - - return emitter; - }; - - const initReporter_ = (opts) => { - opts = _.defaults(opts || {}, { - enabled: true, - path: '/default/path' - }); - - parseConfig = sandbox.stub().returns(opts); - - const geminiReporter = proxyquire('../gemini', { - './lib/config': parseConfig - }); - - return geminiReporter(gemini, opts); - }; - - beforeEach(() => { - gemini = mkGemini_(); - }); - - afterEach(() => sandbox.restore()); - - it('should do nothing if plugin is disabled', () => { - sandbox.stub(GeminiCollector, 'create'); - - initReporter_({enabled: false}); - - assert.notCalled(GeminiCollector.create); - }); - - it('should parse config', () => { - initReporter_({enabled: true, path: '/some/path'}); - - assert.calledOnce(parseConfig); - assert.calledWithMatch(parseConfig, {enabled: true, path: '/some/path'}); - }); - - it('should create collector', () => { - sandbox.stub(GeminiCollector, 'create'); - - initReporter_({enabled: true, path: '/some/path'}); - - assert.calledWith( - GeminiCollector.create, - geminiToolCollector, - {enabled: true, path: '/some/path'} - ); - }); - - describe('call the appropriate event handlers', () => { - beforeEach(() => initReporter_()); - - it('should call appropriate method on test start', () => { - const data = {foo: 'bar'}; - - sandbox.stub(GeminiCollector.prototype, 'markTestStart'); - gemini.emit(gemini.events.BEGIN_STATE, data); - - assert.calledOnceWith(GeminiCollector.prototype.markTestStart, data); - }); - - it('should call appropriate method for passed test', () => { - const data = {equal: true}; - sandbox.stub(GeminiCollector.prototype, 'addSuccess'); - - gemini.emit(gemini.events.TEST_RESULT, data); - - assert.calledOnceWith(GeminiCollector.prototype.addSuccess, data); - }); - - it('should call appropriate method for failed test', () => { - const data = {equal: false}; - sandbox.stub(GeminiCollector.prototype, 'addFail'); - - gemini.emit(gemini.events.TEST_RESULT, data); - - assert.calledOnceWith(GeminiCollector.prototype.addFail, data); - }); - - it('should call appropriate method for skipped test', () => { - const data = {foo: 'bar'}; - sandbox.stub(GeminiCollector.prototype, 'addSkipped'); - - gemini.emit(gemini.events.SKIP_STATE, data); - - assert.calledOnceWith(GeminiCollector.prototype.addSkipped, data); - }); - - it('should call appropriate method for retried test', () => { - const data = {foo: 'bar'}; - sandbox.stub(GeminiCollector.prototype, 'addRetry'); - - gemini.emit(gemini.events.RETRY, data); - - assert.calledOnceWith(GeminiCollector.prototype.addRetry, data); - }); - - it('should call appropriate method for error occurred on test execution', () => { - const data = {foo: 'bar'}; - sandbox.stub(GeminiCollector.prototype, 'addError'); - - gemini.emit(gemini.events.ERROR, data); - - assert.calledOnceWith(GeminiCollector.prototype.addError, data); - }); - - it('should save collected test data into file when the tests are completed', () => { - sandbox.stub(GeminiCollector.prototype, 'saveFile'); - - gemini.emit(gemini.events.END_RUNNER); - - assert.calledOnce(GeminiCollector.prototype.saveFile); - }); - }); -}); diff --git a/test/lib/collector/data-collector/gemini.js b/test/lib/collector/data-collector/gemini.js deleted file mode 100644 index 14eb621..0000000 --- a/test/lib/collector/data-collector/gemini.js +++ /dev/null @@ -1,29 +0,0 @@ -'use strict'; - -const GeminiDataCollector = require('../../../../lib/collector/data-collector/gemini'); - -describe('collector/data-collector/gemini', () => { - let clock; - - beforeEach(() => { - clock = sinon.useFakeTimers(1); - }); - - afterEach(() => clock.restore()); - - it('should has static factory creation method', () => { - assert.instanceOf(GeminiDataCollector.create(), GeminiDataCollector); - }); - - it('should calculate duration for given test', () => { - const dataCollector = GeminiDataCollector.create({}); - - dataCollector.saveStartTime({fullName: 'name'}); - clock.tick(999); - dataCollector.append({fullName: 'name'}); - - assert.deepEqual(dataCollector.getData(), { - 'name': {fullName: 'name', duration: 999} - }); - }); -}); diff --git a/test/lib/collector/gemini.js b/test/lib/collector/gemini.js deleted file mode 100644 index ed60cba..0000000 --- a/test/lib/collector/gemini.js +++ /dev/null @@ -1,188 +0,0 @@ -'use strict'; - -const _ = require('lodash'); -const fs = require('fs-extra'); -const Promise = require('bluebird'); - -const GeminiCollector = require('../../../lib/collector/gemini'); -const GeminiDataCollector = require('../../../lib/collector/data-collector/gemini'); - -describe('collector/gemini', () => { - const sandbox = sinon.sandbox.create(); - let clock; - - const mkToolCollector_ = (opts) => { - return _.defaults(opts || {}, { - configureTestResult: (data) => data, - isFailedTest: sandbox.stub(), - getSkipReason: sandbox.stub() - }); - }; - - const mkGeminiCollector_ = (toolCollectorOpts, opts) => { - const toolCollector = mkToolCollector_(toolCollectorOpts); - const config = _.defaults(opts || {}, { - path: '/default/path' - }); - - return GeminiCollector.create(toolCollector, config); - }; - - const saveReport_ = (collector) => { - return collector.saveFile() - .then(() => fs.outputJsonAsync.firstCall.args[1]); - }; - - beforeEach(() => { - clock = sinon.useFakeTimers(); - sandbox.stub(fs, 'outputJsonAsync').returns(Promise.resolve()); - }); - - afterEach(() => { - clock.restore(); - sandbox.restore(); - }); - - describe('create', () => { - beforeEach(() => sandbox.stub(GeminiDataCollector, 'create')); - - it('should has static factory creation method', () => { - assert.instanceOf(GeminiCollector.create(), GeminiCollector); - }); - - it('should create instance of GeminiDataCollector inside the GeminiCollector creation', () => { - GeminiCollector.create(); - - assert.calledOnce(GeminiDataCollector.create); - }); - }); - - describe('markTestStart', () => { - it('should save test start time in data collector', () => { - sandbox.stub(GeminiDataCollector.prototype, 'saveStartTime'); - - const data = {fullName: 'some name', browserId: 'bro'}; - const collector = mkGeminiCollector_(); - - collector.markTestStart(data); - - assert.calledOnceWith(GeminiDataCollector.prototype.saveStartTime, data); - }); - }); - - describe('should add "duration" time to the', () => { - it('succesfully passed test', () => { - const data = {fullName: 'some name', browserId: 'bro'}; - const collector = mkGeminiCollector_(); - - collector.markTestStart(data); - collector.addSuccess(data); - - return saveReport_(collector).then((result) => { - assert.propertyVal(result['some name.bro'], 'duration', 0); - }); - }); - - it('skipped test', () => { - const data = {fullName: 'some name', browserId: 'bro'}; - const collector = mkGeminiCollector_(); - - collector.markTestStart(data); - collector.addSkipped(data); - - return saveReport_(collector).then((result) => { - assert.propertyVal(result['some name.bro'], 'duration', 0); - }); - }); - - it('failed test', () => { - const data = {fullName: 'some name', browserId: 'bro', err: new Error('test')}; - const collector = mkGeminiCollector_(); - - collector.markTestStart(data); - collector.addFail(data); - - return saveReport_(collector).then((result) => { - assert.propertyVal(result['some name.bro'], 'duration', 0); - }); - }); - - it('errored test', () => { - const data = {fullName: 'some name', browserId: 'bro'}; - const collector = mkGeminiCollector_(); - - collector.markTestStart(data); - collector.addError(data); - - return saveReport_(collector).then((result) => { - assert.propertyVal(result['some name.bro'], 'duration', 0); - }); - }); - - it('errored test if the retry does not fail', () => { - const data = {fullName: 'some name', browserId: 'bro'}; - const collector = mkGeminiCollector_({ - isFailedTest: sandbox.stub().returns(false) - }); - - collector.markTestStart(data); - collector.addRetry(data); - - return saveReport_(collector).then((result) => { - assert.propertyVal(result['some name.bro'], 'duration', 0); - }); - }); - }); - - describe('should add on retry', () => { - it('failed test if the retry fails', () => { - const testError = new Error('test'); - const data = {fullName: 'some name', browserId: 'bro', err: testError}; - const collector = mkGeminiCollector_({ - isFailedTest: sandbox.stub().returns(true) - }); - - collector.addRetry(data); - - return saveReport_(collector).then((result) => { - const bro = result['some name.bro']; - assert.propertyVal(bro, 'status', 'fail'); - assert.deepEqual(bro.errorReason, {message: testError.message, stack: testError.stack}); - assert.deepEqual(bro.retries, [{message: testError.message, stack: testError.stack}]); - }); - }); - - it('errored test if the retry does not fail', () => { - const data = {fullName: 'some name', browserId: 'bro'}; - const collector = mkGeminiCollector_({ - isFailedTest: sandbox.stub().returns(false) - }); - - collector.addRetry(data); - - return saveReport_(collector).then((result) => { - const bro = result['some name.bro']; - assert.propertyVal(bro, 'status', 'error'); - assert.deepEqual(bro.errorReason, {message: undefined, stack: undefined}); - assert.deepEqual(bro.retries, [{message: undefined, stack: undefined}]); - }); - }); - - it('failed test if images are not equal', () => { - const notEqualErrorMessage = 'Images are not equal'; - const data = {fullName: 'some name', browserId: 'bro', equal: false}; - const collector = mkGeminiCollector_({ - isFailedTest: sandbox.stub().returns(true) - }); - - collector.addRetry(data); - - return saveReport_(collector).then((result) => { - const bro = result['some name.bro']; - assert.propertyVal(bro, 'status', 'fail'); - assert.include(bro.errorReason.message, notEqualErrorMessage); - assert.include(bro.retries[0].message, notEqualErrorMessage); - }); - }); - }); -}); diff --git a/test/lib/collector/tool/gemini.js b/test/lib/collector/tool/gemini.js deleted file mode 100644 index a34f72a..0000000 --- a/test/lib/collector/tool/gemini.js +++ /dev/null @@ -1,87 +0,0 @@ -'use strict'; - -const _ = require('lodash'); -const geminiToolCollector = require('../../../../lib/collector/tool/gemini'); -const utils = require('../../../../lib/collector/utils'); - -describe('collector/tool/gemini', () => { - const sandbox = sinon.sandbox.create(); - - afterEach(() => sandbox.restore()); - - describe('configureTestResult', () => { - const mkDataStub_ = (opts) => { - return _.defaults(opts || {}, { - browserId: 'default-bro', - refImg: {path: '/default/ref/path'}, - state: {fullName: 'default full name'}, - suite: { - file: '/default/path', - url: 'http://default/url' - } - }); - }; - - beforeEach(() => sandbox.stub(utils, 'getRelativePath')); - - it('should try to resolve "referencePath"', () => { - const data = mkDataStub_({ - refImg: {path: '/cwd/ref/path'} - }); - - geminiToolCollector.configureTestResult(data); - - assert.calledOnceWith(utils.getRelativePath, '/cwd/ref/path'); - }); - - it('should return configured result', () => { - const data = mkDataStub_({ - browserId: 'bro', - refImg: {path: '/cwd/ref/path'}, - state: {fullName: 'state full name'}, - suite: { - file: '/some/file', - url: 'http://some-url', - fullName: 'suite full name' - } - }); - - utils.getRelativePath.withArgs('/cwd/ref/path').returns('ref/path'); - - const result = geminiToolCollector.configureTestResult(data); - - assert.deepEqual(result, { - fullName: 'state full name', - suiteFullName: 'suite full name', - browserId: 'bro', - referencePath: 'ref/path', - file: '/some/file', - url: 'http://some-url' - }); - }); - }); - - describe('isFailedTest', () => { - it('should return "true" if result has own property "equal"', () => { - assert.isTrue(geminiToolCollector.isFailedTest({equal: true})); - }); - - it('should return "false" if result has not property "equal"', () => { - assert.isFalse(geminiToolCollector.isFailedTest({})); - }); - }); - - describe('getSkipReason', () => { - it('should return default skip reason if "suite.skipComment" is not specified', () => { - assert.strictEqual(geminiToolCollector.getSkipReason({}), 'No skip reason'); - }); - - it('should return skip reason if "suite.skipComment" is specified', () => { - const data = { - suite: {skipComment: 'some-comment'} - }; - - assert.strictEqual(geminiToolCollector.getSkipReason(data), 'some-comment'); - }); - }); -});