Commit 28152658 authored by Chaillet Maxime's avatar Chaillet Maxime

it fixes #210

parent c65845f4
......@@ -9,7 +9,7 @@ import { uploadFile } from '../../api/icat/icatPlus.js'
import { Editor } from '@tinymce/tinymce-react'
import tinymce from 'tinymce/tinymce';
import { EditionModeConfig, ViewModeConfig } from '../../config/tinymce/tinymce.js'
import { GUI_CONFIG } from '../../config/gui.config.js';
import UI from '../../config/ui/config';
import { getFileByEventId } from "../../api/icat/icatPlus"
import { NEW_EVENT_CONTEXT, PLAINTEXT_CONTENT_FORMAT, EDIT_EVENT_CONTEXT, HTML_CONTENT_FORMAT } from '../../constants/EventTypes.js';
......@@ -102,7 +102,7 @@ class HTMLEditor extends Component {
let selectedNode = tinymce.activeEditor.selection.getNode();
if (selectedNode.nodeName === 'IMG' && selectedNode.style.height !== 'auto') {
let nxElement = selectedNode;
nxElement.style.height = GUI_CONFIG().NEW_EVENT_MAX_HEIGHT;
nxElement.style.height = UI.logbook.NEW_EVENT_MAX_HEIGHT;
nxElement.style.width = 'auto'; // a css trick for some browsers IE8 and old iceweasel
nxElement.onload = this.onImageLoaded;
tinymce.activeEditor.dom.replace(nxElement, selectedNode);
......
......@@ -214,15 +214,14 @@ class LazyContentEvent extends React.Component {
getHTMLContent(event) {
return getContent(event.content, 'html') ? convertImagesToThumbnails(getContent(event.content, 'html')) : convertImagesToThumbnails(getContent(event.content, 'plainText'));
}
getClassName(event){
console.log(event.category.toLowerCase() + " " + event.type.toLowerCase() )
if (event.type.toLowerCase() === "annotation"){
getClassName(event) {
if (event.type.toLowerCase() === "annotation") {
return 'text-primary';
}
if (event.category.toLowerCase() === "error"){
if (event.category.toLowerCase() === "error") {
return 'text-danger';
}
if (event.category.toLowerCase() === "commandline"){
if (event.category.toLowerCase() === "commandline") {
return 'text-muted';
}
return 'text-primary';
......@@ -235,7 +234,7 @@ class LazyContentEvent extends React.Component {
if ((this.props.event.type === NOTIFICATION) && this.props.event.previousVersionEvent) {
return <LazyLoad>
<div className={this.getClassName(this.props.event)} dangerouslySetInnerHTML={{ __html: this.getHTMLContent(getOriginalEvent(this.props.event)) }} />
<div className={this.getClassName(this.props.event)} dangerouslySetInnerHTML={{ __html: content }} />
<div className={this.getClassName(this.props.event)} dangerouslySetInnerHTML={{ __html: content }} />
</LazyLoad>;
}
......
import React from "react";
import PropTypes from 'prop-types';
import { GUI_CONFIG } from "../../config/gui.config";
import UI from '../../config/ui/config';
import ReactPaginate from 'react-paginate';
/* This class handles the display of pages for the logbook */
......@@ -33,11 +33,11 @@ class LogbookPager extends React.Component {
* Get the number of pages requested to display the data
*/
getTotalPageNumber() {
if (GUI_CONFIG().EVENTS_PER_PAGE) {
if (this.props.eventCount < GUI_CONFIG().EVENTS_PER_PAGE) {
if (UI.logbook.EVENTS_PER_PAGE) {
if (this.props.eventCount < UI.logbook.EVENTS_PER_PAGE) {
return 1;
} else {
return (Math.ceil(this.props.eventCount / GUI_CONFIG().EVENTS_PER_PAGE));
return (Math.ceil(this.props.eventCount / UI.logbook.EVENTS_PER_PAGE));
}
}
// if in case of error, displays all items on the same page
......
import React from 'react';
import PropTypes from 'prop-types';
import { Grid, Row, Col, FormControl, Popover, OverlayTrigger, Button, Panel, FormGroup, ControlLabel } from 'react-bootstrap';
import { GUI_CONFIG } from '../../../config/gui.config';
import UI from '../../../config/ui/config';
import { GithubPicker } from 'react-color';
import _ from 'lodash';
......@@ -13,7 +13,7 @@ class NewOrEditTagPanel extends React.Component {
constructor(props) {
super(props);
this.state = {
tag: _.cloneDeep(this.props.tag) || { name: '', description: '', color: GUI_CONFIG().DEFAULT_TAG_COLOR, investigationId: this.props.investigationId },
tag: _.cloneDeep(this.props.tag) || { name: '', description: '', color: UI.logbook.DEFAULT_TAG_COLOR, investigationId: this.props.investigationId },
};
this.onChangeComplete = this.onChangeComplete.bind(this);
......@@ -76,7 +76,7 @@ class NewOrEditTagPanel extends React.Component {
>
<div
style={{
backgroundColor: tag.color || GUI_CONFIG().DEFAULT_TAG_COLOR,
backgroundColor: tag.color || UI.logbook.DEFAULT_TAG_COLOR,
width: '30px',
height: '30px',
marginLeft: '50%',
......
......@@ -2,7 +2,7 @@ import React from 'react';
import Proptypes from 'prop-types';
import _ from 'lodash';
import CreatableSelect from 'react-select/lib/Creatable';
import { GUI_CONFIG } from '../../../config/gui.config';
import UI from '../../../config/ui/config';
class TagSelector extends React.Component {
......@@ -71,7 +71,7 @@ class TagSelector extends React.Component {
if (option && action) {
if (action.action === 'create-option') {
let newTag = {
color: GUI_CONFIG().DEFAULT_TAG_COLOR,
color: UI.logbook.DEFAULT_TAG_COLOR,
description: null,
name: option.label,
investigationId: this.props.investigationId
......
/**
* gui.config.js
* GUI configuration file
*/
export function GUI_CONFIG() {
return {
/** Number of logbook events to display per page. EVENTS_PER_PAGE should be lower than EVENTS_PER_DOWNLOAD */
EVENTS_PER_PAGE: 100,
/** Maximum number of logbook events downloaded from the server. This enables to store a larger set of
events than those required for a single page thus reducing HTTP requests to the server. */
EVENTS_PER_DOWNLOAD: 300,
/* the field used to sort events. Most of the time 'creationDate' is used. Possible values: 'creationDate', '_id', 'createdAt', 'updatedAt' */
SORT_EVENTS_BY: '_id',
/* the order the events sorted by SORT_EVENTS_BY will be ordered. Possible values: 1 (for ascending order), -1 (for descending order)*/
SORTING_ORDER: -1,
/** Tinymce editor minimum height when there is a single editor in the modal */
SINGLE_EDITOR_MIN_HEIGHT: "200px",
/** Tinymce editor maximum height when there is a single editor in the modal */
SINGLE_EDITOR_MAX_HEIGHT: "808px",
/** Tinymce editor minimum height when there are 2 editors in the modal */
DUAL_EDITOR_MIN_HEIGHT: "270px",
/** Tinymce editor maximum height when there are 2 editors in the modal */
DUAL_EDITOR_MAX_HEIGHT: "270px",
/* Default tag color used in the logbook when tag color is not set */
DEFAULT_TAG_COLOR: "#a6bded",
/* Refresh event list periodically with a time interval defined by AUTOREFRESH_DELAY when new events arrived.
* When it is set to false, the event list is not refreshed but the amount of new events which arriived is shown.
*/
AUTOREFRESH_EVENTLIST: true,
/* Time interval between requests checking whether new events arrived. (in milliseconds) */
AUTOREFRESH_DELAY: 10000,
}
}
\ No newline at end of file
......@@ -11,7 +11,6 @@ import 'tinymce/plugins/table';
import 'tinymce/plugins/lists';
import 'tinymce/plugins/autoresize';
import 'tinymce/plugins/importcss';
import { GUI_CONFIG } from '../gui.config';
// Configuration file for tinyMCE editor
......
......@@ -20,7 +20,30 @@ var UI =
isDatasetListVisible : true
},
logbook : {
/** Number of logbook events to display per page. EVENTS_PER_PAGE should be lower than EVENTS_PER_DOWNLOAD */
EVENTS_PER_PAGE: 100,
/** Maximum number of logbook events downloaded from the server. This enables to store a larger set of
events than those required for a single page thus reducing HTTP requests to the server. */
EVENTS_PER_DOWNLOAD: 300,
/* the field used to sort events. Most of the time 'creationDate' is used. Possible values: 'creationDate', '_id', 'createdAt', 'updatedAt' */
SORT_EVENTS_BY: '_id',
/* the order the events sorted by SORT_EVENTS_BY will be ordered. Possible values: 1 (for ascending order), -1 (for descending order)*/
SORTING_ORDER: -1,
/** Tinymce editor minimum height when there is a single editor in the modal */
SINGLE_EDITOR_MIN_HEIGHT: "200px",
/** Tinymce editor maximum height when there is a single editor in the modal */
SINGLE_EDITOR_MAX_HEIGHT: "808px",
/** Tinymce editor minimum height when there are 2 editors in the modal */
DUAL_EDITOR_MIN_HEIGHT: "270px",
/** Tinymce editor maximum height when there are 2 editors in the modal */
DUAL_EDITOR_MAX_HEIGHT: "270px",
/* Default tag color used in the logbook when tag color is not set */
DEFAULT_TAG_COLOR: "#a6bded",
/* Refresh event list periodically with a time interval defined by AUTOREFRESH_DELAY when new events arrived.
* When it is set to false, the event list is not refreshed but the amount of new events which arriived is shown.*/
AUTOREFRESH_EVENTLIST: true,
/* Time interval between requests checking whether new events arrived. (in milliseconds) */
AUTOREFRESH_DELAY: 10000,
},
footer : {
text : "European Synchrotron Radiation Facility"
......
......@@ -8,7 +8,7 @@ import EventList from '../../components/Logbook/List/EventList';
import EventListMenu from '../../components/Logbook/Menu/EventListMenu.js';
import { NEW_EVENT_INVISIBLE, NEW_EVENT_VISIBLE, LIST_VIEW, ERROR_MESSAGE_TYPE, INFO_MESSAGE_TYPE, EDIT_EVENT_CONTEXT, EDIT_EVENT_VISIBLE, EDIT_EVENT_INVISIBLE, NEW_EVENT_CONTEXT, LOGBOOK_CONTAINER_CONTEXT, LOGBOOK_CONTEXT_NAME_PROPOSAL, PUBLIC_EVENT_DETAILS_VISIBLE, PUBLIC_EVENT_DETAILS_INVISIBLE } from '../../constants/EventTypes.js';
import { convertPageToPageEventIndexes, isRangeAvailableOnTheClient } from '../../helpers/PaginationHelper.js';
import { GUI_CONFIG } from '../../config/gui.config.js';
import UI from '../../config/ui/config';
import Loading from '../../components/Loading.js';
import UserMessage from '../../components/UserMessage.js';
import { getSelectionFiltersBySearchCriteria, getSelectionFiltersForMongoQuery } from './SelectionFilterHelper.js';
......@@ -47,9 +47,9 @@ export class LogbookContainer extends React.Component {
isShowingEditEventUI: false,
isShowingPublicEventUI: false,
autorefreshEventList: GUI_CONFIG().AUTOREFRESH_EVENTLIST,
autorefreshEventList: UI.logbook.AUTOREFRESH_EVENTLIST,
pageEvents: [], // events currently displayed on the page
sortingFilter: { [GUI_CONFIG().SORT_EVENTS_BY]: GUI_CONFIG().SORTING_ORDER }, // current sorting flter
sortingFilter: { [UI.logbook.SORT_EVENTS_BY]: UI.logbook.SORTING_ORDER }, // current sorting flter
userSearchCriteria: [],
view: LIST_VIEW,
};
......@@ -75,22 +75,19 @@ export class LogbookContainer extends React.Component {
render() {
const { investigationId, user } = this.props;
const selectionFilter = getSelectionFiltersForMongoQuery(this.state.userSearchCriteria, this.state.sortingFilter, this.state.view);
if (this.isAppProperlyConfigured()) {
return (
<div style={{ marginBottom: '40px' }}>
<TagContainer context={LOGBOOK_CONTAINER_CONTEXT} investigationId={investigationId} />
<OverlayBox open={this.state.errorMessage ? true : false} onClose={() => { this.setState({ errorMessage: null }) }} classNames={{ modal: 'userMessageModalClass', closeButton: 'userMessageCloseButton' }}>
<UserMessage type={ERROR_MESSAGE_TYPE} message={this.state.errorMessage} />
{this.state.errorMessage ? <UserMessage type={ERROR_MESSAGE_TYPE} message={this.state.errorMessage} /> : null}
</OverlayBox>
<PeriodicRefresher
initialValue={[]}
intervalInMilliSeconds={GUI_CONFIG().AUTOREFRESH_DELAY}
intervalInMilliSeconds={UI.logbook.AUTOREFRESH_DELAY}
isEnabled={true}
onCallbackSuccess={this.onNewEventsReceived}
periodicCallback={(onSuccess, onFailure) => this.getEventsBySelectionFilter(0, getSelectionFiltersBySearchCriteria(this.state.userSearchCriteria, this.state.view), this.state.sortingFilter, false).then(events => onSuccess(events), error => onFailure(error))}>
......@@ -110,7 +107,7 @@ export class LogbookContainer extends React.Component {
onRefreshEventListMenuItemClicked={() => this.setState({ autorefreshEventList: !this.state.autorefreshEventList })}
onSortingButtonClicked={this.flipEventsSortingOrder}
searchEvents={this.searchEvents}
selectionFilter={selectionFilter}
selectionFilter={getSelectionFiltersForMongoQuery(this.state.userSearchCriteria, this.state.sortingFilter, this.state.view)}
sessionId={user.sessionId}
setNewEventVisibility={this.setNewEventVisibility}
setView={this.setView}
......@@ -292,7 +289,7 @@ export class LogbookContainer extends React.Component {
downloadedEvents: events,
downloadedEventIndexes: { start: offset, end: offset + events.length - 1 },
fetchedEventList: true,
pageEvents: _.slice(events, 0, GUI_CONFIG().EVENTS_PER_PAGE),
pageEvents: _.slice(events, 0, UI.logbook.EVENTS_PER_PAGE),
selectionFilter: selectionFilter,
sortingFilter: sortingFilter,
});
......@@ -327,7 +324,7 @@ export class LogbookContainer extends React.Component {
if (page) {
page = page.selected + 1;
let pageEventIndexes = convertPageToPageEventIndexes(page, GUI_CONFIG().EVENTS_PER_PAGE, this.state.eventCountBySelectionFilter);
let pageEventIndexes = convertPageToPageEventIndexes(page, UI.logbook.EVENTS_PER_PAGE, this.state.eventCountBySelectionFilter);
let areEventsAlreadyDownloaded = isRangeAvailableOnTheClient(pageEventIndexes, this.state.downloadedEventIndexes);
if (areEventsAlreadyDownloaded) {
......@@ -439,7 +436,7 @@ export class LogbookContainer extends React.Component {
*/
getEventsBySelectionFilter(offset, selectionFilter, sortingFilter, useLimit = true) {
const { investigationId, user } = this.props;
sortingFilter = sortingFilter || { [GUI_CONFIG().SORT_EVENTS_BY]: GUI_CONFIG().SORTING_ORDER }
sortingFilter = sortingFilter || { [UI.logbook.SORT_EVENTS_BY]: UI.logbook.SORTING_ORDER }
if (!selectionFilter) {
// there is not selectionfilter as parameter when the user has clicked on a page
selectionFilter = getSelectionFiltersBySearchCriteria(this.state.userSearchCriteria, this.state.view);
......@@ -452,7 +449,7 @@ export class LogbookContainer extends React.Component {
data: {
find: selectionFilter,
sort: sortingFilter,
limit: useLimit === true ? GUI_CONFIG().EVENTS_PER_DOWNLOAD : null,
limit: useLimit === true ? UI.logbook.EVENTS_PER_DOWNLOAD : null,
skip: offset
}
})
......@@ -464,7 +461,6 @@ export class LogbookContainer extends React.Component {
}
getAllEventsAndRefresh(view) {
console.log(this.state.sortingFilter);
this.getEventsBySelectionFilter(0, getSelectionFiltersBySearchCriteria([], view), this.state.sortingFilter)
.then(events => this.refreshEventList(events, 0, getSelectionFiltersBySearchCriteria([], view), this.state.sortingFilter));
......@@ -518,22 +514,22 @@ export class LogbookContainer extends React.Component {
* @returns {boolean} true when the app is properly configured
*/
isAppProperlyConfigured() {
if (!GUI_CONFIG()) {
console.log('[ERROR] [CONFIG] File gui.config.js is missing');
if (!UI.logbook) {
console.log('[ERROR] [CONFIG] logbook section is missing in File src/config/ui/config');
return false;
}
if (!GUI_CONFIG().SORT_EVENTS_BY) {
if (!UI.logbook.SORT_EVENTS_BY) {
console.log('[ERROR] [CONFIG] SORT_EVENTS_BY object is missing');
return false;
} else if (GUI_CONFIG().SORT_EVENTS_BY !== 'creationDate' && GUI_CONFIG().SORT_EVENTS_BY !== '_id' && GUI_CONFIG().SORT_EVENTS_BY !== 'createdAt' && GUI_CONFIG().SORT_EVENTS_BY !== 'updatedAt') {
} else if (UI.logbook.SORT_EVENTS_BY !== 'creationDate' && UI.logbook.SORT_EVENTS_BY !== '_id' && UI.logbook.SORT_EVENTS_BY !== 'createdAt' && UI.logbook.SORT_EVENTS_BY !== 'updatedAt') {
console.log("[ERROR] [CONFIG] SORT_EVENTS_BY value is not supported. Possible values are 'creationDate', '_id', 'createdAt' and 'updatedAt' ");
return false;
}
if (!GUI_CONFIG().SORTING_ORDER) {
if (!UI.logbook.SORTING_ORDER) {
console.log('[ERROR] [CONFIG] SORTING_ORDER object is missing');
return false;
}
if (!GUI_CONFIG().EVENTS_PER_PAGE) {
if (!UI.logbook.EVENTS_PER_PAGE) {
console.log('[ERROR] [CONFIG] EVENTS_PER_PAGE value is missing');
return false;
}
......
import { DOC_VIEW } from '../../constants/EventTypes.js';
import StringConverterForRegexp from 'escape-string-regexp';
import { GUI_CONFIG } from '../../config/gui.config.js';
import UI from '../../config/ui/config';
const REGEXP_FILTER_TYPE = 'regexpFilterType';
const EQUALITY_FILTER_TYPE = 'equalityFilterType';
......@@ -14,12 +13,8 @@ const EQUALITY_FILTER_TYPE = 'equalityFilterType';
* @param {*} view current logbook view
*/
export function getSelectionFiltersForMongoQuery(findCriteria, sortCriteria, view) {
if (!findCriteria) {
findCriteria = [];
}
if (!sortCriteria) {
sortCriteria = { [GUI_CONFIG().SORT_EVENTS_BY]: GUI_CONFIG().SORTING_ORDER };
}
if (!findCriteria) { findCriteria = []; }
if (!sortCriteria) { sortCriteria = { [UI.logbook.SORT_EVENTS_BY]: UI.logbook.SORTING_ORDER }; }
return {
find: getSelectionFiltersBySearchCriteria(findCriteria, view),
......
import React from 'react';
import Enzyme from 'enzyme';
import { createStore, applyMiddleware } from 'redux';
import { persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import logger from 'redux-logger';
import thunk from 'redux-thunk';
import reducer from '../../src/reducers';
import promise from "redux-promise-middleware";
import { LOGGED_IN } from '../../src/constants/ActionTypes';
import { GUI_CONFIG } from '../../src/config/gui.config';
jest.mock("../../src/config/gui.config");
import LogbookContainer from '../../src/containers/Logbook/LogbookContainer';
export function getMountedWrapper() {
/* overrides default configuration */
GUI_CONFIG.mockReturnValue({
EVENTS_PER_PAGE: 2,
SORT_EVENTS_BY: 'creationDate',
SORTING_ORDER: -1,
AUTOREFRESH_DELAY: 100,
AUTOREFRESH_EVENTLIST: false
})
const middleware = [thunk];
const persistConfig = { key: 'root', storage }
const persistedReducer = persistReducer(persistConfig, reducer)
const store = createStore(
persistedReducer,
{ user: { type: LOGGED_IN, username: 'username', sessionId: 'testSessionId' } },
applyMiddleware(...middleware, logger, promise(), thunk)
)
return Enzyme.mount(<LogbookContainer investigationId="testInvestigationId" />, { context: { store } })
};
\ No newline at end of file
......@@ -10,40 +10,39 @@ import thunk from 'redux-thunk'
import reducer from '../../src/reducers'
import promise from "redux-promise-middleware"
import { LOGGED_IN } from '../../src/constants/ActionTypes';
//GUI_CONFIG needs to be mocked before importing logbookContainer
import { GUI_CONFIG } from '../../src/config/gui.config';
jest.mock("../../src/config/gui.config")
import LogbookContainer, { LogbookContainer as LogbookContainerNoConnect } from '../../src/containers/Logbook/LogbookContainer';
import getUIConfiguration from '../uiConfig';
const resources = require('./resources/LogbookContainer.resource.js');
require('it-each')({ testPerIteration: true });
beforeEach(() => {
Enzyme.configure({ adapter: new Adapter() });
jest.resetModules()
})
describe("flipEventsSortingOrder", () => {
describe("AAflipEventsSortingOrder", () => {
it.each(resources.flipEventsSortingOrder, '%s', ['description'],
function (element, next) {
LogbookContainerNoConnect.prototype.getEventsBySelectionFilter = jest.fn((offset, selectionFilter, sortingFilter, useLimit) => Promise.resolve(element.serverResponse_No_Event));
LogbookContainerNoConnect.prototype.getEventCountBySelectionFilter = jest.fn(selectionFilter => Promise.resolve(element.serverResponse_No_EventCount));
//mock the configuration file. Since mockGetUIConfiguration is out of scope of jest.mock(), it must start with 'mock'.
const mockGetUIConfiguration = getUIConfiguration({ SORT_EVENTS_BY: element.SORT_EVENTS_BY, SORTING_ORDER: element.SORTING_ORDER, AUTOREFRESH_EVENTLIST: false })
jest.mock("../../src/config/ui/config", () => mockGetUIConfiguration);
expect(LogbookContainerNoConnect.prototype.getEventsBySelectionFilter).toHaveBeenCalledTimes(0);
let mountedWrapper = getMountedWrapper({ SORT_EVENTS_BY: element.SORT_EVENTS_BY, SORTING_ORDER: element.SORTING_ORDER, AUTOREFRESH_EVENTLIST: false });
mountedWrapper.update();
// require logbook class after the configuration mocking
const LogbookContainerClass = require('../../src/containers/Logbook/LogbookContainer').LogbookContainer;
LogbookContainerClass.prototype.getEventsBySelectionFilter = jest.fn((offset, selectionFilter, sortingFilter, useLimit) => Promise.resolve(element.serverResponse_No_Event));
LogbookContainerClass.prototype.getEventCountBySelectionFilter = jest.fn(selectionFilter => Promise.resolve(element.serverResponse_No_EventCount));
expect(LogbookContainerClass.prototype.getEventsBySelectionFilter).toHaveBeenCalledTimes(0);
expect(LogbookContainerNoConnect.prototype.getEventsBySelectionFilter).toHaveBeenCalledTimes(1);
expect(LogbookContainerNoConnect.prototype.getEventsBySelectionFilter).toHaveBeenCalledWith(expect.anything(), expect.anything(), element.expected.sortingFilterArgAtfirstCall);
let mountedWrapper = getMountedWrapper();
mountedWrapper.update();
expect(LogbookContainerClass.prototype.getEventsBySelectionFilter).toHaveBeenCalledTimes(1);
expect(LogbookContainerClass.prototype.getEventsBySelectionFilter).toHaveBeenCalledWith(expect.anything(), expect.anything(), element.expected.sortingFilterArgAtfirstCall);
mountedWrapper.find('EventListMenu').find({ eventKey: element.eventKey }).find('a').simulate('click');
// check the event list is flipped ie the proper call to the server is done; offset is 0 (ie show first page)
expect(LogbookContainerNoConnect.prototype.getEventsBySelectionFilter).toHaveBeenCalledTimes(2);
expect(LogbookContainerNoConnect.prototype.getEventsBySelectionFilter).toHaveBeenCalledWith(0, expect.anything(), element.expected.sortingFilterArgAtSecondCall);
LogbookContainerNoConnect.prototype.getEventsBySelectionFilter.mockRestore();
LogbookContainerNoConnect.prototype.getEventCountBySelectionFilter.mockRestore();
expect(LogbookContainerClass.prototype.getEventsBySelectionFilter).toHaveBeenCalledTimes(2);
expect(LogbookContainerClass.prototype.getEventsBySelectionFilter).toHaveBeenCalledWith(0, expect.anything(), element.expected.sortingFilterArgAtSecondCall);
next();
})
});
......@@ -644,34 +643,16 @@ describe("flipEventsSortingOrder", () => {
/**
* Get a mounted wrapper
* @param { object} config an object containing the logbook configuration settings. For example {EVENTS_PER_PAGE : 100}. When a config parameter
* is not provided, its value is taken from import { GUI_CONFIG } from '../../src/config/gui.config';
*/
export function getMountedWrapper(config) {
if (config) {
GUI_CONFIG.mockReturnValue({
EVENTS_PER_PAGE: config.EVENTS_PER_PAGE ? config.EVENTS_PER_PAGE : 100,
EVENTS_PER_DOWNLOAD: config.EVENTS_PER_DOWNLOAD ? config.EVENTS_PER_DOWNLOAD : 300,
SORT_EVENTS_BY: config.SORT_EVENTS_BY ? config.SORT_EVENTS_BY : '_id',
SORTING_ORDER: config.SORTING_ORDER ? config.SORTING_ORDER : -1,
SINGLE_EDITOR_MIN_HEIGHT: config.SINGLE_EDITOR_MIN_HEIGHT ? config.SINGLE_EDITOR_MIN_HEIGHT : '200px',
SINGLE_EDITOR_MAX_HEIGHT: config.SINGLE_EDITOR_MAX_HEIGHT ? config.SINGLE_EDITOR_MAX_HEIGHT : '800px',
DUAL_EDITOR_MIN_HEIGHT: config.DUAL_EDITOR_MIN_HEIGHT ? config.DUAL_EDITOR_MIN_HEIGHT : '270px',
DUAL_EDITOR_MAX_HEIGHT: config.DUAL_EDITOR_MAX_HEIGHT ? config.DUAL_EDITOR_MAX_HEIGHT : '270px',
DEFAULT_TAG_COLOR: config.DEFAULT_TAG_COLOR ? config.DEFAULT_TAG_COLOR : "#a6bded",
AUTOREFRESH_EVENTLIST: config.AUTOREFRESH_EVENTLIST === false ? config.AUTOREFRESH_EVENTLIST : true,
AUTOREFRESH_DELAY: config.AUTOREFRESH_DELAY ? config.AUTOREFRESH_DELAY : 10000,
})
const middleware = [thunk];
const persistConfig = { key: 'root', storage }
const persistedReducer = persistReducer(persistConfig, reducer)
const store = createStore(
persistedReducer,
{ user: { type: LOGGED_IN, username: 'username', sessionId: 'testSessionId' } },
applyMiddleware(...middleware, logger, promise(), thunk)
)
return Enzyme.mount(<LogbookContainer investigationId="testInvestigationId" />, { context: { store } })
}
function getMountedWrapper() {
const middleware = [thunk];
const persistConfig = { key: 'root', storage }
const persistedReducer = persistReducer(persistConfig, reducer)
const store = createStore(
persistedReducer,
{ user: { type: LOGGED_IN, username: 'username', sessionId: 'testSessionId' } },
applyMiddleware(...middleware, logger, promise(), thunk)
)
const LogbookContainer = require('../../src/containers/Logbook/LogbookContainer').default;
return Enzyme.mount(<LogbookContainer investigationId="testInvestigationId" />, { context: { store } })
}
\ No newline at end of file
jest.mock("../../src/config/gui.config");
import React from 'react'
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import { getMountedWrapper as getMountedLogbookContainerWrapper } from './LogbookContainer.test';
import { LogbookContainer as LogbookContainerNoConnect } from '../../src/containers/Logbook/LogbookContainer';
import { createStore, applyMiddleware } from 'redux'
import { persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage'
import logger from 'redux-logger'
import thunk from 'redux-thunk'
import reducer from '../../src/reducers'
import promise from "redux-promise-middleware"
import { LOGGED_IN } from '../../src/constants/ActionTypes';
import getUIConfiguration from '../uiConfig';
const IORequestModule = require('../../src/containers/Logbook/IORequests')
const resources = require('./resources/NewlyAvailableEventsDialogue.resource.js');
beforeEach(() => { Enzyme.configure({ adapter: new Adapter() }) })
beforeEach(() => {
Enzyme.configure({ adapter: new Adapter() });
jest.resetModules();
})
describe("NewlyAvailableEventsDialogueIntegrationTests", () => {
// mock and reimplement getTagsByInvestigationId()
......@@ -17,19 +26,24 @@ describe("NewlyAvailableEventsDialogueIntegrationTests", () => {
});
it('callsGetAllEventsAndRefresh', (done) => {
//mock the configuration file. Since mockGetUIConfiguration is out of scope of jest.mock(), it must start with 'mock'.
const mockGetUIConfiguration = getUIConfiguration({ EVENTS_PER_PAGE: 2, SORT_EVENTS_BY: 'creationDate', SORTING_ORDER: -1, AUTOREFRESH_EVENTLIST: false, AUTOREFRESH_DELAY: 100 })
jest.mock("../../src/config/ui/config", () => mockGetUIConfiguration);
LogbookContainerNoConnect.prototype.getEventsBySelectionFilter = jest.fn((offset, selectionFilter, sortingFilter, useLimit) => Promise.resolve(resources.refreshEventList.serverResponse_No_Event))
LogbookContainerNoConnect.prototype.getEventCountBySelectionFilter = jest.fn(selectionFilter => Promise.resolve(resources.refreshEventList.serverResponse_No_EventCount))
// require logbook class after the configuration mocking
const LogbookContainerClass = require('../../src/containers/Logbook/LogbookContainer').LogbookContainer;
LogbookContainerClass.prototype.getEventsBySelectionFilter = jest.fn((offset, selectionFilter, sortingFilter, useLimit) => Promise.resolve(resources.refreshEventList.serverResponse_No_Event))
LogbookContainerClass.prototype.getEventCountBySelectionFilter = jest.fn(selectionFilter => Promise.resolve(resources.refreshEventList.serverResponse_No_EventCount))
const mockedGetAllEventsAndRefresh = jest.spyOn(LogbookContainerNoConnect.prototype, 'getAllEventsAndRefresh');
const mockedGetAllEventsAndRefresh = jest.spyOn(LogbookContainerClass.prototype, 'getAllEventsAndRefresh');
const wrapper = getMountedLogbookContainerWrapper({ EVENTS_PER_PAGE: 2, SORT_EVENTS_BY: 'creationDate', SORTING_ORDER: -1, AUTOREFRESH_EVENTLIST: false, AUTOREFRESH_DELAY: 100 });
const wrapper = getMountedWrapper();
wrapper.update();
expect(mockedGetAllEventsAndRefresh).toHaveBeenCalledTimes(1); //called by component will mount
// change the mock functions to simulate that another event was created in the mean time. This is required so that the refresh glyphicon is rendered.
LogbookContainerNoConnect.prototype.getEventsBySelectionFilter.mockImplementation((offset, selectionFilter, sortingFilter, useLimit) => Promise.resolve(resources.refreshEventList.serverResponse_One_Event))
LogbookContainerNoConnect.prototype.getEventCountBySelectionFilter.mockImplementation(selectionFilter => Promise.resolve(resources.refreshEventList.serverResponse_One_EventCount))
LogbookContainerClass.prototype.getEventsBySelectionFilter.mockImplementation((offset, selectionFilter, sortingFilter, useLimit) => Promise.resolve(resources.refreshEventList.serverResponse_One_Event))
LogbookContainerClass.prototype.getEventCountBySelectionFilter.mockImplementation(selectionFilter => Promise.resolve(resources.refreshEventList.serverResponse_One_EventCount))
// wait 500ms, it should be sufficient for the periodicRefresher to make the second call
setTimeout(() => {
......@@ -42,11 +56,17 @@ describe("NewlyAvailableEventsDialogueIntegrationTests", () => {
})
it('refreshes the event list when the user clicks the icon', done => {
// start the logbook container, mock that one event is retrieved from the server
LogbookContainerNoConnect.prototype.getEventsBySelectionFilter = jest.fn((offset, selectionFilter, sortingFilter, useLimit) => Promise.resolve(resources.refreshEventList.serverResponse_One_Event))
LogbookContainerNoConnect.prototype.getEventCountBySelectionFilter = jest.fn(selectionFilter => Promise.resolve(resources.refreshEventList.serverResponse_One_EventCount))
//mock the configuration file. Since mockGetUIConfiguration is out of scope of jest.mock(), it must start with 'mock'.
const mockGetUIConfiguration = getUIConfiguration({ EVENTS_PER_PAGE: 2, SORT_EVENTS_BY: 'creationDate', SORTING_ORDER: -1, AUTOREFRESH_EVENTLIST: false, AUTOREFRESH_DELAY: 100 })
jest.mock("../../src/config/ui/config", () => mockGetUIConfiguration);
const wrapper = getMountedLogbookContainerWrapper({ EVENTS_PER_PAGE: 2, SORT_EVENTS_BY: 'creationDate', SORTING_ORDER: -1, AUTOREFRESH_EVENTLIST: false, AUTOREFRESH_DELAY: 100 });
// require logbook class after the configuration mocking
const LogbookContainerClass = require('../../src/containers/Logbook/LogbookContainer').LogbookContainer;
// start the logbook container, mock that one event is retrieved from the server
LogbookContainerClass.prototype.getEventsBySelectionFilter = jest.fn((offset, selectionFilter, sortingFilter, useLimit) => Promise.resolve(resources.refreshEventList.serverResponse_One_Event))
LogbookContainerClass.prototype.getEventCountBySelectionFilter = jest.fn(selectionFilter => Promise.resolve(resources.refreshEventList.serverResponse_One_EventCount))
const wrapper = getMountedWrapper();
setTimeout(() => {
// after 200ms, the event list should have been rendered
......@@ -54,8 +74,8 @@ describe("NewlyAvailableEventsDialogueIntegrationTests", () => {
expect(wrapper.find('Event')).toHaveLength(1);
// Here we simulate that a new event was created. So the server returns 2 events
LogbookContainerNoConnect.prototype.getEventsBySelectionFilter.mockImplementation((offset, selectionFilter, sortingFilter, useLimit) => Promise.resolve(resources.refreshEventList.serverResponse_Two_Event))
LogbookContainerNoConnect.prototype.getEventCountBySelectionFilter.mockImplementation(selectionFilter => Promise.resolve(resources.refreshEventList.serverResponse_Two_EventCount))
LogbookContainerClass.prototype.getEventsBySelectionFilter.mockImplementation((offset, selectionFilter, sortingFilter, useLimit) => Promise.resolve(resources.refreshEventList.serverResponse_Two_Event))
LogbookContainerClass.prototype.getEventCountBySelectionFilter.mockImplementation(selectionFilter => Promise.resolve(resources.refreshEventList.serverResponse_Two_EventCount))
setTimeout(() => {
// wait 500ms, it should be sufficient for the periodicRefresher to make the second call
......@@ -72,4 +92,20 @@ describe("NewlyAvailableEventsDialogueIntegrationTests", () => {
}, 500);
}, 200)
})
});
\ No newline at end of file
});
/**
* Get a mounted wrapper
*/
function getMountedWrapper() {
const middleware = [thunk];
const persistConfig = { key: 'root', storage }
const persistedReducer = persistReducer(persistConfig, reducer)
const store = createStore(
persistedReducer,
{ user: { type: LOGGED_IN, username: 'username', sessionId: 'testSessionId' } },
applyMiddleware(...middleware, logger, promise(), thunk)
)
const LogbookContainer = require('../../src/containers/Logbook/LogbookContainer').default;
return Enzyme.mount(<LogbookContainer investigationId="testInvestigationId" />, { context: { store } })
}
\ No newline at end of file
/**
* Function used to mock the app UI configuration for tests
*/
export default function getUIConfiguration(config) {
return {
__esModule: true,
default: {
status: {
offline: {
enabled: false,
message: "Sorry, we're down for scheduled maintenance right now."
}
},
menu: {
applicationTittle: "Data Portal",
isSearchVisible: true,
isClosedDataVisible: true,
isOpenDataVisible: true,
isMySelectionVisible: true
},
loginForm: {
text: "Sign in with your ESRF's user account"
},
investigationContainer: {
isDatasetListVisible: true
},
logbook: {
EVENTS_PER_PAGE: config.EVENTS_PER_PAGE ? config.EVENTS_PER_PAGE : 100,
EVENTS_PER_DOWNLOAD: config.EVENTS_PER_DOWNLOAD ? config.EVENTS_PER_DOWNLOAD : 300,
SORT_EVENTS_BY: config.SORT_EVENTS_BY ? config.SORT_EVENTS_BY : '_id',
SORTING_ORDER: config.SORTING_ORDER ? config.SORTING_ORDER : -1,
SINGLE_EDITOR_MIN_HEIGHT: config.SINGLE_EDITOR_MIN_HEIGHT ? config.SINGLE_EDITOR_MIN_HEIGHT : '200px',
SINGLE_EDITOR_MAX_HEIGHT: config.SINGLE_EDITOR_MAX_HEIGHT ? config.SINGLE_EDITOR_MAX_HEIGHT : '800px',
DUAL_EDITOR_MIN_HEIGHT: config.DUAL_EDITOR_MIN_HEIGHT ? config.DUAL_EDITOR_MIN_HEIGHT : '270px',
DUAL_EDITOR_MAX_HEIGHT: config.DUAL_EDITOR_MAX_HEIGHT ? config.DUAL_EDITOR_MAX_HEIGHT : '270px',
DEFAULT_TAG_COLOR: config.DEFAULT_TAG_COLOR ? config.DEFAULT_TAG_COLOR : "#a6bded",
AUTOREFRESH_EVENTLIST: config.AUTOREFRESH_EVENTLIST === false ? config.AUTOREFRESH_EVENTLIST : true,
AUTOREFRESH_DELAY: config.AUTOREFRESH_DELAY ? config.AUTOREFRESH_DELAY : 10000
},
footer: {
text: "European Synchrotron Radiation Facility"
}
}
}
}
\ No newline at end of file
import React from 'react'
import Enzyme from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'
const IORequestModule = require('../../src/containers/Logbook/IORequests')
import { LogbookContainer } from '../../src/containers/Logbook/LogbookContainer';