diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..4c63036 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,28 @@ +name: CI + +on: + push: + branches: [master] + pull_request: + +permissions: + contents: read + +jobs: + test: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + node: [22, 24, 26] + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 + with: + persist-credentials: false + - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 + with: + node-version: ${{ matrix.node }} + cache: npm + registry-url: https://registry.npmjs.org + - run: npm ci --ignore-scripts + - run: npm test diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ddedbd1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +node_modules/ +coverage/ +*.tgz diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..49e685b --- /dev/null +++ b/package-lock.json @@ -0,0 +1,22 @@ +{ + "name": "when-conditional", + "version": "2.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "when-conditional", + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "setimmediate": "^1.0.2" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "license": "MIT" + } + } +} diff --git a/package.json b/package.json index eedcbf1..6ed7a7c 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,9 @@ "version": "2.0.0", "description": "A simple little asyncronous if check and conditional method", "main": "when.js", + "scripts": { + "test": "node --test test/*.js" + }, "repository": { "type": "git", "url": "https://github.com/thekemkid/when-conditional.git" diff --git a/test/test-clear.js b/test/test-clear.js index 69795fc..7a7e897 100644 --- a/test/test-clear.js +++ b/test/test-clear.js @@ -1,21 +1,40 @@ -var when = require('../'); -var someVar = false; - -var interval = setInterval(function(){ - console.log('someVar is ' + someVar); - if(someVar === true) clearInterval(interval); -}, 1000); - -var immediate = when(function condition(){ - return (someVar === true); -}, function code(){ - console.log("someVar is now true, and this was only triggered when it became true!"); -}); - -setTimeout(function(){ - someVar = true; -}, 10000); - -setTimeout(function(){ - immediate.clear(); -}, 5000); +const test = require("node:test"); +const assert = require("node:assert/strict"); +const { setImmediate } = require("node:timers/promises"); +const when = require("../"); + +test("clear stops future checks and is safe to repeat", async (t) => { + let checks = 0; + let calls = 0; + const handle = when( + () => { + checks++; + return false; + }, + () => calls++, + ); + t.after(() => handle.clear()); + + handle.clear(); + handle.clear(); + await setImmediate(); + + assert.equal(checks, 1); + assert.equal(calls, 0); +}); + +test("setters do not restart a cancelled controller", async (t) => { + let calls = 0; + const handle = when( + () => false, + () => calls++, + ); + t.after(() => handle.clear()); + + handle.clear(); + handle.setCondition(() => true); + handle.setCode(() => calls++); + await setImmediate(); + + assert.equal(calls, 0); +}); diff --git a/test/test-reset.js b/test/test-reset.js index a2450fa..ebd78be 100644 --- a/test/test-reset.js +++ b/test/test-reset.js @@ -1,28 +1,58 @@ -var when = require('../'); -var someVar = false; - -var interval = setInterval(function(){ - console.log('someVar is ' + someVar); - if(someVar === true) clearInterval(interval); -}, 1000); - -var when = when(function condition(){ - return (someVar === true); -}, function code(){ - console.log("someVar is now true, and this was only triggered when it became true!"); -}); - -setTimeout(function(){ - someVar = true; -}, 10000); - -setTimeout(function(){ - when.clear(); -}, 5000); - -setTimeout(function(){ - when.reset(); - when.setCode(function setNewCode(){ - console.log("someVar is now true, and this was only triggered when it became true AND after it was reset AND after the 'code' CB was changed! \\0/"); - }) -}, 8000); +const test = require("node:test"); +const assert = require("node:assert/strict"); +const { setImmediate } = require("node:timers/promises"); +const when = require("../"); + +test("reset checks a cancelled controller synchronously", (t) => { + let ready = false; + let calls = 0; + const handle = when( + () => ready, + () => calls++, + ); + t.after(() => handle.clear()); + + handle.clear(); + ready = true; + handle.reset(); + + assert.equal(calls, 1); +}); + +test("reset checks a completed controller synchronously", (t) => { + let calls = 0; + const handle = when( + () => true, + () => calls++, + ); + t.after(() => handle.clear()); + + assert.equal(calls, 1); + handle.reset(); + assert.equal(calls, 2); +}); + +test("a callback can reset the controller after asynchronous success", async (t) => { + let ready = false; + let calls = 0; + const handle = when( + () => ready, + () => { + calls++; + if (calls === 1) { + ready = false; + handle.reset(); + } + }, + ); + t.after(() => handle.clear()); + + ready = true; + await setImmediate(); + assert.equal(calls, 1); + ready = true; + await setImmediate(); + assert.equal(calls, 2); + await setImmediate(); + assert.equal(calls, 2); +}); diff --git a/test/test.js b/test/test.js index 64ff908..0a532ed 100644 --- a/test/test.js +++ b/test/test.js @@ -1,18 +1,64 @@ -var when = require('../'); -var someVar = false; - -var interval = setInterval(function(){ - console.log('someVar is ' + someVar); - if(someVar === true) clearInterval(interval); -}, 1000); - -var immediate = when(function condition(){ - return (someVar === true); -}, function code(){ - console.log("someVar is now true, and this was only triggered when it became true!"); -}); - -setTimeout(function(){ - someVar = true; -}, 10000); - +const test = require("node:test"); +const assert = require("node:assert/strict"); +const { setImmediate } = require("node:timers/promises"); +const when = require("../"); + +test("calls the callback synchronously when the initial condition is truthy", (t) => { + let calls = 0; + const handle = when( + () => "ready", + () => calls++, + ); + t.after(() => handle.clear()); + + assert.equal(calls, 1); +}); + +test("checks a false condition again and calls the callback once", async (t) => { + let ready = false; + let calls = 0; + const handle = when( + () => ready, + () => calls++, + ); + t.after(() => handle.clear()); + + assert.equal(calls, 0); + ready = true; + await setImmediate(); + assert.equal(calls, 1); + await setImmediate(); + assert.equal(calls, 1); +}); + +test("uses replacement condition and callback while active", async (t) => { + let oldCalls = 0; + let newCalls = 0; + const handle = when( + () => false, + () => oldCalls++, + ); + t.after(() => handle.clear()); + + handle.setCondition(() => true); + handle.setCode(() => newCalls++); + await setImmediate(); + + assert.equal(oldCalls, 0); + assert.equal(newCalls, 1); +}); + +test("setters do not restart a completed controller", async (t) => { + let calls = 0; + const handle = when( + () => true, + () => calls++, + ); + t.after(() => handle.clear()); + + handle.setCondition(() => true); + handle.setCode(() => calls++); + await setImmediate(); + + assert.equal(calls, 1); +});