Skip to content

Commit

Permalink
add support for int, bool, and arrays of random values
Browse files Browse the repository at this point in the history
  • Loading branch information
okwolf committed Apr 26, 2019
1 parent 42a1349 commit e22ffc1
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 31 deletions.
15 changes: 7 additions & 8 deletions api.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,11 +191,8 @@ const MergingAction = state => [
<a name="module_fx.exports.Random"></a>

### fx.exports.Random(props)
Describes an effect that will call an action with a [randomly generated number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random) within a range.
If provided the range will be `[min, max)` or else the default range is `[0, 1)`. The random number will be provided as the action `data`.

Use [`Math.floor`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/floor) if you want a random integer instead of a floating-point number.
Remember the range will be `max` exclusive, so use your largest desired int + 1.
Describes an effect that will call an action with one or more randomly generated value(s).
If provided the range for [random numeric values](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random) will be `[min, max)` or else the default range is `[0, 1)`. Also `bool`eans, `int`egers, and arrays of `values` are supported. The random value will be provided as the action `data`.

**Kind**: static method of [<code>fx</code>](#module_fx)

Expand All @@ -205,6 +202,9 @@ Remember the range will be `max` exclusive, so use your largest desired int + 1.
| props.action | <code>\*</code> | action to call with the random number result |
| props.min | <code>number</code> | minimum random number to generate |
| props.max | <code>number</code> | maximum random number to generate |
| props.int | <code>boolean</code> | round number to nearest integer |
| props.bool | <code>boolean</code> | generate a boolean instead of a number (ignores numeric options) |
| props.values | <code>Array.&lt;object&gt;</code> | generate an array of values (ignores other options, each object accepts same props as the root) |

**Example**
```js
Expand All @@ -214,10 +214,9 @@ const RollDie = state => [
state,
Random({
min: 1,
// We use the max of 7 to include all values of 6.x
max: 7,
action: (_, randomNumber) => {
const roll = Math.floor(randomNumber)
int: true,
action: (_, roll) => {
// roll will be an int from 1-6

// return new state using roll
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "hyperapp-fx",
"version": "2.0.0-alpha.5",
"version": "2.0.0-alpha.6",
"description": "Effects for use with Hyperapp",
"main": "dist/hyperappFx.js",
"module": "src/index.js",
Expand Down
47 changes: 30 additions & 17 deletions src/fx/Random.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,51 @@
function generateRandom(props) {
if (props.values) {
return props.values.map(generateRandom)
}
var min = props.min || 0
var max = props.max || 1
if (props.int) max++
if (props.bool) {
min = 0
max = 2
}
var randomValue = Math.random() * (max - min) + min
if (props.int || props.bool) {
randomValue = Math.floor(randomValue)
}
if (props.bool) {
randomValue = !!randomValue
}
return randomValue
}

function randomEffect(props, dispatch) {
var randomValue = Math.random() * (props.max - props.min) + props.min
var randomValue = generateRandom(props)
dispatch(props.action, randomValue)
}

/**
* Describes an effect that will call an action with a [randomly generated number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random) within a range.
* If provided the range will be `[min, max)` or else the default range is `[0, 1)`. The random number will be provided as the action `data`.
*
* Use [`Math.floor`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/floor) if you want a random integer instead of a floating-point number.
* Remember the range will be `max` exclusive, so use your largest desired int + 1.
* Describes an effect that will call an action with one or more randomly generated value(s).
* If provided the range for [random numeric values](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random) will be `[min, max)` or else the default range is `[0, 1)`. Also `bool`eans, `int`egers, and arrays of `values` are supported. The random value will be provided as the action `data`.
*
* @memberof module:fx
* @param {object} props
* @param {*} props.action - action to call with the random number result
* @param {number} props.min - minimum random number to generate
* @param {number} props.max - maximum random number to generate
* @param {boolean} props.int - round number to nearest integer
* @param {boolean} props.bool - generate a boolean instead of a number (ignores numeric options)
* @param {object[]} props.values - generate an array of values (ignores other options, each object accepts same props as the root)
* @example
* import { Random } from "hyperapp-fx"
*
* const RollDie = state => [
* state,
* Random({
* min: 1,
* // We use the max of 7 to include all values of 6.x
* max: 7,
* action: (_, randomNumber) => {
* const roll = Math.floor(randomNumber)
* int: true,
* action: (_, roll) => {
* // roll will be an int from 1-6
*
* // return new state using roll
Expand All @@ -34,12 +54,5 @@ function randomEffect(props, dispatch) {
* ]
*/
export function Random(props) {
return [
randomEffect,
{
action: props.action,
min: props.min || 0,
max: props.max || 1
}
]
return [randomEffect, props]
}
52 changes: 47 additions & 5 deletions test/fx/Random.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,70 @@ import { runFx } from "../utils"
import { Random } from "../../src"

describe("Random effect", () => {
const defaultRandom = Math.random
afterEach(() => {
Math.random = defaultRandom
})
it("should call Math.random with default range", () => {
const randomValue = 0.5
const defaultRandom = Math.random
Math.random = () => randomValue

const action = jest.fn()
const randomFx = Random({ action })
const { dispatch } = runFx(randomFx)
expect(dispatch).toBeCalledWith(action, randomValue)

Math.random = defaultRandom
})

it("should call Math.random with custom range", () => {
const defaultRandom = Math.random
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)
})

Math.random = defaultRandom
it("should generate integers", () => {
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)
})

it("should generate false booleans", () => {
Math.random = () => 0.4

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

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

const action = jest.fn()
const randomFx = Random({
values: [
{},
{ min: 2, max: 5 },
{ int: true, min: 1, max: 3 },
{ bool: true }
],
action
})
const { dispatch } = runFx(randomFx)
expect(dispatch).toBeCalledWith(action, [0.5, 3.5, 2, true])
})
})

0 comments on commit e22ffc1

Please sign in to comment.