Skip to content

Commit

Permalink
VERSION 1.3.0 - added durationUnderflow. added some tests
Browse files Browse the repository at this point in the history
  • Loading branch information
tran-simon committed May 4, 2021
1 parent 8b23c48 commit 99cc86e
Show file tree
Hide file tree
Showing 10 changed files with 170 additions and 26 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"duration-picker",
"durations"
],
"version": "1.2.3",
"version": "1.3.0",
"license": "MIT",
"main": "dist/index.js",
"author": "tran-simon",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ exports[`DurationFieldsContainer can match snapshot 1`] = `
class="MuiGrid-root MuiGrid-container MuiGrid-spacing-xs-2 MuiGrid-justify-xs-space-around"
>
<div
class="MuiGrid-root MuiGrid-item"
class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-true"
>
<div
class="MuiFormControl-root MuiTextField-root"
class="MuiFormControl-root MuiTextField-root MuiFormControl-fullWidth"
>
<div
class="MuiInputBase-root MuiInput-root MuiInput-underline MuiInputBase-formControl MuiInput-formControl"
class="MuiInputBase-root MuiInput-root MuiInput-underline MuiInputBase-fullWidth MuiInput-fullWidth MuiInputBase-formControl MuiInput-formControl"
>
<input
aria-invalid="false"
Expand All @@ -25,13 +25,13 @@ exports[`DurationFieldsContainer can match snapshot 1`] = `
</div>
</div>
<div
class="MuiGrid-root MuiGrid-item"
class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-true"
>
<div
class="MuiFormControl-root MuiTextField-root"
class="MuiFormControl-root MuiTextField-root MuiFormControl-fullWidth"
>
<div
class="MuiInputBase-root MuiInput-root MuiInput-underline MuiInputBase-formControl MuiInput-formControl"
class="MuiInputBase-root MuiInput-root MuiInput-underline MuiInputBase-fullWidth MuiInput-fullWidth MuiInputBase-formControl MuiInput-formControl"
>
<input
aria-invalid="false"
Expand Down
24 changes: 24 additions & 0 deletions src/__tests__/__snapshots__/durationPicker.test.tsx.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`durationPicker can match snapshot 1`] = `
<DocumentFragment>
<div
class="MuiFormControl-root MuiTextField-root"
>
<div
class="MuiInputBase-root MuiInput-root MuiInput-underline MuiInputBase-formControl MuiInput-formControl"
>
<input
aria-invalid="false"
class="MuiInputBase-input MuiInput-input"
readonly=""
type="text"
value=""
/>
</div>
</div>
<div>
{"weeks":1,"days":2,"hours":3,"minutes":4,"seconds":5}
</div>
</DocumentFragment>
`;
48 changes: 37 additions & 11 deletions src/__tests__/durationFieldsContainer.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ describe('DurationFieldsContainer', () => {
const emptyDuration = {};

const Comp = ({
views = ['minutes', 'seconds'],
duration = {...emptyDuration, minutes: 5, seconds: 2},
views = ['hours', 'minutes'],
duration = {...emptyDuration, hours: 5, minutes: 2},
setDuration = setDurationMock,
...props
}: Partial<DurationFieldsContainerProps>) => {
Expand Down Expand Up @@ -44,22 +44,23 @@ describe('DurationFieldsContainer', () => {
const utils = render(
<Comp duration={{
...emptyDuration,
days: 1,
hours: 1,
minutes: 1,
seconds: 1
seconds: 30,
}}/>
);
const fields: any[] = utils.getAllByTitle('fieldTitle')
expect(fields[0].value).toBe("61")
expect(fields[1].value).toBe("1")
expect(fields[0].value).toBe("25")
expect(fields[1].value).toBe("1.5")
});

it('can setDuration to greater than views show', async () => {
it('can setDuration to smaller than views show', async () => {
const utils = render(
<Comp duration={{
...emptyDuration,
minutes: 1,
seconds: 1
hours: 1,
minutes: 1
}}/>
);

Expand All @@ -73,9 +74,34 @@ describe('DurationFieldsContainer', () => {
expect(setDurationMock).toHaveBeenCalledWith({
weeks: undefined,
days: undefined,
hours: undefined,
minutes: 61,
seconds: 1
hours: 61,
minutes: 1,
seconds: undefined
})
})

it('can setDuration to smaller than views show', async () => {
const utils = render(
<Comp duration={{
...emptyDuration,
hours: 1,
minutes: 1
}}/>
);

const fields: any[] = utils.getAllByTitle('fieldTitle')

fireEvent.change(fields[1], {target: {value: '0.5'}})
fireEvent.blur(fields[1])

expect(fields[1].value).toBe('0.5')

expect(setDurationMock).toHaveBeenCalledWith({
weeks: undefined,
days: undefined,
hours: 1,
minutes: 0.5,
seconds: undefined
})
})
})
31 changes: 31 additions & 0 deletions src/__tests__/durationPicker.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import * as React from 'react'
import {render, waitFor} from "@testing-library/react";
import {DurationPicker} from "../durationPicker";
import * as DurationDialog from '../durationDialog'


jest.mock('../durationDialog', () => {
return {
DurationDialog: ({duration}: any) => (<div>{JSON.stringify(duration)}</div>)
}
})

describe('durationPicker', () => {
const onValueChange = jest.fn()
const formatDuration = jest.fn()
//1 week + 2 days + 3 hours + 4 min + 5 secs
const time = 604800 + 172800 + 10800 + 240 + 5;

it('can match snapshot', async () => {
await waitFor(() => {
expect(
render(
<DurationPicker
value={time}
onValueChange={onValueChange}
formatDuration={formatDuration}/>
).asFragment()
).toMatchSnapshot();
})
})
})
30 changes: 29 additions & 1 deletion src/__tests__/utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {durationToTime, getDurationOverflow, timeToDuration} from "../utils";
import {durationToTime, getDurationOverflow, getDurationUnderflow, timeToDuration} from "../utils";


describe('timeToDuration', ()=>{
Expand Down Expand Up @@ -89,3 +89,31 @@ describe('getDurationOverflow', ()=>{
expect(getDurationOverflow(duration, 'minutes')).toEqual(expected)
})
})

describe('getDurationUnderflow', ()=>{
it('can getDurationUnderflow', ()=>{
const duration = {
weeks: undefined,
days: 2,
hours: 3,
minutes: 4,
seconds: 5
}

const expected = 4/60 + 5/60/60;

expect(getDurationUnderflow(duration, 'hours')).toEqual(expected)

expect(getDurationUnderflow({
minutes: 1,
seconds: 1
}, 'minutes')).toEqual(1/60)

expect(getDurationUnderflow({
days:3,
hours:2,
minutes: undefined,
seconds: 45
}, 'days')).toEqual(2/24 + 45 / 60 / 60 / 24)
})
})
3 changes: 2 additions & 1 deletion src/durationField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ export const DurationField = ({value: _value, onConfirm, ...props}: DurationFiel
type="number"
onChange={({target}) => {
const num = +target.value
setValue(isNaN(num) ? null : num);
setValue(isNaN(num) || !target.value ? null : num);
}}
onBlur={() => {
onConfirm(value)
}}
value={value ?? ''}
fullWidth
{...props}
/>
)
Expand Down
12 changes: 8 additions & 4 deletions src/durationFieldsContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {Dispatch} from 'react'
import {DurationField, DurationFieldProps} from "./durationField";
import {DurationType, DurationView, Labels} from "./types";
import DefaultLabels from "./defaultLabelsEn.json";
import {getDurationOverflow} from "./utils";
import {getDurationOverflow, getDurationUnderflow} from "./utils";


export type DurationFieldsContainerProps = {
Expand All @@ -26,7 +26,7 @@ export const DurationFieldsContainer = ({
GridItemProps,
GridContainerProps,
DurationFieldProps
}: DurationFieldsContainerProps)=>{
}: DurationFieldsContainerProps) => {
const labels = {
...DefaultLabels,
..._labels
Expand All @@ -35,12 +35,16 @@ export const DurationFieldsContainer = ({
return (
<Grid container spacing={2} justify='space-around' {...GridContainerProps}>
{views.map((view, i) => {
const acc = i === 0 ? getDurationOverflow(duration, view) : 0
const acc = i === 0 ?
getDurationOverflow(duration, view) :
i === views.length - 1 ?
getDurationUnderflow(duration, view) :
0

const value = ((duration[view] || 0) + acc) || null

return (
<Grid item key={i} {...GridItemProps}>
<Grid item key={i} xs {...GridItemProps}>
<DurationField
label={labels[view]}
value={value}
Expand Down
30 changes: 30 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,33 @@ export const getDurationOverflow = (duration: DurationType, view: DurationView):
}
return acc
}

/**
* Get the time value from a duration by adding the values of the views smaller than 'view'
*
* Ex:
* duration: {
* minutes: 1,
* seconds: 1,
* }
* view: 'minutes'
*
* res:
* (seconds)
* = 1 * 1/60 = 0.016666
*
* @param duration The duration object
* @param view The view up to it will add
*/
export const getDurationUnderflow = (duration: DurationType, view: DurationView): number => {
let acc = 0;
const reversedViews = [...VIEWS].reverse()
for (const key of reversedViews) {
if (key === view) {
break;
}

acc += (duration[key] || 0) / toSecondsMultipliers[view] * toSecondsMultipliers[key]
}
return acc
}

0 comments on commit 99cc86e

Please sign in to comment.