diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..6313b56
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+* text=auto eol=lf
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
new file mode 100644
index 0000000..9857501
--- /dev/null
+++ b/.github/CODEOWNERS
@@ -0,0 +1 @@
+* @okwolf
\ No newline at end of file
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 273e10d..8356895 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -2,18 +2,18 @@ name: CI
on: [push, pull_request]
jobs:
test:
- runs-on: ubuntu-latest
+ runs-on: ${{ matrix.os }}
strategy:
matrix:
- node-version: [12.x, 14.x, 16.x]
+ os: [ubuntu-latest, macos-latest, windows-latest]
+ node: [18, 20, 22]
steps:
- - uses: actions/checkout@v2
- - name: Use Node.js ${{ matrix.node-version }}
- uses: actions/setup-node@v1
+ - uses: actions/checkout@v4
+ - name: Use Node.js ${{ matrix.node }}
+ uses: actions/setup-node@v4
with:
- node-version: ${{ matrix.node-version }}
- - run: |
- npm i -g codecov
- npm i
- npm run check
- codecov
+ node-version: ${{ matrix.node }}
+ - run: npm run release:dry
+ - uses: codecov/codecov-action@v4
+ with:
+ token: ${{ secrets.CODECOV_TOKEN }}
diff --git a/.prettierrc b/.prettierrc
deleted file mode 100644
index aa67954..0000000
--- a/.prettierrc
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "semi": false,
- "trailingComma": "none",
- "arrowParens": "avoid"
-}
diff --git a/README.md b/README.md
index a0a2d6d..020d02f 100644
--- a/README.md
+++ b/README.md
@@ -11,8 +11,8 @@ A handy set of effects for use with [Hyperapp](https://github.com/jorgebucaran/h
Here's a taste of how to use a common effect for making HTTP requests. The app displays inspiring quotes about design, fetching a new quote each time the user clicks on the current one. Go ahead and [try it online here](https://codepen.io/okwolf/pen/vPbMaa?editors=0010).
```js
-import { app, h, text } from "hyperapp"
-import { Http } from "hyperapp-fx"
+import { app, h, text } from "hyperapp";
+import { Http } from "hyperapp-fx";
const GetQuote = () => [
"...",
@@ -20,13 +20,13 @@ const GetQuote = () => [
url: "https://api.quotable.io/random",
action: (_, { content }) => content
})
-]
+];
app({
init: "Click here for quotes",
view: quote => h("h1", { onclick: GetQuote }, text(quote)),
node: document.getElementById("app")
-})
+});
```
More [examples](https://github.com/okwolf/hyperapp-playground) are available to show other effects in action.
@@ -40,13 +40,13 @@ npm i hyperapp-fx
Then with a module bundler like [Rollup](https://rollupjs.org) or [Webpack](https://webpack.js.org), use as you would anything else.
```js
-import { Http } from "hyperapp-fx"
+import { Http } from "hyperapp-fx";
```
-If you don't want to set up a build environment, you can download Hyperapp FX from a CDN like [unpkg.com](https://unpkg.com/hyperapp-fx) and it will be globally available through the window.hyperappFx object. We support all ES5-compliant browsers, including Internet Explorer 10 and above. Use of the [`Http`](api.md#module_fx.exports.Http) effect requires a polyfill.
+If you don't want to set up a build environment, you can import Hyperapp FX from a CDN like [esm.sh](https://esm.sh/hyperapp-fx). We support all modern browsers used by at least 1% of the world.
-```html
-
+```js
+import { Http } from "https://esm.sh/hyperapp-fx";
```
## [API documentation](api.md)
diff --git a/eslint.config.js b/eslint.config.js
new file mode 100644
index 0000000..062ce40
--- /dev/null
+++ b/eslint.config.js
@@ -0,0 +1,34 @@
+import js from "@eslint/js";
+import globals from "globals";
+import compat from "eslint-plugin-compat";
+
+export default [
+ js.configs.recommended,
+ {
+ plugins: { compat },
+ rules: {
+ "no-use-before-define": "error",
+ "no-var": "error",
+ "prefer-const": "error",
+ "compat/compat": "error"
+ }
+ },
+ {
+ files: ["src/**/*.js", "test/**/*.js"],
+ languageOptions: {
+ globals: globals.browser
+ }
+ },
+ {
+ files: ["test/**/*.js", "*.js"],
+ languageOptions: {
+ globals: globals.node
+ }
+ },
+ {
+ files: ["test/**/*.js"],
+ languageOptions: {
+ globals: globals.jest
+ }
+ }
+];
diff --git a/package.json b/package.json
index e8d8e92..d5cde15 100644
--- a/package.json
+++ b/package.json
@@ -2,60 +2,38 @@
"name": "hyperapp-fx",
"version": "2.0.0-beta.2",
"description": "Effects for use with Hyperapp",
- "main": "dist/hyperappFx.js",
"type": "module",
"module": "src/index.js",
"peerDependencies": {
"hyperapp": "^2.0.0"
},
"devDependencies": {
- "eslint": "=8.8.0",
- "eslint-plugin-compat": "=4.0.2",
- "jest": "=27.5.0",
- "jsdoc-to-markdown": "=7.1.1",
- "jsdom": "=19.0.0",
- "prettier": "=2.5.1",
- "rollup": "=2.67.0",
- "uglify-js": "=3.15.0"
+ "eslint": "=8.57.0",
+ "eslint-plugin-compat": "=5.0.0",
+ "jest": "=29.7.0",
+ "jest-environment-jsdom": "=29.7.0",
+ "jsdoc-to-markdown": "=8.0.1",
+ "prettier": "=3.3.2",
+ "rollup": "=4.18.0",
+ "uglify-js": "=3.18.0"
},
"scripts": {
- "clean": "npx --ignore-existing --quiet rimraf coverage dist node_modules",
- "format": "prettier --write \"{src,test}/**/*.js\"",
- "format:check": "prettier --list-different \"{src,test}/**/*.js\"",
- "lint": "eslint {src,test}/**/*.js",
+ "clean": "npx --quiet rimraf coverage dist node_modules",
+ "format": "prettier --write \"**/*.js\"",
+ "format:check": "prettier --list-different \"**/*.js\"",
+ "lint": "eslint . --ignore-pattern dist",
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js --coverage --no-cache",
"doc": "jsdoc2md src/fx/*.js src/subs/*.js > api.md",
- "bundle": "rollup -i src/index.js -o dist/hyperappFx.js -m -f umd -n hyperappFx",
- "minify": "uglifyjs dist/hyperappFx.js -o dist/hyperappFx.js -mc pure_funcs=['Object.defineProperty'] --source-map includeSources,url=hyperappFx.js.map",
"check": "npm run format:check && npm run lint && npm t",
- "build": "npm run check && npm run bundle && npm run minify",
- "release:dry": "npm run clean && npm i && npm run check && npm run build && npm run doc",
+ "release:dry": "npm run clean && npm i && npm run check && npm run doc",
"release": "node --experimental-json-modules release"
},
- "eslintConfig": {
- "extends": "eslint:recommended",
- "plugins": [
- "compat"
- ],
- "parserOptions": {
- "ecmaVersion": "latest",
- "sourceType": "module"
- },
- "env": {
- "browser": true
- },
- "rules": {
- "no-use-before-define": "error",
- "compat/compat": "error"
- },
- "settings": {
- "polyfills": [
- "fetch"
- ]
- }
+ "prettier": {
+ "trailingComma": "none",
+ "arrowParens": "avoid"
},
"browserslist": [
- "IE 10"
+ "> 1%"
],
"jest": {
"testEnvironment": "jsdom",
diff --git a/release.js b/release.js
index 82cdaa1..3dbd0dc 100644
--- a/release.js
+++ b/release.js
@@ -1,30 +1,30 @@
-import { execSync } from "child_process"
-import packageJson from "./package.json"
-import { fileURLToPath } from "url"
-import { dirname } from "path"
+import { execSync } from "child_process";
+import packageJson from "./package.json";
+import { fileURLToPath } from "url";
+import { dirname } from "path";
-const __filename = fileURLToPath(import.meta.url)
-const __dirname = dirname(__filename)
-const exec = command => execSync(command, { encoding: "utf8" }).trim()
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = dirname(__filename);
+const exec = command => execSync(command, { encoding: "utf8" }).trim();
const exitWithError = error => {
- process.stderr.write(`\x1b[1;31m${error}\x1b[0m\n\n`)
- process.exit(1)
-}
+ process.stderr.write(`\x1b[1;31m${error}\x1b[0m\n\n`);
+ process.exit(1);
+};
-const gitBranchName = exec("git rev-parse --abbrev-ref HEAD")
+const gitBranchName = exec("git rev-parse --abbrev-ref HEAD");
if (gitBranchName !== "master") {
- exitWithError("please checkout the master branch to make a release!")
+ exitWithError("please checkout the master branch to make a release!");
}
-const workingCopyChanges = exec("git status --porcelain")
+const workingCopyChanges = exec("git status --porcelain");
if (workingCopyChanges) {
- exitWithError("please commit your changes before making a release!")
+ exitWithError("please commit your changes before making a release!");
}
-const tagExists = exec(`git tag -l "${packageJson.version}"`)
+const tagExists = exec(`git tag -l "${packageJson.version}"`);
if (tagExists) {
- exitWithError(`${packageJson.version} has already been released!`)
+ exitWithError(`${packageJson.version} has already been released!`);
}
execSync(
@@ -34,4 +34,4 @@ execSync(
stdio: "inherit",
cwd: __dirname
}
-)
+);
diff --git a/src/fx/Console.js b/src/fx/Console.js
index 020a03a..1f96a8f 100644
--- a/src/fx/Console.js
+++ b/src/fx/Console.js
@@ -1,6 +1,6 @@
function consoleEffect(_, args) {
// eslint-disable-next-line no-console
- console.log.apply(null, args)
+ console.log.apply(null, args);
}
/**
@@ -22,5 +22,5 @@ function consoleEffect(_, args) {
* ]
*/
export function Console() {
- return [consoleEffect, arguments]
+ return [consoleEffect, arguments];
}
diff --git a/src/fx/Cookie.js b/src/fx/Cookie.js
index f21ed0f..40a464c 100644
--- a/src/fx/Cookie.js
+++ b/src/fx/Cookie.js
@@ -1,17 +1,17 @@
-import { assign } from "../utils.js"
+import { assign } from "../utils.js";
-var validCookieNameChars =
- "abdefghijklmnqrstuvxyzABDEFGHIJKLMNQRSTUVXYZ0123456789!#$%&'*+-.^_`|~"
-var validCookieValueChars = validCookieNameChars + "()/:<>?@[]{}"
+const validCookieNameChars =
+ "abdefghijklmnqrstuvxyzABDEFGHIJKLMNQRSTUVXYZ0123456789!#$%&'*+-.^_`|~";
+const validCookieValueChars = validCookieNameChars + "()/:<>?@[]{}";
function nameEncoder(value) {
return value
.toString()
.split("")
.map(function (c) {
- return validCookieNameChars.indexOf(c) > -1 ? c : encodeURIComponent(c)
+ return validCookieNameChars.indexOf(c) > -1 ? c : encodeURIComponent(c);
})
- .join("")
+ .join("");
}
function valueEncoder(value) {
@@ -19,45 +19,45 @@ function valueEncoder(value) {
.toString()
.split("")
.map(function (c) {
- return validCookieValueChars.indexOf(c) > -1 ? c : encodeURIComponent(c)
+ return validCookieValueChars.indexOf(c) > -1 ? c : encodeURIComponent(c);
})
- .join("")
+ .join("");
}
function writeCookie(name, value, attributes) {
- var attrs = Object.keys(attributes)
+ const attrs = Object.keys(attributes)
.map(function (k) {
- return k + "=" + attributes[k]
+ return k + "=" + attributes[k];
})
- .join(";")
- document.cookie = name + "=" + value + (attrs ? ";" + attrs : "")
+ .join(";");
+ document.cookie = name + "=" + value + (attrs ? ";" + attrs : "");
}
function readCookieEffect(dispatch, props) {
- var cookies = document.cookie.split("; ")
- var cookie = cookies.find(function (c) {
- return c.substr(0, c.indexOf("=")) === props.nameEncoder(props.name)
- })
+ const cookies = document.cookie.split("; ");
+ const cookie = cookies.find(function (c) {
+ return c.substr(0, c.indexOf("=")) === props.nameEncoder(props.name);
+ });
if (cookie) {
- var dispatchProps = assign({}, props.props || {})
+ const dispatchProps = assign({}, props.props || {});
dispatchProps[props.prop || "value"] = props.converter(
props.decoder(cookie.substr(props.nameEncoder(props.name).length + 1))
- )
- dispatch(props.action, dispatchProps)
+ );
+ dispatch(props.action, dispatchProps);
}
}
function writeCookieEffect(dispatch, props) {
- var name = (props.nameEncoder || nameEncoder)(props.name)
- var value = (props.encoder || valueEncoder)(props.converter(props.value))
- var attributes = {}
+ const name = (props.nameEncoder || nameEncoder)(props.name);
+ const value = (props.encoder || valueEncoder)(props.converter(props.value));
+ const attributes = {};
if (props.ttl)
- props.expires = new Date(new Date().getTime() + props.ttl * 1000)
- if (props.path) attributes.path = props.path
- if (props.domain) attributes.domain = props.domain
- if (props.expires) attributes.expires = props.expires.toUTCString()
+ props.expires = new Date(new Date().getTime() + props.ttl * 1000);
+ if (props.path) attributes.path = props.path;
+ if (props.domain) attributes.domain = props.domain;
+ if (props.expires) attributes.expires = props.expires.toUTCString();
- writeCookie(name, value, attributes)
+ writeCookie(name, value, attributes);
}
/**
@@ -97,13 +97,13 @@ export function ReadCookie(props) {
props.converter || props.json
? JSON.parse
: function (v) {
- return v
+ return v;
},
decoder: props.decoder || decodeURIComponent
},
props
)
- ]
+ ];
}
/**
@@ -143,12 +143,12 @@ export function WriteCookie(props) {
props.converter || props.json
? JSON.stringify
: function (v) {
- return v
+ return v;
}
},
props
)
- ]
+ ];
}
/**
@@ -170,5 +170,5 @@ export function WriteCookie(props) {
*/
export function DeleteCookie(props) {
- return WriteCookie(assign(props, { ttl: -1, value: "" }))
+ return WriteCookie(assign(props, { ttl: -1, value: "" }));
}
diff --git a/src/fx/Debounce.js b/src/fx/Debounce.js
index 763e9c2..9174f13 100644
--- a/src/fx/Debounce.js
+++ b/src/fx/Debounce.js
@@ -1,18 +1,18 @@
-var debounceTimeouts = []
+const debounceTimeouts = [];
function debounceEffect(dispatch, props) {
- var timeout = debounceTimeouts.find(function (nextTimeout) {
- return nextTimeout[0] === props.action
- })
+ let timeout = debounceTimeouts.find(function (nextTimeout) {
+ return nextTimeout[0] === props.action;
+ });
if (!timeout) {
- timeout = [props.action]
- debounceTimeouts.push(timeout)
+ timeout = [props.action];
+ debounceTimeouts.push(timeout);
} else {
- clearTimeout(timeout[1])
+ clearTimeout(timeout[1]);
}
timeout[1] = setTimeout(function () {
- dispatch(props.action)
- }, props.wait)
+ dispatch(props.action);
+ }, props.wait);
}
/**
@@ -38,5 +38,5 @@ function debounceEffect(dispatch, props) {
* ]
*/
export function Debounce(props) {
- return [debounceEffect, props]
+ return [debounceEffect, props];
}
diff --git a/src/fx/Dispatch.js b/src/fx/Dispatch.js
index f64cad5..9ed30ff 100644
--- a/src/fx/Dispatch.js
+++ b/src/fx/Dispatch.js
@@ -1,5 +1,5 @@
function dispatchEffect(dispatch, props) {
- dispatch(props.action)
+ dispatch(props.action);
}
/**
@@ -17,5 +17,5 @@ function dispatchEffect(dispatch, props) {
* ]
*/
export function Dispatch(action) {
- return [dispatchEffect, { action: action }]
+ return [dispatchEffect, { action: action }];
}
diff --git a/src/fx/Geo.js b/src/fx/Geo.js
index ec5c19a..5147036 100644
--- a/src/fx/Geo.js
+++ b/src/fx/Geo.js
@@ -1,13 +1,13 @@
function getCurrentPositionEffect(dispatch, props) {
navigator.geolocation.getCurrentPosition(
function (result) {
- return dispatch(props.action, result)
+ return dispatch(props.action, result);
},
function (error) {
- return dispatch(props.error, error)
+ return dispatch(props.error, error);
},
props.options
- )
+ );
}
/**
@@ -34,5 +34,5 @@ function getCurrentPositionEffect(dispatch, props) {
* ]
*/
export function GetCurrentPosition(props) {
- return [getCurrentPositionEffect, props]
+ return [getCurrentPositionEffect, props];
}
diff --git a/src/fx/History.js b/src/fx/History.js
index be82083..a54e98a 100644
--- a/src/fx/History.js
+++ b/src/fx/History.js
@@ -1,15 +1,15 @@
function historyPushEffect(dispatch, props) {
- var title = props.title || document.title
- var url = props.url || location.href
+ const title = props.title || document.title;
+ const url = props.url || location.href;
- history.pushState(props.state, title, url)
+ history.pushState(props.state, title, url);
}
function historyReplaceEffect(dispatch, props) {
- var title = props.title || document.title
- var url = props.url || location.href
+ const title = props.title || document.title;
+ const url = props.url || location.href;
- history.replaceState(props.state, title, url)
+ history.replaceState(props.state, title, url);
}
/**
@@ -34,7 +34,7 @@ function historyReplaceEffect(dispatch, props) {
*/
export function HistoryPush(props) {
- return [historyPushEffect, props]
+ return [historyPushEffect, props];
}
/**
@@ -59,5 +59,5 @@ export function HistoryPush(props) {
*/
export function HistoryReplace(props) {
- return [historyReplaceEffect, props]
+ return [historyReplaceEffect, props];
}
diff --git a/src/fx/Http.js b/src/fx/Http.js
index 9fe4815..61a1fdd 100644
--- a/src/fx/Http.js
+++ b/src/fx/Http.js
@@ -1,22 +1,22 @@
-import { assign } from "../utils.js"
+import { assign } from "../utils.js";
function httpEffect(dispatch, props) {
fetch(props.url, props.options)
.then(function (response) {
if (!response.ok) {
- throw response
+ throw response;
}
- return response
+ return response;
})
.then(function (response) {
- return response[props.response]()
+ return response[props.response]();
})
.then(function (result) {
- dispatch(props.action, result)
+ dispatch(props.action, result);
})
.catch(function (error) {
- dispatch(props.error, error)
- })
+ dispatch(props.error, error);
+ });
}
/**
@@ -60,5 +60,5 @@ export function Http(props) {
},
props
)
- ]
+ ];
}
diff --git a/src/fx/Merge.js b/src/fx/Merge.js
index ce9c545..c45785f 100644
--- a/src/fx/Merge.js
+++ b/src/fx/Merge.js
@@ -1,9 +1,9 @@
-import { assign } from "../utils.js"
+import { assign } from "../utils.js";
function mergeEffect(dispatch, props) {
dispatch(function (state) {
- return assign(state, props.action(state))
- })
+ return assign(state, props.action(state));
+ });
}
/**
@@ -20,5 +20,5 @@ function mergeEffect(dispatch, props) {
* ]
*/
export function Merge(action) {
- return [mergeEffect, { action: action }]
+ return [mergeEffect, { action: action }];
}
diff --git a/src/fx/Random.js b/src/fx/Random.js
index f89dbd4..5b18788 100644
--- a/src/fx/Random.js
+++ b/src/fx/Random.js
@@ -1,27 +1,27 @@
function generateRandom(props) {
if (props.values) {
- return props.values.map(generateRandom)
+ return props.values.map(generateRandom);
}
- var min = props.min || 0
- var max = props.max || 1
- if (props.int) max++
+ let min = props.min || 0;
+ let max = props.max || 1;
+ if (props.int) max++;
if (props.bool) {
- min = 0
- max = 2
+ min = 0;
+ max = 2;
}
- var randomValue = Math.random() * (max - min) + min
+ let randomValue = Math.random() * (max - min) + min;
if (props.int || props.bool) {
- randomValue = Math.floor(randomValue)
+ randomValue = Math.floor(randomValue);
}
if (props.bool) {
- randomValue = !!randomValue
+ randomValue = !!randomValue;
}
- return randomValue
+ return randomValue;
}
function randomEffect(dispatch, props) {
- var randomValue = generateRandom(props)
- dispatch(props.action, randomValue)
+ const randomValue = generateRandom(props);
+ dispatch(props.action, randomValue);
}
/**
@@ -54,5 +54,5 @@ function randomEffect(dispatch, props) {
* ]
*/
export function Random(props) {
- return [randomEffect, props]
+ return [randomEffect, props];
}
diff --git a/src/fx/Storage.js b/src/fx/Storage.js
index 6e1fbee..5f62766 100644
--- a/src/fx/Storage.js
+++ b/src/fx/Storage.js
@@ -1,27 +1,27 @@
-import { assign } from "../utils.js"
+import { assign } from "../utils.js";
function storageArea(area) {
- return window[area + "Storage"] || localStorage
+ return window[area + "Storage"] || localStorage;
}
function writeToStorageEffect(_, props) {
- var value = props.converter(props.value)
- storageArea(props.area).setItem(props.key, value)
+ const value = props.converter(props.value);
+ storageArea(props.area).setItem(props.key, value);
}
function readFromStorageEffect(dispatch, props) {
try {
- var value = props.converter(storageArea(props.area).getItem(props.key))
- var dispatchProps = assign({}, props.props || {})
- dispatchProps[props.prop || "value"] = value
- dispatch(props.action, dispatchProps)
+ const value = props.converter(storageArea(props.area).getItem(props.key));
+ const dispatchProps = assign({}, props.props || {});
+ dispatchProps[props.prop || "value"] = value;
+ dispatch(props.action, dispatchProps);
} catch (error) {
- dispatch(props.error)
+ dispatch(props.error);
}
}
function removeFromStorageEffect(_, props) {
- storageArea(props.area).removeItem(props.key)
+ storageArea(props.area).removeItem(props.key);
}
/**
@@ -56,7 +56,7 @@ export function WriteToStorage(props) {
},
props
)
- ]
+ ];
}
/**
@@ -94,7 +94,7 @@ export function ReadFromStorage(props) {
},
props
)
- ]
+ ];
}
/**
@@ -118,5 +118,5 @@ export function ReadFromStorage(props) {
*/
export function RemoveFromStorage(props) {
- return [removeFromStorageEffect, props]
+ return [removeFromStorageEffect, props];
}
diff --git a/src/fx/Throttle.js b/src/fx/Throttle.js
index 5da3045..74a8c4a 100644
--- a/src/fx/Throttle.js
+++ b/src/fx/Throttle.js
@@ -1,19 +1,19 @@
-var throttleLocks = []
+const throttleLocks = [];
function throttleEffect(dispatch, props) {
- var lock = throttleLocks.find(function (nextLock) {
- return nextLock[0] === props.action
- })
+ let lock = throttleLocks.find(function (nextLock) {
+ return nextLock[0] === props.action;
+ });
if (!lock) {
- lock = [props.action]
- throttleLocks.push(lock)
+ lock = [props.action];
+ throttleLocks.push(lock);
}
if (!lock[1]) {
- dispatch(props.action)
- lock[1] = true
+ dispatch(props.action);
+ lock[1] = true;
setTimeout(function () {
- lock[1] = false
- }, props.rate)
+ lock[1] = false;
+ }, props.rate);
}
}
@@ -40,5 +40,5 @@ function throttleEffect(dispatch, props) {
* ]
*/
export function Throttle(props) {
- return [throttleEffect, props]
+ return [throttleEffect, props];
}
diff --git a/src/fx/Time.js b/src/fx/Time.js
index fda958e..7347278 100644
--- a/src/fx/Time.js
+++ b/src/fx/Time.js
@@ -1,11 +1,11 @@
-import { makeDispatchTime } from "../utils.js"
+import { makeDispatchTime } from "../utils.js";
function nowEffect(dispatch, props) {
- makeDispatchTime(dispatch, props)()
+ makeDispatchTime(dispatch, props)();
}
function delayEffect(dispatch, props) {
- setTimeout(makeDispatchTime(dispatch, props), props.wait)
+ setTimeout(makeDispatchTime(dispatch, props), props.wait);
}
/**
@@ -28,7 +28,7 @@ function delayEffect(dispatch, props) {
* ]
*/
export function Now(props) {
- return [nowEffect, props]
+ return [nowEffect, props];
}
/**
@@ -53,5 +53,5 @@ export function Now(props) {
* ]
*/
export function Delay(props) {
- return [delayEffect, props]
+ return [delayEffect, props];
}
diff --git a/src/fx/WebSocket.js b/src/fx/WebSocket.js
index b3a2a81..3e05949 100644
--- a/src/fx/WebSocket.js
+++ b/src/fx/WebSocket.js
@@ -1,15 +1,15 @@
-import { getOpenWebSocket } from "../utils.js"
+import { getOpenWebSocket } from "../utils.js";
function webSocketSendEffect(dispatch, props) {
- var connection = getOpenWebSocket(props)
+ const connection = getOpenWebSocket(props);
function sendMessage() {
- connection.socket.send(props.data)
- connection.socket.removeEventListener("open", sendMessage)
+ connection.socket.send(props.data);
+ connection.socket.removeEventListener("open", sendMessage);
}
if (connection.socket.readyState === WebSocket.CONNECTING) {
- connection.socket.addEventListener("open", sendMessage)
+ connection.socket.addEventListener("open", sendMessage);
} else {
- sendMessage()
+ sendMessage();
}
}
@@ -35,5 +35,5 @@ function webSocketSendEffect(dispatch, props) {
* ]
*/
export function WebSocketSend(props) {
- return [webSocketSendEffect, props]
+ return [webSocketSendEffect, props];
}
diff --git a/src/fx/index.js b/src/fx/index.js
index f5e5b78..979b264 100644
--- a/src/fx/index.js
+++ b/src/fx/index.js
@@ -2,16 +2,16 @@
* @module fx
*/
-export * from "./Dispatch.js"
-export * from "./Console.js"
-export * from "./Random.js"
-export * from "./Http.js"
-export * from "./Merge.js"
-export * from "./Debounce.js"
-export * from "./Throttle.js"
-export * from "./Storage.js"
-export * from "./History.js"
-export * from "./Cookie.js"
-export * from "./Time.js"
-export * from "./WebSocket.js"
-export * from "./Geo.js"
+export * from "./Dispatch.js";
+export * from "./Console.js";
+export * from "./Random.js";
+export * from "./Http.js";
+export * from "./Merge.js";
+export * from "./Debounce.js";
+export * from "./Throttle.js";
+export * from "./Storage.js";
+export * from "./History.js";
+export * from "./Cookie.js";
+export * from "./Time.js";
+export * from "./WebSocket.js";
+export * from "./Geo.js";
diff --git a/src/index.js b/src/index.js
index 2e04a65..54fe670 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,2 +1,2 @@
-export * from "./fx/index.js"
-export * from "./subs/index.js"
+export * from "./fx/index.js";
+export * from "./subs/index.js";
diff --git a/src/subs/Animation.js b/src/subs/Animation.js
index 2b33c71..b5775fd 100644
--- a/src/subs/Animation.js
+++ b/src/subs/Animation.js
@@ -1,15 +1,15 @@
function animationEffect(dispatch, action) {
- var cancelId
+ let cancelId;
function frame(timestamp) {
- dispatch(action, timestamp)
- cancelId = requestAnimationFrame(frame)
+ dispatch(action, timestamp);
+ cancelId = requestAnimationFrame(frame);
}
- cancelId = requestAnimationFrame(frame)
+ cancelId = requestAnimationFrame(frame);
return function () {
- cancelAnimationFrame(cancelId)
- }
+ cancelAnimationFrame(cancelId);
+ };
}
/**
@@ -46,5 +46,5 @@ function animationEffect(dispatch, action) {
* })
*/
export function Animation(action) {
- return [animationEffect, action]
+ return [animationEffect, action];
}
diff --git a/src/subs/Geo.js b/src/subs/Geo.js
index 037c759..ce01e92 100644
--- a/src/subs/Geo.js
+++ b/src/subs/Geo.js
@@ -1,17 +1,17 @@
function watchPositionEffect(dispatch, props) {
- var cancelId = navigator.geolocation.watchPosition(
+ const cancelId = navigator.geolocation.watchPosition(
function (result) {
- return dispatch(props.action, result)
+ return dispatch(props.action, result);
},
function (error) {
- return dispatch(props.error, error)
+ return dispatch(props.error, error);
},
props.options
- )
+ );
return function () {
- navigator.geolocation.clearWatch(cancelId)
- }
+ navigator.geolocation.clearWatch(cancelId);
+ };
}
/**
@@ -32,5 +32,5 @@ function watchPositionEffect(dispatch, props) {
* })
*/
export function WatchPosition(props) {
- return [watchPositionEffect, props]
+ return [watchPositionEffect, props];
}
diff --git a/src/subs/History.js b/src/subs/History.js
index b64548f..e497937 100644
--- a/src/subs/History.js
+++ b/src/subs/History.js
@@ -1,7 +1,7 @@
-import { makeRemoveListener } from "../utils.js"
+import { makeRemoveListener } from "../utils.js";
function historyPopEffect(dispatch, props) {
- return makeRemoveListener(window, dispatch, props.action, "popstate")
+ return makeRemoveListener(window, dispatch, props.action, "popstate");
}
/**
@@ -24,5 +24,5 @@ function historyPopEffect(dispatch, props) {
*/
export function HistoryPop(props) {
- return [historyPopEffect, props]
+ return [historyPopEffect, props];
}
diff --git a/src/subs/Keyboard.js b/src/subs/Keyboard.js
index 030c75a..95fdf7c 100644
--- a/src/subs/Keyboard.js
+++ b/src/subs/Keyboard.js
@@ -1,20 +1,20 @@
-import { makeRemoveListener } from "../utils.js"
+import { makeRemoveListener } from "../utils.js";
function keyboardEffect(dispatch, props) {
- var removeListenerForEvent = makeRemoveListener.bind(
+ const removeListenerForEvent = makeRemoveListener.bind(
null,
document,
dispatch,
props.action
- )
- var removeDown = props.downs ? removeListenerForEvent("keydown") : null
- var removeUp = props.ups ? removeListenerForEvent("keyup") : null
- var removePress = props.presses ? removeListenerForEvent("keypress") : null
+ );
+ const removeDown = props.downs ? removeListenerForEvent("keydown") : null;
+ const removeUp = props.ups ? removeListenerForEvent("keyup") : null;
+ const removePress = props.presses ? removeListenerForEvent("keypress") : null;
return function () {
- removeDown && removeDown()
- removeUp && removeUp()
- removePress && removePress()
- }
+ removeDown && removeDown();
+ removeUp && removeUp();
+ removePress && removePress();
+ };
}
/**
@@ -39,5 +39,5 @@ function keyboardEffect(dispatch, props) {
* })
*/
export function Keyboard(props) {
- return [keyboardEffect, props]
+ return [keyboardEffect, props];
}
diff --git a/src/subs/Time.js b/src/subs/Time.js
index 66d8cb9..c4ebcf0 100644
--- a/src/subs/Time.js
+++ b/src/subs/Time.js
@@ -1,11 +1,11 @@
-import { makeDispatchTime } from "../utils.js"
+import { makeDispatchTime } from "../utils.js";
function intervalEffect(dispatch, props) {
- var dispatchTime = makeDispatchTime(dispatch, props)
- var everyInterval = setInterval(dispatchTime, props.every)
+ const dispatchTime = makeDispatchTime(dispatch, props);
+ const everyInterval = setInterval(dispatchTime, props.every);
return function () {
- everyInterval && clearInterval(everyInterval)
- }
+ everyInterval && clearInterval(everyInterval);
+ };
}
/**
@@ -46,5 +46,5 @@ function intervalEffect(dispatch, props) {
* })
*/
export function Interval(props) {
- return [intervalEffect, props]
+ return [intervalEffect, props];
}
diff --git a/src/subs/WebSocket.js b/src/subs/WebSocket.js
index 8d9b31d..a7fa05e 100644
--- a/src/subs/WebSocket.js
+++ b/src/subs/WebSocket.js
@@ -2,65 +2,65 @@ import {
getOpenWebSocket,
makeRemoveListener,
closeWebSocket
-} from "../utils.js"
+} from "../utils.js";
function webSocketListenEffect(dispatch, props) {
- var connection = getOpenWebSocket(props)
- var removeListen = makeRemoveListener(
+ const connection = getOpenWebSocket(props);
+ const removeListen = makeRemoveListener(
connection.socket,
dispatch,
props.action,
"message"
- )
- connection.listeners.push(removeListen)
- var removeError
+ );
+ connection.listeners.push(removeListen);
+ let removeError;
if (props.error) {
removeError = makeRemoveListener(
connection.socket,
dispatch,
props.error,
"error"
- )
- connection.listeners.push(removeError)
+ );
+ connection.listeners.push(removeError);
}
- var removeOpen
+ let removeOpen;
if (props.open) {
removeOpen = makeRemoveListener(
connection.socket,
dispatch,
props.open,
"open"
- )
- connection.listeners.push(removeOpen)
+ );
+ connection.listeners.push(removeOpen);
}
- var removeClose
+ let removeClose;
if (props.close) {
removeClose = makeRemoveListener(
connection.socket,
dispatch,
props.close,
"close"
- )
- connection.listeners.push(removeClose)
+ );
+ connection.listeners.push(removeClose);
}
return function () {
- removeListen && removeListen()
- removeError && removeError()
- removeOpen && removeOpen()
- removeClose && removeClose()
+ removeListen && removeListen();
+ removeError && removeError();
+ removeOpen && removeOpen();
+ removeClose && removeClose();
connection.listeners = connection.listeners.filter(function (listener) {
return (
listener !== removeListen &&
listener !== removeError &&
listener !== removeOpen &&
listener !== removeClose
- )
- })
+ );
+ });
if (connection.listeners.length === 0) {
- closeWebSocket(props)
+ closeWebSocket(props);
}
- }
+ };
}
/**
@@ -83,5 +83,5 @@ function webSocketListenEffect(dispatch, props) {
* })
*/
export function WebSocketListen(props) {
- return [webSocketListenEffect, props]
+ return [webSocketListenEffect, props];
}
diff --git a/src/subs/index.js b/src/subs/index.js
index 4b95da8..0312c29 100644
--- a/src/subs/index.js
+++ b/src/subs/index.js
@@ -2,9 +2,9 @@
* @module subs
*/
-export * from "./Time.js"
-export * from "./Animation.js"
-export * from "./Keyboard.js"
-export * from "./WebSocket.js"
-export * from "./History.js"
-export * from "./Geo.js"
+export * from "./Time.js";
+export * from "./Animation.js";
+export * from "./Keyboard.js";
+export * from "./WebSocket.js";
+export * from "./History.js";
+export * from "./Geo.js";
diff --git a/src/utils.js b/src/utils.js
index 265485b..a9c5e9d 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -1,42 +1,42 @@
export function assign(source, assignments) {
- var result = {},
- i
- for (i in source) result[i] = source[i]
- for (i in assignments) result[i] = assignments[i]
- return result
+ const result = {};
+ let i;
+ for (i in source) result[i] = source[i];
+ for (i in assignments) result[i] = assignments[i];
+ return result;
}
export function makeRemoveListener(attachTo, dispatch, action, eventName) {
- var handler = dispatch.bind(null, action)
- attachTo.addEventListener(eventName, handler)
+ const handler = dispatch.bind(null, action);
+ attachTo.addEventListener(eventName, handler);
return function () {
- attachTo.removeEventListener(eventName, handler)
- }
+ attachTo.removeEventListener(eventName, handler);
+ };
}
export function makeDispatchTime(dispatch, props) {
return function () {
- dispatch(props.action, props.asDate ? new Date() : performance.now())
- }
+ dispatch(props.action, props.asDate ? new Date() : performance.now());
+ };
}
-var webSocketConnections = {}
+const webSocketConnections = {};
export function getOpenWebSocket(props) {
- var connection = webSocketConnections[props.url]
+ let connection = webSocketConnections[props.url];
if (!connection) {
connection = {
socket: new WebSocket(props.url, props.protocols),
listeners: []
- }
- webSocketConnections[props.url] = connection
+ };
+ webSocketConnections[props.url] = connection;
}
- return connection
+ return connection;
}
export function closeWebSocket(props) {
- var connection = getOpenWebSocket(props)
+ const connection = getOpenWebSocket(props);
// FIXME: handle close on opening
- connection.socket.close()
- delete webSocketConnections[props.url]
+ connection.socket.close();
+ delete webSocketConnections[props.url];
}
diff --git a/test/.eslintrc b/test/.eslintrc
deleted file mode 100644
index 6e407e7..0000000
--- a/test/.eslintrc
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "env": {
- "node": true,
- "jest": true
- },
- "globals": {
- "Promise": true
- },
- "rules": {
- "compat/compat": "off"
- }
-}
diff --git a/test/fx/Console.test.js b/test/fx/Console.test.js
index 3ab0614..45fd093 100644
--- a/test/fx/Console.test.js
+++ b/test/fx/Console.test.js
@@ -1,20 +1,20 @@
-import { jest } from "@jest/globals"
-import { runFx } from "../utils"
-import { Console } from "../../src"
+import { jest } from "@jest/globals";
+import { runFx } from "../utils";
+import { Console } from "../../src";
/* eslint-disable no-console */
describe("Console effect", () => {
it("should log to console", () => {
- const defaultLog = console.log
+ const defaultLog = console.log;
try {
- const testArgs = ["bar", { some: "data" }, ["list", "of", "data"]]
- console.log = jest.fn()
- const consoleFx = Console(...testArgs)
- runFx(consoleFx)
- expect(console.log).toBeCalledWith(...testArgs)
+ const testArgs = ["bar", { some: "data" }, ["list", "of", "data"]];
+ console.log = jest.fn();
+ const consoleFx = Console(...testArgs);
+ runFx(consoleFx);
+ expect(console.log).toBeCalledWith(...testArgs);
} finally {
- console.log = defaultLog
+ console.log = defaultLog;
}
- })
-})
+ });
+});
/* eslint-enable no-console */
diff --git a/test/fx/Cookie.attributes.test.js b/test/fx/Cookie.attributes.test.js
index 21deb41..c457338 100644
--- a/test/fx/Cookie.attributes.test.js
+++ b/test/fx/Cookie.attributes.test.js
@@ -1,64 +1,64 @@
-import { runFx } from "../utils"
-import { WriteCookie } from "../../src"
+import { runFx } from "../utils";
+import { WriteCookie } from "../../src";
describe("Cookie effect for attributes", () => {
beforeEach(() => {
Object.defineProperty(document, "cookie", {
value: "",
writable: true
- })
- })
+ });
+ });
it("should set path", () => {
const writeCookie = WriteCookie({
name: "name",
value: "value",
path: "/path"
- })
- runFx(writeCookie)
+ });
+ runFx(writeCookie);
- expect(document.cookie).toEqual("name=value;path=/path")
- })
+ expect(document.cookie).toEqual("name=value;path=/path");
+ });
it("should set domain", () => {
const writeCookie = WriteCookie({
name: "name",
value: "value",
domain: ".domain.com"
- })
- runFx(writeCookie)
+ });
+ runFx(writeCookie);
- expect(document.cookie).toEqual("name=value;domain=.domain.com")
- })
+ expect(document.cookie).toEqual("name=value;domain=.domain.com");
+ });
it("should set ttl to expiry date", () => {
- const ttl = 1000
- const now = new Date()
- const expires = new Date(now.getTime() + ttl * 1000)
+ const ttl = 1000;
+ const now = new Date();
+ const expires = new Date(now.getTime() + ttl * 1000);
- const writeCookie = WriteCookie({ name: "name", value: "value", ttl })
- runFx(writeCookie)
+ const writeCookie = WriteCookie({ name: "name", value: "value", ttl });
+ runFx(writeCookie);
expect(document.cookie).toEqual(
"name=value;expires=" + expires.toUTCString()
- )
- })
+ );
+ });
it("should set expiry date", () => {
- const now = new Date()
- const expires = new Date(now.getTime() + 1000 * 1000)
+ const now = new Date();
+ const expires = new Date(now.getTime() + 1000 * 1000);
const writeCookie = WriteCookie({
name: "name",
value: "value",
expires: expires
- })
- runFx(writeCookie)
+ });
+ runFx(writeCookie);
expect(document.cookie).toEqual(
"name=value;expires=" + expires.toUTCString()
- )
- })
+ );
+ });
it("should set multiple attributes", () => {
const writeCookie = WriteCookie({
@@ -66,9 +66,9 @@ describe("Cookie effect for attributes", () => {
value: "value",
domain: "domain.com",
path: "/home"
- })
- runFx(writeCookie)
+ });
+ runFx(writeCookie);
- expect(document.cookie).toEqual("name=value;path=/home;domain=domain.com")
- })
-})
+ expect(document.cookie).toEqual("name=value;path=/home;domain=domain.com");
+ });
+});
diff --git a/test/fx/Cookie.test.js b/test/fx/Cookie.test.js
index 4dde64c..c4ee3d1 100644
--- a/test/fx/Cookie.test.js
+++ b/test/fx/Cookie.test.js
@@ -1,121 +1,121 @@
-import { jest } from "@jest/globals"
-import { runFx } from "../utils"
-import { ReadCookie, WriteCookie, DeleteCookie } from "../../src"
+import { jest } from "@jest/globals";
+import { runFx } from "../utils";
+import { ReadCookie, WriteCookie, DeleteCookie } from "../../src";
describe("Cookie effect", () => {
beforeEach(() => {
document.cookie.split("; ").forEach(c => {
- let cookie = c.substr(0, c.indexOf("="))
+ const cookie = c.substr(0, c.indexOf("="));
document.cookie = `${cookie}=; expires=${new Date(
1970,
0,
1
- ).toUTCString()}`
- })
- })
+ ).toUTCString()}`;
+ });
+ });
describe("for reading cookies", () => {
it("should read a cookie", () => {
- document.cookie = "a=cookie"
+ document.cookie = "a=cookie";
- const action = jest.fn()
- const readCookie = ReadCookie({ action, name: "a" })
- const { dispatch } = runFx(readCookie)
+ const action = jest.fn();
+ const readCookie = ReadCookie({ action, name: "a" });
+ const { dispatch } = runFx(readCookie);
- expect(dispatch).toBeCalledWith(action, { value: "cookie" })
- })
+ expect(dispatch).toBeCalledWith(action, { value: "cookie" });
+ });
it("should handle missing cookies", () => {
- const action = jest.fn()
- const readCookie = ReadCookie({ action, name: "missing" })
- const { dispatch } = runFx(readCookie)
+ const action = jest.fn();
+ const readCookie = ReadCookie({ action, name: "missing" });
+ const { dispatch } = runFx(readCookie);
- expect(dispatch).not.toHaveBeenCalled()
- })
+ expect(dispatch).not.toHaveBeenCalled();
+ });
it("should handle names containing reserved characters", () => {
- document.cookie = "a%3Db=cookie"
+ document.cookie = "a%3Db=cookie";
- const action = jest.fn()
- const readCookie = ReadCookie({ action, name: "a=b" })
- const { dispatch } = runFx(readCookie)
+ const action = jest.fn();
+ const readCookie = ReadCookie({ action, name: "a=b" });
+ const { dispatch } = runFx(readCookie);
- expect(dispatch).toBeCalledWith(action, { value: "cookie" })
- })
+ expect(dispatch).toBeCalledWith(action, { value: "cookie" });
+ });
it("should handle values contains reserved characters", () => {
- document.cookie = "a=b%3Bc"
+ document.cookie = "a=b%3Bc";
- const action = jest.fn()
- const readCookie = ReadCookie({ action, name: "a" })
- const { dispatch } = runFx(readCookie)
+ const action = jest.fn();
+ const readCookie = ReadCookie({ action, name: "a" });
+ const { dispatch } = runFx(readCookie);
- expect(dispatch).toBeCalledWith(action, { value: "b;c" })
- })
+ expect(dispatch).toBeCalledWith(action, { value: "b;c" });
+ });
it("should handle multiple cookies", () => {
- document.cookie = "a=cookie"
- document.cookie = "b=another%20cookie"
+ document.cookie = "a=cookie";
+ document.cookie = "b=another%20cookie";
- const action = jest.fn()
- const readCookie = ReadCookie({ action, name: "b" })
- const { dispatch } = runFx(readCookie)
+ const action = jest.fn();
+ const readCookie = ReadCookie({ action, name: "b" });
+ const { dispatch } = runFx(readCookie);
- expect(dispatch).toBeCalledWith(action, { value: "another cookie" })
- })
- })
+ expect(dispatch).toBeCalledWith(action, { value: "another cookie" });
+ });
+ });
describe("for writing cookies", () => {
it("should be able to write a cookie", () => {
- const writeCookie = WriteCookie({ name: "a", value: "new cookie" })
- runFx(writeCookie)
+ const writeCookie = WriteCookie({ name: "a", value: "new cookie" });
+ runFx(writeCookie);
- expect(document.cookie).toEqual("a=new%20cookie")
- })
+ expect(document.cookie).toEqual("a=new%20cookie");
+ });
it("should handle names contains reserved characters", () => {
- const writeCookie = WriteCookie({ name: "a=b", value: "new cookie" })
- runFx(writeCookie)
+ const writeCookie = WriteCookie({ name: "a=b", value: "new cookie" });
+ runFx(writeCookie);
- expect(document.cookie).toEqual("a%3Db=new%20cookie")
- })
+ expect(document.cookie).toEqual("a%3Db=new%20cookie");
+ });
it("should handle values containing reserved characters", () => {
- const writeCookie = WriteCookie({ name: "a", value: "new; cookie" })
- runFx(writeCookie)
+ const writeCookie = WriteCookie({ name: "a", value: "new; cookie" });
+ runFx(writeCookie);
- expect(document.cookie).toEqual("a=new%3B%20cookie")
- })
- })
+ expect(document.cookie).toEqual("a=new%3B%20cookie");
+ });
+ });
it("should be able to write a json object to a cookie", () => {
const writeCookie = WriteCookie({
name: "a",
value: { an: "object" },
json: true
- })
- runFx(writeCookie)
+ });
+ runFx(writeCookie);
- expect(document.cookie).toEqual("a={%22an%22:%22object%22}")
- })
+ expect(document.cookie).toEqual("a={%22an%22:%22object%22}");
+ });
it("should be able to read a json object from a cookie", () => {
- document.cookie = "a={%22an%22:%22object%22}"
+ document.cookie = "a={%22an%22:%22object%22}";
- const action = jest.fn()
- const readCookie = ReadCookie({ action, name: "a", json: true })
- const { dispatch } = runFx(readCookie)
+ const action = jest.fn();
+ const readCookie = ReadCookie({ action, name: "a", json: true });
+ const { dispatch } = runFx(readCookie);
- expect(dispatch).toBeCalledWith(action, { value: { an: "object" } })
- })
+ expect(dispatch).toBeCalledWith(action, { value: { an: "object" } });
+ });
it("should be able to delete a cookie", () => {
- document.cookie = "a=b"
- expect(document.cookie).toEqual("a=b")
+ document.cookie = "a=b";
+ expect(document.cookie).toEqual("a=b");
- const deleteCookie = DeleteCookie({ name: "a" })
- runFx(deleteCookie)
+ const deleteCookie = DeleteCookie({ name: "a" });
+ runFx(deleteCookie);
- expect(document.cookie).toEqual("")
- })
-})
+ expect(document.cookie).toEqual("");
+ });
+});
diff --git a/test/fx/Debounce.test.js b/test/fx/Debounce.test.js
index c8b1eab..1fa9877 100644
--- a/test/fx/Debounce.test.js
+++ b/test/fx/Debounce.test.js
@@ -1,37 +1,37 @@
-import { jest } from "@jest/globals"
-import { runFx } from "../utils"
-import { Debounce } from "../../src"
+import { jest } from "@jest/globals";
+import { runFx } from "../utils";
+import { Debounce } from "../../src";
describe("Debounce effect", () => {
it("should fire an action after a delay", () => {
- jest.useFakeTimers()
+ jest.useFakeTimers();
try {
- const action = jest.fn()
- const debounceFx = Debounce({ wait: 1000, action })
- const { dispatch } = runFx(debounceFx)
- expect(dispatch).not.toBeCalled()
+ const action = jest.fn();
+ const debounceFx = Debounce({ wait: 1000, action });
+ const { dispatch } = runFx(debounceFx);
+ expect(dispatch).not.toBeCalled();
- jest.runAllTimers()
- expect(dispatch).toBeCalledWith(action)
+ jest.runAllTimers();
+ expect(dispatch).toBeCalledWith(action);
} finally {
- jest.useRealTimers()
+ jest.useRealTimers();
}
- })
+ });
it("should only fire the last action fired while waiting", () => {
- jest.useFakeTimers()
+ jest.useFakeTimers();
try {
- const action = jest.fn()
- const debounceFx = Debounce({ wait: 1000, action })
- const { dispatch: dispatch1 } = runFx(debounceFx)
- const { dispatch: dispatch2 } = runFx(debounceFx)
- expect(dispatch1).not.toBeCalled()
- expect(dispatch2).not.toBeCalled()
+ const action = jest.fn();
+ const debounceFx = Debounce({ wait: 1000, action });
+ const { dispatch: dispatch1 } = runFx(debounceFx);
+ const { dispatch: dispatch2 } = runFx(debounceFx);
+ expect(dispatch1).not.toBeCalled();
+ expect(dispatch2).not.toBeCalled();
- jest.runAllTimers()
- expect(dispatch1).not.toBeCalled()
- expect(dispatch2).toBeCalledWith(action)
+ jest.runAllTimers();
+ expect(dispatch1).not.toBeCalled();
+ expect(dispatch2).toBeCalledWith(action);
} finally {
- jest.useRealTimers()
+ jest.useRealTimers();
}
- })
-})
+ });
+});
diff --git a/test/fx/Dispatch.test.js b/test/fx/Dispatch.test.js
index e151c43..27a93e0 100644
--- a/test/fx/Dispatch.test.js
+++ b/test/fx/Dispatch.test.js
@@ -1,12 +1,12 @@
-import { jest } from "@jest/globals"
-import { runFx } from "../utils"
-import { Dispatch } from "../../src"
+import { jest } from "@jest/globals";
+import { runFx } from "../utils";
+import { Dispatch } from "../../src";
describe("Dispatch effect", () => {
it("should dispatch the action", () => {
- const action = jest.fn()
- const dispatchFx = Dispatch(action)
- const { dispatch } = runFx(dispatchFx)
- expect(dispatch).toBeCalledWith(action)
- })
-})
+ const action = jest.fn();
+ const dispatchFx = Dispatch(action);
+ const { dispatch } = runFx(dispatchFx);
+ expect(dispatch).toBeCalledWith(action);
+ });
+});
diff --git a/test/fx/Geo.test.js b/test/fx/Geo.test.js
index 3fb2a5c..90c36cc 100644
--- a/test/fx/Geo.test.js
+++ b/test/fx/Geo.test.js
@@ -1,31 +1,31 @@
-import { jest } from "@jest/globals"
-import { runFx } from "../utils"
-import { GetCurrentPosition } from "../../src"
+import { jest } from "@jest/globals";
+import { runFx } from "../utils";
+import { GetCurrentPosition } from "../../src";
describe("GetCurrentPosition effect", () => {
it("should return coords on success", () => {
navigator.geolocation = {
getCurrentPosition: function (successCallback) {
- successCallback({ coords: { longitude: 42.0, latitude: 42.1 } })
+ successCallback({ coords: { longitude: 42.0, latitude: 42.1 } });
}
- }
- const action = jest.fn()
- const getCurrentPositionFx = GetCurrentPosition({ action })
- const { dispatch } = runFx(getCurrentPositionFx)
+ };
+ const action = jest.fn();
+ const getCurrentPositionFx = GetCurrentPosition({ action });
+ const { dispatch } = runFx(getCurrentPositionFx);
expect(dispatch).toBeCalledWith(action, {
coords: { longitude: 42.0, latitude: 42.1 }
- })
- })
+ });
+ });
it("should call error handler on error", () => {
navigator.geolocation = {
getCurrentPosition: function (successCallback, errorCallback) {
- errorCallback("things went wrong")
+ errorCallback("things went wrong");
}
- }
- const action = jest.fn()
- const error = jest.fn()
- const getCurrentPositionFx = GetCurrentPosition({ action, error })
- const { dispatch } = runFx(getCurrentPositionFx)
- expect(dispatch).toBeCalledWith(error, "things went wrong")
- })
-})
+ };
+ const action = jest.fn();
+ const error = jest.fn();
+ const getCurrentPositionFx = GetCurrentPosition({ action, error });
+ const { dispatch } = runFx(getCurrentPositionFx);
+ expect(dispatch).toBeCalledWith(error, "things went wrong");
+ });
+});
diff --git a/test/fx/HistoryPush.test.js b/test/fx/HistoryPush.test.js
index 9960a9d..17c0e3f 100644
--- a/test/fx/HistoryPush.test.js
+++ b/test/fx/HistoryPush.test.js
@@ -1,6 +1,6 @@
-import { jest } from "@jest/globals"
-import { runFx } from "../utils"
-import { HistoryPush } from "../../src"
+import { jest } from "@jest/globals";
+import { runFx } from "../utils";
+import { HistoryPush } from "../../src";
describe("HistoryPush effect", () => {
it("should update location and state, and increment history length", () => {
@@ -8,38 +8,38 @@ describe("HistoryPush effect", () => {
state: {},
title: "new title",
url: "#foo"
- })
- expect(history.length).toEqual(1)
- expect(history.state).toEqual(null)
- runFx(historyPush)
- expect(history.length).toEqual(2)
- expect(location.hash).toEqual("#foo")
- expect(history.state).toEqual({})
- })
+ });
+ expect(history.length).toEqual(1);
+ expect(history.state).toEqual(null);
+ runFx(historyPush);
+ expect(history.length).toEqual(2);
+ expect(location.hash).toEqual("#foo");
+ expect(history.state).toEqual({});
+ });
it("should call history.pushState with correct params", () => {
- history.pushState = jest.fn()
+ history.pushState = jest.fn();
const historyPush = HistoryPush({
state: {},
title: "new title",
url: "#foo"
- })
- runFx(historyPush)
- expect(history.pushState).toHaveBeenCalledWith({}, "new title", "#foo")
- })
+ });
+ runFx(historyPush);
+ expect(history.pushState).toHaveBeenCalledWith({}, "new title", "#foo");
+ });
it("should call history.pushState with default title and url", () => {
- history.pushState = jest.fn()
- document.title = "another title"
- location.href = "http://localhost/#bar"
+ history.pushState = jest.fn();
+ document.title = "another title";
+ location.href = "http://localhost/#bar";
const historyPush = HistoryPush({
state: {}
- })
- runFx(historyPush)
+ });
+ runFx(historyPush);
expect(history.pushState).toHaveBeenCalledWith(
{},
"another title",
"http://localhost/#bar"
- )
- })
-})
+ );
+ });
+});
diff --git a/test/fx/HistoryReplace.test.js b/test/fx/HistoryReplace.test.js
index 6642270..c82d0b7 100644
--- a/test/fx/HistoryReplace.test.js
+++ b/test/fx/HistoryReplace.test.js
@@ -1,6 +1,6 @@
-import { jest } from "@jest/globals"
-import { runFx } from "../utils"
-import { HistoryReplace } from "../../src"
+import { jest } from "@jest/globals";
+import { runFx } from "../utils";
+import { HistoryReplace } from "../../src";
describe("HistoryReplace effect", () => {
it("should update location and state, and not increment history length", () => {
@@ -8,39 +8,39 @@ describe("HistoryReplace effect", () => {
state: {},
title: "new title",
url: "#bar"
- })
+ });
- expect(history.length).toEqual(1)
- expect(history.state).toEqual(null)
- runFx(historyReplace)
- expect(history.length).toEqual(1)
- expect(location.hash).toEqual("#bar")
- expect(history.state).toEqual({})
- })
+ expect(history.length).toEqual(1);
+ expect(history.state).toEqual(null);
+ runFx(historyReplace);
+ expect(history.length).toEqual(1);
+ expect(location.hash).toEqual("#bar");
+ expect(history.state).toEqual({});
+ });
it("should call history.replaceState with correct params", () => {
- history.replaceState = jest.fn()
+ history.replaceState = jest.fn();
const historyReplace = HistoryReplace({
state: {},
title: "new title",
url: "#foo"
- })
- runFx(historyReplace)
- expect(history.replaceState).toHaveBeenCalledWith({}, "new title", "#foo")
- })
+ });
+ runFx(historyReplace);
+ expect(history.replaceState).toHaveBeenCalledWith({}, "new title", "#foo");
+ });
it("should call history.replaceState with default title and url", () => {
- history.replaceState = jest.fn()
- document.title = "another title"
- location.href = "http://localhost/#bar"
+ history.replaceState = jest.fn();
+ document.title = "another title";
+ location.href = "http://localhost/#bar";
const historyReplace = HistoryReplace({
state: {}
- })
- runFx(historyReplace)
+ });
+ runFx(historyReplace);
expect(history.replaceState).toHaveBeenCalledWith(
{},
"another title",
"http://localhost/#bar"
- )
- })
-})
+ );
+ });
+});
diff --git a/test/fx/Http.test.js b/test/fx/Http.test.js
index e1cc8df..9d8a3ae 100644
--- a/test/fx/Http.test.js
+++ b/test/fx/Http.test.js
@@ -1,66 +1,66 @@
-import { jest } from "@jest/globals"
-import { runFx } from "../utils"
-import { Http } from "../../src"
+import { jest } from "@jest/globals";
+import { runFx } from "../utils";
+import { Http } from "../../src";
describe("Http effect", () => {
it("should get json", done => {
- const testUrl = "https://example.com"
+ const testUrl = "https://example.com";
global.fetch = (url, options) => {
- expect(url).toBe(testUrl)
- expect(options).toEqual({})
+ expect(url).toBe(testUrl);
+ expect(options).toEqual({});
return Promise.resolve({
ok: true,
json: () => Promise.resolve({ response: "data" })
- })
- }
+ });
+ };
- const action = jest.fn()
- const httpFx = Http({ url: testUrl, action })
- const { dispatch } = runFx(httpFx)
+ const action = jest.fn();
+ const httpFx = Http({ url: testUrl, action });
+ const { dispatch } = runFx(httpFx);
process.nextTick(() => {
- expect(dispatch).toBeCalledWith(action, { response: "data" })
- delete global.fetch
- done()
- })
- })
+ expect(dispatch).toBeCalledWith(action, { response: "data" });
+ delete global.fetch;
+ done();
+ });
+ });
it("should get text", done => {
- const testUrl = "https://example.com/hello"
+ const testUrl = "https://example.com/hello";
global.fetch = (url, options) => {
- expect(url).toBe(testUrl)
- expect(options).toEqual({})
+ expect(url).toBe(testUrl);
+ expect(options).toEqual({});
return Promise.resolve({
ok: true,
text: () => Promise.resolve("hello world")
- })
- }
- const action = jest.fn()
- const httpFx = Http({ url: testUrl, response: "text", action })
- const { dispatch } = runFx(httpFx)
+ });
+ };
+ const action = jest.fn();
+ const httpFx = Http({ url: testUrl, response: "text", action });
+ const { dispatch } = runFx(httpFx);
process.nextTick(() => {
- expect(dispatch).toBeCalledWith(action, "hello world")
- delete global.fetch
- done()
- })
- })
+ expect(dispatch).toBeCalledWith(action, "hello world");
+ delete global.fetch;
+ done();
+ });
+ });
it("should post json", done => {
- const testUrl = "/login"
+ const testUrl = "/login";
global.fetch = (url, options) => {
- expect(url).toBe(testUrl)
+ expect(url).toBe(testUrl);
expect(options).toEqual({
method: "POST",
body: {
user: "username",
pass: "password"
}
- })
+ });
return Promise.resolve({
ok: true,
json: () => Promise.resolve({ result: "authenticated" })
- })
- }
- const action = jest.fn()
+ });
+ };
+ const action = jest.fn();
const httpFx = Http({
url: testUrl,
options: {
@@ -68,76 +68,76 @@ describe("Http effect", () => {
body: { user: "username", pass: "password" }
},
action
- })
- const { dispatch } = runFx(httpFx)
+ });
+ const { dispatch } = runFx(httpFx);
process.nextTick(() => {
- expect(dispatch).toBeCalledWith(action, { result: "authenticated" })
- delete global.fetch
- done()
- })
- })
+ expect(dispatch).toBeCalledWith(action, { result: "authenticated" });
+ delete global.fetch;
+ done();
+ });
+ });
it("should call the error handler on error", done => {
- const testUrl = "https://example.com/hello"
- const error = new Error("Failed")
+ const testUrl = "https://example.com/hello";
+ const error = new Error("Failed");
global.fetch = (url, options) => {
- expect(url).toBe(testUrl)
- expect(options).toEqual({})
- return Promise.reject(error)
- }
+ expect(url).toBe(testUrl);
+ expect(options).toEqual({});
+ return Promise.reject(error);
+ };
- const successAction = jest.fn()
- const errorAction = jest.fn()
+ const successAction = jest.fn();
+ const errorAction = jest.fn();
const httpFx = Http({
url: testUrl,
response: "text",
action: successAction,
error: errorAction
- })
- const { dispatch } = runFx(httpFx)
+ });
+ const { dispatch } = runFx(httpFx);
process.nextTick(() => {
- expect(dispatch).toBeCalledWith(errorAction, error)
- delete global.fetch
- done()
- })
- })
+ expect(dispatch).toBeCalledWith(errorAction, error);
+ delete global.fetch;
+ done();
+ });
+ });
it("should call default action on error", done => {
- const testUrl = "https://example.com/hello"
- const error = new Error("Failed")
+ const testUrl = "https://example.com/hello";
+ const error = new Error("Failed");
global.fetch = (url, options) => {
- expect(url).toBe(testUrl)
- expect(options).toEqual({})
- return Promise.reject(error)
- }
- const action = jest.fn()
- const httpFx = Http({ url: testUrl, response: "text", action })
- const { dispatch } = runFx(httpFx)
+ expect(url).toBe(testUrl);
+ expect(options).toEqual({});
+ return Promise.reject(error);
+ };
+ const action = jest.fn();
+ const httpFx = Http({ url: testUrl, response: "text", action });
+ const { dispatch } = runFx(httpFx);
process.nextTick(() => {
- expect(dispatch).toBeCalledWith(action, error)
- delete global.fetch
- done()
- })
- })
+ expect(dispatch).toBeCalledWith(action, error);
+ delete global.fetch;
+ done();
+ });
+ });
it("should call default action on error when response is not OK", done => {
- const testUrl = "https://example.com/hello"
+ const testUrl = "https://example.com/hello";
const response = {
ok: false
- }
+ };
global.fetch = (url, options) => {
- expect(url).toBe(testUrl)
- expect(options).toEqual({})
- return Promise.resolve(response)
- }
- const action = jest.fn()
- const httpFx = Http({ url: testUrl, response: "text", action })
- const { dispatch } = runFx(httpFx)
+ expect(url).toBe(testUrl);
+ expect(options).toEqual({});
+ return Promise.resolve(response);
+ };
+ const action = jest.fn();
+ const httpFx = Http({ url: testUrl, response: "text", action });
+ const { dispatch } = runFx(httpFx);
process.nextTick(() => {
- expect(dispatch).toBeCalledWith(action, response)
- delete global.fetch
- done()
- })
- })
-})
+ expect(dispatch).toBeCalledWith(action, response);
+ delete global.fetch;
+ done();
+ });
+ });
+});
diff --git a/test/fx/Merge.test.js b/test/fx/Merge.test.js
index 1840ba0..f75da22 100644
--- a/test/fx/Merge.test.js
+++ b/test/fx/Merge.test.js
@@ -1,16 +1,16 @@
-import { jest } from "@jest/globals"
-import { runFx } from "../utils"
-import { Merge } from "../../src"
+import { jest } from "@jest/globals";
+import { runFx } from "../utils";
+import { Merge } from "../../src";
describe("Merge effect", () => {
it("should shallow merge existing state with new state returned by action", () => {
- const inc = jest.fn(({ count }) => ({ count: count + 1 }))
- const batchFx = Merge(inc)
- const { dispatch } = runFx(batchFx)
- expect(dispatch).toBeCalledWith(expect.any(Function))
+ const inc = jest.fn(({ count }) => ({ count: count + 1 }));
+ const batchFx = Merge(inc);
+ const { dispatch } = runFx(batchFx);
+ expect(dispatch).toBeCalledWith(expect.any(Function));
expect(dispatch.mock.calls[0][0]({ count: 0, other: "state" })).toEqual({
count: 1,
other: "state"
- })
- })
-})
+ });
+ });
+});
diff --git a/test/fx/Random.test.js b/test/fx/Random.test.js
index 41c6c9d..522562f 100644
--- a/test/fx/Random.test.js
+++ b/test/fx/Random.test.js
@@ -1,62 +1,62 @@
-import { jest } from "@jest/globals"
-import { runFx } from "../utils"
-import { Random } from "../../src"
+import { jest } from "@jest/globals";
+import { runFx } from "../utils";
+import { Random } from "../../src";
describe("Random effect", () => {
- const defaultRandom = Math.random
+ const defaultRandom = Math.random;
afterEach(() => {
- Math.random = defaultRandom
- })
+ Math.random = defaultRandom;
+ });
it("should call Math.random with default range", () => {
- const randomValue = 0.5
- Math.random = () => randomValue
+ const randomValue = 0.5;
+ Math.random = () => randomValue;
- const action = jest.fn()
- const randomFx = Random({ action })
- const { dispatch } = runFx(randomFx)
- expect(dispatch).toBeCalledWith(action, randomValue)
- })
+ const action = jest.fn();
+ const randomFx = Random({ action });
+ const { dispatch } = runFx(randomFx);
+ expect(dispatch).toBeCalledWith(action, randomValue);
+ });
it("should call Math.random with custom range", () => {
- Math.random = () => 0.5
+ Math.random = () => 0.5;
- const action = jest.fn()
- const randomFx = Random({ min: 2, max: 5, action })
- const { dispatch } = runFx(randomFx)
- expect(dispatch).toBeCalledWith(action, 3.5)
- })
+ const action = jest.fn();
+ const randomFx = Random({ min: 2, max: 5, action });
+ const { dispatch } = runFx(randomFx);
+ expect(dispatch).toBeCalledWith(action, 3.5);
+ });
it("should generate integers", () => {
- Math.random = () => 0.5
+ Math.random = () => 0.5;
- const action = jest.fn()
- const randomFx = Random({ int: true, min: 1, max: 3, action })
- const { dispatch } = runFx(randomFx)
- expect(dispatch).toBeCalledWith(action, 2)
- })
+ const action = jest.fn();
+ const randomFx = Random({ int: true, min: 1, max: 3, action });
+ const { dispatch } = runFx(randomFx);
+ expect(dispatch).toBeCalledWith(action, 2);
+ });
it("should generate false booleans", () => {
- Math.random = () => 0.4
+ Math.random = () => 0.4;
- const action = jest.fn()
- const randomFx = Random({ bool: true, action })
- const { dispatch } = runFx(randomFx)
- expect(dispatch).toBeCalledWith(action, false)
- })
+ const action = jest.fn();
+ const randomFx = Random({ bool: true, action });
+ const { dispatch } = runFx(randomFx);
+ expect(dispatch).toBeCalledWith(action, false);
+ });
it("should generate true booleans", () => {
- Math.random = () => 0.5
+ Math.random = () => 0.5;
- const action = jest.fn()
- const randomFx = Random({ bool: true, action })
- const { dispatch } = runFx(randomFx)
- expect(dispatch).toBeCalledWith(action, true)
- })
+ const action = jest.fn();
+ const randomFx = Random({ bool: true, action });
+ const { dispatch } = runFx(randomFx);
+ expect(dispatch).toBeCalledWith(action, true);
+ });
it("should generate multiple values", () => {
- Math.random = () => 0.5
+ Math.random = () => 0.5;
- const action = jest.fn()
+ const action = jest.fn();
const randomFx = Random({
values: [
{},
@@ -65,8 +65,8 @@ describe("Random effect", () => {
{ bool: true }
],
action
- })
- const { dispatch } = runFx(randomFx)
- expect(dispatch).toBeCalledWith(action, [0.5, 3.5, 2, true])
- })
-})
+ });
+ const { dispatch } = runFx(randomFx);
+ expect(dispatch).toBeCalledWith(action, [0.5, 3.5, 2, true]);
+ });
+});
diff --git a/test/fx/Storage.test.js b/test/fx/Storage.test.js
index da2d26f..03b1445 100644
--- a/test/fx/Storage.test.js
+++ b/test/fx/Storage.test.js
@@ -1,93 +1,93 @@
-import { jest } from "@jest/globals"
-import { runFx } from "../utils"
-import { WriteToStorage, ReadFromStorage } from "../../src"
-import { RemoveFromStorage } from "../../src/fx/Storage"
+import { jest } from "@jest/globals";
+import { runFx } from "../utils";
+import { WriteToStorage, ReadFromStorage } from "../../src";
+import { RemoveFromStorage } from "../../src/fx/Storage";
const mockStorage = (store = {}) => {
- jest.spyOn(Storage.prototype, "setItem").mockImplementation(jest.fn())
+ jest.spyOn(Storage.prototype, "setItem").mockImplementation(jest.fn());
jest
.spyOn(Storage.prototype, "getItem")
- .mockImplementation(key => store[key] || null)
- jest.spyOn(Storage.prototype, "removeItem").mockImplementation(jest.fn())
-}
+ .mockImplementation(key => store[key] || null);
+ jest.spyOn(Storage.prototype, "removeItem").mockImplementation(jest.fn());
+};
-const reverser = s => s.split("").reverse().join("")
+const reverser = s => s.split("").reverse().join("");
describe("WriteToStorage effect", () => {
beforeEach(() => {
- mockStorage()
- })
+ mockStorage();
+ });
it("should write to storage", () => {
- const writeToStorageFx = WriteToStorage({ key: "bar", value: "123" })
- runFx(writeToStorageFx)
- expect(sessionStorage.setItem).toBeCalledWith("bar", '"123"')
- })
+ const writeToStorageFx = WriteToStorage({ key: "bar", value: "123" });
+ runFx(writeToStorageFx);
+ expect(sessionStorage.setItem).toBeCalledWith("bar", '"123"');
+ });
it("should support a custom converter", () => {
const writeToStorageFx = WriteToStorage({
key: "bar",
value: "foo",
converter: reverser
- })
- runFx(writeToStorageFx)
- expect(sessionStorage.setItem).toBeCalledWith("bar", "oof")
- })
-})
+ });
+ runFx(writeToStorageFx);
+ expect(sessionStorage.setItem).toBeCalledWith("bar", "oof");
+ });
+});
describe("ReadFromStorage effect", () => {
beforeEach(() => {
- mockStorage({ foo: '"bar"', soo: '"cat"' })
- })
+ mockStorage({ foo: '"bar"', soo: '"cat"' });
+ });
it("should read from storage", () => {
- const action = jest.fn()
- const readFromStorageFx = ReadFromStorage({ key: "soo", action })
- const { dispatch } = runFx(readFromStorageFx)
- expect(dispatch).toBeCalledWith(action, { value: "cat" })
- expect(sessionStorage.getItem).toBeCalledWith("soo")
- })
+ const action = jest.fn();
+ const readFromStorageFx = ReadFromStorage({ key: "soo", action });
+ const { dispatch } = runFx(readFromStorageFx);
+ expect(dispatch).toBeCalledWith(action, { value: "cat" });
+ expect(sessionStorage.getItem).toBeCalledWith("soo");
+ });
it("should call error function on parse error", () => {
- mockStorage({ foo: "rab" })
- const action = jest.fn()
- const readFromStorageFx = ReadFromStorage({ key: "foo", error: action })
- const { dispatch } = runFx(readFromStorageFx)
- expect(dispatch).toBeCalledWith(action)
- expect(sessionStorage.getItem).toBeCalledWith("soo")
- })
+ mockStorage({ foo: "rab" });
+ const action = jest.fn();
+ const readFromStorageFx = ReadFromStorage({ key: "foo", error: action });
+ const { dispatch } = runFx(readFromStorageFx);
+ expect(dispatch).toBeCalledWith(action);
+ expect(sessionStorage.getItem).toBeCalledWith("soo");
+ });
it("should support a custom converter to read", () => {
- mockStorage({ foo: "rab" })
- const action = jest.fn()
+ mockStorage({ foo: "rab" });
+ const action = jest.fn();
const readFromStorageFx = ReadFromStorage({
key: "foo",
action,
converter: reverser
- })
- const { dispatch } = runFx(readFromStorageFx)
- expect(dispatch).toBeCalledWith(action, { value: "bar" })
- expect(sessionStorage.getItem).toBeCalledWith("foo")
- })
+ });
+ const { dispatch } = runFx(readFromStorageFx);
+ expect(dispatch).toBeCalledWith(action, { value: "bar" });
+ expect(sessionStorage.getItem).toBeCalledWith("foo");
+ });
it("should support action prop", () => {
- const action = jest.fn()
+ const action = jest.fn();
const readFromStorageFx = ReadFromStorage({
key: "foo",
action,
prop: "text"
- })
- const { dispatch } = runFx(readFromStorageFx)
- expect(dispatch).toBeCalledWith(action, { text: "bar" })
- expect(sessionStorage.getItem).toBeCalledWith("foo")
- })
-})
+ });
+ const { dispatch } = runFx(readFromStorageFx);
+ expect(dispatch).toBeCalledWith(action, { text: "bar" });
+ expect(sessionStorage.getItem).toBeCalledWith("foo");
+ });
+});
describe("DeleteFromStorage effect", () => {
it("should remove from storage", () => {
- mockStorage({ foo: "bar" })
- const removeFromStorageFx = RemoveFromStorage({ key: "foo" })
- runFx(removeFromStorageFx)
- expect(sessionStorage.removeItem).toBeCalledWith("foo")
- })
-})
+ mockStorage({ foo: "bar" });
+ const removeFromStorageFx = RemoveFromStorage({ key: "foo" });
+ runFx(removeFromStorageFx);
+ expect(sessionStorage.removeItem).toBeCalledWith("foo");
+ });
+});
diff --git a/test/fx/Throttle.test.js b/test/fx/Throttle.test.js
index 89718d7..97ca265 100644
--- a/test/fx/Throttle.test.js
+++ b/test/fx/Throttle.test.js
@@ -1,30 +1,30 @@
-import { jest } from "@jest/globals"
-import { runFx } from "../utils"
-import { Throttle } from "../../src"
+import { jest } from "@jest/globals";
+import { runFx } from "../utils";
+import { Throttle } from "../../src";
describe("Throttle effect", () => {
it("should fire a single action immediately", () => {
- const action = jest.fn()
- const debounceFx = Throttle({ rate: 1000, action })
- const { dispatch } = runFx(debounceFx)
- expect(dispatch).toBeCalledWith(action)
- })
+ const action = jest.fn();
+ const debounceFx = Throttle({ rate: 1000, action });
+ const { dispatch } = runFx(debounceFx);
+ expect(dispatch).toBeCalledWith(action);
+ });
it("should only fire an action once within a rate limit", () => {
- jest.useFakeTimers()
+ jest.useFakeTimers();
try {
- const action = jest.fn()
- const debounceFx = Throttle({ wait: 1000, action })
- const { dispatch: dispatch1 } = runFx(debounceFx)
- const { dispatch: dispatch2 } = runFx(debounceFx)
- expect(dispatch1).toBeCalledWith(action)
- expect(dispatch2).not.toBeCalled()
+ const action = jest.fn();
+ const debounceFx = Throttle({ wait: 1000, action });
+ const { dispatch: dispatch1 } = runFx(debounceFx);
+ const { dispatch: dispatch2 } = runFx(debounceFx);
+ expect(dispatch1).toBeCalledWith(action);
+ expect(dispatch2).not.toBeCalled();
- jest.runAllTimers()
- expect(dispatch2).not.toBeCalled()
- const { dispatch: dispatch3 } = runFx(debounceFx)
- expect(dispatch3).toBeCalledWith(action)
+ jest.runAllTimers();
+ expect(dispatch2).not.toBeCalled();
+ const { dispatch: dispatch3 } = runFx(debounceFx);
+ expect(dispatch3).toBeCalledWith(action);
} finally {
- jest.useRealTimers()
+ jest.useRealTimers();
}
- })
-})
+ });
+});
diff --git a/test/fx/Time.test.js b/test/fx/Time.test.js
index 7b1430e..8c178ef 100644
--- a/test/fx/Time.test.js
+++ b/test/fx/Time.test.js
@@ -1,75 +1,75 @@
-import { jest } from "@jest/globals"
-import { runFx } from "../utils"
-import { Now, Delay } from "../../src"
+import { jest } from "@jest/globals";
+import { runFx } from "../utils";
+import { Now, Delay } from "../../src";
describe("Now effect", () => {
it("should get the current time", () => {
- jest.useFakeTimers()
- const timestamp = 9001
- const defaultPerformance = global.performance
- global.performance = { now: () => timestamp }
+ jest.useFakeTimers();
+ const timestamp = 9001;
+ const defaultPerformance = global.performance;
+ global.performance = { now: () => timestamp };
try {
- const action = jest.fn()
- const timeFx = Now({ action })
- const { dispatch } = runFx(timeFx)
- expect(dispatch).toBeCalledWith(action, timestamp)
+ const action = jest.fn();
+ const timeFx = Now({ action });
+ const { dispatch } = runFx(timeFx);
+ expect(dispatch).toBeCalledWith(action, timestamp);
} finally {
- global.performance = defaultPerformance
- jest.useRealTimers()
+ global.performance = defaultPerformance;
+ jest.useRealTimers();
}
- })
+ });
it("should get the current date", () => {
- const timestamp = 9001
- const defaultDate = global.Date
+ const timestamp = 9001;
+ const defaultDate = global.Date;
global.Date = function () {
- return { timestamp }
- }
+ return { timestamp };
+ };
try {
- const action = jest.fn()
- const timeFx = Now({ asDate: true, action })
- const { dispatch } = runFx(timeFx)
- expect(dispatch).toBeCalledWith(action, { timestamp })
+ const action = jest.fn();
+ const timeFx = Now({ asDate: true, action });
+ const { dispatch } = runFx(timeFx);
+ expect(dispatch).toBeCalledWith(action, { timestamp });
} finally {
- global.Date = defaultDate
+ global.Date = defaultDate;
}
- })
-})
+ });
+});
describe("Delay effect", () => {
it("should get the current time after a delay", () => {
- jest.useFakeTimers()
- const timestamp = 666
- const defaultPerformance = global.performance
- global.performance = { now: () => timestamp }
+ jest.useFakeTimers();
+ const timestamp = 666;
+ const defaultPerformance = global.performance;
+ global.performance = { now: () => timestamp };
try {
- const action = jest.fn()
- const timeFx = Delay({ wait: timestamp, action })
- const { dispatch } = runFx(timeFx)
- expect(dispatch).not.toBeCalled()
- jest.runAllTimers()
- expect(dispatch).toBeCalledWith(action, timestamp)
+ const action = jest.fn();
+ const timeFx = Delay({ wait: timestamp, action });
+ const { dispatch } = runFx(timeFx);
+ expect(dispatch).not.toBeCalled();
+ jest.runAllTimers();
+ expect(dispatch).toBeCalledWith(action, timestamp);
} finally {
- global.performance = defaultPerformance
- jest.useRealTimers()
+ global.performance = defaultPerformance;
+ jest.useRealTimers();
}
- })
+ });
it("should get the current date after a delay", () => {
- jest.useFakeTimers()
- const timestamp = 666
- const defaultDate = global.Date
+ jest.useFakeTimers();
+ const timestamp = 666;
+ const defaultDate = global.Date;
global.Date = function () {
- return { timestamp }
- }
+ return { timestamp };
+ };
try {
- const action = jest.fn()
- const timeFx = Delay({ wait: timestamp, asDate: true, action })
- const { dispatch } = runFx(timeFx)
- expect(dispatch).not.toBeCalled()
- jest.runAllTimers()
- expect(dispatch).toBeCalledWith(action, { timestamp })
+ const action = jest.fn();
+ const timeFx = Delay({ wait: timestamp, asDate: true, action });
+ const { dispatch } = runFx(timeFx);
+ expect(dispatch).not.toBeCalled();
+ jest.runAllTimers();
+ expect(dispatch).toBeCalledWith(action, { timestamp });
} finally {
- global.Date = defaultDate
- jest.useRealTimers()
+ global.Date = defaultDate;
+ jest.useRealTimers();
}
- })
-})
+ });
+});
diff --git a/test/fx/WebSocketClient.test.js b/test/fx/WebSocketClient.test.js
index 32c13df..87e2b53 100644
--- a/test/fx/WebSocketClient.test.js
+++ b/test/fx/WebSocketClient.test.js
@@ -1,56 +1,56 @@
-import { jest } from "@jest/globals"
-import { runFx } from "../utils"
-import { WebSocketSend } from "../../src"
+import { jest } from "@jest/globals";
+import { runFx } from "../utils";
+import { WebSocketSend } from "../../src";
describe("WebSocketSend effect", () => {
- const url = "wss://localhost"
- const mockWebSocket = {}
- const defaultWebSocket = global.WebSocket
+ const url = "wss://localhost";
+ const mockWebSocket = {};
+ const defaultWebSocket = global.WebSocket;
beforeEach(() => {
- mockWebSocket.readyState = 1
- mockWebSocket.send = jest.fn()
- mockWebSocket.addEventListener = jest.fn()
- mockWebSocket.removeEventListener = jest.fn()
- mockWebSocket.close = jest.fn()
- global.WebSocket = jest.fn(() => mockWebSocket)
- global.WebSocket.CONNECTING = 0
- })
+ mockWebSocket.readyState = 1;
+ mockWebSocket.send = jest.fn();
+ mockWebSocket.addEventListener = jest.fn();
+ mockWebSocket.removeEventListener = jest.fn();
+ mockWebSocket.close = jest.fn();
+ global.WebSocket = jest.fn(() => mockWebSocket);
+ global.WebSocket.CONNECTING = 0;
+ });
afterEach(() => {
- global.WebSocket = defaultWebSocket
- })
+ global.WebSocket = defaultWebSocket;
+ });
it("should create a new WebSocket without protocols if not connected", () => {
- const webSocketFx = WebSocketSend({ url })
- runFx(webSocketFx)
+ const webSocketFx = WebSocketSend({ url });
+ runFx(webSocketFx);
- expect(WebSocket).toBeCalledWith(url, undefined)
- expect(mockWebSocket.close).not.toBeCalled()
- })
+ expect(WebSocket).toBeCalledWith(url, undefined);
+ expect(mockWebSocket.close).not.toBeCalled();
+ });
it("should send a message if connected", () => {
- const message = { some: "message value" }
- const webSocketFx = WebSocketSend({ url, data: message })
- runFx(webSocketFx)
+ const message = { some: "message value" };
+ const webSocketFx = WebSocketSend({ url, data: message });
+ runFx(webSocketFx);
- expect(mockWebSocket.send).toBeCalledWith(message)
- })
+ expect(mockWebSocket.send).toBeCalledWith(message);
+ });
it("should queue sending a message if not connected", () => {
- mockWebSocket.readyState = 0
- const message = { some: "message value" }
- const webSocketFx = WebSocketSend({ url, data: message })
- runFx(webSocketFx)
+ mockWebSocket.readyState = 0;
+ const message = { some: "message value" };
+ const webSocketFx = WebSocketSend({ url, data: message });
+ runFx(webSocketFx);
expect(mockWebSocket.addEventListener).toBeCalledWith(
"open",
expect.any(Function)
- )
- expect(mockWebSocket.send).not.toBeCalled()
- expect(mockWebSocket.removeEventListener).not.toBeCalled()
+ );
+ expect(mockWebSocket.send).not.toBeCalled();
+ expect(mockWebSocket.removeEventListener).not.toBeCalled();
- const openListener = mockWebSocket.addEventListener.mock.calls[0][1]
- openListener()
- expect(mockWebSocket.send).toBeCalledWith(message)
+ const openListener = mockWebSocket.addEventListener.mock.calls[0][1];
+ openListener();
+ expect(mockWebSocket.send).toBeCalledWith(message);
expect(mockWebSocket.removeEventListener).toBeCalledWith(
"open",
expect.any(Function)
- )
- })
-})
+ );
+ });
+});
diff --git a/test/subs/Animation.test.js b/test/subs/Animation.test.js
index 8057857..e238753 100644
--- a/test/subs/Animation.test.js
+++ b/test/subs/Animation.test.js
@@ -1,27 +1,27 @@
-import { jest } from "@jest/globals"
-import { runFx } from "../utils"
-import { Animation } from "../../src"
+import { jest } from "@jest/globals";
+import { runFx } from "../utils";
+import { Animation } from "../../src";
describe("Animation subscription", () => {
it("should fire an action each frame until unsubscribed", () => {
- const cancelId = 9001
- const timestamp = 1001
- const defaultRequestAnimationFrame = requestAnimationFrame
- const defaultCancelAnimationFrame = cancelAnimationFrame
+ const cancelId = 9001;
+ const timestamp = 1001;
+ const defaultRequestAnimationFrame = requestAnimationFrame;
+ const defaultCancelAnimationFrame = cancelAnimationFrame;
global.requestAnimationFrame = jest.fn().mockImplementationOnce(cb => {
- cb(timestamp)
- return cancelId
- })
- global.cancelAnimationFrame = jest.fn()
- const action = jest.fn()
- const frameFx = Animation(action)
- const { dispatch, unsubscribe } = runFx(frameFx)
- expect(dispatch).toBeCalledWith(action, timestamp)
- expect(requestAnimationFrame).toBeCalledWith(expect.any(Function))
+ cb(timestamp);
+ return cancelId;
+ });
+ global.cancelAnimationFrame = jest.fn();
+ const action = jest.fn();
+ const frameFx = Animation(action);
+ const { dispatch, unsubscribe } = runFx(frameFx);
+ expect(dispatch).toBeCalledWith(action, timestamp);
+ expect(requestAnimationFrame).toBeCalledWith(expect.any(Function));
- unsubscribe()
- expect(global.cancelAnimationFrame).toBeCalledWith(cancelId)
- global.requestAnimationFrame = defaultRequestAnimationFrame
- global.cancelAnimationFrame = defaultCancelAnimationFrame
- })
-})
+ unsubscribe();
+ expect(global.cancelAnimationFrame).toBeCalledWith(cancelId);
+ global.requestAnimationFrame = defaultRequestAnimationFrame;
+ global.cancelAnimationFrame = defaultCancelAnimationFrame;
+ });
+});
diff --git a/test/subs/Geo.test.js b/test/subs/Geo.test.js
index 9ad87fa..60a21c3 100644
--- a/test/subs/Geo.test.js
+++ b/test/subs/Geo.test.js
@@ -1,41 +1,41 @@
-import { jest } from "@jest/globals"
-import { runFx } from "../utils"
-import { WatchPosition } from "../../src"
+import { jest } from "@jest/globals";
+import { runFx } from "../utils";
+import { WatchPosition } from "../../src";
describe("WatchPosition effect", () => {
it("should return coords on success", () => {
navigator.geolocation = {
watchPosition: function (successCallback) {
- successCallback({ coords: { longitude: 42.0, latitude: 42.1 } })
- return 12
+ successCallback({ coords: { longitude: 42.0, latitude: 42.1 } });
+ return 12;
},
clearWatch: function (watchId) {
- expect(watchId).toBe(12)
+ expect(watchId).toBe(12);
}
- }
- const action = jest.fn()
- const watchPositionFx = WatchPosition({ action })
- const { dispatch, unsubscribe } = runFx(watchPositionFx)
+ };
+ const action = jest.fn();
+ const watchPositionFx = WatchPosition({ action });
+ const { dispatch, unsubscribe } = runFx(watchPositionFx);
expect(dispatch).toBeCalledWith(action, {
coords: { longitude: 42.0, latitude: 42.1 }
- })
- unsubscribe()
- })
+ });
+ unsubscribe();
+ });
it("should call error handler on error", () => {
navigator.geolocation = {
watchPosition: function (successCallback, errorCallback) {
- errorCallback("things went wrong")
- return 34
+ errorCallback("things went wrong");
+ return 34;
},
clearWatch: function (watchId) {
- expect(watchId).toBe(34)
+ expect(watchId).toBe(34);
}
- }
- const action = jest.fn()
- const error = jest.fn()
- const watchPositionFx = WatchPosition({ action, error })
- const { dispatch, unsubscribe } = runFx(watchPositionFx)
- expect(dispatch).toBeCalledWith(error, "things went wrong")
- unsubscribe()
- })
-})
+ };
+ const action = jest.fn();
+ const error = jest.fn();
+ const watchPositionFx = WatchPosition({ action, error });
+ const { dispatch, unsubscribe } = runFx(watchPositionFx);
+ expect(dispatch).toBeCalledWith(error, "things went wrong");
+ unsubscribe();
+ });
+});
diff --git a/test/subs/History.test.js b/test/subs/History.test.js
index 6ee3d94..79383d0 100644
--- a/test/subs/History.test.js
+++ b/test/subs/History.test.js
@@ -1,21 +1,21 @@
-import { jest } from "@jest/globals"
-import { runFx } from "../utils"
-import { HistoryPop } from "../../src"
+import { jest } from "@jest/globals";
+import { runFx } from "../utils";
+import { HistoryPop } from "../../src";
describe("History subscription", () => {
it("should add and remove popstate listener", () => {
- const action = jest.fn()
- const historyPop = HistoryPop({ action })
- const { dispatch, unsubscribe } = runFx(historyPop)
+ const action = jest.fn();
+ const historyPop = HistoryPop({ action });
+ const { dispatch, unsubscribe } = runFx(historyPop);
const popStateEvent = new PopStateEvent("popstate", {
state: { foo: "bar" }
- })
- window.dispatchEvent(popStateEvent)
- expect(dispatch).toBeCalledWith(action, popStateEvent)
- unsubscribe()
+ });
+ window.dispatchEvent(popStateEvent);
+ expect(dispatch).toBeCalledWith(action, popStateEvent);
+ unsubscribe();
- dispatch.mockReset()
- document.dispatchEvent(popStateEvent)
- expect(dispatch).not.toBeCalled()
- })
-})
+ dispatch.mockReset();
+ document.dispatchEvent(popStateEvent);
+ expect(dispatch).not.toBeCalled();
+ });
+});
diff --git a/test/subs/Keyboard.test.js b/test/subs/Keyboard.test.js
index 99f15db..a359029 100644
--- a/test/subs/Keyboard.test.js
+++ b/test/subs/Keyboard.test.js
@@ -1,45 +1,45 @@
-import { jest } from "@jest/globals"
-import { runFx } from "../utils"
-import { Keyboard } from "../../src"
+import { jest } from "@jest/globals";
+import { runFx } from "../utils";
+import { Keyboard } from "../../src";
describe("Keyboard subscription", () => {
it("should add and remove keydown listener", () => {
- const keyEvent = new KeyboardEvent("keydown", { key: "a", code: "KeyA" })
- const action = jest.fn()
- const keyboardFx = Keyboard({ downs: true, action })
- const { dispatch, unsubscribe } = runFx(keyboardFx)
- document.dispatchEvent(keyEvent)
- expect(dispatch).toBeCalledWith(action, keyEvent)
+ const keyEvent = new KeyboardEvent("keydown", { key: "a", code: "KeyA" });
+ const action = jest.fn();
+ const keyboardFx = Keyboard({ downs: true, action });
+ const { dispatch, unsubscribe } = runFx(keyboardFx);
+ document.dispatchEvent(keyEvent);
+ expect(dispatch).toBeCalledWith(action, keyEvent);
- dispatch.mockReset()
- unsubscribe()
- document.dispatchEvent(keyEvent)
- expect(dispatch).not.toBeCalled()
- })
+ dispatch.mockReset();
+ unsubscribe();
+ document.dispatchEvent(keyEvent);
+ expect(dispatch).not.toBeCalled();
+ });
it("should add and remove keyup listener", () => {
- const keyEvent = new KeyboardEvent("keyup", { key: "a", code: "KeyA" })
- const action = jest.fn()
- const keyboardFx = Keyboard({ ups: true, action })
- const { dispatch, unsubscribe } = runFx(keyboardFx)
- document.dispatchEvent(keyEvent)
- expect(dispatch).toBeCalledWith(action, keyEvent)
+ const keyEvent = new KeyboardEvent("keyup", { key: "a", code: "KeyA" });
+ const action = jest.fn();
+ const keyboardFx = Keyboard({ ups: true, action });
+ const { dispatch, unsubscribe } = runFx(keyboardFx);
+ document.dispatchEvent(keyEvent);
+ expect(dispatch).toBeCalledWith(action, keyEvent);
- dispatch.mockReset()
- unsubscribe()
- document.dispatchEvent(keyEvent)
- expect(dispatch).not.toBeCalled()
- })
+ dispatch.mockReset();
+ unsubscribe();
+ document.dispatchEvent(keyEvent);
+ expect(dispatch).not.toBeCalled();
+ });
it("should add and remove keypress listener", () => {
- const keyEvent = new KeyboardEvent("keypress", { key: "a", code: "KeyA" })
- const action = jest.fn()
- const keyboardFx = Keyboard({ presses: true, action })
- const { dispatch, unsubscribe } = runFx(keyboardFx)
- document.dispatchEvent(keyEvent)
- expect(dispatch).toBeCalledWith(action, keyEvent)
+ const keyEvent = new KeyboardEvent("keypress", { key: "a", code: "KeyA" });
+ const action = jest.fn();
+ const keyboardFx = Keyboard({ presses: true, action });
+ const { dispatch, unsubscribe } = runFx(keyboardFx);
+ document.dispatchEvent(keyEvent);
+ expect(dispatch).toBeCalledWith(action, keyEvent);
- dispatch.mockReset()
- unsubscribe()
- document.dispatchEvent(keyEvent)
- expect(dispatch).not.toBeCalled()
- })
-})
+ dispatch.mockReset();
+ unsubscribe();
+ document.dispatchEvent(keyEvent);
+ expect(dispatch).not.toBeCalled();
+ });
+});
diff --git a/test/subs/Time.test.js b/test/subs/Time.test.js
index fe357d0..825d5aa 100644
--- a/test/subs/Time.test.js
+++ b/test/subs/Time.test.js
@@ -1,62 +1,62 @@
-import { jest } from "@jest/globals"
-import { runFx } from "../utils"
-import { Interval } from "../../src"
+import { jest } from "@jest/globals";
+import { runFx } from "../utils";
+import { Interval } from "../../src";
describe("Interval subscription", () => {
it("should get the current time at an interval until unsubscribed", () => {
- jest.useFakeTimers()
- const every = 1000
- let now = 0
- const defaultPerformance = global.performance
- global.performance = { now: () => (now += every) }
+ jest.useFakeTimers();
+ const every = 1000;
+ let now = 0;
+ const defaultPerformance = global.performance;
+ global.performance = { now: () => (now += every) };
try {
- const action = jest.fn()
- const intervalSub = Interval({ every, action })
- const { dispatch, unsubscribe } = runFx(intervalSub)
- expect(dispatch).not.toBeCalled()
- jest.runOnlyPendingTimers()
- expect(dispatch).toBeCalledWith(action, every)
+ const action = jest.fn();
+ const intervalSub = Interval({ every, action });
+ const { dispatch, unsubscribe } = runFx(intervalSub);
+ expect(dispatch).not.toBeCalled();
+ jest.runOnlyPendingTimers();
+ expect(dispatch).toBeCalledWith(action, every);
- dispatch.mockReset()
- jest.runOnlyPendingTimers()
- expect(dispatch).toBeCalledWith(action, 2 * every)
+ dispatch.mockReset();
+ jest.runOnlyPendingTimers();
+ expect(dispatch).toBeCalledWith(action, 2 * every);
- dispatch.mockReset()
- unsubscribe()
- jest.runOnlyPendingTimers()
- expect(dispatch).not.toBeCalled()
+ dispatch.mockReset();
+ unsubscribe();
+ jest.runOnlyPendingTimers();
+ expect(dispatch).not.toBeCalled();
} finally {
- global.performance = defaultPerformance
- jest.useRealTimers()
+ global.performance = defaultPerformance;
+ jest.useRealTimers();
}
- })
+ });
it("should get the current date at an interval until unsubscribed", () => {
- jest.useFakeTimers()
- const every = 1000
- let now = 0
- const defaultDate = global.Date
+ jest.useFakeTimers();
+ const every = 1000;
+ let now = 0;
+ const defaultDate = global.Date;
global.Date = function () {
- return { now: (now += every) }
- }
+ return { now: (now += every) };
+ };
try {
- const action = jest.fn()
- const intervalSub = Interval({ every, asDate: true, action })
- const { dispatch, unsubscribe } = runFx(intervalSub)
- expect(dispatch).not.toBeCalled()
- jest.runOnlyPendingTimers()
- expect(dispatch).toBeCalledWith(action, { now: every })
+ const action = jest.fn();
+ const intervalSub = Interval({ every, asDate: true, action });
+ const { dispatch, unsubscribe } = runFx(intervalSub);
+ expect(dispatch).not.toBeCalled();
+ jest.runOnlyPendingTimers();
+ expect(dispatch).toBeCalledWith(action, { now: every });
- dispatch.mockReset()
- jest.runOnlyPendingTimers()
- expect(dispatch).toBeCalledWith(action, { now: 2 * every })
+ dispatch.mockReset();
+ jest.runOnlyPendingTimers();
+ expect(dispatch).toBeCalledWith(action, { now: 2 * every });
- dispatch.mockReset()
- unsubscribe()
- jest.runOnlyPendingTimers()
- expect(dispatch).not.toBeCalled()
+ dispatch.mockReset();
+ unsubscribe();
+ jest.runOnlyPendingTimers();
+ expect(dispatch).not.toBeCalled();
} finally {
- global.Date = defaultDate
- jest.useRealTimers()
+ global.Date = defaultDate;
+ jest.useRealTimers();
}
- })
-})
+ });
+});
diff --git a/test/subs/WebSocketClient.test.js b/test/subs/WebSocketClient.test.js
index ebb0058..bf1716b 100644
--- a/test/subs/WebSocketClient.test.js
+++ b/test/subs/WebSocketClient.test.js
@@ -1,114 +1,114 @@
-import { jest } from "@jest/globals"
-import { runFx } from "../utils"
-import { WebSocketListen } from "../../src"
+import { jest } from "@jest/globals";
+import { runFx } from "../utils";
+import { WebSocketListen } from "../../src";
describe("WebSocketListen subscription", () => {
- const url = "wss://localhost"
- const mockWebSocket = {}
- const defaultWebSocket = global.WebSocket
+ const url = "wss://localhost";
+ const mockWebSocket = {};
+ const defaultWebSocket = global.WebSocket;
beforeEach(() => {
- mockWebSocket.readyState = 1
- mockWebSocket.send = jest.fn()
- mockWebSocket.addEventListener = jest.fn()
- mockWebSocket.removeEventListener = jest.fn()
- mockWebSocket.close = jest.fn()
- global.WebSocket = jest.fn(() => mockWebSocket)
- })
+ mockWebSocket.readyState = 1;
+ mockWebSocket.send = jest.fn();
+ mockWebSocket.addEventListener = jest.fn();
+ mockWebSocket.removeEventListener = jest.fn();
+ mockWebSocket.close = jest.fn();
+ global.WebSocket = jest.fn(() => mockWebSocket);
+ });
afterEach(() => {
- global.WebSocket = defaultWebSocket
- })
+ global.WebSocket = defaultWebSocket;
+ });
it("should create a new WebSocket without protocols if not connected and close on unsubscribe", () => {
- const webSocketFx = WebSocketListen({ url })
- const { unsubscribe } = runFx(webSocketFx)
+ const webSocketFx = WebSocketListen({ url });
+ const { unsubscribe } = runFx(webSocketFx);
- expect(WebSocket).toBeCalledWith(url, undefined)
- expect(mockWebSocket.close).not.toBeCalled()
+ expect(WebSocket).toBeCalledWith(url, undefined);
+ expect(mockWebSocket.close).not.toBeCalled();
- unsubscribe()
- expect(mockWebSocket.close).toBeCalled()
- })
+ unsubscribe();
+ expect(mockWebSocket.close).toBeCalled();
+ });
it("should create a new WebSocket with protocols if not connected and close on unsubscribe", () => {
- const protocols = ["soap", "wamp"]
- const webSocketFx = WebSocketListen({ url, protocols })
- const { unsubscribe } = runFx(webSocketFx)
+ const protocols = ["soap", "wamp"];
+ const webSocketFx = WebSocketListen({ url, protocols });
+ const { unsubscribe } = runFx(webSocketFx);
- expect(WebSocket).toBeCalledWith(url, protocols)
- expect(mockWebSocket.close).not.toBeCalled()
+ expect(WebSocket).toBeCalledWith(url, protocols);
+ expect(mockWebSocket.close).not.toBeCalled();
- unsubscribe()
- expect(mockWebSocket.close).toBeCalled()
- })
+ unsubscribe();
+ expect(mockWebSocket.close).toBeCalled();
+ });
it("should listen for messages and remove the listener on unsubscribe", () => {
- const message = JSON.stringify({ some: "message value" })
- const action = jest.fn()
- const webSocketFx = WebSocketListen({ url, action })
- const { dispatch, unsubscribe } = runFx(webSocketFx)
+ const message = JSON.stringify({ some: "message value" });
+ const action = jest.fn();
+ const webSocketFx = WebSocketListen({ url, action });
+ const { dispatch, unsubscribe } = runFx(webSocketFx);
expect(mockWebSocket.addEventListener).toBeCalledWith(
"message",
expect.any(Function)
- )
- expect(mockWebSocket.removeEventListener).not.toBeCalled()
+ );
+ expect(mockWebSocket.removeEventListener).not.toBeCalled();
- const messageListener = mockWebSocket.addEventListener.mock.calls[0][1]
- messageListener(message)
- expect(dispatch).toBeCalledWith(action, message)
+ const messageListener = mockWebSocket.addEventListener.mock.calls[0][1];
+ messageListener(message);
+ expect(dispatch).toBeCalledWith(action, message);
- unsubscribe()
+ unsubscribe();
expect(mockWebSocket.removeEventListener).toBeCalledWith(
"message",
expect.any(Function)
- )
- })
+ );
+ });
it("should handle errors and remove the listener on unsubscribe", () => {
- const errorMessage = new Error("uh oh!")
- const error = jest.fn()
- const webSocketFx = WebSocketListen({ url, error })
- const { dispatch, unsubscribe } = runFx(webSocketFx)
+ const errorMessage = new Error("uh oh!");
+ const error = jest.fn();
+ const webSocketFx = WebSocketListen({ url, error });
+ const { dispatch, unsubscribe } = runFx(webSocketFx);
expect(mockWebSocket.addEventListener).toBeCalledWith(
"error",
expect.any(Function)
- )
- expect(mockWebSocket.removeEventListener).not.toBeCalled()
+ );
+ expect(mockWebSocket.removeEventListener).not.toBeCalled();
- const errorListener = mockWebSocket.addEventListener.mock.calls[1][1]
- errorListener(errorMessage)
- expect(dispatch).toBeCalledWith(error, errorMessage)
+ const errorListener = mockWebSocket.addEventListener.mock.calls[1][1];
+ errorListener(errorMessage);
+ expect(dispatch).toBeCalledWith(error, errorMessage);
- unsubscribe()
+ unsubscribe();
expect(mockWebSocket.removeEventListener).toBeCalledWith(
"error",
expect.any(Function)
- )
- })
+ );
+ });
it("should reuse an existing WebSocket and not close the socket if another socket is already listening", () => {
- const onopen = jest.fn()
- const onclose = jest.fn()
+ const onopen = jest.fn();
+ const onclose = jest.fn();
- const listen1 = jest.fn()
+ const listen1 = jest.fn();
const webSocketFx1 = WebSocketListen({
url,
listen: listen1,
open: onopen,
close: onclose
- })
- const { unsubscribe: unsubscribe1 } = runFx(webSocketFx1)
+ });
+ const { unsubscribe: unsubscribe1 } = runFx(webSocketFx1);
- WebSocket.mockReset()
- const listen2 = jest.fn()
+ WebSocket.mockReset();
+ const listen2 = jest.fn();
const webSocketFx2 = WebSocketListen({
url,
listen: listen2,
open: onopen,
close: onclose
- })
- const { unsubscribe: unsubscribe2 } = runFx(webSocketFx2)
- expect(WebSocket).not.toBeCalled()
+ });
+ const { unsubscribe: unsubscribe2 } = runFx(webSocketFx2);
+ expect(WebSocket).not.toBeCalled();
- unsubscribe1()
- expect(mockWebSocket.close).not.toBeCalled()
- unsubscribe2()
- expect(mockWebSocket.close).toBeCalled()
- })
-})
+ unsubscribe1();
+ expect(mockWebSocket.close).not.toBeCalled();
+ unsubscribe2();
+ expect(mockWebSocket.close).toBeCalled();
+ });
+});
diff --git a/test/utils.js b/test/utils.js
index 93d1389..4ba35d3 100644
--- a/test/utils.js
+++ b/test/utils.js
@@ -1,7 +1,7 @@
-import { jest } from "@jest/globals"
+import { jest } from "@jest/globals";
export const runFx = fx => {
- const dispatch = jest.fn()
- const unsubscribe = fx[0](dispatch, fx[1])
- return { dispatch, unsubscribe }
-}
+ const dispatch = jest.fn();
+ const unsubscribe = fx[0](dispatch, fx[1]);
+ return { dispatch, unsubscribe };
+};