From 5536494779eae89fdcaa1436eace05b2ff13acb8 Mon Sep 17 00:00:00 2001 From: DudaGod Date: Tue, 2 Apr 2019 16:03:40 +0300 Subject: [PATCH] feat: ability to add meta info extenders --- README.md | 29 +++++++++++++-- gemini.js | 2 +- hermione.js | 2 +- lib/gui/server.js | 4 ++ .../tool-runner-factory/base-tool-runner.js | 2 +- lib/plugin-api.js | 21 +++++++++-- lib/report-builder-factory/report-builder.js | 8 ++-- lib/server-utils.js | 6 ++- lib/static/components/controls/menu-bar.js | 6 +-- lib/static/components/section/body/index.js | 19 ++++++++-- .../components/section/body/meta-info.js | 8 ++-- lib/static/modules/default-state.js | 5 ++- lib/static/modules/reducer.js | 9 ++--- lib/static/styles.css | 4 ++ test/gemini.js | 20 ++++++---- test/hermione.js | 20 ++++++---- test/lib/gui/server.js | 9 +++++ .../tool-runner-factory/base-tool-runner.js | 6 +-- .../gemini/report-subscriber.js | 2 +- .../hermione/report-subsciber.js | 2 +- test/lib/plugin-api.js | 22 ++++++++++- .../report-builder-factory/report-builder.js | 6 +-- .../static/components/controls/menu-bar.js | 6 ++- .../section/{body.js => body/index.js} | 30 ++++++++++++++- .../components/section/body/meta-info.js | 37 +++++++++++++++++++ 25 files changed, 225 insertions(+), 60 deletions(-) rename test/lib/static/components/section/{body.js => body/index.js} (91%) create mode 100644 test/lib/static/components/section/body/meta-info.js diff --git a/README.md b/README.md index 2cae6075b..7107584ca 100644 --- a/README.md +++ b/README.md @@ -24,9 +24,9 @@ directory. * **baseHost** (optional) - `String` - it changes original host for view in the browser; by default original host does not change * **scaleImages** (optional) – `Boolean` – fit images into page width; `false` by default * **lazyLoadOffset** (optional) - `Number` - allows you to specify how far above and below the viewport you want to begin loading images. Lazy loading would be disabled if you specify 0. `800` by default. -* **errorPatterns** (optional) - `Array` - error message patterns for 'Group by error' mode. +* **errorPatterns** (optional) - `Array` - error message patterns for 'Group by error' mode. Array element must be `Object` ({'*name*': `String`, '*pattern*': `String`}) or `String` (interpret as *name* and *pattern*). -Test will be associated with group if test error matches on group error pattern. +Test will be associated with group if test error matches on group error pattern. New group will be created if test cannot be associated with existing groups. Also there is ability to override plugin parameters by CLI options or environment variables @@ -74,7 +74,6 @@ Add plugin to your `hermione` config file: ```js module.exports = { // ... - plugins: { 'html-reporter/hermione': { enabled: true, @@ -141,5 +140,27 @@ Adds item to html report as link: @param {String} text of link @param {String} url of link -tool.htmlReporter.addExtraItem(linkText, linkUrl) +tool.htmlReporter.addExtraItem('some-text', 'some-url') ``` + +In this case url with link 'some-url' and text 'some-text' will be added to the menu bar. + +### addMetaInfoExtender + +Extend meta-info of each test using passed data: + +```js +tool.htmlReporter.addMetaInfoExtender(name, value); +``` + +* **name** (required) `String` - name of meta info +* **value** (required) `Function` - handler to which `suite` and `extraItems` are passed + +Example: +```js +tool.htmlReporter.addMetaInfoExtender('foo', (suite, extraItems) => { + return suite.suitePath.join(' ') + extraItems.platform; +}); +``` + +In this case a line `suite full name: some-platform` will be added to the meta info of each test. diff --git a/gemini.js b/gemini.js index d48431b34..867a4caa7 100644 --- a/gemini.js +++ b/gemini.js @@ -35,7 +35,7 @@ function prepareData(gemini, reportBuilder) { gemini.on(gemini.events.END, (stats) => resolve( reportBuilder .setStats(stats) - .setExtraItems(gemini.htmlReporter.extraItems) + .setApiValues(gemini.htmlReporter.values) )); }); } diff --git a/hermione.js b/hermione.js index f28880b4e..6bba074b7 100644 --- a/hermione.js +++ b/hermione.js @@ -30,7 +30,7 @@ function prepareData(hermione, reportBuilder) { hermione.on(hermione.events.RUNNER_END, (stats) => resolve( reportBuilder .setStats(stats) - .setExtraItems(hermione.htmlReporter.extraItems) + .setApiValues(hermione.htmlReporter.values) )); }); diff --git a/lib/gui/server.js b/lib/gui/server.js index 268570d1f..30d7e4563 100644 --- a/lib/gui/server.js +++ b/lib/gui/server.js @@ -30,6 +30,10 @@ exports.start = ({paths, tool, guiApi, configs}) => { app.addClient(res); }); + server.set('json replacer', (key, val) => { + return typeof val === 'function' ? val.toString() : val; + }); + server.get('/init', (req, res) => { res.json(app.data); }); diff --git a/lib/gui/tool-runner-factory/base-tool-runner.js b/lib/gui/tool-runner-factory/base-tool-runner.js index 479537c93..984af0446 100644 --- a/lib/gui/tool-runner-factory/base-tool-runner.js +++ b/lib/gui/tool-runner-factory/base-tool-runner.js @@ -30,7 +30,7 @@ module.exports = class ToolRunner { this._eventSource = new EventSource(); this._reportBuilder = ReportBuilderFactory.create(this._toolName, tool, pluginConfig); - this._reportBuilder.setExtraItems(tool.htmlReporter.extraItems); + this._reportBuilder.setApiValues(tool.htmlReporter.values); } get config() { diff --git a/lib/plugin-api.js b/lib/plugin-api.js index 8477546e9..f7c64af50 100644 --- a/lib/plugin-api.js +++ b/lib/plugin-api.js @@ -2,14 +2,29 @@ module.exports = class HtmlReporter { constructor() { - this._extraItems = {}; + this._values = { + extraItems: {}, + metaInfoExtenders: {} + }; } addExtraItem(key, value) { - this._extraItems[key] = value; + this._values.extraItems[key] = value; } get extraItems() { - return this._extraItems; + return this._values.extraItems; + } + + addMetaInfoExtender(key, value) { + this._values.metaInfoExtenders[key] = value; + } + + get metaInfoExtenders() { + return this._values.metaInfoExtenders; + } + + get values() { + return this._values; } }; diff --git a/lib/report-builder-factory/report-builder.js b/lib/report-builder-factory/report-builder.js index 3f12f44cb..5211106c3 100644 --- a/lib/report-builder-factory/report-builder.js +++ b/lib/report-builder-factory/report-builder.js @@ -19,7 +19,7 @@ module.exports = class ReportBuilder { this._tree = {name: 'root'}; this._skips = []; this._tool = tool; - this._extraItems = {}; + this._apiValues = {}; this._pluginConfig = pluginConfig; this._TestAdapter = TestAdapter; } @@ -104,8 +104,8 @@ module.exports = class ReportBuilder { return this; } - setExtraItems(extraItems) { - this._extraItems = extraItems; + setApiValues(values) { + this._apiValues = values; return this; } @@ -213,7 +213,7 @@ module.exports = class ReportBuilder { skips: _.uniq(this._skips, JSON.stringify), suites: this._tree.children, config: {defaultView, baseHost, scaleImages, lazyLoadOffset, errorPatterns}, - extraItems: this._extraItems, + apiValues: this._apiValues, date: new Date().toString() }, this._stats); } diff --git a/lib/server-utils.js b/lib/server-utils.js index f6dca7550..ad42bb513 100644 --- a/lib/server-utils.js +++ b/lib/server-utils.js @@ -124,8 +124,12 @@ function hasImage(formattedResult) { } function prepareCommonJSData(data) { + const stringifiedData = JSON.stringify(data, (key, val) => { + return typeof val === 'function' ? val.toString() : val; + }); + return [ - `var data = ${JSON.stringify(data)};`, + `var data = ${stringifiedData};`, 'try { module.exports = data; } catch(e) {}' ].join('\n'); } diff --git a/lib/static/components/controls/menu-bar.js b/lib/static/components/controls/menu-bar.js index 662e12f72..93dd9489d 100644 --- a/lib/static/components/controls/menu-bar.js +++ b/lib/static/components/controls/menu-bar.js @@ -1,6 +1,6 @@ 'use strict'; -import React, {Component, Fragment} from 'react'; +import React, {Component} from 'react'; import {connect} from 'react-redux'; import PropTypes from 'prop-types'; import {Dropdown} from 'semantic-ui-react'; @@ -22,7 +22,7 @@ class MenuBar extends Component { const {extraItems} = this.props; if (isEmpty(extraItems)) { - return (); + return null; } return ( @@ -35,4 +35,4 @@ class MenuBar extends Component { } } -export default connect(({extraItems}) => ({extraItems}))(MenuBar); +export default connect(({apiValues: {extraItems}}) => ({extraItems}))(MenuBar); diff --git a/lib/static/components/section/body/index.js b/lib/static/components/section/body/index.js index 1f51862ae..85a5a1ed3 100644 --- a/lib/static/components/section/body/index.js +++ b/lib/static/components/section/body/index.js @@ -1,6 +1,6 @@ 'use strict'; -import {isEmpty, defaults, pick, values} from 'lodash'; +import {isEmpty, defaults, pick, values, mapValues, omitBy} from 'lodash'; import React, {Component} from 'react'; import {connect} from 'react-redux'; import {bindActionCreators} from 'redux'; @@ -78,6 +78,16 @@ class Body extends Component { this.props.actions.toggleStateResult({browserId, suitePath, stateName, retryIndex, opened}); } + getExtraMetaInfo = () => { + const {suite, apiValues: {extraItems, metaInfoExtenders}} = this.props; + + return omitBy(mapValues(metaInfoExtenders, (extender) => { + const stringifiedFn = extender.startsWith('return') ? extender : `return ${extender}`; + + return new Function(stringifiedFn)()(suite, extraItems); + }), isEmpty); + } + _toggleTestResult({opened}) { const {result: {name: browserId}, suite: {suitePath}} = this.props; @@ -169,7 +179,7 @@ class Body extends Component { {this._addRetryButton()} - + {description && } {this._getTabs()} @@ -179,10 +189,11 @@ class Body extends Component { } export default connect( - ({gui, running, suites, suiteIds}) => ({ + ({gui, running, suites, suiteIds, apiValues}) => ({ failed: values(pick(suites, suiteIds.failed)), gui, - running + running, + apiValues }), (dispatch) => ({actions: bindActionCreators(actions, dispatch)}) )(Body); diff --git a/lib/static/components/section/body/meta-info.js b/lib/static/components/section/body/meta-info.js index 3efec1d8d..2e9929e5c 100644 --- a/lib/static/components/section/body/meta-info.js +++ b/lib/static/components/section/body/meta-info.js @@ -33,12 +33,14 @@ const metaToElements = (metaInfo) => { export default class MetaInfo extends Component { static propTypes = { metaInfo: PropTypes.object.isRequired, - suiteUrl: PropTypes.string.isRequired + suiteUrl: PropTypes.string.isRequired, + getExtraMetaInfo: PropTypes.func.isRequired } render() { - const {metaInfo, suiteUrl} = this.props; - const formattedMetaInfo = Object.assign({}, metaInfo, {url: mkLinkToUrl(suiteUrl, metaInfo.url)}); + const {metaInfo, suiteUrl, getExtraMetaInfo} = this.props; + const extraMetaInfo = getExtraMetaInfo(); + const formattedMetaInfo = Object.assign({}, metaInfo, extraMetaInfo, {url: mkLinkToUrl(suiteUrl, metaInfo.url)}); const metaElements = metaToElements(formattedMetaInfo); return ( diff --git a/lib/static/modules/default-state.js b/lib/static/modules/default-state.js index b8838244b..6b2dbba77 100644 --- a/lib/static/modules/default-state.js +++ b/lib/static/modules/default-state.js @@ -14,7 +14,10 @@ export default Object.assign(defaults, { failed: [] }, closeIds: [], - extraItems: {}, + apiValues: { + extraItems: {}, + metaInfoExtenders: {} + }, loading: {}, modal: {}, stats: { diff --git a/lib/static/modules/reducer.js b/lib/static/modules/reducer.js index 3aaff0c59..9c9c83e2e 100644 --- a/lib/static/modules/reducer.js +++ b/lib/static/modules/reducer.js @@ -12,7 +12,7 @@ const localStorage = window.localStorage; function getInitialState(data) { const {skips, suites, config, total, updated, passed, - failed, skipped, warned, retries, perBrowser, extraItems, gui = false, date} = data; + failed, skipped, warned, retries, perBrowser, apiValues, gui = false, date} = data; const {errorPatterns, scaleImages, lazyLoadOffset, defaultView} = config; const parsedURL = new URL(window.location.href); const filteredBrowsers = parsedURL.searchParams.getAll('browser'); @@ -25,7 +25,7 @@ function getInitialState(data) { skips, groupedErrors, config, - extraItems, + apiValues, date: dateToLocaleString(date), stats: { all: {total, updated, passed, failed, skipped, retries, warned}, @@ -49,7 +49,7 @@ export default function reducer(state = getInitialState(compiledData), action) { autoRun, suites, skips, - extraItems, + apiValues, config: {scaleImages, lazyLoadOffset} } = action.payload; const {errorPatterns} = state.config; @@ -71,7 +71,7 @@ export default function reducer(state = getInitialState(compiledData), action) { autoRun, skips, groupedErrors, - extraItems, + apiValues, view: {scaleImages, lazyLoadOffset} }, formattedSuites @@ -355,4 +355,3 @@ function forceUpdateSuiteData(suites, test) { const id = getSuiteId(test); suites[id] = cloneDeep(suites[id]); } - diff --git a/lib/static/styles.css b/lib/static/styles.css index d17c367c8..1b5db5170 100644 --- a/lib/static/styles.css +++ b/lib/static/styles.css @@ -540,6 +540,10 @@ a:active { text-decoration: none; } +.menu-item__link::first-letter { + text-transform: uppercase; +} + .image-box__placeholder { position: relative; display: table-cell; diff --git a/test/gemini.js b/test/gemini.js index 9ffc91453..48733cc53 100644 --- a/test/gemini.js +++ b/test/gemini.js @@ -84,7 +84,7 @@ describe('lib/gemini', () => { sandbox.spy(ReportBuilder.prototype, 'setStats'); sandbox.stub(ReportBuilder.prototype, 'addSuccess'); - sandbox.stub(ReportBuilder.prototype, 'setExtraItems'); + sandbox.stub(ReportBuilder.prototype, 'setApiValues'); sandbox.stub(ReportBuilder.prototype, 'save'); }); @@ -110,14 +110,18 @@ describe('lib/gemini', () => { return initReporter_().then(() => assert.calledOnce(PluginAdapter.prototype.init)); }); - it('should set extra items', () => { - return initReporter_() - .then(() => { - gemini.htmlReporter.addExtraItem('some', 'item'); - gemini.emit(gemini.events.END); + it('should set values added through api', async () => { + await initReporter_(); - assert.calledOnceWith(ReportBuilder.prototype.setExtraItems, {some: 'item'}); - }); + gemini.htmlReporter.addExtraItem('key1', 'value1'); + gemini.htmlReporter.addMetaInfoExtender('key2', 'value2'); + + gemini.emit(gemini.events.END); + + assert.calledOnceWith(ReportBuilder.prototype.setApiValues, { + extraItems: {key1: 'value1'}, + metaInfoExtenders: {key2: 'value2'} + }); }); it('should save statistic', () => { diff --git a/test/hermione.js b/test/hermione.js index 5aa403596..13ccf921e 100644 --- a/test/hermione.js +++ b/test/hermione.js @@ -81,7 +81,7 @@ describe('lib/hermione', () => { sandbox.stub(ReportBuilder.prototype, 'addError'); sandbox.stub(ReportBuilder.prototype, 'addFail'); sandbox.stub(ReportBuilder.prototype, 'addRetry'); - sandbox.stub(ReportBuilder.prototype, 'setExtraItems'); + sandbox.stub(ReportBuilder.prototype, 'setApiValues'); sandbox.stub(ReportBuilder.prototype, 'save'); }); @@ -192,14 +192,18 @@ describe('lib/hermione', () => { }); }); - it('should set extra items', () => { - return initReporter_() - .then(() => { - hermione.htmlReporter.addExtraItem('some', 'item'); + it('should set values added through api', async () => { + await initReporter_(); - return hermione.emitAndWait(hermione.events.RUNNER_END); - }) - .then(() => assert.calledOnceWith(ReportBuilder.prototype.setExtraItems, {some: 'item'})); + hermione.htmlReporter.addExtraItem('key1', 'value1'); + hermione.htmlReporter.addMetaInfoExtender('key2', 'value2'); + + await hermione.emitAndWait(hermione.events.RUNNER_END); + + assert.calledOnceWith(ReportBuilder.prototype.setApiValues, { + extraItems: {key1: 'value1'}, + metaInfoExtenders: {key2: 'value2'} + }); }); it('should save statistic', () => { diff --git a/test/lib/gui/server.js b/test/lib/gui/server.js index 936eec601..11d77f57e 100644 --- a/test/lib/gui/server.js +++ b/test/lib/gui/server.js @@ -15,6 +15,7 @@ describe('lib/gui/server', () => { const mkExpressApp_ = () => ({ use: sandbox.stub(), get: sandbox.stub(), + set: sandbox.stub(), post: sandbox.stub(), listen: sandbox.stub().callsArg(2), static: sandbox.stub() @@ -84,4 +85,12 @@ describe('lib/gui/server', () => { assert.calledOnce(App.prototype.finalize); }); }); + + it('should correctly set json replacer', async () => { + const guiApi = mkApi_(); + + await startServer({guiApi}); + + assert.calledOnceWith(expressStub.set, 'json replacer', sinon.match.func); + }); }); diff --git a/test/lib/gui/tool-runner-factory/base-tool-runner.js b/test/lib/gui/tool-runner-factory/base-tool-runner.js index 354cd1bb9..ded274045 100644 --- a/test/lib/gui/tool-runner-factory/base-tool-runner.js +++ b/test/lib/gui/tool-runner-factory/base-tool-runner.js @@ -76,11 +76,11 @@ describe('lib/gui/tool-runner-factory/base-tool-runner', () => { }); describe('create', () => { - it('should set extra items', () => { - tool = {htmlReporter: {extraItems: {some: 'item'}}}; + it('should set values added through api', () => { + tool = {htmlReporter: {values: {foo: 'bar'}}}; initGuiReporter(); - assert.calledWith(reportBuilder.setExtraItems, {some: 'item'}); + assert.calledWith(reportBuilder.setApiValues, {foo: 'bar'}); }); }); diff --git a/test/lib/gui/tool-runner-factory/gemini/report-subscriber.js b/test/lib/gui/tool-runner-factory/gemini/report-subscriber.js index fe0fafe91..da4762531 100644 --- a/test/lib/gui/tool-runner-factory/gemini/report-subscriber.js +++ b/test/lib/gui/tool-runner-factory/gemini/report-subscriber.js @@ -23,7 +23,7 @@ describe('lib/gui/tool-runner-factory/gemini/report-subscriber', () => { reportBuilder = sinon.createStubInstance(ReportBuilder); sandbox.stub(ReportBuilder, 'create').returns(reportBuilder); reportBuilder.save.resolves(); - reportBuilder.setExtraItems.returns(reportBuilder); + reportBuilder.setApiValues.returns(reportBuilder); client = new EventEmitter(); sandbox.spy(client, 'emit'); diff --git a/test/lib/gui/tool-runner-factory/hermione/report-subsciber.js b/test/lib/gui/tool-runner-factory/hermione/report-subsciber.js index 3d905c18e..3dce3a8ed 100644 --- a/test/lib/gui/tool-runner-factory/hermione/report-subsciber.js +++ b/test/lib/gui/tool-runner-factory/hermione/report-subsciber.js @@ -26,7 +26,7 @@ describe('lib/gui/tool-runner-factory/hermione/report-subscriber', () => { reportBuilder = sinon.createStubInstance(ReportBuilder); sandbox.stub(ReportBuilder, 'create').returns(reportBuilder); reportBuilder.save.resolves(); - reportBuilder.setExtraItems.returns(reportBuilder); + reportBuilder.setApiValues.returns(reportBuilder); sandbox.stub(reporterHelper, 'saveTestImages').resolves(); diff --git a/test/lib/plugin-api.js b/test/lib/plugin-api.js index 0f384b7a0..f0b3e19f0 100644 --- a/test/lib/plugin-api.js +++ b/test/lib/plugin-api.js @@ -8,6 +8,26 @@ describe('plugin api', () => { pluginApi.addExtraItem('some', 'item'); - assert.deepEqual(pluginApi.extraItems, {some: 'item'}); + assert.deepEqual(pluginApi.values.extraItems, {some: 'item'}); + }); + + it('should store meta info extenders', () => { + const pluginApi = new PluginApi(); + + pluginApi.addMetaInfoExtender('name', 'value'); + + assert.deepEqual(pluginApi.values.metaInfoExtenders, {name: 'value'}); + }); + + it('should return all stored values', () => { + const pluginApi = new PluginApi(); + + pluginApi.addExtraItem('key1', 'value1'); + pluginApi.addMetaInfoExtender('key2', 'value2'); + + assert.deepEqual(pluginApi.values, { + extraItems: {key1: 'value1'}, + metaInfoExtenders: {key2: 'value2'} + }); }); }); diff --git a/test/lib/report-builder-factory/report-builder.js b/test/lib/report-builder-factory/report-builder.js index abd8eaa20..9da19cc64 100644 --- a/test/lib/report-builder-factory/report-builder.js +++ b/test/lib/report-builder-factory/report-builder.js @@ -144,12 +144,12 @@ describe('ReportBuilder', () => { assert.match(reportBuilder.getResult(), {foo: 'bar'}); }); - it('should set passed extra items', () => { + it('should set values added through api', () => { const reportBuilder = mkReportBuilder_(); - reportBuilder.setExtraItems({some: 'item'}); + reportBuilder.setApiValues({key: 'value'}); - assert.deepEqual(reportBuilder.getResult().extraItems, {some: 'item'}); + assert.deepEqual(reportBuilder.getResult().apiValues, {key: 'value'}); }); it('should add skipped test to result', () => { diff --git a/test/lib/static/components/controls/menu-bar.js b/test/lib/static/components/controls/menu-bar.js index dd17efff5..8d711d989 100644 --- a/test/lib/static/components/controls/menu-bar.js +++ b/test/lib/static/components/controls/menu-bar.js @@ -6,7 +6,7 @@ import {Dropdown} from 'semantic-ui-react'; describe('', () => { it('should show passed items as links in dropdown menu', () => { const component = mkConnectedComponent(, { - initialState: {extraItems: {some: 'link'}} + initialState: {apiValues: {extraItems: {some: 'link'}}} }); const dropDown = component.find(Dropdown.Item).first(); @@ -15,7 +15,9 @@ describe('', () => { }); it('should not show dropdown menu if extra items are not passed', () => { - const component = mkConnectedComponent(); + const component = mkConnectedComponent(, { + initialState: {apiValues: {extraItems: {}}} + }); const dropDown = component.find(Dropdown.Item).first(); assert.equal(dropDown.length, 0); diff --git a/test/lib/static/components/section/body.js b/test/lib/static/components/section/body/index.js similarity index 91% rename from test/lib/static/components/section/body.js rename to test/lib/static/components/section/body/index.js index ad34ecc06..3f6b667a3 100644 --- a/test/lib/static/components/section/body.js +++ b/test/lib/static/components/section/body/index.js @@ -1,8 +1,9 @@ import React from 'react'; import proxyquire from 'proxyquire'; import {defaults} from 'lodash'; -import {mkConnectedComponent, mkTestResult_, mkSuite_, mkImg_} from '../utils'; -import {mkBrowserResult} from '../../../../utils'; +import MetaInfo from 'lib/static/components/section/body/meta-info'; +import {mkConnectedComponent, mkTestResult_, mkSuite_, mkImg_} from '../../utils'; +import {mkBrowserResult} from '../../../../../utils'; import {SUCCESS, FAIL, ERROR} from 'lib/constants/test-statuses'; describe('', () => { @@ -268,4 +269,29 @@ describe('', () => { assert.calledOnceWith(actionsStub.retryTest, suite, 'bro'); }); }); + + describe('meta-info', () => { + it('should pass "getExtraMetaInfo" props to meta info component', () => { + const component = mkBodyComponent(); + const metaInfoProps = component.find(MetaInfo).props(); + + assert.isFunction(metaInfoProps.getExtraMetaInfo); + }); + + it('should return result of calling stringified function from "metaInfoExtenders"', () => { + const suite = mkSuite_(); + const extraItems = {item1: 1}; + const extender = () => 'foo-bar-baz'; + const metaInfoExtenders = {extender1: extender.toString()}; + + const component = mkBodyComponent({suite}, { + apiValues: {extraItems, metaInfoExtenders} + }); + + const metaInfoProps = component.find(MetaInfo).props(); + const result = metaInfoProps.getExtraMetaInfo(); + + assert.deepEqual(result, {extender1: 'foo-bar-baz'}); + }); + }); }); diff --git a/test/lib/static/components/section/body/meta-info.js b/test/lib/static/components/section/body/meta-info.js new file mode 100644 index 000000000..ab92748bc --- /dev/null +++ b/test/lib/static/components/section/body/meta-info.js @@ -0,0 +1,37 @@ +import React from 'react'; +import {defaults} from 'lodash'; +import MetaInfo from 'lib/static/components/section/body/meta-info'; +import {mkConnectedComponent} from '../../utils'; + +describe('', () => { + const sandbox = sinon.createSandbox(); + + let getExtraMetaInfo; + + const mkMetaInfoComponent = (props = {}) => { + props = defaults(props, { + metaInfo: {}, + suiteUrl: 'default-url', + getExtraMetaInfo + }); + + return mkConnectedComponent(); + }; + + beforeEach(() => { + getExtraMetaInfo = sandbox.stub().named('getExtraMetaInfo').returns({}); + }); + + afterEach(() => sandbox.restore()); + + it('should render all meta info from test, extra meta info and link to url', () => { + getExtraMetaInfo.returns({baz: 'qux'}); + const expectedMetaInfo = ['foo: bar', 'baz: qux', 'url: some-url']; + + const component = mkMetaInfoComponent({metaInfo: {foo: 'bar'}, suiteUrl: 'some-url'}); + + component.find('.toggle-open__item').forEach((node, i) => { + assert.equal(node.text(), expectedMetaInfo[i]); + }); + }); +});