initially on "jsdemo" though now far removed from those beginnnings.
[...]
</pre>
+
+ <div id="testMOTD"><div id="mkwsMOTD">This is the mkwsMOTD div</div></div>
</body>
</html>
initially on "jsdemo" though now far removed from those beginnnings.
[...]
</pre>
+ <div id="testMOTD"><div id="mkwsMOTD">This is the mkwsMOTD div</div></div>
</body>
</html>
"show_record_url": false // URLs not configured for pp2
};
</script>
- <script type="text/javascript" src="//code.jquery.com/jquery-1.6.4.min.js"></script>
+ <script type="text/javascript" src="//code.jquery.com/jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="tools/htdocs/pz2.js"></script>
<script type="text/javascript" src="tools/htdocs/handlebars-v1.1.2.js"></script>
<script type="text/javascript" src="tools/htdocs/jquery.json-2.4.js"></script>
</tr>
</table>
+ <div id="testMOTD"><div id="mkwsMOTD">This is the mkwsMOTD div</div></div>
</body>
</html>
perpage_default: 10
};
</script>
- <script type="text/javascript" src="//code.jquery.com/jquery-1.6.4.min.js"></script>
+ <script type="text/javascript" src="//code.jquery.com/jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="tools/htdocs/pz2.js"></script>
<script type="text/javascript" src="tools/htdocs/handlebars-v1.1.2.js"></script>
<script type="text/javascript" src="tools/htdocs/jquery.json-2.4.js"></script>
</head>
<body>
+ <div id="testMOTD"><div id="mkwsMOTD">This is the mkwsMOTD div</div></div>
<table width="100%" border="0">
<tr>
<td>
and Mike. I collected them for my own use, but I hope they will turn out
to be helpful to anyone who needs to get started with mkws.
+Environment
+-----------
+
+apt-get install yui-compressor
+get nodejs, sudo make install, ln -s /usr/local/bin/npm ~/bin/npm if needed
+
+cd .../mkws; make check
+
+
+Apache
+------
+You need to set up a local apache.
+ * add 'mkws' in /etc/hosts to point to 127.0.0.2
+ * symlinked .../mkws/tools/apache2/mkws-heikki to /etc/apache/sites-available
+ * a2ensite mkws-heikki
+ * a2enmod rewrite
+ * a2enmod headers
+ * service apache2 reload
+ * Check that your browser sees somethig in http://mkws/ and
+ http://mkws/jasmine-popup.html. If need be, enable javascript etc.
Libraries
---------
Unit tests
----------
-if you want understand the test than you can look at mkws/test/spec/mkws-config.js
+Tests are based on jasmine. a general description of jasmine is on
+http://jasmine.github.io/1.3/introduction.html
+
+If you want understand the test than you can look at mkws/test/spec/mkws-config.js
and mkws/test/spec/mkws-pazpar2.js . See also mkws/test/README.txt
+The test scripts are included from the test page, for example
+mkws/examples/htdocs/jasmine-popup.html has
+<script type="text/javascript" src="test/spec/mkws-pazpar2.js"></script>
+
+
+
Structure of mkws.js
--------------------
MIKE = PATH=$$PATH:/usr/local/lib/node-v0.10.24-linux-x64/bin
PHANTOMJS_URL=https://mkws-dev.indexdata.com/jasmine-popup.html
-PHANTOMJS_TIMEOUT=12
+PHANTOMJS_TIMEOUT=16
NPM_INSTALL_FLAGS=-q
JASMINE_NODE= ./node_modules/jasmine-node/bin/jasmine-node
-PHANTOMJS= ./bomb.pl ./node_modules/phantomjs/bin/phantomjs
+PHANTOMJS= ./node_modules/phantomjs/bin/phantomjs
IMAGES= ./images
SCREENSHOT_WIDTH= 360 480 640 768 1024 1200 1440 2048
+PERL_SCRIPTS= bomb.pl
all: check
terse:
$(MIKE) jasmine-node --noColor --captureExceptions --forceexit spec
-phantomjs:
- ${PHANTOMJS} phantom/evaluate.js ${PHANTOMJS_URL} ${PHANTOMJS_TIMEOUT}
+phantomjs p:
+ ./bomb.pl --timeout="${PHANTOMJS_TIMEOUT}.5" ${PHANTOMJS} phantom/run-jasmine.js ${PHANTOMJS_URL} ${PHANTOMJS_TIMEOUT}
screenshot:
${PHANTOMJS} phantom/screenshot.js ${PHANTOMJS_URL} ${IMAGES}/screenshot.png 1200 1000
jsbeautifier -j $$i > $@.tmp && mv -f $@.tmp $$i; \
done
+perltidy:
+ @ls ${PERL_SCRIPTS} | xargs -n1 -P16 perl -c 2>/dev/null
+ @ls ${PERL_SCRIPTS} | xargs -n2 -P8 perltidy -b
+
+
node_modules node-modules:
npm install ${NPM_INSTALL_FLAGS}
help:
@echo "make [ all | check | clean | distclean ]"
@echo " [ phantomjs | screenshot ]"
- @echo " [ jsbeautifier | node-modules ]"
+ @echo " [ jsbeautifier | perltidy ]"
+ @echo " [ node-modules ]"
@echo ""
- @echo "DEBUG=1 make phantomjs PHANTOMJS_TIMEOUT=8 PHANTOM_URL=https://mkws-dev.indexdata.com/jasmine-popup.html"
+ @echo "DEBUG=1 make phantomjs PHANTOMJS_TIMEOUT=8 PHANTOMJS_URL=https://mkws-dev.indexdata.com/jasmine-popup.html"
GetOptions(
"help" => \$help,
"debug=i" => \$debug,
- "timeout=i" => \$timeout,
+ "timeout=f" => \$timeout,
) or die usage;
my @system = @ARGV;
--- /dev/null
+/*
+ Fetch a mkws/jasmine based page into node.js, evaluate the page and check if test status
+ This should make it possible to run the test on the command line in jenkins. e.g.:
+
+ phantomjs evaluate.js https://mkws-dev.indexdata.com/jasmine-local-popup.html
+*/
+
+var page = require('webpage').create(),
+ system = require('system');
+
+if (system.args.length === 1) {
+ console.log('Usage: screenshot.js <some URL>');
+ phantom.exit();
+}
+var url = system.args[1];
+
+var run_time = 8; // poll up to seconds
+if (system.args[2] && parseFloat(system.args[2]) > 0) {
+ run_time = parseFloat(system.args[2]);
+}
+
+page.viewportSize = {
+ width: 1200,
+ height: 1000
+};
+
+// 0: silent, 1: some infos, 2: display console.log() output
+var debug = 2;
+if (typeof system.env['DEBUG'] != 'undefined' && parseInt(system.env['DEBUG']) != NaN) {
+ debug = system.env['DEBUG'];
+ if (debug > 0) console.log("reset debug level to: " + debug);
+}
+
+/************************/
+
+function wait_for_jasmine(checkFx, readyFx, failFx, timeout) {
+ var max_timeout = timeout ? timeout : run_time * 1000,
+ start = new Date().getTime(),
+ result, condition = false;
+
+ var interval = setInterval(function () {
+ if (debug == 1) console.log(".");
+
+ // done
+ if (condition) {
+ clearInterval(interval);
+ result.time = (new Date().getTime() - start);
+ result.failed ? failFx(result) : readyFx(result);
+ phantom.exit(result.failed == 0 ? 0 : 2);
+ }
+
+ // timeout
+ else if (new Date().getTime() - start >= max_timeout) {
+ result.time = (new Date().getTime() - start);
+ failFx(result);
+ phantom.exit(1);
+ }
+
+ // checking
+ else {
+ result = checkFx();
+ if (result) condition = result.done;
+ }
+
+ }, 500); //< repeat check every N ms
+};
+
+function dump_html(file) {
+ // not yet implemented
+ var spawn = require('child_process').spawn,
+ lynx = spawn("lynx", ["-nolist", "-dump", file]);
+
+ lynx.stdout.on('data', function (data) {
+ console.log('lynx >> ' + data);
+ });
+
+ // lynx.stderr.on('data', function (data) { console.log('stderr: ' + data); });
+ // lynx.on('close', function (code) { console.log('child process exited with code ' + code) });
+};
+
+// redirect webkit console.log() output
+page.onConsoleMessage = function (message) {
+ if (debug >= 2) console.log(message);
+};
+
+// cat webkit alert()
+page.onAlert = function (msg) {
+ console.log("Alert: " + msg);
+};
+
+// display HTTP errors
+page.onResourceError = function (resourceError) {
+ // console.log('phantomjs error code: ' + resourceError.errorCode);
+ console.log(resourceError.errorString);
+ phantom.exit(3);
+};
+
+page.open(url, function (status) {
+ if (debug >= 1) console.log("fetch " + url + " with status: " + status);
+
+ if (status != 'success') {
+ console.log("Failed to fetch page, give up. Network error?");
+ phantom.exit(1);
+ }
+
+ if (debug >= 1) console.log("polling MKWS jasmine test status for " + run_time + " seconds");
+
+
+ var exit = wait_for_jasmine(function () {
+ return page.evaluate(function () {
+ if (!window || !window.$ || !window.mkws) {
+ console.log("No window object found");
+ return false;
+ }
+
+ var $ = window.$;
+ var error_msg = [""];
+ var passing = $(".passingAlert").text() || window.$(".failingAlert").text();
+
+ // extract failed tests
+ var list = $('.results > #details > .specDetail.failed');
+ if (list && list.length > 0) {
+ error_msg.push("==> " + list.length + ' test(s) FAILED:');
+ for (i = 0; i < list.length; ++i) {
+ var el = list[i],
+ desc = el.querySelector('.description'),
+ msg = el.querySelector('.resultMessage.fail');
+ error_msg.push($(desc).text());
+ error_msg.push($(msg).text());
+ }
+ }
+
+ return {
+ mkws: window.mkws,
+ done: $('.symbolSummary .pending').length == 0,
+ html: $("html").html(),
+ duration: $(".duration").text(),
+ error_msg: error_msg,
+ failed: list.length,
+ passing: passing
+ };
+ })
+ },
+
+ function (result) {
+ if (debug < 1) return;
+
+ console.log("");
+ console.log("MKWS tests are successfully done in " + result.time / 1000 + " seconds. Hooray!");
+ console.log("jasmine duration: " + result.duration);
+ console.log("jasmine passing: " + result.passing);
+ },
+
+ function (result) {
+ var error_png = "./mkws-error.png";
+ var error_html = "./mkws-error.html";
+
+ var html = result.html + "\n\n<!-- mkws: " + JSON.stringify(result.mkws) + " -->\n";
+ var fs = require('fs');
+ fs.write(error_html, html, "wb");
+ dump_html(error_html);
+
+ console.log("MKWS tests failed after " + result.time / 1000 + " seconds");
+ console.log(result.error_msg.join("\n"));
+ console.log("keep screenshot in '" + error_png + "'");
+ page.render(error_png);
+
+ console.log("keep html DOM in '" + error_html + "'");
+ // console.log("you may run: lynx -nolist -dump " + error_html);
+ }, run_time * 1000);
+});
// get references from mkws.js, lazy evaluation
var debug = function (text) {
- mkws.debug(text)
+ mkws.debug("Jasmine: " + text)
}
// Define empty mkws_config for simple applications that don't define it.
});
});
+describe("Check MOTD before search", function () {
+ // Check that the MOTD has been moved into its container, and
+ // is visible before the search.
+ // the mkwsMOTD div was originally inside a testMOTD div, which should
+ // now be emtpy
+ // Note that the testMOTD is a regular div, and uses #testMOTD,
+ // since the automagic class-making does not apply to it.
+ it("MOTD is hidden", function () {
+ expect($(".mkwsMOTD").length).toBe(1);
+ expect($("#testMOTD").length).toBe(1);
+ expect($("#testMOTD").text()).toMatch("^ *$");
+ });
+
+ it("mkwsMOTDContainer has received the text", function () {
+ expect($(".mkwsMOTDContainer").length).toBe(1);
+ expect($(".mkwsMOTDContainer").text()).toMatch(/MOTD/);
+ });
+});
+
describe("Check pazpar2 search", function () {
it("pazpar2 was successfully initialized", function () {
expect(mkws_config.error).toBe(undefined);
runs(function () {
debug("Click on submit button");
- var click = $("input.mkwsButton").trigger("click");
- expect(click.length).toBe(1);
+ $("input.mkwsButton").trigger("click");
})
});
});
+describe("Check MOTD after search", function () {
+ it("MOTD is hidden", function () {
+ expect($(".mkwsMOTD").length).toBe(1);
+ expect($(".mkwsMOTD").is(":hidden")).toBe(true);
+ debug("motd t=" + $(".mkwsMOTD").text());
+ debug("motd v=" + $(".mkwsMOTD").is(":visible"));
+ });
+});
+
/*
* This part runs in background. It should be rewritten with
function my_click(id, time) {
setTimeout(function () {
debug("trigger click on id: " + id);
- var click = $(id).trigger("click");
-
- debug("next/prev: " + id + " click is success: " + click.length);
- expect(click.length).toBe(1);
+ $(id).trigger("click");
}, time * jasmine_config.second);
}
waitsFor(function () {
hits = get_hit_counter();
-
return hits > expected_hits;
}, "Expect " + expected_hits + " hits", max_time * jasmine_config.second);
-
runs(function () {
debug("mkws pager found records: '" + hits + "'");
expect($(".mkwsPager").length).toBe(1);
return $("div.mkwsFacetSources").length == 1 ? true : false;
}, "check for facet sources", 4 * jasmine_config.second);
-
// everything displayed?
runs(function () {
var sources = $("div.mkwsFacetSources");
var author_number = 2; // 2=first author
// do not click on author with numbers, e.g.: "Bower, James M. Beeman, David, 1938-"
// do not click on author names without a comma, e.g.: "Joe Barbara"
+ // because searching on such authors won't find anything.
var terms = $("div.mkwsFacetAuthors div.term a");
for (var i = 0; i < terms.length; i++) {
var term = $(terms[i]).text();
break;
}
}
+ if ($("div.mkwsFacetAuthors div.term:nth-child(" + author_number + ") a").text().length == 0) {
+ debug("No good authors found. Not clicking on the bad ones");
+ return;
+ }
- var click = $("div.mkwsFacetAuthors div.term:nth-child(" + author_number + ") a").trigger("click");
- debug("limit author click is success: " + click.length);
- expect(click.length).toBe(1);
+ debug("Clicking on author (" + author_number + ") " + $("div.mkwsFacetAuthors div.term:nth-child(" + author_number + ") a").text());
+ $("div.mkwsFacetAuthors div.term:nth-child(" + author_number + ") a").trigger("click");
waitsFor(function () {
return get_hit_counter() < hits_all_targets ? true : false;
break;
}
}
+ if ($("div.mkwsFacetSources div.term:nth-child(" + source_number + ") a").text().length == 0) {
+ debug("No good source found. Not clicking on the bad ones");
+ return;
+ }
- var click = $("div.mkwsFacetSources div.term:nth-child(" + source_number + ") a").trigger("click");
- debug("limit source click " + (source_number - 1) + " is success: " + click.length);
- expect(click.length).toBe(1);
+ $("div.mkwsFacetSources div.term:nth-child(" + source_number + ") a").trigger("click");
waitsFor(function () {
if ($("div.mkwsNavi").length && $("div.mkwsNavi").text().match(/(Source|datenquelle|kilder): /i)) {
});
});
+
+describe("Check record list", function () {
+ it("got a record", function () {
+ var linkaddr = "div.mkwsRecords div.record:nth-child(1) a";
+ var waitcount = 0;
+
+ // wait for new records
+ $("div.mkwsRecords").bind("DOMSubtreeModified propertychange", function () {
+ waitcount++;
+ debug("DOM div.mkwsRecords changed");
+ });
+
+ waitsFor(function () {
+ return waitcount > 0 && $(linkaddr).length > 0;
+ }, "wait until we see a new record", 2.2 * jasmine_config.second);
+
+ runs(function () {
+ expect(waitcount).toBeGreaterThan(0);
+ $("div.mkwsRecords").unbind("DOMSubtreeModified");
+ });
+ });
+});
+
describe("Show record", function () {
var record_number = 1; // the Nth record in hit list
it("show record author", function () {
return;
}
- var urls = $("div#mkwsRecords div.record:nth-child(" + record_number + ") div table tbody tr td a");
+ var urls = $("div.mkwsRecords div.record:nth-child(" + record_number + ") div table tbody tr td a");
debug("number of extracted URL from record: " + urls.length);
+ // expect(urls.length).toBeGreaterThan(0); // LoC has records without links
for (var i = 0; i < urls.length; i++) {
var url = $(urls[i]);
- debug("URL: " + url.attr('href'));
+ debug("URL: " + url.attr('href') + " text: " + url.text());
+
expect(url.attr('href')).not.toBe(null);
expect(url.attr('href')).toMatch(/^https?:\/\/[a-z0-9]+\.[0-9a-z].*\//i);
- expect(url.attr('href')).toBe(url.text());
+ expect(url.text()).not.toBe("");
}
});
});
});
it("switch to target view", function () {
- var click = $("div.mkwsSwitch").children('a').eq(1).trigger("click");
- debug("target view click is success: " + click.length);
- expect(click.length).toBe(1);
+ $("div.mkwsSwitch").children('a').eq(1).trigger("click");
// now the target table must be visible
expect($("div.mkwsBytarget").is(":visible")).toBe(true);
});
it("switch back to record view", function () {
- var click = $("div.mkwsSwitch").children('a').eq(0).trigger("click");
- debug("record view click is success: " + click.length);
- expect(click.length).toBe(1);
+ $("div.mkwsSwitch").children('a').eq(0).trigger("click");
// now the target table must be visible
expect($("div.mkwsBytarget").is(":visible")).toBe(false);
} else {
return false;
}
-
}, "wait for Active clients: 0/1", 4 * jasmine_config.second);
-
/*
runs(function () {
var clients = $("div#mkwsStat span.clients");
expect(clients.text()).toEqual("0/1");
});
*/
-
});
-
});
/* done */
#JQUERY_URL= http://code.jquery.com/jquery-1.9.1.min.js
#JQUERY_URL= http://code.jquery.com/jquery-1.8.3.min.js
#JQUERY_URL= http://code.jquery.com/jquery-1.7.2.min.js
-#JQUERY_URL= http://code.jquery.com/jquery-1.6.4.min.js
-#JQUERY_URL= http://code.jquery.com/jquery-1.4.4.min.js
JQUERY_UI_URL= http://code.jquery.com/ui/1.10.3/jquery-ui.js
#JQUERY_UI_URL= http://code.jquery.com/ui/1.8.0/jquery-ui.min.js
JQUERY_JSON_URL= https://jquery-json.googlecode.com/files/jquery.json-2.4.js
-HANDLEBARS_URL= http://builds.handlebarsjs.com.s3.amazonaws.com/handlebars-v1.1.2.js -o $@
+HANDLEBARS_URL= http://builds.handlebarsjs.com.s3.amazonaws.com/handlebars-v1.1.2.js
PP2_URL= http://git.indexdata.com/?p=pazpar2.git;a=blob_plain;f=js/pz2.js;hb=HEAD
VERSION = $(shell tr -d '\012' < VERSION)
rm -f $@.new
${JQUERY_JSON_FILE}:
- curl -sSf ${JQUERY_JSON_URL} -o $@
+ curl -sSf ${JQUERY_JSON_URL} -o $@.tmp
+ mv -f $@.tmp $@
${HANDLEBARS_FILE}:
- curl -sSf ${HANDLEBARS_URL} -o $@
+ curl -sSf ${HANDLEBARS_URL} -o $@.tmp
+ mv -f $@.tmp $@
${PP2_FILE}:
curl -sSf "${PP2_URL}" -o $@.tmp
function findnode(selector, teamName) {
teamName = teamName || m_teamName;
- selector = selector.split(',').map(function(s) {
+ selector = $.map(selector.split(','), function(s, i) {
return s + '.mkwsTeam_' + teamName;
}).join(',');