It depends on how independent the library is from OH. If it’s generic JS, then any JS focused testing approach/suite will work just fine. If it requires some interaction with OH you’ll need to either mock up the OH interactions (when using a testing suite) or test while connected to OH.
Personally I’m not doing anything that is complex enough so simply exercising the code in an OH rule is sufficient for my testing needs
Kind of. Everything discussed above is for the old Nashorn JS Add-on which is ECMAScript 5.1. If you want to use a much more recent version of JS you should use the JS Scripting add-on. This supports npm modules for libraries. See JavaScript Scripting - Automation | openHAB.
Importing is also different using require instead of include.
Also, there is now the cache to save variables instead of using this as demonstrated above.
Note that all of the examples above have been rewritten in the newer ECMAScript and are available in openhab_rules_tools which you can install using openhabian-config or through npm (instructions on the link).
With the newer JS Scripting the Offline Alert example would look something like:
triggers:
- id: "1"
configuration:
time: 08:00
type: timer.TimeOfDayTrigger
conditions:
- inputs: {}
id: "2"
configuration:
itemName: ServiceStatuses
state: ON
operator: "!="
type: core.ItemStateCondition
actions:
- inputs: {}
id: "3"
configuration:
type: application/javascript
script: >-
var {utils} = require('rlk_personal');
var nullItems = utils.getNames("ServiceStatuses", function(i) { return i.state.class == UnDefType.class; });
console.info(nullItems);
var offItems = utils.getNames("ServiceStatuses", function(i) { return i.state == OFF; });
console.info(offItems);
var msg = "";
if(nullItems.length > 0) {
msg = "The following sensors are in an unknown state: " + nullItems;
}
if(offItems.length > 0) {
if(msg.length > 0) msg += "\n";
msg += "The following sensors are known to be offline: " + offItems;
}
utils.sendInfo(msg);
type: script.ScriptAction
The reimplementation of utils (which is part of a node module I created called rlk_personal:
exports.sendAlert = function(message, logger) {
var logger = (logger) ? logger : log('sendAlert');
logger.warn('ALERT: ' + message);
actions.NotificationAction.sendBroadcastNotification(message, 'alarm', 'alert');
}
exports.sendInfo = function(message, logger) {
var logger = (logger) ? logger : log('sendInfo');
logger.info('INFO: ' + message);
}
exports.isNight = function() {
const currToD = items.getItem('TimeOfDay').state;
return currToD == 'NIGHT' || currToD == 'BED';
}
exports.isAway = function() {
return exports.isNight() || items.getItem('Presence').state != 'ON';
}
exports.getNames = function(group, filterFunc) {
return items.getItem(group.name || group).members
.filter(filterFunc)
.map(s => (s.getMetadata()['name']) ? s.getMetadata()['name'].value : s.label)
.join(', ');
}
You will notice that the code is much shorter, is a lot less work to set up thanks to the helper library that comes with the add-on, and uses pure JS Classes, Objects, and idioms everywhere instead of needing to jump back and forth between JS and Java as shown in the original post. You can especially see this in the getNames function where the original uses Java’s streams API to filter the Java List as opposed to the new verison that uses all JavaScript Array manipulation and features.