Skip to content
Snippets Groups Projects
Verified Commit ac5f5dbb authored by Timm Fitschen's avatar Timm Fitschen
Browse files

TST: some tests for new_module

parent 5f0b328e
No related branches found
No related tags found
No related merge requests found
...@@ -33,30 +33,68 @@ ...@@ -33,30 +33,68 @@
* @requires jQuery * @requires jQuery
* @requires logger * @requires logger
*/ */
var new_module = function ($, logger, is_in_view_port, retrieve_config, plotly) { var new_module = function ($, logger, is_in_view_port, load_config, getEntityPath, connection) {
/**
* Check if an entity has a path attribute and one of a set of extensions.
*
* Note: the array of extensions must contain only lower-case strings.
*
* @param {HTMLElement} entity
* @param {string[]} extensions - an array of file extesions, e.g. `jpg`.
* @return {boolean} true iff the entity has a path with one of the
* extensionss.
*/
const _path_has_file_extension = function (entity, extensions) {
var path = getEntityPath(entity);
if (path) {
for (ext in extensions) {
if(path.toLowerCase().endsWith(ext)) {
return true;
}
}
}
return false;
}
const _create_video_preview = function (entity) {
var path = connection.getFileSystemPath() + getEntityPath(entity);
return $(`<video control="controls"><source src="${path}"/></video>`)[0];
}
const _create_picture_preview = function (entity) {
var path = connection.getFileSystemPath() + getEntityPath(entity);
return $(`<img class="entity-image-preview" style="max-width: 200px; max-height=140px;" src="${path}"/>`)[0];
}
var fallback_preview = undefined;
/** /**
* TODO Please adhere to JSDoc standards: https://jsdoc.app/ * TODO Please adhere to JSDoc standards: https://jsdoc.app/
*/ */
const _default_creators = [ const _default_creators = [
{ // TODO pictures (remove from entity.xsl) { // pictures
id: "_default_creators.pictures", id: "_default_creators.pictures",
is_applicable: (entity) => false, is_applicable: (entity) => _path_has_file_extension(
create: undefined, entity, ["jpg", "png", "gif", "svg"]),
create: _create_picture_preview
}, },
{ // TODO videos (remove from entity.xsl) { // videos
id: "_default_creators.videos", id: "_default_creators.videos",
is_applicable: (entity) => false, is_applicable: (entity) => _path_has_file_extension(
create: undefined, entity, ["mp4", "mov", "webm"]),
create: _create_video_preview,
}, },
{ // default { // fallback
id: "_default_creators.fallback", id: "_default_creators.fallback",
is_applicable: (entity) => true, is_applicable: (entity) => true,
create: (entity) => "Fall-back preview.", create: (entity) => fallback_preview,
}, },
]; ];
const previewShownEvent = new Event("new_module.preview.shown");
const previewReadyEvent = new Event("new_module.preview.ready"); const previewReadyEvent = new Event("new_module.preview.ready");
/** /**
...@@ -64,6 +102,7 @@ var new_module = function ($, logger, is_in_view_port, retrieve_config, plotly) ...@@ -64,6 +102,7 @@ var new_module = function ($, logger, is_in_view_port, retrieve_config, plotly)
*/ */
const _css_class_preview_container = "caosdb-f-new_module-container"; const _css_class_preview_container = "caosdb-f-new_module-container";
const _css_class_preview_container_resolvable = "caosdb-f-new_module-container-resolvable"; const _css_class_preview_container_resolvable = "caosdb-f-new_module-container-resolvable";
const _css_class_preview_container_button = "caosdb-f-new_module-container-button";
/** /**
* TODO Please adhere to JSDoc standards: https://jsdoc.app/ * TODO Please adhere to JSDoc standards: https://jsdoc.app/
...@@ -99,10 +138,16 @@ var new_module = function ($, logger, is_in_view_port, retrieve_config, plotly) ...@@ -99,10 +138,16 @@ var new_module = function ($, logger, is_in_view_port, retrieve_config, plotly)
* must have a (deep) child with class `caosdb-f-new_module-container`. * must have a (deep) child with class `caosdb-f-new_module-container`.
*/ */
var set_preview_container = function (entity, element) { var set_preview_container = function (entity, element) {
var preview_container = get_preview_container(entity); var preview_container = $(get_preview_container(entity));
if (preview_container) { if (preview_container[0]) {
$(preview_container).empty(); preview_container.empty();
$(preview_container).append(element); var buttons = preview_container.siblings(`.${_css_class_preview_container_button}`);
if (element) {
buttons.css({"visibility": "initial"});
preview_container.append(element);
} else {
buttons.css({"visibility": "hidden"});
}
} else { } else {
logger.error(new Error("Could not find the preview container.")); logger.error(new Error("Could not find the preview container."));
} }
...@@ -129,7 +174,9 @@ var new_module = function ($, logger, is_in_view_port, retrieve_config, plotly) ...@@ -129,7 +174,9 @@ var new_module = function ($, logger, is_in_view_port, retrieve_config, plotly)
set_preview_container(entity, wait); set_preview_container(entity, wait);
const result = await preview; const result = await preview;
set_preview_container(entity, result); set_preview_container(entity, result);
entity.dispatchEvent(previewReadyEvent); if (result) {
entity.dispatchEvent(previewReadyEvent);
}
} catch (err) { } catch (err) {
logger.error(err); logger.error(err);
const err_msg = "An error occured while loading this preview"; const err_msg = "An error occured while loading this preview";
...@@ -187,12 +234,14 @@ var new_module = function ($, logger, is_in_view_port, retrieve_config, plotly) ...@@ -187,12 +234,14 @@ var new_module = function ($, logger, is_in_view_port, retrieve_config, plotly)
*/ */
var add_preview_container = function (entity) { var add_preview_container = function (entity) {
const button_show = $('<button class="btn btn-xs"><span class="glyphicon glyphicon-menu-down"/> Show Preview</button>') const button_show = $('<button class="btn btn-xs"><span class="glyphicon glyphicon-menu-down"/> Show Preview</button>')
.css({width: "100%"});
const button_hide = $('<button class="btn btn-xs"><span class="glyphicon glyphicon-menu-up"/> Show Preview</button>')
.css({width: "100%"}) .css({width: "100%"})
.addClass(_css_class_preview_container_button);
const button_hide = $('<button class="btn btn-xs"><span class="glyphicon glyphicon-menu-up"/> Hide Preview</button>')
.css({width: "100%"})
.addClass(_css_class_preview_container_button)
.hide(); .hide();
const style = { padding: "0px 10px" }; const style = { padding: "0px 10px" };
const container = $(`<div class="collapse ${_css_class_preview_container}"/>`) const container = $(`<div class="collapse"/>`)
.addClass(_css_class_preview_container) .addClass(_css_class_preview_container)
.addClass(_css_class_preview_container_resolvable) .addClass(_css_class_preview_container_resolvable)
.css(style); .css(style);
...@@ -208,6 +257,7 @@ var new_module = function ($, logger, is_in_view_port, retrieve_config, plotly) ...@@ -208,6 +257,7 @@ var new_module = function ($, logger, is_in_view_port, retrieve_config, plotly)
} }
button_show.click(show); button_show.click(show);
button_hide.click(hide); button_hide.click(hide);
container.on("shown.bs.collapse", () => { container[0].dispatchEvent(previewShownEvent); });
$(entity).append(container); $(entity).append(container);
$(entity).append(button_show); $(entity).append(button_show);
$(entity).append(button_hide); $(entity).append(button_hide);
...@@ -226,26 +276,24 @@ var new_module = function ($, logger, is_in_view_port, retrieve_config, plotly) ...@@ -226,26 +276,24 @@ var new_module = function ($, logger, is_in_view_port, retrieve_config, plotly)
* created. * created.
*/ */
var root_preview_handler = async function (entity) { var root_preview_handler = async function (entity) {
var container = $(get_preview_container(entity) || add_preview_container(entity));
if (container.hasClass(_css_class_preview_container_resolvable)) {
const preview = root_preview_creator(entity); container.removeClass(_css_class_preview_container_resolvable);
if (preview) { const preview = root_preview_creator(entity);
set_preview(entity, preview); set_preview(entity, preview);
} }
} }
/** /**
* Trigger the root_preview_handler for all entities when the view port has * Trigger the root_preview_handler for all entities within the view port
* changed with a delay. * when the view port.
*/ */
var root_preview_handler_trigger = function () { var root_preview_handler_trigger = function () {
var entities = $(".caosdb-entity-panel,.caosdb-entity-preview"); var entities = $(".caosdb-entity-panel,.caosdb-entity-preview");
for (let entity of entities) { for (let entity of entities) {
var container = $(get_preview_container(entity) || add_preview_container(entity));
// TODO viewport + 1000 px
if (container.hasClass(_css_class_preview_container_resolvable) && is_in_view_port(container[0])) { // TODO viewport + 1000 px for earlier loading
container.removeClass(_css_class_preview_container_resolvable); if (is_in_view_port(entity)) {
root_preview_handler(entity); root_preview_handler(entity);
} }
} }
...@@ -291,48 +339,35 @@ var new_module = function ($, logger, is_in_view_port, retrieve_config, plotly) ...@@ -291,48 +339,35 @@ var new_module = function ($, logger, is_in_view_port, retrieve_config, plotly)
throw new Error("Wrong version in config."); throw new Error("Wrong version in config.");
} }
_creators = config.creators;
};
/**
* TODO Please adhere to JSDoc standards: https://jsdoc.app/
*/
var load_config = async function () {
var user_config = await retrieve_config("json/new_module.json");
var config = {
version: user_config.version,
delay: (user_config.delay || 500),
creators: [],
};
// append/load creators // append/load creators
for (let c of user_config.creators) { _creators.splice(0, _creators.length);
for (let c of config.creators) {
// TODO check deps // TODO check deps
config.creators.push({ _creators.push({
id: c.id, id: c.id,
is_applicable: eval(c.is_applicable), is_applicable: typeof c.is_applicable === "function" ? c.is_applicable : eval(c.is_applicable),
create: eval(c.create) create: typeof c.create === "function" ? c.create : eval(c.create)
}); });
} }
// append default creators // append default creators
config.creators = config.creators.concat(_default_creators); for (let c of _default_creators) {
_creators.push(c);
return config; }
}; };
/** /**
* TODO Please adhere to JSDoc standards: https://jsdoc.app/ * TODO Please adhere to JSDoc standards: https://jsdoc.app/
*/ */
var init = async function () { var init = async function (config) {
logger.info("new_module initialized"); logger.info("new_module initialized");
try { try {
const config = await load_config(); let _config = config || await load_config("json/new_module.json");
await configure(config); await configure(_config);
init_watcher(config.delay || 500, root_preview_handler_trigger); init_watcher(_config.delay || 500, root_preview_handler_trigger);
// trigger the whole thing for the first time // trigger the whole thing for the first time
root_preview_handler_trigger(); root_preview_handler_trigger();
...@@ -344,22 +379,28 @@ var new_module = function ($, logger, is_in_view_port, retrieve_config, plotly) ...@@ -344,22 +379,28 @@ var new_module = function ($, logger, is_in_view_port, retrieve_config, plotly)
} }
return { return {
previewShownEvent: previewShownEvent,
previewReadyEvent: previewReadyEvent, previewReadyEvent: previewReadyEvent,
init: init, init: init,
init_watcher: init_watcher, init_watcher: init_watcher,
configure: configure, configure: configure,
add_preview_container: add_preview_container,
_creators: _creators,
_css_class_preview_container,
_css_class_preview_container_button,
_css_class_preview_container_resolvable,
} }
}($, log.getLogger("new_module"), resolve_references.is_in_viewport_vertically, load_config, Plotly); }($, log.getLogger("new_module"), resolve_references.is_in_viewport_vertically, load_config, getEntityPath, connection);
/** /**
* Helper for plotly * Helper for plotly
*/ */
var plotly_preview = function (logger, new_module, preview, plotly) { var plotly_preview = function (logger, new_module, plotly) {
var create_plot = function (data) { var create_plot = function (data) {
var div = $('<div/>')[0]; var div = $('<div/>')[0];
plotly.newPlot(div, data, { margin: { t: 0}, height: 200}, {responsive: true}); plotly.newPlot(div, data, { margin: { t: 0}, height: 400, widht: 400 }, {responsive: true});
return div; return div;
} }
...@@ -371,10 +412,10 @@ var plotly_preview = function (logger, new_module, preview, plotly) { ...@@ -371,10 +412,10 @@ var plotly_preview = function (logger, new_module, preview, plotly) {
} }
var init = function () { var init = function () {
window.addEventListener(preview.showPreviewEvent.type,
resize_plots_event_handler, true);
window.addEventListener(new_module.previewReadyEvent.type, window.addEventListener(new_module.previewReadyEvent.type,
resize_plots_event_handler, true); resize_plots_event_handler, true);
window.addEventListener(new_module.previewShownEvent.type,
resize_plots_event_handler, true);
} }
return { return {
...@@ -382,7 +423,7 @@ var plotly_preview = function (logger, new_module, preview, plotly) { ...@@ -382,7 +423,7 @@ var plotly_preview = function (logger, new_module, preview, plotly) {
init: init, init: init,
}; };
}(log.getLogger("plotly_preview"), new_module, preview, Plotly); }(log.getLogger("plotly_preview"), new_module, Plotly);
// this will be replaced by require.js in the future. // this will be replaced by require.js in the future.
......
...@@ -289,6 +289,13 @@ this.connection = new function() { ...@@ -289,6 +289,13 @@ this.connection = new function() {
return base; return base;
} }
/**
* Return the root path of the file system resource.
*/
this.getFileSystemPath = function () {
return connection.getBasePath() + "FileSystem/";
}
/** /**
* Return a full URI for these entities. * Return a full URI for these entities.
* *
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
<script src="js/bootstrap-select.js"></script> <script src="js/bootstrap-select.js"></script>
<script src="js/bootstrap-autocomplete.min.js"></script> <script src="js/bootstrap-autocomplete.min.js"></script>
<script src="js/webcaosdb.js"></script> <script src="js/webcaosdb.js"></script>
<script src="js/plotly.js"></script>
<script> <script>
caosdb_modules.auto_init = false; caosdb_modules.auto_init = false;
log.setLevel("trace"); log.setLevel("trace");
......
...@@ -24,10 +24,32 @@ ...@@ -24,10 +24,32 @@
var new_module_test_suite = function ($, new_module, QUnit) { var new_module_test_suite = function ($, new_module, QUnit) {
var test_config = { "version": 0.1,
"deps": ["getParents", "getEntityName"],
"creators": [
{ "id": "test.success",
"is_applicable": "(entity) => getParents(entity).map(par => par.name).includes('TestPreviewRecordType') && getEntityName(entity) === 'TestPreviewRecord-success'",
"create": "(entity) => 'SUCCESS'"
},
{ "id": "test.error",
"is_applicable": "(entity) => getParents(entity).map(par => par.name).includes('TestPreviewRecordType') && getEntityName(entity) === 'TestPreviewRecord-error'",
"create": "(entity) => new Promise((res,rej) => {rej('Test Error');})"
},
{ "id": "test.load-forever",
"is_applicable": "(entity) => getParents(entity).map(par => par.name).includes('TestPreviewRecordType') && getEntityName(entity) === 'TestPreviewRecord-load-forever'",
"create": "(entity) => new Promise((res,rej) => {})"
},
{ "id": "test.success-2",
"is_applicable": "(entity) => getParents(entity).map(par => par.name).includes('TestPreviewRecordType') && getEntityName(entity) !== 'TestPreviewRecord-fall-back'",
"create": "(entity) => { return plotly_preview.create_plot([{x: [1,2,3,4,5], y: [1,2,4,8,16]}]); }"
}
]
};
QUnit.module("new_module.js", { QUnit.module("new_module.js", {
before: function (assert) { before: async function (assert) {
// setup before module, e.g.: // setup before module
new_module.init(); await new_module.configure(test_config);
}, },
beforeEach: function (assert) { beforeEach: function (assert) {
// setup before each test // setup before each test
...@@ -40,11 +62,26 @@ var new_module_test_suite = function ($, new_module, QUnit) { ...@@ -40,11 +62,26 @@ var new_module_test_suite = function ($, new_module, QUnit) {
} }
}); });
QUnit.test("hello_world", function (assert) { QUnit.test("_creators", function (assert) {
assert.equal(new_module.hello(), "Hello, world!", "hello returns the correct string"); assert.equal(new_module._creators.length, 7, "seven creators");
new_module.addressee = "you"; });
assert.equal(new_module.hello(), "Hello, you!", "changed adressee");
assert.notOk(new_module._hello, "_hello is private"); QUnit.test("add_preview_container", function(assert) {
var entity = $("<div/>");
var container = $(new_module.add_preview_container(entity[0]));
assert.ok(container.hasClass(new_module._css_class_preview_container), `has class ${new_module._css_class_preview_container}`);
assert.ok(container.hasClass(new_module._css_class_preview_container_resolvable), `has class ${new_module._css_class_preview_container_resolvable}`);
});
QUnit.test("root_preview_handler", async function(assert) {
for (let name_suffix of ["fall-back", "error", "load-forever", "success"]) {
let name = "TestPreviewRecord-" + name_suffix;
let entity_xml = `<Response><Record name="${name}"><Parent name='TestPreviewRecordType'/></Record></Response>`;
let entity = (await transformation.transformEntities(str2xml(entity_xml)))[0];
assert.equal(getEntityName(entity), name);
new_module.root_preview_handler(entity[0]);
}
}); });
}($, new_module, QUnit); }($, new_module, QUnit);
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment