Skip to content

Latest commit

 

History

History
888 lines (653 loc) · 25.7 KB

File metadata and controls

888 lines (653 loc) · 25.7 KB

Requirements for mytimeout

Purpose

Node-red-contrib-mytimeout is a countdown timer that can be trigged by sending it input. It will run until the timer runs out where it will turn off. It can be turned off, stopped or cancelled with the correct input. It can be ‘tickled’ (restarted) with an on message or any other command not listed below. Meaning, if you send it junk, you have tickled the timer to continue to run. You can dynamically change the timeout and warning values by sending the appropriate Javacript object to the input.

Node-red-contrib-mytimeout can send and receive to the same MQTT topic. If the input matches the previously sent output, the message is ignored to avoid an endless loop. But be careful, it the message sent is modified and does not match the previous message sent, then the message will be sent and loops will occur. This will cause node-red to become totally unresponsive.

Requirements

  1. node-red-contrib-mytimeout (mytimeout) is a countdown timer
  2. mytimeout can be ‘tickled’ (restarted) with an on message or any other command not listed below. Meaning, if you send it junk, you have tickled the timer to continue to run.
    1. what about no payload, is that possible?
    2. Define ‘junk’
    3. what are the exceptions?
  3. You can dynamically change the timeout and warning values by sending the appropriate Javacript object to the input. This restarts mytimeout
  4. mytimeout has 2 outputs, the command output and the ticks output
  5. the commands output contains the commands issued by the timer (on/off/warn/stop/cancel(?) cancel maybe silent on cmds output)
  6. the ticks output contains the running state of the timer and addition information
  7. mytimeout is triggered by sending it an input, when turned on it will send an on-msg
    1. except when the payload is ” (blank), then the on-msg won’t be sent but the timer will start. Need a Note here
  8. mytimeout will run until the timer times out when it sends an off-msg (unless a stop or cancel message has been sent)
  9. at a preset time a warn-msg will be sent (if set)
  10. the timer can be turned off, stopped or cancelled and the appropriate message will be sent
  11. Must be able to use the same topic to subscribe and publish on without resending the same message (positive feedback). If the input matches the previously sent commands output, the message is ignored to avoid an endless loop.
  12. An empty Warning state payload entry (reword this) or warning seconds will cause mytimeout to skip sending the warning message
  13. An empty Timer On payload will cause mytimeout to start/restart the time but not send the on command, mytimeout can still send the warning (if so set) and off commands. Ticks output will still occur.
  14. Convert float values to int (round up, round down ???)

Test cases

These are not unit tests, I haven’t figured out how to write a unit test for this node-red node. These are node functionality / itegration tests.

Samples:

Basic

This is a standard minimal JSON object sent to mytimeout. We can drop the _msgid, timeout and warning but in the sample I sent I minimized the amount of time a default node needs to run so I wouldn’t have 31 lines in the ticks array.

node

This is the default mytimeout node used for testing. Since we need to set it up a 5/2 should work well enough.

      { id: "n1", type: "mytimeout",
        name:       "myTimeout",
        outsafe:    "on", /* If blank we should get no on msg */
        outwarning: "warning",
        outunsafe:  "off",
        timer:      2,
        warning:    1,
        wires:      [["n2"], ["n3"]] },
      { id: "n2", type: "helper" },
      { id: "n3", type: "helper" }

{ id: "n1", type: "mytimeout",
  name:       nom,
  outsafe:    'on', /* If blank we should get no on msg */
  outwarning: "warning",
  outunsafe:  'off',
  timer:      5,
  warning:    2,
  wires:      [["n2"], ["n3"]] },

sent

{"_msgid":"13828afd.df31c5","payload":"on","timeout":5,"warning":2}

cmnds

{"_msgid":"13828afd.df31c5","payload":"on","timeout":5,"warning":2,"topic":""}
{"_msgid":"13828afd.df31c5","payload":"Warning","timeout":5,"warning":2,"topic":""}
{"_msgid":"13828afd.df31c5","payload":"off","timeout":5,"warning":2,"topic":""}

ticks

{"payload":5,"state":1,"flag":"ticks > 0","_msgid":"8c50272c.e4dc78"}
{"payload":4,"state":1,"flag":"ticks > 0","_msgid":"2890a4cb.4571ec"}
{"payload":3,"state":1,"flag":"ticks > 0","_msgid":"6c60bd4c.d6a284"}
{"payload":2,"state":2,"flag":"warn >= ticks","_msgid":"523bfa12.4de134"}
{"payload":1,"state":2,"flag":"warn >= ticks","_msgid":"cefc13aa.cff88"}
{"payload":0,"state":0,"flag":"off","_msgid":"13828afd.df31c5"}

MQTT payload object as string

I often send HA commands from outside of node-red via MQTT topics. When doing this with mosquitto_pub I often need to send the JSON object in the payload. Mytimeout is programmed to read this string, search for the string payload anad convert the string to a JSON object.

node

This is the default mytimeout node used for testing. Since we need to set it up a 5/2 should work well enough.

{ id: "n1", type: "mytimeout",
  name:       nom,
  outsafe:    'on', /* If blank we should get no on msg */
  outwarning: "warning",
  outunsafe:  'off',
  timer:      5,
  warning:    2,
  wires:[["n2"], ["n3"]] },

sent

{"topic":"home/test/mytimeout", "payload":"{\"payload\": \"on\", \"timeout\": 6, \"TestNo\":\"0001\" }", "qos":0, "retain":false, "_msgid":"49d6f819.7b4eb8"}

cmnds

{"topic":"","payload":"on","qos":0,"retain":false,"_msgid":"49d6f819.7b4eb8","timeout":6,"TestNo":"0001"}
{"topic":"","payload":"Warning","qos":0,"retain":false,"_msgid":"49d6f819.7b4eb8","timeout":6,"TestNo":"0001"}
{"topic":"","payload":"off","qos":0,"retain":false,"_msgid":"49d6f819.7b4eb8","timeout":6,"TestNo":"0001"}

ticks

{"payload":6,"state":1,"flag":"ticks > 0","_msgid":"7b8be61f.17fbe8"}
{"payload":5,"state":2,"flag":"warn >= ticks","_msgid":"53e8025f.19fcfc"}
{"payload":4,"state":2,"flag":"warn >= ticks","_msgid":"72ded430.23362c"}
{"payload":3,"state":2,"flag":"warn >= ticks","_msgid":"11089b18.fb2435"}
{"payload":2,"state":2,"flag":"warn >= ticks","_msgid":"3a5000c1.a0b71"}
{"payload":1,"state":2,"flag":"warn >= ticks","_msgid":"5a02330c.d2220c"}
{"payload":0,"state":0,"flag":"off","_msgid":"49d6f819.7b4eb8"}

TC mytimeout Node

[ ] - Prerequisite

Because this testing doesn’t use the html config we need to add the defaults we want to use in the node setup

var flow = [
   { id: "n1", type: "mytimeout",
     name:       nom,
     outsafe:    'on', /* If blank we should get no on msg */
     outwarning: "warning",
     outunsafe:  'off',
     timer:      5,
     warning:    2,
     wires:[["n2"], ["n3"]] },
   { id: "n2", type: "helper" }, /* Output commands */
   { id: "n3", type: "helper" }  /* Output state of ticks */
];

Where n1 is the input to the node, n2 is the cmnds output, and n3 is the ticks output from the node.

[ ] - TC 0 - Load test

Test

  • Tests that the module loads and that some attributes are set

Expected results

[ ] - TC 1 - Base test, send on

Test

  • Run with default flow, test for on/warning/off, number of commands, number of ticks

Expected results

  • ‘on’ in cmnds[0]
  • ‘warning’ in cmnds[1]
  • ‘off’ in cmnds[0]
  • cmnds length of 3
  • ticks[0] properties …
  • ticks[2] properties …
  • ticks[5] properties …
  • ticks length of 6 (?)

[ ] - TC 1 - Base test, send 1

Test

  • Run with default flow, test for on/warning/off, number of commands, number of ticks

Expected results

  • ‘on’ in cmnds[0]
  • ‘warning’ in cmnds[1]
  • ‘off’ in cmnds[0]
  • cmnds length of 3
  • ticks[0] properties …
  • ticks[2] properties …
  • ticks[5] properties …
  • ticks length of 6 (?)

[ ] - TC 1 - Base test, send ‘1’

Test

  • Run with default flow, test for on/warning/off, number of commands, number of ticks

Expected results

  • ‘on’ in cmnds[0]
  • ‘warning’ in cmnds[1]
  • ‘off’ in cmnds[0]
  • cmnds length of 3
  • ticks[0] properties …
  • ticks[2] properties …
  • ticks[5] properties …
  • ticks length of 6 (?)

[ ] - TC 2 - Base test, send stop

Test

  • x

Expected results

  • x

[ ] - TC 3 - Base test, send cancel

Test

  • x

Expected results

  • x

[ ] - TC 4 - Test with empty payload ” and no warning msg

Test

  • x

Expected results

  • x

[ ] - TC 5 - Test with timeout override (integer)

Test

  • x

Expected results

  • x

[ ] - TC 6 - Test with short timeout override and extra attribute

Test

  • x

Expected results

  • x

[ ] - TC 7 - Test off with “off”

Test

  • x

Expected results

  • x

[ ] - TC 6a- Test with turn off with “0” and extra attribute

Test

  • x

Expected results

  • x

[ ] - TC 8 - Test off with 0

Test

  • x

Expected results

  • x

[ ] - TC 8 - Test off with “0”

Test

  • x

Expected results

  • x

[ ] - TC 9 - Test stop

Test

  • x

Expected results

  • x

[ ] - TC 10 - Test on with no warning (warning value as an integer)

Test

  • x

Expected results

  • x

[ ] - TC 11 - Test on on (send an on, then send another on before the timer turns off)

Test

  • x

Expected results

  • x

[ ] - TC 12 - Test on/on with floats

Test

  • x

Expected results

  • x

[ ] - TC 13 - Test on with no warning (warning value as a string)

Test

  • x

Expected results

  • x

[ ] - TC 14 - Test with timeout override (string)

Test

  • x

Expected results

  • x

[ ] - TC 15 - Test with ‘junk’ payload, timeout 3, warning ‘0’

Test

  • x

Expected results

  • x

[ ] - TC 16 - Test on, on with payload = ”

Test

  • x

Expected results

  • x

[ ] - TC 17 - Test on/off

Test

  • x

Expected results

  • x

[ ] - TC 18 - Test on/stop

Test

  • x

Expected results

  • x

[ ] - TC 19 - Test on/cancel

Test

  • x

Expected results

  • x

[ ] - TC 20 - Test ON (ignore case test)

Test

  • x

Expected results

  • x

[ ] - TC 21 - Test Warning wih floats

Test

  • x

Expected results

  • x

[ ] - TC 22 - Should turn on/on, Tx on

Test

  • x

Expected results

  • x

[ ] - TC 23 - Should turn on/on (2nd no payload), Tx on

Test

  • x

Expected results

  • x

[ ] - TC 24 - Should turn on with junk, Tx junk (Test with ‘junk’ payload, timeout 3, warning ‘0’)

Test

  • x

Expected results

  • x

[ ] - TC 25 - Should turn on with junk with no outwarning (”), Tx junk (Test with ‘junk’ payload, timeout 3, warning ‘0’)

Test

  • x

Expected results

  • x

[ ] - TC 26 - Should turn on with junk with outwarning not defined & warning (0), Tx junk )Test with ‘junk’ payload, timeout 3, warning ‘0’)

Test

  • x

Expected results

  • x

[ ] - TC 27 - Should turn on with junk with outwarning &warning defined, Tx junk & warning 0 (Test with ‘junk’ payload, timeout 3, warning ‘0’)

Test

  • x

Expected results

  • x

[ ] - TC xx - Need additional test cases here

Test

  • x

Expected results

  • x

TC mytimeout Node/MQTT flow test

[ ] - TC 01 - send on, same topic In/Out (full flow test w/mqtt)

Test

  • x

Expected results

  • x

[ ] - TC xx - Need additional test cases here

Test

  • x

Expected results

  • x

Future requirements

  1. add support for pause
  2. add support for {{mustache}} in HTML config (see template core and testing code)
  3. add support for copying the rest of the incoming message to both outputs
  4. add support for inverted logic

Commands - Incoming message structure

{"payload":"on"}
or
{"payload":"on","timeout":5}
or
{"payload":"on","timeout":5,"warning":2}
  • payload
    • ‘1’ -
    • ‘on’ -
    • ‘0’ -
    • ‘off’ -
    • ‘stop’ -
    • ‘cancel’ -
    • ‘pause’ -
    • junk - really need to properly define this
    • blank - need to define this

ticks format

states

  • 0 - timer not running (counted down, off, stop or cancel)
  • 1 - timer running
  • 2 - timer running, warning issued
  • 3 - timer paused

flags

  • ticks > 0 - timer counting down
  • warn >= ticks - timer counting down, warning issued
  • off - timer not running
  • pause - timer is pause
  • stop - timer not running (just a different reason) no off(?), tick information issued
  • cancel - timer not running, no off will be sent and ticks issued
  • unknown - Shouldn’t happen, not code but there for future use

Options

  • Debug logging
  • ignore payload case
  • repeat (not used)
  • again (not used)
  • inverted logic (not yet implemented)

Notes

CLI commands

tput clear; npm test ; ps ax | egrep node-red | egrep -v grep

mosquitto_sub -v -t home/test/switchTimer | awk ‘{ print strftime(“%F_%T.%s”), “” $0; fflush(); }’ | tee ${file} # ^Z bg

mosquitto_sub -v -t home/test/mytimeout | awk ‘{ print strftime(“%F_%T.%s”), “” $0; fflush(); }’ | tee ${file} # ^Z bg mosquitto_sub -v -t home/test/mytimeoutJson | awk ‘{ print strftime(“%F_%T.%s”), “” $0; fflush(); }’ | tee ${file} # ^Z bg mosquitto_sub -v -t home/test/ticksJson | awk ‘{ print strftime(“%F_%T.%s”), “” $0; fflush(); }’ | tee ${file} # ^Z bg

mosquitto_pub -t ‘home/test/mytimeout’ -m ‘{ “payload”: “on”, “timeout” : 10, “warning”: 2 }’ && sleep 3 && mosquitto_pub -t ‘home/test/switchTimer’ -m ‘{ “payload”: “stop”}’ && sleep 10 && echo mosquitto_pub -t ‘home/test/switchTimer’ -m ‘{ “payload”: “on”, “timeout” : 10, “warning”: 2 }’ && sleep 3 && mosquitto_pub -t ‘home/test/switchTimer’ -m ‘{ “payload”: “stop”}’ && sleep 10 && echo mosquitto_pub -t ‘home/test/switchTimer’ -m ‘{ “payload”: “”, “timeout” : 4, “warning”: 2 }’

mosquitto_pub -t ‘home/test/mytimeout’ -m ‘{ “payload”: “”, “timeout” : 4, “warning”: 2 }’

2021-01-13_02:26:07.1610522767 home/test/switchTimer { “payload”: “junk”, “timer” : 4, “warning”: 2 } 2021-01-13_02:26:07.1610522767 home/test/switchTimer on 2021-01-13_02:26:35.1610522795 home/test/switchTimer warning 2021-01-13_02:26:37.1610522797 home/test/switchTimer off

mosquitto_sub -v -t home/test/switchTimer | awk ‘{ print strftime(“%F_%T.%s”), “” $0; fflush(); }’ | tee ${file}

mocha t/txample_spec.js

Notes & Links

https://github.com/ksvan/node-red-contrib-verisure/wiki/Detailed-setup—automated-nodered-test

Sample TCs

/* */
//
// ===========================================================================================
//
it("TCxx - Dummy, should be timed", function (done) {
  var testCase = "000x";

  var flow = [
    { id: "n1", type: "mytimeout", name: nom, output: 2, wires:[["n2"], ["n3"]] },
    { id: "n2", type: "helper" },
    { id: "n3", type: "helper" }
  ];

  try {
    helper.load(myNode, flow, function () {
      try {
        (true).should.be.true();
        done();
      } catch(err) {
        console.log("Ooops");
        done(err);
      }
    });
  } catch(err) {
    console.log(err);
    done();
  }
});
/* */

/* * /
//
// ===========================================================================================
//
// https://github.com/node-red/node-red/blob/15a600c763cfeafee72016e05113ebca5358a3be/test/nodes/core/function/10-switch_spec.js#L640
it("TCxx - should treat non-existant msg property conditional as undefined", function(done) {
  var flow = [{
    "id":"switchNode1",
    "type":"switch",
    "z":"feee1df.c3263e",
    "name":"",
    "property":"payload",
    "propertyType":"msg",
    "rules":[{"t":"eq","v":"this.does.not.exist","vt":"msg"}],
    "checkall":"true",
    "outputs":1,
    "x":190,
    "y":440,
    "wires":[["helperNode1"]]},
   {id:"helperNode1", type:"helper", wires:[]}];

  helper.load(switchNode, flow, function() {
    var switchNode1 = helper.getNode("switchNode1");
    var helperNode1 = helper.getNode("helperNode1");
    var received = [];

    helperNode1.on("input", function(msg) {
      received.push(msg);
    });

    // First message should be dropped as payload is not undefined
    switchNode1.receive({topic:"messageOne",payload:""});

    // Second message should pass through as payload is undefined
    switchNode1.receive({topic:"messageTwo",payload:undefined});

    setTimeout(function() {
      try {
        received.should.have.lengthOf(1);
        received[0].should.have.a.property("topic","messageTwo");
        done();
      } catch(err) {
        done(err);
      }
    },500)
  });
});
/* */
/*
** Main output
** n2: {"_msgid":"65d8f152.8e917","payload":"on","topic":"","timeout":30}
** Ticks output
** n3: {"payload":30,"state":1,"flag":"ticks > 0","_msgid":"5e5dd4bf.1be32c"}
* /
//
// ===========================================================================================
//
it('TC01 - Should turn on Tx on', function (done) {
  var testCase = "0001";
  var flow = [
    { id: "n1", type: "mytimeout",
      name:       nom,
      outsafe:    "on",
      outwarning: "warning",
      outunsafe:  "off",
      warning:    "5",
      timer:      "30",
      debug:      "0",
      wires:[["n2"],["n3"]] },
    { id: "n2", type: "helper" },
    { id: "n3", type: "helper" }
  ];
  helper.load(myNode, flow, function () {
    var n2 = helper.getNode("n3");
    var n2 = helper.getNode("n2");
    var n1 = helper.getNode("n1");

    n2.on("input", function (msg) {
      msg.should.have.property("payload", "on");
      done();
    });
    n1.receive({ payload: "on", testCase: testCase });
  });
});
/* */
/* */
//
// ===========================================================================================
//
it("TC01b- Should turn on, Tx on", function (done) { // ???
  var testCase = "0001b";

  var timeOut = 5;
  var turnOff = 2;
  var isDone  = false;

  var cmnds = [];
  var ticks = [];

  var t = 0;
  var c = 0;

  this.timeout((timeOut+2)*1000); // run timer for timeOut plus 2 seconds overrun

  // Node 1:{"id":"n1","type":"mytimeout","_closeCallbacks":[null],"_inputCallbacks":null,"name":"MyTimeout","wires":[["n2"],["n3"]],"_wireCount":2,"timer":5,"state":"stop","warning":2,"outsafe":"on","outwarn":"warning","outunsafe":"off","_events":{},"_eventsCount":1}
  const On  = "on";
  const Off = "off";

  var flow = [
    { id: "n1", type: "mytimeout", name: nom,
      outsafe:    On,
      outwarning: "warning",
      outunsafe:  Off,
      timer:      timeOut,
      warning:    turnOff,
      debug:      "0",
      wires:[["n2"], ["n3"]] },
    { id: "n2", type: "helper" },
    { id: "n3", type: "helper" }
  ];

  helper.load(myNode, flow, function () {
    var fini = 0;

    var n3 = helper.getNode("n3");
    var n2 = helper.getNode("n2");
    var n1 = helper.getNode("n1");

    // Need to run the n2 & n3 until I get the last command (off) and the last tick.
    n2.on("input", function (msg) {
      cmnds[c++] = JSON.parse(JSON.stringify(msg)); // Can't just to cmnds[c++] = msg (not a new copy, just a pointer)

      // do until payload = "off"
      try {
        if(msg.payload == Off) {
          //console.log("\nCmnds: " + JSON.stringify(cmnds));
          cmnds.should.have.length(3, "Number of commands issued");
          cmnds[0].should.have.property("payload", On);
          cmnds[1].should.have.property("payload", 'warning');
          cmnds[2].should.have.property("payload", Off);
        }
      } catch(err) {
        //console.log ("Node 1:" + JSON.stringify(n1) + "\n");
        console.log("Cmnds: " + JSON.stringify(cmnds));
        console.log(`Ticks: ` + JSON.stringify(ticks) + `\nn1.timer: ${n1.timer}\n`);

        console.log("Cmnds Err: " + err);
        done("Cmnds Err:"  + err);
      }
    });

    n3.on("input", function (msg) {
      ticks[t++] = JSON.parse(JSON.stringify(msg)); // Can't just to ticks[t++] = msg (not a new copy, just a pointer)

      // do until payload = 0
      if(msg.payload == 0) {
        try {
          var j = timeOut; // n1.timer - turnOff;
          var idx = n1.timer + 1;
          for(let i = 0; i < idx ; i++) {
            ticks[i].payload.should.be.exactly(j--); // Count down to 0
          }
          
          done();
        } catch(err) {
          console.log("Ticks: " + JSON.stringify(ticks) + `\nn1.timer: ${n1.timer}\n`);
          console.log("Ticks Err: " + err);
          done(err);
        }
      }
    });

    n1.receive({ payload: "on", testCase: testCase });
  });
});
/* */

Odd results

✓ Should turn normal on/off, Tx on w/floats - TC xx (6014ms) Cmnds: [{“payload”:”oN”,”extra”:”extra1”,”_msgid”:”2d8d4a69.e05dc6”}, {“payload”:”oN”,”extra”:”extra2”,”_msgid”:”dddb657f.d12eb8”}, {“payload”:”warning”,”extra”:”extra2”,”_msgid”:”dddb657f.d12eb8”}, {“payload”:”oFF”,”extra”:”extra2”,”_msgid”:”dddb657f.d12eb8”}]

Ticks: [{“payload”:10,”state”:1,”flag”:”ticks > 0”,”_msgid”:”89a08871.dcb0c8”}, {“payload”:9,”state”:1,”flag”:”ticks > 0”,”_msgid”:”a48abf83.220cc”}, {“payload”:8,”state”:1,”flag”:”ticks > 0”,”_msgid”:”33ca89f0.30d226”}, {“payload”:7,”state”:1,”flag”:”ticks > 0”,”_msgid”:”5138258e.062ddc”}, {“payload”:10,”state”:1,”flag”:”ticks > 0”,”_msgid”:”89e191fa.b388f”}, {“payload”:9,”state”:1,”flag”:”ticks > 0”,”_msgid”:”b03b1bfa.334ff8”}, {“payload”:8,”state”:1,”flag”:”ticks > 0”,”_msgid”:”23b3c00d.3091d”}, {“payload”:7,”state”:1,”flag”:”ticks > 0”,”_msgid”:”f64bfafe.c7efc8”}, {“payload”:6,”state”:1,”flag”:”ticks > 0”,”_msgid”:”ddd1e1f7.c9e8a”}, {“payload”:5,”state”:1,”flag”:”ticks > 0”,”_msgid”:”39e08930.853336”}, {“payload”:4,”state”:1,”flag”:”ticks > 0”,”_msgid”:”1da0bd7b.8d2983”}, {“payload”:3,”state”:1,”flag”:”ticks > 0”,”_msgid”:”680f940.c242f6c”}, {“payload”:2,”state”:2,”flag”:”warn >= ticks”,”_msgid”:”94c884b3.bd6068”}, {“payload”:1,”state”:2,”flag”:”warn >= ticks”,”_msgid”:”5b080bb1.1be1f4”}, {“payload”:0,”state”:0,”flag”:”off”,”_msgid”:”dddb657f.d12eb8”}]

Ticks Err: AssertionError: expected Array [ Object { payload: 10, state: 1, flag: ‘ticks > 0’, _msgid: ‘89a08871.dcb0c8’ }, Object { payload: 9, state: 1, flag: ‘ticks > 0’, _msgid: ‘a48abf83.220cc’ }, Object { payload: 8, state: 1, flag: ‘ticks > 0’, _msgid: ‘33ca89f0.30d226’ }, Object { payload: 7, state: 1, flag: ‘ticks > 0’, _msgid: ‘5138258e.062ddc’ }, Object { payload: 10, state: 1, flag: ‘ticks > 0’, _msgid: ‘89e191fa.b388f’ }, Object { payload: 9, state: 1, flag: ‘ticks > 0’, _msgid: ‘b03b1bfa.334ff8’ }, Object { payload: 8, state: 1, flag: ‘ticks > 0’, _msgid: ‘23b3c00d.3091d’ }, Object { payload: 7, state: 1, flag: ‘ticks > 0’, _msgid: ‘f64bfafe.c7efc8’ }, Object { payload: 6, state: 1, flag: ‘ticks > 0’, _msgid: ‘ddd1e1f7.c9e8a’ }, Object { payload: 5, state: 1, flag: ‘ticks > 0’, _msgid: ‘39e08930.853336’ }, Object { payload: 4, state: 1, flag: ‘ticks > 0’, _msgid: ‘1da0bd7b.8d2983’ }, Object { payload: 3, state: 1, flag: ‘ticks > 0’, _msgid: ‘680f940.c242f6c’ }, Object { payload: 2, state: 2, flag: ‘warn >= ticks’, _msgid: ‘94c884b3.bd6068’ }, Object { payload: 1, state: 2, flag: ‘warn >= ticks’, _msgid: ‘5b080bb1.1be1f4’ }, Object { payload: 0, state: 0, flag: “off”, _msgid: ‘dddb657f.d12eb8’ } ] to have property length of 10 (got 15)

Results

Basic mytimeout Node ✓ TC00 - should be loaded ✓ TC01 - timed on, minimal time (2/1), TX on (4010ms) ✓ TC02 - stop, should be timed, TX stop (4008ms) ✓ TC03 - cancel, should be timed, TX cancel (4007ms) ✓ TC05 - Should turn off Tx off ✓ TC06 - Should turn off Tx 0 ✓ TC07 - Should on with no warning (warning value as an integer), Tx on (4006ms) ✓ TC08 - Should turn off, Tx off ✓ TC08 - Should turn off, Tx 0 ✓ TC11 - Should turn on/on, Tx on (7007ms) ✓ TC11a- Should turn on/” with warning, Tx on (7009ms) ✓ TC11b- Should turn on/” with no warning, Tx on (7007ms) ✓ TC15 - Should turn on then off, Tx on (4010ms) ✓ TC16 - Should turn on then stop, Tx on (4010ms) ✓ TC19 - Should turn on then cancel, Tx on (4010ms) ✓ TCxx - Should turn on 2 Tx 1 (1006ms) ✓ TC20?- Should turn on 2, complex Tx 1 (4007ms) ✓ TC21a- Should turn normal on/off, Tx on w/floats (6011ms) ✓ TC23 - Should turn on/on (2nd no payload), Tx on - TC xx (15020ms) ✓ TC24 - Should turn on with junk, Tx junk (6012ms) ✓ TC25 - Should turn on with junk with no outwarning (”), Tx junk (6013ms) ✓ TC26 - Should turn on with junk with outwarning not defined & warning (0), Tx junk (6012ms) ✓ TC27 - Should turn on with junk with outwarning &warning defined, Tx junk & warning 0 (6014ms)

mytimeout Node/MQTT flow test ✓ TC00 - should be loaded

X Promise tests ✓ TC01 - Dummy, should be true ✓ TC02 - Dummy, should be false ✓ TC03 - should fail and I should catch it ✓ TC04 - timed on, minimal time (2/1), TX on (4007ms)

28 passing (2m)

-[ Fini ]------------------------------ ----------------------------------------

Emacs Org-mode stuff