Commit 9804b28b authored by Maxime Chaillet's avatar Maxime Chaillet Committed by Chaillet Maxime

use karma to test the app. display the proposal and beamline in a table.

parent 459a58d1
RewriteEngine On
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
......
......@@ -7,26 +7,29 @@
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
<!-- Using grunt-wiredep, the proper js files from bower components are included below -->
<!-- bower:js -->
<script src="bower_components/jquery/dist/jquery.js"></script>
<script src="bower_components/dustjs-linkedin/dist/dust-full.min.js"></script>
<script src="bower_components/bootstrap/dist/js/bootstrap.js"></script>
<script src="bower_components/dustjs-helpers/dist/dust-helpers.min.js"></script>
<script src="bower_components/lodash/lodash.js"></script>
<script src="bower_components/moment/moment.js"></script>
<!-- endbower -->
<!-- Using grunt-include-source, the proper js files created by us (not minified) are included below -->
<script src="src/author.js"></script>
<script src="src/beamlineurl.js"></script>
<script src="src/citation.js"></script>
<script src="src/constants.js"></script>
<script src="src/doicontroller.js"></script>
<script src="src/doiData.js"></script>
<script src="src/doiview.js"></script>
<script src="src/event.js"></script>
<script src="src/experimentalreportcontroller.js"></script>
<script src="src/jsonextractor.js"></script>
<script src="src/metadataTableHelper.js"></script>
<!-- Using grunt-wiredep, the proper js files from bower components are included below -->
<!-- bower:js -->
<script src="bower_components/jquery/dist/jquery.js"></script>
<script src="bower_components/dustjs-linkedin/dist/dust-full.min.js"></script>
<script src="bower_components/bootstrap/dist/js/bootstrap.js"></script>
<script src="bower_components/dustjs-helpers/dist/dust-helpers.min.js"></script>
<script src="bower_components/lodash/lodash.js"></script>
<script src="bower_components/moment/moment.js"></script>
<!-- endbower -->
<!-- bower:css -->
<link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css" />
......
......@@ -7,12 +7,13 @@
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
<!-- Using grunt-include-source, the proper js files created by us (not minified) are included below -->
<!-- include: "type": "js", "files": "src/*.js" -->
<!-- Using grunt-wiredep, the proper js files from bower components are included below -->
<!-- bower:js -->
<!-- endbower -->
<!-- Using grunt-include-source, the proper js files created by us (not minified) are included below -->
<!-- include: "type": "js", "files": "src/*.js" -->
<!-- bower:css -->
<!-- endbower -->
......
......@@ -72,4 +72,4 @@
</div>
</footer>
</body>
</html>
\ No newline at end of file
</html>
// Karma configuration
// Generated on Thu Oct 11 2018 23:09:22 GMT+0200 (CEST)
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine', 'browserify'],
// list of files / patterns to load in the browser
files: [
'src/jsonextractor.js',
'src/constants.js',
'tests/jsonExtractor.test.js',
'bower_components/lodash/lodash.js'
],
// list of files / patterns to exclude
exclude: [
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
'tests/jsonExtractor.test.js': [ 'browserify' ]
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['Firefox'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false,
// Concurrency level
// how many browser should be started simultaneous
concurrency: Infinity
})
}
This diff is collapsed.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
{
"name": "doi-landing-page",
"jest": {
"rootDir": "tests"
},
"version": "0.0.0",
"description": "",
"main": "Gruntfile.js",
"dependencies": {
"grunt": "^1.0.1",
"grunt-contrib-jshint": "^1.1.0",
"grunt-contrib-uglify": "^3.2.1",
"grunt-contrib-watch": "^1.0.0",
"grunt-dust": "^0.9.4",
"grunt-dustjs": "^1.4.0",
"grunt-wiredep": "^3.0.1"
},
"devDependencies": {
"grunt": "^1.0.1",
"grunt-contrib-cssmin": "^2.2.1",
"grunt-contrib-jshint": "^1.1.0",
"grunt-include-source": "^1.1.0",
"grunt-plato": "^1.4.0",
"jest": "^23.6.0"
},
"scripts": {
"test": "jest --watchAll"
},
"repository": {
"type": "git",
"url": "git@gitlab.esrf.fr:icat/doi-landing-page.git"
},
"author": "",
"license": "ISC"
}
\ No newline at end of file
"name": "doi-landing-page",
"version": "0.0.0",
"description": "",
"main": "Gruntfile.js",
"dependencies": {
"grunt": "^1.0.1",
"grunt-contrib-jshint": "^1.1.0",
"grunt-contrib-uglify": "^3.2.1",
"grunt-contrib-watch": "^1.0.0",
"grunt-dust": "^0.9.4",
"grunt-dustjs": "^1.4.0",
"grunt-wiredep": "^3.0.1"
},
"devDependencies": {
"browserify": "^16.2.3",
"grunt": "^1.0.1",
"grunt-contrib-cssmin": "^2.2.1",
"grunt-contrib-jshint": "^1.1.0",
"grunt-include-source": "^1.1.0",
"grunt-plato": "^1.4.0",
"jasmine-core": "^3.2.1",
"karma": "^3.0.0",
"karma-browserify": "^5.3.0",
"karma-chrome-launcher": "^2.2.0",
"karma-firefox-launcher": "^1.1.0",
"karma-jasmine": "^1.1.2",
"watchify": "^3.11.0"
},
"scripts": {
"test": "./node_modules/jest/bin/jest.js"
},
"repository": {
"type": "git",
"url": "git@gitlab.esrf.fr:icat/doi-landing-page.git"
},
"author": "",
"license": "ISC"
}
var CONSTANTS = {
ES_RESOURCE_TYPE : "experimental session resource type",
DC_RESOURCE_TYPE : "dataset collection resource type"
};
//module.exports = CONSTANTS;
......@@ -3,6 +3,7 @@ function DoiData() {
}
/**
* Get the accessibility status
* @param {string} resourceType the resource type for this DOI
* @param {string} sessionDate The timeStamp the experiment was started
* @param {string} publiclyAccessibleYear The year the data will be publicly accesssible.
* @return {string}
......@@ -10,19 +11,24 @@ function DoiData() {
* "Restricted access" : the data is still under embargo. Only accessible to experimental team members
*
* */
DoiData.prototype.getAccessibilityStatus = function( sessionDate, publiclyAccessibleYear ) {
DoiData.prototype.getAccessibilityStatus = function (resourceType, sessionDate, publiclyAccessibleYear) {
if (resourceType) {
if (resourceType === CONSTANTS.ES_RESOURCE_TYPE) {
if (publiclyAccessibleYear && sessionDate) {
var publiclyAvailableDate = moment(publiclyAccessibleYear, "YYYY");
var now = moment();
if ( publiclyAccessibleYear && sessionDate ) {
var publiclyAvailableDate = moment( publiclyAccessibleYear, "YYYY" );
var now = moment();
if ( now > publiclyAvailableDate ) {
if (now > publiclyAvailableDate) {
return "Open access";
} else if (now <= publiclyAvailableDate) {
return "Restricted access";
}
}
} else if (resourceType === CONSTANTS.DC_RESOURCE_TYPE){
return "Open access";
} else if ( now <= publiclyAvailableDate ) {
return "Restricted access";
}
}
console.log( "Failed to determine whether the accessibility of the DOI." );
console.log("Failed to determine whether the accessibility of the DOI.");
return "Accessibility status could not be determined";
};
This diff is collapsed.
......@@ -3,6 +3,7 @@ function DOIView() {
this.mainPanelId = "main";
this.reportPanelId = "expReport";
this.badgePanelId = "badges";
this.metadataDivId = 'metadata';
this.reportExperimentFileNames = null;
this.failedRecievingExpReport = false;
......@@ -58,6 +59,7 @@ DOIView.prototype.renderDOIData = function (doiData) {
$('#' + _this.mainPanelId).html(out);
_this.isDOIAlreadyRendered = true;
_this.renderBadges(doiData);
_this.renderMetadata(doiData);
/**
* If there are experimental reports already retrieved then render them after
* the rendering of the DOI
......@@ -131,9 +133,8 @@ DOIView.prototype.renderErrorForExperimentalReport = function () {
/**
* Render the badge template in the corresponding div
*
* */
* @param {object} data : the doiData object as constructed by the doiController
*/
DOIView.prototype.renderBadges = function (data) {
if (data) {
var _this = this;
......@@ -143,10 +144,24 @@ DOIView.prototype.renderBadges = function (data) {
}, function (err, out) {
$('#' + _this.badgePanelId).html(out);
});
}
};
/**
* Render the badge template in the corresponding div
*/
DOIView.prototype.renderMetadata = function (data) {
if (data) {
var _this = this;
dust.render('metadata_tpl', {
data: data
}, function (err, out) {
$('#' + _this.metadataDivId).html(out);
});
}
};
/**
* Set the message which is displayed just above the "Access data button" in experimental data box.
*
......
function JsonExtractor(json) {
}
......@@ -14,7 +13,7 @@ function JsonExtractor(json) {
JsonExtractor.prototype.extractInvestigationId = function (data) {
var regExp = RegExp(/\/\w*-*[Ee][Ss][Rr][Ff]-[Ee][Ss]-(\d+)$/);
//return regExp.exec( data.doi )[1];
return "investigationId"
return "investigationId";
};
/**
......@@ -28,9 +27,12 @@ JsonExtractor.prototype.extractInvestigationId = function (data) {
JsonExtractor.prototype.getFieldFromSubject = function (subject, field) {
if (subject) {
if (subject[0]) {
var regExp = new RegExp("^" + field, 'i');
for (var i = 0; i < subject[0].length; i++) {
if (subject[0][i].subject_scheme === field) {
return _.split(subject[0][i].text, ',');
if (regExp.test(subject[0][i].subject_scheme)) {
if (subject[0][i].text) {
return _.split(subject[0][i].text, ',');
}
}
}
}
......@@ -89,14 +91,17 @@ JsonExtractor.prototype.getResourceTypeGeneral = function (data) {
/**
* Get the resource type
* @param {object}
* data The data object provided by datacite
* @return {string}
* The resource tyoe. Null if it does not exist.
* @param {object} data The data object provided by datacite
* @return {string} Resource tyoe. Null if it does not exist.
* */
JsonExtractor.prototype.getResourceType = function (data) {
if (data && data.resource_type) {
return data.resource_type;
if (data.resource_type === "Experiment Session") {
return CONSTANTS.ES_RESOURCE_TYPE;
}
if (data.resource_type === "Datacollection") {
return CONSTANTS.DC_RESOURCE_TYPE;
}
}
return null;
};
};
\ No newline at end of file
function proposalBeamLineTable(chunk, context, bodies, params) {
var proposals = params.proposals;
var beamlines = params.beamlines;
chunk.write('<table class="table table-striped">');
chunk.write('<thead>');
chunk.write('<tr>');
chunk.write('<th scope="col">Proposal</th>');
chunk.write('<th scope="col">Beamline</th>');
chunk.write('</tr>');
chunk.write('</thead>');
chunk.write('<tbody>');
for (let index = 0; index < proposals.length; index++) {
const proposal = proposals[index];
const beamline = beamlines[index];
chunk.write('<tr>');
chunk.write('<td>' + proposals[index] + '</td>');
if (beamlines[index]) {
chunk.write('<td>' + beamlines[index] + '</td>');
} else {
chunck.write('<td> unknown </td>');
}
chunk.write('</tr>');
}
chunk.write('</tbody>');
chunk.write('</table>');
return chunk.render(bodies.block, context);
}
dust.helpers.proposalBeamLineTable = proposalBeamLineTable;
<div class="row margin-left-0 margin-right-0">
{@eq key=data.resourceType value="Experiment Session"}
{@eq key=data.resourceType value=CONSTANTS.ES_RESOURCE_TYPE}
<div class="col-auto padding-right-2 padding-left-2">
<span class="badge badge-secondary font-1p4rem " > Session </span>
</div>
</div>
{/eq}
{@eq key=data.resourceType value=CONSTANTS.DC_RESOURCE_TYPE}
<div class="col-auto padding-right-2 padding-left-2">
<span class="badge badge-secondary font-1p4rem " > Collection </span>
</div>
{/eq}
<div class="col"> </div>
......
......@@ -54,67 +54,7 @@
<hr>
<div class="row">
<div class="col">
<div class="myBorder-left">
<label> Proposal </label>
{?data.proposalNumber}
<div class="padding-left-15">{data.proposalNumber}</div>
{:else}
<div class="padding-left-15"> Not available</div>
{/data.proposalNumber}
</div>
</div>
<div class="col">
<div class="myBorder-left">
<label> Publication year </label>
{?data.mintingYear}
<div class="padding-left-15">{data.mintingYear}</div>
{:else}
<div class="padding-left-15"> Not available</div>
{/data.mintingYear}
</div>
</div>
<div class="col">
<div class="myBorder-left">
<label> Beamline </label>
{?data.beamline}
{@eq key=data.beamlineUrl value="noLink"}
<div class="padding-left-15">{data.beamline}</div>
{:else}
<div class="padding-left-15">
<a href="{data.beamlineUrl}" target="_blank"> {data.beamline} </a>
</div>
{/eq}
{:else}
<div class="padding-left-15">Not available</div>
{/data.beamline}
</div>
</div>
<div class="col">
<div class="myBorder-left">
<label> Session date </label>
{?data.sessionDate}
<div class="padding-left-15">{data.sessionDate}</div>
{:else}
<div class="padding-left-15"> Not available</div>
{/data.sessionDate}
</div>
</div>
<div class="col-4">
<div class="myBorder-left">
<label>Category </label>
{?data.proposalType}
<div class="padding-left-15">{data.proposalType}</div>
{:else}
<div class="padding-left-15"> Not available</div>
{/data.proposalType}
</div>
</div>
<div class="row" id="metadata">
</div>
<hr>
......@@ -157,7 +97,7 @@
<div class="row">
<div class="col-1"> </div>
<div class="col-10">
<form action="https://icat.esrf.fr/#/browse/facility/ESRF/proposal/{data.proposalNumber}/investigation/{data.investigationId}/dataset" target="_blank">
<form action="https://icat.esrf.fr/#/browse/facility/ESRF/proposal/{data.proposalName}/investigation/{data.investigationId}/dataset" target="_blank">
<button type="submit" class="btn btn-primary btn-lg btn-block"> Access data </button>
</form>
</div>
......
{@eq key=data.resourceType value=data.ES_RESOURCE_TYPE}
<div class="col">
<div class="myBorder-left">
<label> Proposal </label>
{?data.proposalName}
<div class="padding-left-15">{data.proposalName}</div>
{:else}
<div class="padding-left-15"> Not available</div>
{/data.proposalName}
</div>
</div>
<div class="col">
<div class="myBorder-left">
<label> Publication year </label>
{?data.mintingYear}
<div class="padding-left-15">{data.mintingYear}</div>
{:else}
<div class="padding-left-15"> Not available</div>
{/data.mintingYear}
</div>
</div>
<div class="col">
<div class="myBorder-left">
<label> Beamline </label>
{?data.beamline}
{@eq key=data.beamlineUrl value="noLink"}
<div class="padding-left-15">{data.beamline}</div>
{:else}
<div class="padding-left-15">
<a href="{data.beamlineUrl}" target="_blank"> {data.beamline} </a>
</div>
{/eq}
{:else}
<div class="padding-left-15">Not available</div>
{/data.beamline}
</div>
</div>
<div class="col">
<div class="myBorder-left">
<label> Session date </label>
{?data.sessionDate}
<div class="padding-left-15">{data.sessionDate}</div>
{:else}
<div class="padding-left-15"> Not available</div>
{/data.sessionDate}
</div>
</div>
<div class="col-4">
<div class="myBorder-left">
<label>Category </label>
{?data.proposalType}
<div class="padding-left-15">{data.proposalType}</div>
{:else}
<div class="padding-left-15"> Not available</div>
{/data.proposalType}
</div>
</div>
{/eq}
{@eq key=data.resourceType value=data.DC_RESOURCE_TYPE}
<div class="container-fluid">
<div class="row">
<div class="col-sm-3">
<div class="myBorder-left">
{@proposalBeamLineTable proposals=data.proposalName beamlines=data.beamline }
{/proposalBeamLineTable}
</div>
</div>
<div class="col-sm-9">
le reste
</div>
</div>
</div>
{/eq}
describe("jsonExtractor", () => {
describe("getFieldFromSubject()", () => {
it("extract field composed of a string without coma", () => {
let actualSubject = [
[
{
"subject_scheme": "Proposal",
"text": "IH-HC-3376"
}
]
];
let expectedField = ["IH-HC-3376"];
let myJsonExtractor = new JsonExtractor();
expect(myJsonExtractor.getFieldFromSubject(actualSubject, "Proposal")).toEqual(expectedField);
})
it("extract field composed of a string with coma", () => {
let actualSubject = [
[
{
"subject_scheme": "Proposal",
"text": "MA-4196,MD-1207"
}
]
];
let expectedField = ["MA-4196", "MD-1207"];
let myJsonExtractor = new JsonExtractor();
expect(myJsonExtractor.getFieldFromSubject(actualSubject, "Proposal")).toEqual(expectedField);
})
it("is case insensitive on the field", () => {
let actualSubject = [
[
{
"subject_scheme": "instrument",
"text": "id01"
}
]
];
let expectedField = ["id01"];
let myJsonExtractor = new JsonExtractor();
expect(myJsonExtractor.getFieldFromSubject(actualSubject, "Instrument")).toEqual(expectedField);
})
it("returns null when the field does not exist in the subject", () => {
let actualSubject = [
[
{
"subject_scheme": "Instrument",
"text": "id01"
}
]
];
let expectedField = null;
let myJsonExtractor = new JsonExtractor();
expect(myJsonExtractor.getFieldFromSubject(actualSubject, "Proposal")).toEqual(expectedField);
})
it("returns null when the field exists but has no text associated", () => {
let actualSubject = [
[
{
"subject_scheme": "Proposal",
}
]
];
let expectedField = null;
let myJsonExtractor = new JsonExtractor();
expect(myJsonExtractor.getFieldFromSubject(actualSubject, "Proposal")).toEqual(expectedField);
})
})
describe("getResourceType()", () => {
it("returns ES_RESOURCE_TYPE when the doi resource type is 'experiment session'", () => {
let actualDoiData = {
"resource_type": "Experiment Session"
};
let expectedResourceType = CONSTANTS.ES_RESOURCE_TYPE;
let myJsonExtractor = new JsonExtractor();
expect(myJsonExtractor.getResourceType(actualDoiData)).toEqual(expectedResourceType);
})
it("returns DC_RESOURCE_TYPE when the doi resource type is 'Datacollection'", () => {
let actualDoiData = {
"resource_type": "Datacollection"
};
let expectedResourceType = CONSTANTS.DC_RESOURCE_TYPE;
let myJsonExtractor = new JsonExtractor();
expect(myJsonExtractor.getResourceType(actualDoiData)).toEqual(expectedResourceType);
})
it("returns null when the doi resource type is not present", () => {
let actualDoiData = {
"title": "just a title",
};
let expectedResourceType = null;
let myJsonExtractor = new JsonExtractor();
expect(myJsonExtractor.getResourceType(actualDoiData)).toEqual(expectedResourceType);
})
})
})
/**
* This file contains data received from datacite for different DOIs.
* doiData1 : metadata associated to a doi created from an experimental session
* doiData2 : metadata associated to a doi created from dataset collection
*/
export const doiData1 = {
"id": "https://doi.org/10.15151/esrf-es-90632078",
"doi": "10.15151/esrf-es-90632078",
"creator": [
{
"type": "Person",
"name": "Steven LEAKE",
"givenName": "Steven",
"familyName": "LEAKE"
},
{
"type": "Person",