You're Invited:Meet the Socket Team at BlackHat and DEF CON in Las Vegas, Aug 4-6.RSVP
Socket
Book a DemoInstallSign in
Socket

react-schedule-selector

Package Overview
Dependencies
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-schedule-selector - npm Package Compare versions

Comparing version

to
1.0.4

.vscode/launch.json

36

dist/lib/ScheduleSelector.js

@@ -14,2 +14,6 @@ 'use strict';

var _add_minutes = require('date-fns/add_minutes');
var _add_minutes2 = _interopRequireDefault(_add_minutes);
var _add_hours = require('date-fns/add_hours');

@@ -58,8 +62,2 @@

var formatHour = function formatHour(hour) {
var h = hour === 0 || hour === 12 || hour === 24 ? 12 : hour % 12;
var abb = hour < 12 || hour === 24 ? 'am' : 'pm';
return '' + h + abb;
};
var Wrapper = (0, _styledComponents2.default)('div').withConfig({

@@ -126,13 +124,13 @@ displayName: 'ScheduleSelector__Wrapper',

var labels = [React.createElement(DateLabel, { key: -1 })]; // Ensures time labels start at correct location
for (var t = _this.props.minTime; t <= _this.props.maxTime; t += 1) {
_this.dates[0].forEach(function (time) {
labels.push(React.createElement(
TimeLabelCell,
{ key: t },
{ key: time.toString() },
React.createElement(
TimeText,
null,
formatHour(t)
(0, _format2.default)(time, _this.props.timeFormat)
)
));
}
});
return React.createElement(

@@ -148,3 +146,3 @@ Column,

Column,
{ key: dayOfTimes[0], margin: _this.props.margin },
{ key: dayOfTimes[0].toString(), margin: _this.props.margin },
React.createElement(

@@ -221,6 +219,9 @@ GridCell,

_this.cellToDate = new Map();
var minutesInChunk = Math.floor(60 / props.hourlyChunks);
for (var d = 0; d < props.numDays; d += 1) {
var currentDay = [];
for (var h = props.minTime; h <= props.maxTime; h += 1) {
currentDay.push((0, _add_hours2.default)((0, _add_days2.default)(startTime, d), h));
for (var h = props.minTime; h < props.maxTime; h += 1) {
for (var c = 0; c < props.hourlyChunks; c += 1) {
currentDay.push((0, _add_minutes2.default)((0, _add_hours2.default)((0, _add_days2.default)(startTime, d), h), c * minutesInChunk));
}
}

@@ -297,4 +298,7 @@ _this.dates.push(currentDay);

var targetElement = document.elementFromPoint(clientX, clientY);
var cellTime = this.cellToDate.get(targetElement);
return cellTime;
if (targetElement) {
var cellTime = this.cellToDate.get(targetElement);
return cellTime;
}
return null;
};

@@ -419,3 +423,5 @@

maxTime: 23,
hourlyChunks: 1,
startDate: new Date(),
timeFormat: 'ha',
dateFormat: 'M/D',

@@ -422,0 +428,0 @@ margin: 3,

{
"name": "react-schedule-selector",
"version": "1.0.3",
"version": "1.0.4",
"description": "A mobile-friendly when2meet-style grid-based schedule selector",

@@ -21,5 +21,6 @@ "author": "Bibek Ghimire",

"postpublish": "yarn docs:deploy",
"build": "yarn lib:build && yarn docs:build",
"build": "yarn clean && yarn lib:build && yarn docs:build",
"lint": "eslint src/**/*.{js,jsx} --quiet",
"format": "prettier --write \"src/**/*.{js,jsx}\"",
"clean": "rm -rf dist",
"cover": "jest --coverage && cat ./coverage/lcov.info | coveralls",

@@ -67,3 +68,3 @@ "test": "jest",

"eslint-plugin-react": "^7.7.0",
"flow-bin": "^0.71.0",
"flow-bin": "^0.132.0",
"jest": "^23.2.0",

@@ -73,3 +74,3 @@ "jest-styled-components": "^6.2.0",

"moment": "^2.22.2",
"parcel-bundler": "^1.8.0",
"parcel-bundler": "^1.12.4",
"prettier": "^1.14.2",

@@ -76,0 +77,0 @@ "react": "^16.0.0",

@@ -5,3 +5,3 @@ # React Schedule Selector

A mobile-friendly when2meet-style grid-based schedule selector built with [styled components](https://github.com/styled-components/styled-components) and [date-fns](https://date-fns.org/).
A mobile-friendly when2meet-style grid-based schedule selector built with [styled components](https://github.com/styled-components/styled-components) and [date-fns](https://date-fns.org/).

@@ -35,2 +35,3 @@ [Live example](http://react-schedule-selector.surge.sh/)

maxTime={22}
hourlyChunks={2}
onChange={this.handleChange}

@@ -84,3 +85,3 @@ />

**description**: The date on which the grid should start (time portion is ignored, specify start time via `minTime`)
**description**: The date on which the grid should start (time portion is ignored, specify start time via `minTime`)

@@ -95,3 +96,3 @@ **required**: no

**description**: The number of days to show, startin from today
**description**: The number of days to show, starting from today

@@ -102,2 +103,12 @@ **required**: no

#### `hourlyChunks`
**type**: `number`
**description**: How many chunks to divide each hour into (e.g. `2` divides the hour into half-hour steps, `4` into 15-minute steps)
**required**: no
**default value**: `1`
#### `minTime`

@@ -133,2 +144,12 @@

#### `timeFormat`
**type**: `string`
**description**: The [time format](https://date-fns.org/v1.29.0/docs/format) to be used for the row labels
**required**: no
**default value**: `'ha'`
#### `margin`

@@ -135,0 +156,0 @@

@@ -14,23 +14,45 @@ // @flow

}
* {
box-sizing: border-box;
}
`
const MainDiv = styled.div`
display: flex;
flex-direction: column;
align-items: center;
`
const IntroText = styled.div`
width: 100%;
text-align: center;
`
const ScheduleSelectorCard = styled.div`
border-radius: 25px;
box-shadow: 0px 0px 2px #222222;
box-shadow: 10px 2px 30px rgba(0, 0, 0, 0.15);
padding: 20px;
width: 90%;
max-width: 800px;
& > * {
flex-grow: 1;
}
`
const EmojiCell = styled.span.attrs({
role: 'img',
'aria-label': 'checked'
})`
text-align: center;
const Links = styled.div`
display: flex;
justify-content: center;
border: 1px solid rgba(0, 0, 0, 0.3);
&:hover {
background-color: rgba(236, 146, 64, 0.3);
}
margin-top: 20px;
`
const ExternalLink = styled.a`
background-color: ${props => props.color};
color: white;
padding: 10px;
border-radius: 3px;
cursor: pointer;
text-decoration: none;
margin: 5px;
`
type StateType = {

@@ -47,9 +69,9 @@ schedule: Array<Date>

// eslint-disable-next-line
renderCustomCell = (time: Date, selected: boolean, innerRef: (HTMLElement => void)) => (selected ? <EmojiCell innerRef={innerRef}>✅</EmojiCell> : <EmojiCell innerRef={innerRef}>❌</EmojiCell>)
render(): React.Element<*> {
return (
<div>
<h1>Schedule Selector with Custom Renderer</h1>
<MainDiv>
<IntroText>
<h1>React Schedule Selector</h1>
<p>Tap to select one time or drag to select multiple times at once.</p>
</IntroText>
<ScheduleSelectorCard>

@@ -59,11 +81,21 @@ <ScheduleSelector

maxTime={20}
numDays={5}
startDate={new Date('Fri May 18 2018 17:57:06 GMT-0700 (PDT)')}
numDays={7}
selection={this.state.schedule}
onChange={this.handleDateChange}
renderDateCell={this.renderCustomCell}
dateFormat="ddd"
hourlyChunks={2}
timeFormat="h:mma"
/>
</ScheduleSelectorCard>
</div>
<Links>
<ExternalLink color="#24292e" href="https://github.com/bibekg/react-schedule-selector">
GitHub
</ExternalLink>
<ExternalLink color="#cb3838" href="https://npmjs.com/package/react-schedule-selector">
NPM
</ExternalLink>
<ExternalLink color="#292929" href="https://medium.com/@bibekg/react-schedule-selector-6cd5bf1f4968">
Medium
</ExternalLink>
</Links>
</MainDiv>
)

@@ -70,0 +102,0 @@ }

@@ -7,2 +7,3 @@ // @flow

// Import only the methods we need from date-fns in order to keep build size small
import addMinutes from 'date-fns/add_minutes'
import addHours from 'date-fns/add_hours'

@@ -18,8 +19,2 @@ import addDays from 'date-fns/add_days'

const formatHour = (hour: number): string => {
const h = hour === 0 || hour === 12 || hour === 24 ? 12 : hour % 12
const abb = hour < 12 || hour === 24 ? 'am' : 'pm'
return `${h}${abb}`
}
const Wrapper = styled.div`

@@ -96,3 +91,5 @@ display: flex;

maxTime: number,
hourlyChunks: number,
dateFormat: string,
timeFormat: string,
margin: number,

@@ -131,3 +128,3 @@ unselectedColor: string,

static defaultProps = {
static defaultProps: PropsType = {
selection: [],

@@ -138,3 +135,5 @@ selectionScheme: 'square',

maxTime: 23,
hourlyChunks: 1,
startDate: new Date(),
timeFormat: 'ha',
dateFormat: 'M/D',

@@ -155,6 +154,9 @@ margin: 3,

this.cellToDate = new Map()
const minutesInChunk = Math.floor(60 / props.hourlyChunks)
for (let d = 0; d < props.numDays; d += 1) {
const currentDay = []
for (let h = props.minTime; h <= props.maxTime; h += 1) {
currentDay.push(addHours(addDays(startTime, d), h))
for (let h = props.minTime; h < props.maxTime; h += 1) {
for (let c = 0; c < props.hourlyChunks; c += 1) {
currentDay.push(addMinutes(addHours(addDays(startTime, d), h), c * minutesInChunk))
}
}

@@ -224,4 +226,7 @@ this.dates.push(currentDay)

const targetElement = document.elementFromPoint(clientX, clientY)
const cellTime = this.cellToDate.get(targetElement)
return cellTime
if (targetElement) {
const cellTime = this.cellToDate.get(targetElement)
return cellTime
}
return null
}

@@ -305,9 +310,9 @@

const labels = [<DateLabel key={-1} />] // Ensures time labels start at correct location
for (let t = this.props.minTime; t <= this.props.maxTime; t += 1) {
this.dates[0].forEach(time => {
labels.push(
<TimeLabelCell key={t}>
<TimeText>{formatHour(t)}</TimeText>
<TimeLabelCell key={time.toString()}>
<TimeText>{formatDate(time, this.props.timeFormat)}</TimeText>
</TimeLabelCell>
)
}
})
return <Column margin={this.props.margin}>{labels}</Column>

@@ -317,3 +322,3 @@ }

renderDateColumn = (dayOfTimes: Array<Date>) => (
<Column key={dayOfTimes[0]} margin={this.props.margin}>
<Column key={dayOfTimes[0].toString()} margin={this.props.margin}>
<GridCell margin={this.props.margin}>

@@ -320,0 +325,0 @@ <DateLabel>{formatDate(dayOfTimes[0], this.props.dateFormat)}</DateLabel>

@@ -22,174 +22,195 @@ /* eslint-disable flowtype/* */

beforeAll(() => {
document.elementFromPoint = jest.fn()
document.removeEventListener = jest.fn()
})
describe('snapshot tests', () => {
it('renders correctly with default render logic', () => {
const component = renderer.create(
<ScheduleSelector selection={getTestSchedule()} startDate={startDate} numDays={5} onChange={() => undefined} />
)
const tree = component.toJSON()
expect(tree).toMatchSnapshot()
describe('ScheduleSelector', () => {
beforeAll(() => {
const fakeElement = document.createElement('div')
document.elementFromPoint = jest.fn().mockReturnValue(fakeElement)
document.removeEventListener = jest.fn()
})
it('renders correctly with custom render prop', () => {
const customDateCellRenderer = (date, selected) => (
<div className={`${selected && 'selected'} test-date-cell-renderer`}>{date.toDateString()}</div>
)
describe('snapshot tests', () => {
it('renders correctly with default render logic', () => {
const component = renderer.create(
<ScheduleSelector selection={getTestSchedule()} startDate={startDate} numDays={5} onChange={() => undefined} />
)
const tree = component.toJSON()
expect(tree).toMatchSnapshot()
})
const component = renderer.create(
<ScheduleSelector
selection={getTestSchedule()}
startDate={startDate}
numDays={5}
onChange={() => undefined}
renderDateCell={customDateCellRenderer}
/>
)
it('renders correctly with custom render prop', () => {
const customDateCellRenderer = (date, selected) => (
<div className={`${selected && 'selected'} test-date-cell-renderer`}>{date.toDateString()}</div>
)
const tree = component.toJSON()
expect(tree).toMatchSnapshot()
const component = renderer.create(
<ScheduleSelector
selection={getTestSchedule()}
startDate={startDate}
numDays={5}
onChange={() => undefined}
renderDateCell={customDateCellRenderer}
/>
)
const tree = component.toJSON()
expect(tree).toMatchSnapshot()
})
})
})
it('getTimeFromTouchEvent returns the time for that cell', () => {
const component = shallow(<ScheduleSelector />)
const mainSpy = jest.spyOn(component.instance(), 'getTimeFromTouchEvent')
const mockCellTime = new Date()
const mockEvent = {
touches: [{ clientX: 1, clientY: 2 }]
}
const cellToDateSpy = jest.spyOn(component.instance().cellToDate, 'get').mockReturnValue(mockCellTime)
it('getTimeFromTouchEvent returns the time for that cell', () => {
const component = shallow(<ScheduleSelector />)
const mainSpy = jest.spyOn(component.instance(), 'getTimeFromTouchEvent')
const mockCellTime = new Date()
const mockEvent = {
touches: [{ clientX: 1, clientY: 2 }]
}
const cellToDateSpy = jest.spyOn(component.instance().cellToDate, 'get').mockReturnValue(mockCellTime)
component.instance().getTimeFromTouchEvent(mockEvent)
component.instance().getTimeFromTouchEvent(mockEvent)
expect(document.elementFromPoint).toHaveBeenCalledWith(mockEvent.touches[0].clientX, mockEvent.touches[0].clientY)
expect(cellToDateSpy).toHaveBeenCalled()
expect(mainSpy).toHaveReturnedWith(mockCellTime)
expect(document.elementFromPoint).toHaveBeenCalledWith(mockEvent.touches[0].clientX, mockEvent.touches[0].clientY)
expect(cellToDateSpy).toHaveBeenCalled()
expect(mainSpy).toHaveReturnedWith(mockCellTime)
mainSpy.mockRestore()
cellToDateSpy.mockRestore()
})
mainSpy.mockRestore()
cellToDateSpy.mockRestore()
})
it('endSelection calls the onChange prop and resets selection state', () => {
const changeSpy = jest.fn()
const component = shallow(<ScheduleSelector onChange={changeSpy} />)
const setStateSpy = jest.spyOn(component.instance(), 'setState')
it('endSelection calls the onChange prop and resets selection state', () => {
const changeSpy = jest.fn()
const component = shallow(<ScheduleSelector onChange={changeSpy} />)
const setStateSpy = jest.spyOn(component.instance(), 'setState')
component.instance().endSelection()
component.instance().endSelection()
expect(changeSpy).toHaveBeenCalledWith(component.state('selectionDraft'))
expect(setStateSpy).toHaveBeenCalledWith({
selectionType: null,
selectionStart: null
})
expect(changeSpy).toHaveBeenCalledWith(component.state('selectionDraft'))
expect(setStateSpy).toHaveBeenCalledWith({
selectionType: null,
selectionStart: null
setStateSpy.mockRestore()
})
setStateSpy.mockRestore()
})
describe('mouse handlers', () => {
const spies = {}
let component
let anInstance
describe('mouse handlers', () => {
const spies = {}
let component
let anInstance
beforeAll(() => {
spies.onMouseDown = jest.spyOn(ScheduleSelector.prototype, 'handleSelectionStartEvent')
spies.onMouseEnter = jest.spyOn(ScheduleSelector.prototype, 'handleMouseEnterEvent')
spies.onMouseUp = jest.spyOn(ScheduleSelector.prototype, 'handleMouseUpEvent')
component = shallow(<ScheduleSelector />)
anInstance = component.find('.rgdp__grid-cell').first()
})
beforeAll(() => {
spies.onMouseDown = jest.spyOn(ScheduleSelector.prototype, 'handleSelectionStartEvent')
spies.onMouseEnter = jest.spyOn(ScheduleSelector.prototype, 'handleMouseEnterEvent')
spies.onMouseUp = jest.spyOn(ScheduleSelector.prototype, 'handleMouseUpEvent')
component = shallow(<ScheduleSelector />)
anInstance = component.find('.rgdp__grid-cell').first()
})
test.each([['onMouseDown'], ['onMouseEnter'], ['onMouseUp']])('calls the handler for %s', name => {
anInstance.prop(name)()
expect(spies[name]).toHaveBeenCalled()
spies[name].mockClear()
})
test.each([['onMouseDown'], ['onMouseEnter'], ['onMouseUp']])('calls the handler for %s', name => {
anInstance.prop(name)()
expect(spies[name]).toHaveBeenCalled()
spies[name].mockClear()
})
afterAll(() => {
Object.keys(spies).forEach(spyName => {
spies[spyName].mockRestore()
afterAll(() => {
Object.keys(spies).forEach(spyName => {
spies[spyName].mockRestore()
})
})
})
})
describe('touch handlers', () => {
const spies = {}
let component
let anInstance
const mockEvent = {}
describe('touch handlers', () => {
const spies = {}
let component
let anInstance
const mockEvent = {}
beforeAll(() => {
spies.onTouchStart = jest.spyOn(ScheduleSelector.prototype, 'handleSelectionStartEvent')
spies.onTouchMove = jest.spyOn(ScheduleSelector.prototype, 'handleTouchMoveEvent')
spies.onTouchEnd = jest.spyOn(ScheduleSelector.prototype, 'handleTouchEndEvent')
component = shallow(<ScheduleSelector />)
anInstance = component.find('.rgdp__grid-cell').first()
mockEvent.touches = [{ clientX: 1, clientY: 2 }, { clientX: 100, clientY: 200 }]
})
beforeAll(() => {
spies.onTouchStart = jest.spyOn(ScheduleSelector.prototype, 'handleSelectionStartEvent')
spies.onTouchMove = jest.spyOn(ScheduleSelector.prototype, 'handleTouchMoveEvent')
spies.onTouchEnd = jest.spyOn(ScheduleSelector.prototype, 'handleTouchEndEvent')
component = shallow(<ScheduleSelector />)
anInstance = component.find('.rgdp__grid-cell').first()
mockEvent.touches = [{ clientX: 1, clientY: 2 }, { clientX: 100, clientY: 200 }]
})
test.each([['onTouchStart', []], ['onTouchMove', [mockEvent]], ['onTouchEnd', []]])(
'calls the handler for %s',
(name, args) => {
anInstance.prop(name)(...args)
expect(spies[name]).toHaveBeenCalled()
spies[name].mockClear()
}
)
test.each([['onTouchStart', []], ['onTouchMove', [mockEvent]], ['onTouchEnd', []]])(
'calls the handler for %s',
(name, args) => {
anInstance.prop(name)(...args)
expect(spies[name]).toHaveBeenCalled()
spies[name].mockClear()
}
)
afterAll(() => {
Object.keys(spies).forEach(spyName => {
spies[spyName].mockRestore()
afterAll(() => {
Object.keys(spies).forEach(spyName => {
spies[spyName].mockRestore()
})
})
})
})
it('handleTouchMoveEvent updates the availability draft', () => {
const mockCellTime = new Date()
const getTimeSpy = jest.spyOn(ScheduleSelector.prototype, 'getTimeFromTouchEvent').mockReturnValue(mockCellTime)
const updateDraftSpy = jest.spyOn(ScheduleSelector.prototype, 'updateAvailabilityDraft')
it('handleTouchMoveEvent updates the availability draft', () => {
const mockCellTime = new Date()
const getTimeSpy = jest.spyOn(ScheduleSelector.prototype, 'getTimeFromTouchEvent').mockReturnValue(mockCellTime)
const updateDraftSpy = jest.spyOn(ScheduleSelector.prototype, 'updateAvailabilityDraft')
const component = shallow(<ScheduleSelector />)
component.instance().handleTouchMoveEvent({})
expect(updateDraftSpy).toHaveBeenCalledWith(mockCellTime)
const component = shallow(<ScheduleSelector />)
component.instance().handleTouchMoveEvent({})
expect(updateDraftSpy).toHaveBeenCalledWith(mockCellTime)
getTimeSpy.mockRestore()
updateDraftSpy.mockRestore()
})
getTimeSpy.mockRestore()
updateDraftSpy.mockRestore()
})
describe('updateAvailabilityDraft', () => {
it.each([['add', 1], ['remove', 1], ['add', -1], ['remove', -1]])(
'updateAvailabilityDraft handles addition and removals, for forward and reversed drags',
(type, amount, done) => {
const start = moment(startDate)
.add(5, 'hours')
.toDate()
const end = moment(start)
.add(amount, 'hours')
.toDate()
const outOfRangeOne = moment(start)
.add(amount + 5, 'hours')
.toDate()
describe('updateAvailabilityDraft', () => {
it.each([['add', 1], ['remove', 1], ['add', -1], ['remove', -1]])(
'updateAvailabilityDraft handles addition and removals, for forward and reversed drags',
(type, amount, done) => {
const start = moment(startDate)
.add(5, 'hours')
.toDate()
const end = moment(start)
.add(amount, 'hours')
.toDate()
const outOfRangeOne = moment(start)
.add(amount + 5, 'hours')
.toDate()
const setStateSpy = jest.spyOn(ScheduleSelector.prototype, 'setState')
const component = shallow(
<ScheduleSelector
// Initialize the initial selection based on whether this test is adding or removing
selection={type === 'remove' ? [start, end, outOfRangeOne] : [outOfRangeOne]}
startDate={start}
numDays={5}
minTime={0}
maxTime={23}
/>
)
component.setState(
{
selectionType: type,
selectionStart: start
},
() => {
component.instance().updateAvailabilityDraft(end, () => {
expect(setStateSpy).toHaveBeenLastCalledWith({ selectionDraft: expect.arrayContaining([]) })
setStateSpy.mockRestore()
done()
})
}
)
}
)
it('updateAvailabilityDraft handles a single cell click correctly', done => {
const setStateSpy = jest.spyOn(ScheduleSelector.prototype, 'setState')
const component = shallow(
<ScheduleSelector
// Initialize the initial selection based on whether this test is adding or removing
selection={type === 'remove' ? [start, end, outOfRangeOne] : [outOfRangeOne]}
startDate={start}
numDays={5}
minTime={0}
maxTime={23}
/>
)
const component = shallow(<ScheduleSelector />)
const start = startDate
component.setState(
{
selectionType: type,
selectionType: 'add',
selectionStart: start
},
() => {
component.instance().updateAvailabilityDraft(end, () => {
expect(setStateSpy).toHaveBeenLastCalledWith({ selectionDraft: expect.arrayContaining([]) })
component.instance().updateAvailabilityDraft(null, () => {
expect(setStateSpy).toHaveBeenCalledWith({ selectionDraft: expect.arrayContaining([]) })
setStateSpy.mockRestore()

@@ -200,111 +221,124 @@ done()

)
}
)
it('updateAvailabilityDraft handles a single cell click correctly', done => {
const setStateSpy = jest.spyOn(ScheduleSelector.prototype, 'setState')
const component = shallow(<ScheduleSelector />)
const start = startDate
component.setState(
{
selectionType: 'add',
selectionStart: start
},
() => {
component.instance().updateAvailabilityDraft(null, () => {
expect(setStateSpy).toHaveBeenCalledWith({ selectionDraft: expect.arrayContaining([]) })
setStateSpy.mockRestore()
done()
})
}
)
})
})
})
describe('componentDidMount', () => {
it('runs properly on a full mount', () => {
mount(<ScheduleSelector />)
describe('componentDidMount', () => {
it('runs properly on a full mount', () => {
mount(<ScheduleSelector />)
})
})
})
describe('componentWillUnmount', () => {
it('removes the mouseup event listener', () => {
const component = shallow(<ScheduleSelector />)
const endSelectionMethod = component.instance().endSelection
component.unmount()
expect(document.removeEventListener).toHaveBeenCalledWith('mouseup', endSelectionMethod)
})
describe('componentWillUnmount', () => {
it('removes the mouseup event listener', () => {
const component = shallow(<ScheduleSelector />)
const endSelectionMethod = component.instance().endSelection
component.unmount()
expect(document.removeEventListener).toHaveBeenCalledWith('mouseup', endSelectionMethod)
})
it('removes the touchmove event listeners from the date cells', () => {
const component = shallow(<ScheduleSelector />)
const mockDateCell = {
removeEventListener: jest.fn()
}
component.instance().cellToDate.set(mockDateCell, new Date())
component.unmount()
it('removes the touchmove event listeners from the date cells', () => {
const component = shallow(<ScheduleSelector />)
const mockDateCell = {
removeEventListener: jest.fn()
}
component.instance().cellToDate.set(mockDateCell, new Date())
component.unmount()
expect(mockDateCell.removeEventListener).toHaveBeenCalledWith('touchmove', expect.anything())
expect(mockDateCell.removeEventListener).toHaveBeenCalledWith('touchmove', expect.anything())
})
})
})
describe('componentWillReceiveProps', () => {
it('makes the selection prop override the existing selection draft', () => {
const setStateSpy = jest.spyOn(ScheduleSelector.prototype, 'setState')
const component = shallow(<ScheduleSelector />)
const mockNextProps = {
selection: ['foo', 'bar']
}
component.instance().componentWillReceiveProps(mockNextProps)
expect(setStateSpy).toHaveBeenCalledWith({
selectionDraft: expect.arrayContaining(mockNextProps.selection)
describe('componentWillReceiveProps', () => {
it('makes the selection prop override the existing selection draft', () => {
const setStateSpy = jest.spyOn(ScheduleSelector.prototype, 'setState')
const component = shallow(<ScheduleSelector />)
const mockNextProps = {
selection: ['foo', 'bar']
}
component.instance().componentWillReceiveProps(mockNextProps)
expect(setStateSpy).toHaveBeenCalledWith({
selectionDraft: expect.arrayContaining(mockNextProps.selection)
})
})
})
})
describe('handleTouchEndEvent', () => {
const component = shallow(<ScheduleSelector />)
const setStateSpy = jest.spyOn(component.instance(), 'setState')
const updateDraftSpy = jest.spyOn(component.instance(), 'updateAvailabilityDraft').mockImplementation((a, b) => b())
const endSelectionSpy = jest.spyOn(component.instance(), 'endSelection').mockImplementation(jest.fn())
describe('handleTouchEndEvent', () => {
const component = shallow(<ScheduleSelector />)
const setStateSpy = jest.spyOn(component.instance(), 'setState')
const updateDraftSpy = jest.spyOn(component.instance(), 'updateAvailabilityDraft').mockImplementation((a, b) => b())
const endSelectionSpy = jest.spyOn(component.instance(), 'endSelection').mockImplementation(jest.fn())
it('handles regular events correctly', () => {
component.instance().handleTouchEndEvent()
it('handles regular events correctly', () => {
component.instance().handleTouchEndEvent()
expect(setStateSpy).toHaveBeenLastCalledWith({ isTouchDragging: false })
expect(updateDraftSpy).toHaveBeenCalled()
expect(endSelectionSpy).toHaveBeenCalled()
expect(setStateSpy).toHaveBeenLastCalledWith({ isTouchDragging: false })
expect(updateDraftSpy).toHaveBeenCalled()
expect(endSelectionSpy).toHaveBeenCalled()
setStateSpy.mockClear()
updateDraftSpy.mockClear()
endSelectionSpy.mockClear()
setStateSpy.mockClear()
updateDraftSpy.mockClear()
endSelectionSpy.mockClear()
})
it('handles single-touch-tap events correctly', done => {
// Set touch dragging to true and make sure updateDraftSpy doesn't get called
component.setState(
{
isTouchDragging: true
},
() => {
component.instance().handleTouchEndEvent()
expect(updateDraftSpy).not.toHaveBeenCalled()
expect(endSelectionSpy).toHaveBeenCalled()
expect(setStateSpy).toHaveBeenLastCalledWith({ isTouchDragging: false })
setStateSpy.mockRestore()
updateDraftSpy.mockRestore()
endSelectionSpy.mockRestore()
done()
}
)
})
})
it('handles single-touch-tap events correctly', done => {
// Set touch dragging to true and make sure updateDraftSpy doesn't get called
component.setState(
{
isTouchDragging: true
},
() => {
component.instance().handleTouchEndEvent()
expect(updateDraftSpy).not.toHaveBeenCalled()
expect(endSelectionSpy).toHaveBeenCalled()
expect(setStateSpy).toHaveBeenLastCalledWith({ isTouchDragging: false })
setStateSpy.mockRestore()
updateDraftSpy.mockRestore()
endSelectionSpy.mockRestore()
done()
describe('preventScroll', () => {
it('prevents the event default', () => {
const event = {
preventDefault: jest.fn()
}
)
preventScroll(event)
expect(event.preventDefault).toHaveBeenCalled()
})
})
})
describe('preventScroll', () => {
it('prevents the event default', () => {
const event = {
preventDefault: jest.fn()
}
preventScroll(event)
expect(event.preventDefault).toHaveBeenCalled()
describe('minute-level resolution', () => {
it('splits hours using the hourlyChunks prop', () => {
// 15-minute resolution
const component = shallow(<ScheduleSelector minTime={1} maxTime={2} hourlyChunks={4} />)
expect(component.find('ScheduleSelector__TimeLabelCell')).toHaveLength(4)
// 5-minute resolution
const componentTwo = shallow(<ScheduleSelector minTime={1} maxTime={2} hourlyChunks={12} />)
expect(componentTwo.find('ScheduleSelector__TimeLabelCell')).toHaveLength(12)
})
it('formats the time column using the timeFormat prop', () => {
// 15-minute resolution
const component = shallow(<ScheduleSelector minTime={1} maxTime={2} timeFormat="h:mma" hourlyChunks={4} />)
expect(
component
.find('ScheduleSelector__TimeLabelCell')
.at(1)
.render()
.text()
).toEqual('1:15am')
// 5-minute resolution
const componentTwo = shallow(<ScheduleSelector minTime={1} maxTime={2} timeFormat="h:mma" hourlyChunks={12} />)
expect(
componentTwo
.find('ScheduleSelector__TimeLabelCell')
.at(1)
.render()
.text()
).toEqual('1:05am')
})
})
})

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet