@@ -1335,11 +1260,10 @@ Please refer to [examples](https://github.com/namespace-ee/react-calendar-timeli
The library supports right sidebar.

-To use it, you need to add two props to the `
` component:
+To use it, you need to add a props to the `
` component:
```jsx
rightSidebarWidth={150}
-rightSidebarContent={
Second filter
}
```
And add `rightTitle` prop to the groups objects:
@@ -1352,33 +1276,12 @@ And add `rightTitle` prop to the groups objects:
}
```
-## The timeline header doesn't fix to the top of the container when I scroll down.
-
-There are two causes of this:
-
-* you are passing `stickyHeader={false}` to the timeline component. The header by default has sticky behavior unless you tell it not to using this prop.
-* the browser you are viewing the timeline in doesn't support `position: sticky`. In this scenario, you will need to polyfill this behavior using the `headerRef`.
-
-In this example, we use [stickyfill](https://github.com/wilddeer/stickyfill) as our sticky polyfill
-
-```jsx
-// add a handler in your parent component that accepts a DOM element
-// with this element, pass the element into a polyfill library
-
-handleHeaderRef = (el) => {
- // polyfill dom element with stickyfill
- Stickyfill.addOne(el)
-}
+If you are using Custom Headers then you need to add `SidebarHeader` component under `TimelineHeader` with variant `right`
-// in render, pass this handler to the `headerRef` prop:
+## The timeline header doesn't fix to the top of the container when I scroll down.
-render() {
-
-}
```
## I'm using Babel with Rollup or Webpack 2+ and I'm getting strange bugs with click events
diff --git a/__fixtures__/stateAndProps.js b/__fixtures__/stateAndProps.js
index 6427947ec..69c4690d9 100644
--- a/__fixtures__/stateAndProps.js
+++ b/__fixtures__/stateAndProps.js
@@ -1,10 +1,16 @@
import { defaultKeys } from 'lib/default-config'
import {items} from './itemsAndGroups'
+
+export const visibleTimeStart = 1540501200000
+export const visibleTimeEnd = 1540587600000
+
export const props = {
keys: defaultKeys,
lineHeight: 30,
stackItems: 'space',
- itemHeightRatio: 0.75
+ itemHeightRatio: 0.75,
+ visibleTimeEnd,
+ visibleTimeStart,
}
export const propsNoStack = {
@@ -12,8 +18,6 @@ export const propsNoStack = {
stackItems: false,
}
-export const visibleTimeStart = 1540501200000
-export const visibleTimeEnd = 1540587600000
export const state = {
draggingItem: undefined,
diff --git a/__tests__/components/Headers/CustomHeader.test.js b/__tests__/components/Headers/CustomHeader.test.js
index 06883ce1f..34779bb93 100644
--- a/__tests__/components/Headers/CustomHeader.test.js
+++ b/__tests__/components/Headers/CustomHeader.test.js
@@ -5,238 +5,367 @@ import DateHeader from 'lib/headers/DateHeader'
import SidebarHeader from 'lib/headers/SidebarHeader'
import TimelineHeaders from 'lib/headers/TimelineHeaders'
import CustomHeader from 'lib/headers/CustomHeader'
+import { RenderHeadersWrapper } from '../../test-utility/header-renderer'
+import { getCustomHeadersInTimeline } from '../../test-utility/headerRenderers'
+import { parsePxToNumbers } from '../../test-utility/index'
import 'jest-dom/extend-expect'
import moment from 'moment'
-import { items, groups } from '../../../__fixtures__/itemsAndGroups'
-import { visibleTimeEnd, visibleTimeStart } from '../../../__fixtures__/stateAndProps'
+describe('CustomHeader Component Test', () => {
+ afterEach(cleanup)
-const defaultProps = {
- groups,
- items,
- defaultTimeStart: moment(visibleTimeStart, 'x'),
- defaultTimeEnd: moment(visibleTimeEnd, 'x'),
-}
+ it('Given CustomHeader When pass a unit to it Then header should render that unit', () => {
+ const { getAllByTestId } = render(
+ getCustomHeadersInTimeline({
+ unit: 'month',
+ timelineState: {
+ timelineUnit: 'month',
+ canvasTimeStart: moment.utc('1/6/2018', 'DD/MM/YYYY').valueOf(),
+ canvasTimeEnd: moment.utc('1/6/2020', 'DD/MM/YYYY').valueOf(),
+ visibleTimeStart: moment.utc('1/1/2019', 'DD/MM/YYYY').valueOf(),
+ visibleTimeEnd: moment.utc('1/1/2020', 'DD/MM/YYYY').valueOf()
+ }
+ })
+ )
+ const intervals = getAllByTestId('customHeaderInterval')
+ const start = moment(intervals[0].textContent, 'DD/MM/YYYY')
+ const end = moment(intervals[1].textContent, 'DD/MM/YYYY')
+ expect(end.diff(start, 'M')).toBe(1)
+ })
+ it('Given CustomHeader When pass a style props with (width, position) Then it should not override the default values', () => {
+ const { getByTestId } = render(
+ getCustomHeadersInTimeline({
+ props: { style: { width: 0, position: 'fixed' } }
+ })
+ )
+ const { width, position } = getComputedStyle(getByTestId('customHeader'))
+ expect(width).not.toBe('0px')
+ expect(position).not.toBe('fixed')
+ })
-describe('CustomHeader Component Test', () => {
-
- afterEach(cleanup)
- // Render The Example In The Docs
- it('Given CustomHeader When render Then it should renderd Correctly in the timeline', () => {
- const { getByTestId } = render(
-
-
-
- {({ getRootProps }) => {
- return Left
- }}
-
-
-
-
- {({
- headerContext: { intervals },
- getRootProps,
- getIntervalProps,
- showPeriod
- }) => {
- return (
-
- {intervals.map(interval => {
- const intervalStyle = {
- // height: 30,
- lineHeight: '30px',
- textAlign: 'center',
- borderLeft: '1px solid black',
- cursor: 'pointer',
- backgroundColor: 'Turquoise',
- color: 'white'
- }
- return (
-
{
- showPeriod(interval.startTime, interval.endTime)
- }}
- {...getIntervalProps({
- interval,
- style: intervalStyle
- })}
- >
-
- {interval.startTime.format('YYYY')}
-
-
- )
- })}
-
- )
- }}
-
-
-
- )
+ it('Given CustomHeader When pass a style props other than (width, position) Then it should rendered Correctly', () => {
+ const { getByTestId } = render(
+ getCustomHeadersInTimeline({ props: { style: { color: 'white' } } })
+ )
+ const { color } = getComputedStyle(getByTestId('customHeader'))
+ expect(color).toBe('white')
+ })
- expect(getByTestId('customHeader')).toBeInTheDocument()
- })
- it('Given CustomHeader When pass a unit to it Then it should take it', () => {
- const { getByTestId, rerender } = render(getCustomHeadersInTimeline({ unit: "year" }));
- expect(getByTestId('customHeader')).toHaveTextContent('01/01/2018')
+ it('Given CustomHeader When pass an interval style with (width, position and left) Then it should not override the default values', () => {
+ const { getByTestId } = render(
+ getCustomHeadersInTimeline({
+ intervalStyle: {
+ width: 0,
+ position: 'fixed',
+ left: 1222222
+ }
+ })
+ )
+ const { width, position, left } = getComputedStyle(
+ getByTestId('customHeaderInterval')
+ )
+ expect(width).not.toBe('0px')
+ expect(position).not.toBe('fixed')
+ expect(left).not.toBe('1222222px')
+ })
+ it('Given CustomHeader When pass an interval style other than (width, position and left) Then it should rendered correctly', () => {
+ const { getByTestId } = render(
+ getCustomHeadersInTimeline({
+ intervalStyle: {
+ lineHeight: '30px',
+ textAlign: 'center',
+ borderLeft: '1px solid black',
+ cursor: 'pointer',
+ color: 'white'
+ }
+ })
+ )
+ const {
+ lineHeight,
+ textAlign,
+ borderLeft,
+ cursor,
+ color
+ } = getComputedStyle(getByTestId('customHeaderInterval'))
+ expect(lineHeight).toBe('30px')
+ expect(textAlign).toBe('center')
+ expect(borderLeft).toBe('1px solid black')
+ expect(cursor).toBe('pointer')
+ expect(color).toBe('white')
+ })
- rerender(getCustomHeadersInTimeline({ unit: "month" }));
- expect(getByTestId('customHeader')).toHaveTextContent('10/01/2018')
+ it('Given a CustomHeader When not pass any unit prop Then it Should take the default timeline unit', () => {
+ const { getAllByTestId } = render(
+ getCustomHeadersInTimeline({
+ timelineState: {
+ //default unit we are testing
+ timelineUnit: 'month',
+ canvasTimeStart: moment.utc('1/6/2018', 'DD/MM/YYYY').valueOf(),
+ canvasTimeEnd: moment.utc('1/6/2020', 'DD/MM/YYYY').valueOf(),
+ visibleTimeStart: moment.utc('1/1/2019', 'DD/MM/YYYY').valueOf(),
+ visibleTimeEnd: moment.utc('1/1/2020', 'DD/MM/YYYY').valueOf()
+ }
+ })
+ )
+ const intervals = getAllByTestId('customHeaderInterval')
+ const start = moment(intervals[0].textContent, 'DD/MM/YYYY')
+ const end = moment(intervals[1].textContent, 'DD/MM/YYYY')
+ expect(end.diff(start, 'M')).toBe(1)
+ })
- rerender(getCustomHeadersInTimeline({ unit: "day" }));
- expect(getByTestId('customHeader')).toHaveTextContent('10/25/2018')
- expect(getByTestId('customHeader')).toHaveTextContent('10/26/2018')
- expect(getByTestId('customHeader')).toHaveTextContent('10/27/2018')
- })
- it('Given CustomHeader When pass a style props with (width, position) Then it should not ovverride the default values', () => {
- const { getByTestId } = render(getCustomHeadersInTimeline({ props: { style: { width: 0, position: 'fixed' } } }));
- const { width, position } = getComputedStyle(getByTestId('customHeader'))
- expect(width).not.toBe('0px')
- expect(position).not.toBe('fixed')
+ it("Given CustomHeader When rendered Then intervals don't overlap in position", () => {
+ const { getAllByTestId } = render(getCustomHeadersInTimeline())
+ const intervals = getAllByTestId('customHeaderInterval')
+ const intervalsCoordinations = intervals.map(interval => {
+ const { left, width } = getComputedStyle(interval)
+ return {
+ left: parsePxToNumbers(left),
+ right: parsePxToNumbers(left) + parsePxToNumbers(width)
+ }
})
+ for (let index = 0; index < intervalsCoordinations.length - 1; index++) {
+ const a = intervalsCoordinations[index]
+ const b = intervalsCoordinations[index + 1]
+ expect(Math.abs(a.right - b.left)).toBeLessThan(0.1)
+ }
+ })
- it('Given CustomHeader When pass a style props other than (width, position) Then it should renderd Correctly', () => {
- const { getByTestId } = render(getCustomHeadersInTimeline({ props: { style: { height: 150 } } }));
- const { height } = getComputedStyle(getByTestId('customHeader'))
- expect(height).toBe("150px")
+ it('Given CustomHeader When passing child renderer Then showPeriod should be passed', () => {
+ const showPeriod = () => {}
+ const renderer = jest.fn(() => {
+ return
header
})
+ render(
+
+
+ {renderer}
+
+
+ )
+ expect(renderer.mock.calls[0][0].showPeriod).toBe(showPeriod)
+ })
- it('Given CustomHeader When pass an interval style with (width, position, left) Then it should not ovverride the default values', () => {
- const { getByTestId } = render(getCustomHeadersInTimeline({
- intervalStyle: {
- width: 0,
- position: 'fixed',
- left: 0
- }
- }));
- const { width, position, left } = getComputedStyle(getByTestId('customHeaderInterval'))
- expect(width).not.toBe('0px')
- expect(position).not.toBe('fixed')
- expect(left).not.toBe('0px')
+ it('Given CustomHeader When passing child renderer Then headerContext should be passed', () => {
+ const renderer = jest.fn(() => {
+ return
header
})
- it('Given CustomHeader When pass an interval style other than (width, position) Then it should rendered correctly', () => {
- const { getByTestId } = render(getCustomHeadersInTimeline({
- intervalStyle: {
- lineHeight: '30px',
- textAlign: 'center',
- borderLeft: '1px solid black',
- cursor: 'pointer',
- color: 'white'
- }
- }));
- const { lineHeight, textAlign, borderLeft, cursor, color } = getComputedStyle(getByTestId('customHeaderInterval'))
- expect(lineHeight).toBe('30px')
- expect(textAlign).toBe('center')
- expect(borderLeft).toBe('1px solid black')
- expect(cursor).toBe('pointer')
- expect(color).toBe('white')
+ render(
+
+
+ {renderer}
+
+
+ )
+ const headerContext = renderer.mock.calls[0][0].headerContext
+ expect(headerContext).toBeDefined()
+ })
+
+ it('Given CustomHeader When passing child renderer Then headerContext should be passed with intervals and unit', () => {
+ const renderer = jest.fn(() => {
+ return
header
})
- it('Given a CustomHeader When pass a jsx as a children Then it Should be rendered Correctly', () => {
- const { getByText } = render(getCustomHeadersInTimeline())
- expect(getByText('Should Be Rendered')).toBeInTheDocument()
+ render(
+
+
+ {renderer}
+
+
+ )
+ const headerContext = renderer.mock.calls[0][0].headerContext
+ const intervals = headerContext.intervals
+ const unit = headerContext.unit
+ expect(intervals).toBeDefined()
+ expect(intervals).toEqual(
+ expect.arrayContaining([
+ expect.objectContaining({
+ startTime: expect.any(moment),
+ endTime: expect.any(moment),
+ labelWidth: expect.any(Number),
+ left: expect.any(Number)
+ })
+ ])
+ )
+ expect(unit).toEqual(expect.any(String))
+ })
+
+ it('Given CustomHeader When passing child renderer Then timelineContext should be passed', () => {
+ const renderer = jest.fn(() => {
+ return
header
})
- it('Given a CustomHeader When not pass any unit prop Then it Should take the default timeline unit (year)', () => {
- const { getByTestId } = render(getCustomHeadersInTimeline())
- expect(getByTestId('customHeader')).toHaveTextContent('01/01/2018')
+ render(
+
+
+ {renderer}
+
+
+ )
+ const timelineContext = renderer.mock.calls[0][0].timelineContext
+ expect(timelineContext).toBeDefined()
+ expect(timelineContext).toMatchObject({
+ timelineWidth: expect.any(Number),
+ visibleTimeStart: expect.any(Number),
+ visibleTimeEnd: expect.any(Number),
+ canvasTimeStart: expect.any(Number),
+ canvasTimeEnd: expect.any(Number)
})
- it('Given DateHeader When Rendered with day unit Then getIntervalStyle function shuold be act correctly', () => {
- const props = getIntervalStyle({ startTime: moment("2018-10-27T21:00:00.000"), canvasTimeStart: 1540414800000, ratio: 0.5, unit: 'month', labelWidth: 150 })
- expect(props).toEqual({
- left: 124200000,
- width: 150,
- position: 'absolute'
- })
+ })
+
+ describe('CustomHeader Intervals', () => {
+ it('Given intervals Then they should have the same width', () => {
+ const renderer = jest.fn(() => {
+ return
header
+ })
+ render(
+
+
+ {renderer}
+
+
+ )
+
+ const headerContext = renderer.mock.calls[0][0].headerContext
+ const intervals = headerContext.intervals
+ const widths = intervals.map(interval => interval.labelWidth)
+ for (let index = 0; index < widths.length - 1; index++) {
+ const a = widths[index]
+ const b = widths[index + 1]
+
+ expect(Math.abs(b - a)).toBeLessThan(0.1)
+ }
})
- it('Given CustomHeader When pass a style in props obj to props renderer Then it should not override correctly render it', () => {
- const { getByTestId } = render(getCustomHeadersInTimeline({props: {'aria-hidden': false}}))
- expect(getByTestId('customHeader')).toHaveAttribute('aria-hidden')
+ it('Given intervals Then left property should be different', () => {
+ const renderer = jest.fn(() => {
+ return
header
+ })
+ render(
+
+
+ {renderer}
+
+
+ )
+ const headerContext = renderer.mock.calls[0][0].headerContext
+ const intervals = headerContext.intervals
+ const lefts = intervals.map(interval => interval.left)
+ for (let index = 0; index < lefts.length - 1; index++) {
+ const a = lefts[index]
+ const b = lefts[index + 1]
+ expect(a).toBeLessThan(b)
+ }
})
- describe('Testing Diffrent Unit Values', () => {
- it('Given CustomHeader When pass a year unit then it should render it correctly', () => {
- const { getByTestId } = render(getCustomHeadersInTimeline({ unit: 'year' }));
- expect(getByTestId('customHeader')).toHaveTextContent('01/01/2018')
- })
- it('Given CustomHeader When pass a month unit then it should render it correctly', () => {
- const { getByTestId } = render(getCustomHeadersInTimeline({ unit: 'month' }));
- expect(getByTestId('customHeader')).toHaveTextContent('10/01/2018')
- })
- it('Given CustomHeader When pass a day unit then it should render it correctly', () => {
- const { getByTestId } = render(getCustomHeadersInTimeline({ unit: 'day' }));
- expect(getByTestId('customHeader')).toHaveTextContent('10/25/2018')
- })
- it('Given CustomHeader When pass a hour unit then it should render it correctly', () => {
- const { getByTestId } = render(getCustomHeadersInTimeline({ unit: 'hour' }));
- expect(getByTestId('customHeader')).toHaveTextContent('10/25/2018')
- })
+ })
+
+ it('Given CustomHeader When passing extra props Then it will be passed to the renderProp', () => {
+ const renderer = jest.fn(() => {
+ return
header
})
-
-})
+ const props = {
+ data: 'some'
+ }
+ render(
+
+
+ {renderer}
+
+
+ )
+ expect(renderer.mock.calls[0][0].data).toBe(props)
+ })
+ // Render The Example In The Docs
+ it('Given CustomHeader When render Then it should render Correctly in the timeline', () => {
+ const { getByTestId } = render(
+
+
+
+ {({ getRootProps }) => {
+ return Left
+ }}
+
+
+
+
+ {({
+ headerContext: { intervals },
+ getRootProps,
+ getIntervalProps,
+ showPeriod
+ }) => {
+ return (
+
+ {intervals.map(interval => {
+ const intervalStyle = {
+ // height: 30,
+ lineHeight: '30px',
+ textAlign: 'center',
+ borderLeft: '1px solid black',
+ cursor: 'pointer',
+ backgroundColor: 'Turquoise',
+ color: 'white'
+ }
+ return (
+
{
+ showPeriod(interval.startTime, interval.endTime)
+ }}
+ {...getIntervalProps({
+ interval,
+ style: intervalStyle
+ })}
+ >
+
+ {interval.startTime.format('YYYY')}
+
+
+ )
+ })}
+
+ )
+ }}
+
+
+
+ )
+
+ expect(getByTestId('customHeader')).toBeInTheDocument()
+ })
+ it('Given Custom Header When passing react stateless component to render prop Then it should render', () => {
+ const Renderer = props => {
+ return
header
+ }
-function getCustomHeadersInTimeline({ unit = "year", props, intervalStyle } = {}) {
-
- return (
-
-
-
- {({ getRootProps }) => {
- return Left
- }}
-
-
-
-
- {({
- headerContext: { intervals },
- getRootProps,
- getIntervalProps,
- showPeriod
- }, extraProps) => {
- return (
-
- {intervals.map(interval => {
- return (
-
{
- showPeriod(interval.startTime, interval.endTime)
- }}
- {...getIntervalProps({
- interval,
- style: intervalStyle
- })}
- >
-
- {interval.startTime.format('MM/DD/YYYY')}
-
-
- )
- })}
-
- Should Be Rendered
-
-
-
- )
- }}
-
-
-
- )
-}
-
-
-const getIntervalStyle = ({ startTime, canvasTimeStart, ratio, unit, labelWidth, style }) => {
- const left = Math.round((startTime.valueOf() - canvasTimeStart) * ratio)
- const unitValue = startTime.get(unit === 'day' ? 'date' : unit)
- const firstOfType = unitValue === (unit === 'day' ? 1 : 0)
- const leftCorrect = firstOfType ? 1 : 0
- return {
- ...style,
- left: left - leftCorrect,
- width: labelWidth,
- position: 'absolute'
+ const { getByText } = render(
+
+
+ {Renderer}
+
+
+ )
+ expect(getByText('header')).toBeInTheDocument()
+ })
+
+ it('Given Custom Header When passing react component to render prop Then it should render', () => {
+ class Renderer extends React.Component {
+ render() {
+ return
header
+ }
}
-}
+
+ const { getByText } = render(
+
+
+ {Renderer}
+
+
+ )
+ expect(getByText('header')).toBeInTheDocument()
+ })
+})
diff --git a/__tests__/components/Headers/DateHeader.test.js b/__tests__/components/Headers/DateHeader.test.js
index 857d2dbf0..460908629 100644
--- a/__tests__/components/Headers/DateHeader.test.js
+++ b/__tests__/components/Headers/DateHeader.test.js
@@ -1,309 +1,434 @@
import React from 'react'
-import { render, cleanup, within } from 'react-testing-library'
+import { render, cleanup, within, fireEvent } from 'react-testing-library'
import Timeline from 'lib/Timeline'
import DateHeader from 'lib/headers/DateHeader'
import SidebarHeader from 'lib/headers/SidebarHeader'
import TimelineHeaders from 'lib/headers/TimelineHeaders'
import 'jest-dom/extend-expect'
+import { RenderHeadersWrapper } from '../../test-utility/header-renderer'
import moment from 'moment'
-import { items, groups } from '../../../__fixtures__/itemsAndGroups'
-import { visibleTimeEnd, visibleTimeStart } from '../../../__fixtures__/stateAndProps'
-import { TimelineStateProvider } from 'lib/timeline/TimelineStateContext'
-import { TimelineHeadersProvider } from 'lib/headers/HeadersContext'
-const defaultProps = {
- groups,
- items,
- defaultTimeStart: moment(visibleTimeStart, 'x'),
- defaultTimeEnd: moment(visibleTimeEnd, 'x'),
-}
-
-describe("Testing DateHeader Component", () => {
- beforeEach(() => {
- Element.prototype.getBoundingClientRect = jest.fn(() => {
- return {
- width: 1000,
- height: 120,
- top: 0,
- left: 0,
- bottom: 0,
- right: 0,
- }
- });
- })
+describe('Testing DateHeader Component', () => {
afterEach(cleanup)
+ const format = 'MM/DD/YYYY hh:mm a'
+
// Testing The Example In The Docs
- it("Given DateHeader When rendered Then it should be rendered correctly in the timeLine", () => {
+ it('Given DateHeader When rendered Then it should be rendered correctly in the timeLine', () => {
const { getAllByTestId } = render(
-
+
{({ getRootProps }) => {
return Left
}}
-
+
{
- return
- {intervalContext.intervalText}
-
+ return (
+
+ {intervalContext.intervalText}
+
+ )
}}
/>
-
+
)
expect(getAllByTestId('dateHeader')).toHaveLength(3)
-
})
- it("Given Dateheader When pass a string typed labelFormat Then it should render the intervals with hte given format", () => {
- const { getAllByTestId } = render(dateHeaderComponent({ unit: "day", labelFormat: "MM/DD" }));
- expect(getAllByTestId('dateHeader')[1]).toHaveTextContent('10/25')
- expect(getAllByTestId('dateHeader')[1]).toHaveTextContent('10/26')
- expect(getAllByTestId('dateHeader')[1]).toHaveTextContent('10/27')
- expect(getAllByTestId('dateHeader')[0]).toHaveTextContent('Thursday, October 25')
+ describe('DateHeader labelFormat', () => {
+ afterEach(cleanup)
- })
+ it('Given Dateheader When pass a string typed labelFormat Then it should render the intervals with the given format', () => {
+ const { getAllByTestId } = render(
+ dateHeaderComponent({ unit: 'day', labelFormat: 'MM/DD' })
+ )
+ expect(getAllByTestId('dateHeader')[1]).toHaveTextContent('10/25')
+ expect(getAllByTestId('dateHeader')[1]).toHaveTextContent('10/26')
+ expect(getAllByTestId('dateHeader')[1]).toHaveTextContent('10/27')
+ })
- it("Given Dateheader When pass an object typed labelFormat Then it should render the intervals with hte given format", () => {
- const { getAllByTestId } = render(dateHeaderComponent({ unit: "day", labelFormat: { day: { long: "MM/DD/YYYY" } } }));
+ it('Given Dateheader When pass a function typed labelFormat Then it should render the intervals with the given format', () => {
+ const formatlabel = jest.fn(interval => interval[0].format('MM/DD/YYYY'))
+ const { getAllByTestId } = render(
+ dateHeaderComponent({ unit: 'day', labelFormat: formatlabel })
+ )
- expect(getAllByTestId('dateHeader')[1]).toHaveTextContent('10/25/2018')
- expect(getAllByTestId('dateHeader')[1]).toHaveTextContent('10/26/2018')
- expect(getAllByTestId('dateHeader')[1]).toHaveTextContent('10/27/2018')
- expect(getAllByTestId('dateHeader')[0]).toHaveTextContent('Thursday, October 25')
- })
- it("Given Dateheader When pass a function typed labelFormat Then it should render the intervals with hte given format", () => {
- const formatlabel = jest.fn((interval, unit, labelWidth) => interval[0].format("MM/DD/YYYY"))
- const { getAllByTestId } = render(dateHeaderComponent({ unit: "day", labelFormat: formatlabel }));
+ expect(formatlabel).toHaveBeenCalled()
- expect(formatlabel).toHaveBeenCalled()
-
- expect(getAllByTestId('dateHeader')[1]).toHaveTextContent('10/25/2018')
- expect(getAllByTestId('dateHeader')[1]).toHaveTextContent('10/26/2018')
- expect(getAllByTestId('dateHeader')[1]).toHaveTextContent('10/27/2018')
+ expect(getAllByTestId('dateHeader')[1]).toHaveTextContent('10/25/2018')
+ expect(getAllByTestId('dateHeader')[1]).toHaveTextContent('10/26/2018')
+ expect(getAllByTestId('dateHeader')[1]).toHaveTextContent('10/27/2018')
+ })
- expect(getAllByTestId('dateHeader')[0]).toHaveTextContent('Thursday, October 25')
+ it('Given Dateheader When pass a function typed labelFormat Then it should be called with an interval, label width and unit', () => {
+ const formatlabel = jest.fn(interval => interval[0].format('MM/DD/YYYY'))
+ render(dateHeaderComponent({ unit: 'day', labelFormat: formatlabel }))
- })
+ expect(formatlabel).toHaveBeenCalled()
- it("Given Dateheader When pass a string typed labelFormat Then it should be called with the right params", () => {
- const formatlabel = jest.fn((interval, unit, labelWidth) => interval[0].format("MM/DD/YYYY"))
- render(dateHeaderComponent({ unit: "day", labelFormat: formatlabel }))
- expect(formatlabel).toHaveBeenCalled()
- expect(formatlabel).toHaveBeenCalledWith(expect.any(Array), "day", expect.any(Number))
+ formatlabel.mock.calls.forEach(param => {
+ const [[start, end], unit, labelWidth] = param
+ expect(moment.isMoment(start)).toBeTruthy()
+ expect(moment.isMoment(end)).toBeTruthy()
+ expect(end.diff(start, 'd')).toBe(1)
+ expect(unit).toBe('day')
+ expect(labelWidth).toEqual(expect.any(Number))
+ })
+ })
})
-
-
- it("Given Dateheader When click on the primary header Then it should change the unit", async () => {
-
- const formatlabel = jest.fn((interval, unit, labelWidth) => interval[0].format("MM/DD/YYYY"))
- const { getByTestId, getAllByTestId } = render(dateHeaderComponent({ unit: "day", labelFormat: formatlabel }));
+ it('Given Dateheader When click on the primary header Then it should change the unit', async () => {
+ const formatlabel = jest.fn(interval => interval[0].format('MM/DD/YYYY'))
+ const showPeriod = jest.fn()
+ const { getByTestId } = render(
+ dateHeaderComponent({ unit: 'day', labelFormat: formatlabel, showPeriod })
+ )
// Arrange
const primaryHeader = getByTestId('dateHeader')
- const seconderyHeader = getAllByTestId('dateHeader')[2]
// Act
- const primaryFirstClick = within(primaryHeader).getByText('Friday, October 26, 2018').parentElement
+ const primaryFirstClick = within(primaryHeader).getByText('2018')
+ .parentElement
primaryFirstClick.click()
- const primarySecondClick = within(primaryHeader).getByText('October 2018').parentElement
- primarySecondClick.click()
-
- // Assert
- expect(seconderyHeader).toHaveTextContent('January')
- expect(primaryHeader).toHaveTextContent('2018')
- })
-
- it("Given Dateheader When click on the secondary header Then it should change the unit", async () => {
-
- const formatlabel = jest.fn((interval, unit, labelWidth) => interval[0].format("MM/DD/YYYY"))
- const { getByTestId, getAllByTestId } = render(dateHeaderComponent({ unit: "day", labelFormat: formatlabel }));
- // Arrange
- const primaryHeader = getByTestId('dateHeader')
- const seconderyHeader = getAllByTestId('dateHeader')[2]
-
- const primaryFirstClick = within(primaryHeader).getByText('Friday, October 26, 2018').parentElement
- primaryFirstClick.click()
- const primarySecondClick = within(primaryHeader).getByText('October 2018').parentElement
-
- primarySecondClick.click()
-
- // Act
- const secondaryFirstClick = within(seconderyHeader).queryByText('January')
- secondaryFirstClick.click()
- expect(primaryHeader).toHaveTextContent('December 2016')
- const secondarySecondClick = within(seconderyHeader).queryByText('1')
- secondarySecondClick.click()
- expect(primaryHeader).toHaveTextContent('Wednesday, November 30, 2016')
- })
-
- it('Given DateHeadr When click on primary or secondary Then onTimeChange function should be called with the right params', () => {
- const handleTimeChange = jest.fn((visibleTimeStart, visibleTimeEnd, updateScrollCanvas) =>
- updateScrollCanvas(visibleTimeStart, visibleTimeEnd))
- const { getByTestId, getAllByTestId, debug } = render(dateHeaderComponent({ unit: "day", handleTimeChange: handleTimeChange }));
- const primaryHeader = within(getByTestId('dateHeader')).getByText('Friday, October 26, 2018').parentElement
- primaryHeader.click()
- const secondaryHeader = within(getAllByTestId('dateHeader')[1]).getByText('1').parentElement
- expect(handleTimeChange).toBeCalled()
- expect(handleTimeChange).toBeCalledTimes(1)
- expect(handleTimeChange).toBeCalledWith(expect.any(Number), expect.any(Number), expect.any(Function))
- expect(handleTimeChange).toReturn()
-
- secondaryHeader.click();
- expect(handleTimeChange).toBeCalled()
- expect(handleTimeChange).toBeCalledTimes(1)
- expect(handleTimeChange).toBeCalledWith(expect.any(Number), expect.any(Number), expect.any(Function))
- expect(handleTimeChange).toReturn()
+ expect(showPeriod).toBeCalled()
+ const [start, end] = showPeriod.mock.calls[0]
+ expect(start.format('DD/MM/YYYY hh:mm a')).toBe('01/01/2018 12:00 am')
+ expect(end.format('DD/MM/YYYY hh:mm a')).toBe('31/12/2018 11:59 pm')
})
it('Given Dateheader When pass a className Then it should be applied to DateHeader', () => {
- const { getAllByTestId } = render(dateHeaderComponent({ labelFormat: "MM/DD/YYYY", className: 'test-class-name' }));
+ const { getAllByTestId } = render(
+ dateHeaderComponent({
+ labelFormat: 'MM/DD/YYYY',
+ className: 'test-class-name'
+ })
+ )
expect(getAllByTestId('dateHeader')[1]).toHaveClass('test-class-name')
})
- it('Given Interval When pass an ovveride values for (width, left, position) it should not ovverride the default values', () => {
- const { getAllByTestId } = render(dateHeaderComponent({ labelFormat: "MM/DD/YYYY", props: { style: { width: 100, position: 'fixed' } } }));
- const { width, position } = getComputedStyle(getAllByTestId('interval')[0])
+ it('Given Interval When pass an override values for (width, left, position) it should not override the default values', () => {
+ const { getAllByTestId } = render(
+ dateHeaderComponent({
+ labelFormat: 'MM/DD/YYYY',
+ props: { style: { width: 100, position: 'fixed', left: 2342 } }
+ })
+ )
+ const { width, position, left } = getComputedStyle(
+ getAllByTestId('interval')[0]
+ )
expect(width).not.toBe('100px')
expect(position).not.toBe('fixed')
+ expect(left).not.toBe('2342px')
})
- it('Given Interval When pass an override (width, position) Then it should render the default values for it', () => {
- const { getAllByTestId } = render(dateHeaderComponent({ labelFormat: "MM/DD/YYYY", props: { style: { width: 100, position: 'fixed' } } }));
+ it('Given Interval When pass an override (width, position) Then it should ignore these values', () => {
+ const { getAllByTestId, debug } = render(
+ dateHeaderComponent({
+ labelFormat: 'MM/DD/YYYY',
+ props: { style: { width: 100, position: 'fixed' } }
+ })
+ )
const { width, position } = getComputedStyle(getAllByTestId('interval')[0])
- expect(width).toBe('36px')
+ expect(width).not.toBe('1000px')
expect(position).toBe('absolute')
-
-
})
it('Given Interval When pass any style other than (position, width, left) through the Dateheader Then it should take it', () => {
- const { getAllByTestId } = render(dateHeaderComponent({ labelFormat: "MM/DD/YYYY", props: { style: { display: 'flex' } } }));
+ const { getAllByTestId } = render(
+ dateHeaderComponent({
+ labelFormat: 'MM/DD/YYYY',
+ props: { style: { display: 'flex' } }
+ })
+ )
const { display } = getComputedStyle(getAllByTestId('interval')[0])
expect(display).toBe('flex')
-
- })
- it('Given unit Dateheader When pass a style Object Then it should render the given style correctly', () => {
- const { getAllByTestId } = render(dateHeaderComponent({ style: { height: 50 }, labelFormat: "MM/DD/YYYY" }));
- const { height } = getComputedStyle(getAllByTestId('dateHeader')[1])
-
- expect(height).toBe('50px')
})
it('Given DateHeader component When pass an intervalRenderer prop then it should be called with the right params', () => {
- const intervalRenderer = jest.fn(({ getIntervalProps, intervalContext }, props) =>
{intervalContext.intervalText}
)
- const { getByTestId, rerender } = render(dateHeaderWithIntervalRenderer({ intervalRenderer: intervalRenderer }))
+ const intervalRenderer = jest.fn(
+ ({ getIntervalProps, intervalContext, data }) => (
+
+ {intervalContext.intervalText}
+
+ )
+ )
+ const props = {
+ title: 'some title'
+ }
+ render(
+ dateHeaderWithIntervalRenderer({
+ intervalRenderer: intervalRenderer,
+ props
+ })
+ )
const bluePrint = {
getIntervalProps: expect.any(Function),
intervalContext: expect.any(Object)
}
expect(intervalRenderer).toBeCalled()
expect(intervalRenderer).toReturn()
- // because we did not pass a props then the function will called with undefined props
- expect(intervalRenderer).toBeCalledWith(expect.objectContaining(bluePrint), undefined)
- rerender(dateHeaderWithIntervalRenderer({ intervalRenderer: intervalRenderer, props: { style: { height: 50 } } }))
- expect(intervalRenderer).toBeCalledWith(expect.objectContaining(bluePrint), expect.any(Object))
- expect(getByTestId('myAwesomeInterval')).toBeInTheDocument()
+ expect(intervalRenderer.mock.calls[0][0].data).toBe(props)
+ expect(intervalRenderer.mock.calls[0][0].getIntervalProps).toEqual(
+ expect.any(Function)
+ )
+ expect(intervalRenderer.mock.calls[0][0].intervalContext).toEqual(
+ expect.any(Object)
+ )
})
- describe('Testing The Label Format Diffrent Cases', () => {
- it('Given DateHeader When resize the width of the screen to 1000 Then it Should take the long format', () => {
- Element.prototype.getBoundingClientRect = jest.fn(() => ({ width: 1000 }));
- const { getAllByTestId, rerender } = render(dateHeaderComponent({
- unit: "day", labelFormat: {
- day: { short: "DD", medium: "DD/MM", mediumLong: "MM/YYYY", long: "MM/DD/YYYY", }
- }
- }));
- expect(getAllByTestId('dateHeader')[1]).toHaveTextContent('10/26/2018')
+
+ describe('DateHeader Unit Values', () => {
+ it('Given DateHeader When not passing a unit then the date header unit should be same as timeline unit', () => {
+ const { getAllByTestId } = render(
+
+
+ interval[0].format(format)} />
+
+
+ )
+ const intervals = getAllByTestId('dateHeaderInterval').map(
+ interval => interval.textContent
+ )
+ for (let index = 0; index < intervals.length - 1; index++) {
+ const a = intervals[index]
+ const b = intervals[index + 1]
+
+ const timeStampA = moment(a, format)
+ const timeStampB = moment(b, format)
+ const diff = timeStampB.diff(timeStampA, 'day')
+ expect(diff).toBe(1)
+ }
+ })
+ it('Given DateHeader When passing a unit then the date header unit should be same as unit passed', () => {
+ const { getAllByTestId } = render(
+
+
+ interval[0].format(format)}
+ />
+
+
+ )
+ const intervals = getAllByTestId('dateHeaderInterval').map(
+ interval => interval.textContent
+ )
+ for (let index = 0; index < intervals.length - 1; index++) {
+ const a = intervals[index]
+ const b = intervals[index + 1]
+
+ const timeStampA = moment(a, format)
+ const timeStampB = moment(b, format)
+ const diff = timeStampB.diff(timeStampA, 'day')
+ expect(diff).toBe(1)
+ }
+ })
+
+ it('Given DateHeader When passing primaryHeader Then the header unit should be bigger the timeline unit', () => {
+ const { getAllByTestId } = render(
+
+
+ interval[0].format(format)}
+ />
+
+
+ )
+ const intervals = getAllByTestId('dateHeaderInterval').map(
+ interval => interval.textContent
+ )
+ for (let index = 0; index < intervals.length - 1; index++) {
+ const a = intervals[index]
+ const b = intervals[index + 1]
+
+ const timeStampA = moment(a, format)
+ const timeStampB = moment(b, format)
+ const diff = timeStampB.diff(timeStampA, 'month')
+ expect(diff).toBe(1)
+ }
+ })
+
+ it('Given DateHeader When not passing unit Then the header unit should be same as the timeline unit', () => {
+ const { getAllByTestId } = render(
+
+
+ interval[0].format(format)} />
+
+
+ )
+ const intervals = getAllByTestId('dateHeaderInterval').map(
+ interval => interval.textContent
+ )
+ for (let index = 0; index < intervals.length - 1; index++) {
+ const a = intervals[index]
+ const b = intervals[index + 1]
+
+ const timeStampA = moment(a, format)
+ const timeStampB = moment(b, format)
+ const diff = timeStampB.diff(timeStampA, 'day')
+ expect(diff).toBe(1)
+ }
})
+ })
- it('Given DateHeader When resize the width of the screen to 250 Then it Should take the mediumLong format', () => {
- Element.prototype.getBoundingClientRect = jest.fn(() => ({ width: 250 }));
- const { getAllByTestId } = render(dateHeaderComponent({
- unit: "day", labelFormat: {
- day: { short: "DD", medium: "DD/MM", mediumLong: "MM/YYYY", long: "MM/DD/YYYY", }
- }
- }));
- expect(getAllByTestId('dateHeader')[1]).toHaveTextContent('10/2018')
- expect(getAllByTestId('dateHeader')[1]).toHaveTextContent('10/2018')
- expect(getAllByTestId('dateHeader')[1]).toHaveTextContent('10/2018')
+ describe('DateHeader Interval', () => {
+ it('Given DateHeader Interval When passing on click event to the prop getter Then it should trigger', () => {
+ const onClick = jest.fn()
+ const { getAllByTestId } = render(
+
+
+ {
+ return (
+
+ {intervalContext.intervalText}
+
+ )
+ }}
+ />
+
+
+ )
+ const intervals = getAllByTestId('interval')
+ fireEvent.click(intervals[0])
+ expect(onClick).toHaveBeenCalled()
})
- it('Given DateHeader When resize the width of the screen to 200 Then it Should take the medium format', () => {
- Element.prototype.getBoundingClientRect = jest.fn(() => ({ width: 200 }));
- const { getAllByTestId } = render(dateHeaderComponent({
- unit: "day", labelFormat: {
- day: { short: "DD", medium: "DD/MM", mediumLong: "MM/YYYY", long: "MM/DD/YYYY", }
- }
- }));
- expect(getAllByTestId('dateHeader')[1]).toHaveTextContent('25/10')
- expect(getAllByTestId('dateHeader')[1]).toHaveTextContent('26/10')
- expect(getAllByTestId('dateHeader')[1]).toHaveTextContent('27/10')
+ it('Given DateHeader When passing interval renderer Then it should be rendered', () => {
+ const { getByTestId } = render(
+
+
+ {
+ return (
+
+ {intervalContext.intervalText}
+
+ )
+ }}
+ />
+
+
+ )
+ expect(getByTestId('interval')).toBeInTheDocument()
})
- it('Given DateHeader When resize the width of the screen to 100 Then it Should take the short format', () => {
- Element.prototype.getBoundingClientRect = jest.fn(() => ({ width: 100 }));
- const { getAllByTestId } = render(dateHeaderComponent({
- unit: "day", labelFormat: {
- day: { short: "DD", medium: "DD/MM", mediumLong: "MM/YYYY", long: "MM/DD/YYYY", }
- }
- }));
- expect(getAllByTestId('dateHeader')[1]).toHaveTextContent('26')
+ it("Given DateHeader When passing interval renderer Then it should called with interval's context", () => {
+ const renderer = jest.fn(({ getIntervalProps, intervalContext }) => {
+ return (
+
+ {intervalContext.intervalText}
+
+ )
+ })
+ render(
+
+
+
+
+
+ )
+ expect(renderer.mock.calls[0][0].intervalContext).toEqual(
+ expect.objectContaining({
+ interval: expect.objectContaining({
+ startTime: expect.any(moment),
+ endTime: expect.any(moment),
+ labelWidth: expect.any(Number),
+ left: expect.any(Number)
+ }),
+ intervalText: expect.any(String)
+ })
+ )
})
})
+ it('Given DateHeader When passing a stateless react component to interval renderer Then it should render', () => {
+ const Renderer = ({ getIntervalProps, intervalContext }) => {
+ return (
+
+ {intervalContext.intervalText}
+
+ )
+ }
+ const { getByTestId } = render(
+
+
+
+ {({ getRootProps }) => {
+ return Left
+ }}
+
+
+
+
+
+
+ )
- describe('Testing Diffrent Unit Values', () => {
- it('Given DateHeader When pass a year unit to the timeline then it should take it as default', () => {
- const children =
- const {getAllByTestId} = renderDateHeaderWithContext({unit: 'year', children: children});
- const primaryHeader = getAllByTestId('dateHeader')[0]
- const secondaryHeader = getAllByTestId('dateHeader')[1]
- expect(primaryHeader).toHaveTextContent('2019')
- expect(secondaryHeader).toHaveTextContent('2019')
- })
- it('Given DateHeader When pass a month unit to the timeline then it should take it as default', () => {
- const children =
- const {getAllByTestId} = renderDateHeaderWithContext({unit: 'month', children: children});
- const primaryHeader = getAllByTestId('dateHeader')[0]
- const secondaryHeader = getAllByTestId('dateHeader')[1]
- expect(primaryHeader).toHaveTextContent('2019')
- expect(secondaryHeader).toHaveTextContent('January 2019')
- })
- it('Given DateHeader When pass a day unit to the timeline then it should take it as default', () => {
- const children =
- const {getAllByTestId} = renderDateHeaderWithContext({unit: 'day', children: children});
- const primaryHeader = getAllByTestId('dateHeader')[0]
- const secondaryHeader = getAllByTestId('dateHeader')[1]
- expect(primaryHeader).toHaveTextContent('January 2019')
- expect(secondaryHeader).toHaveTextContent('Monday, January 21, 2019')
- })
- it('Given DateHeader When pass a hour unit to the timeline then it should take it as default', () => {
- const children =
- const {getAllByTestId} = renderDateHeaderWithContext({unit: 'hour', children: children});
- const primaryHeader = getAllByTestId('dateHeader')[0]
- const secondaryHeader = getAllByTestId('dateHeader')[1]
- expect(primaryHeader).toHaveTextContent('Monday, January 21, 2019')
- expect(secondaryHeader).toHaveTextContent('30')
- })
+ expect(getByTestId('interval-a')).toBeInTheDocument()
})
+ it('Given DateHeader When passing a react component to interval renderer Then it should render', () => {
+ class Renderer extends React.Component {
+ render() {
+ const { getIntervalProps, intervalContext } = this.props
+ return (
+
+ {intervalContext.intervalText}
+
+ )
+ }
+ }
+ const { getByTestId } = render(
+
+
+
+ {({ getRootProps }) => {
+ return Left
+ }}
+
+
+
+
+
+
+ )
+ expect(getByTestId('interval-a')).toBeInTheDocument()
+ })
})
-function dateHeaderComponent({ labelFormat, unit, props, className, style, handleTimeChange } = {}) {
-
+function dateHeaderComponent({
+ labelFormat,
+ unit,
+ props,
+ className,
+ style,
+ showPeriod
+} = {}) {
return (
-
-
@@ -311,91 +436,45 @@ function dateHeaderComponent({ labelFormat, unit, props, className, style, handl
return Left
}}
-
+
{
- return
- {intervalContext.intervalText}
-
-
+ intervalRenderer={({ getIntervalProps, intervalContext, data }) => {
+ return (
+
+ {intervalContext.intervalText}
+
+ )
}}
/>
-
+
)
}
function dateHeaderWithIntervalRenderer({ intervalRenderer, props } = {}) {
-
return (
-
-
+
{({ getRootProps }) => {
return Left
}}
-
+
-
+
)
}
-
-
-function renderDateHeaderWithContext({unit, children} = {})
-{
- const oneDay = 1000 * 60 * 60 * 24
- const now = Date.now()
- const visibleTimeStart = now - oneDay
- const visibleTimeEnd = now + oneDay
- const defaultTimelineState = {
- visibleTimeStart,
- visibleTimeEnd,
- canvasTimeStart: visibleTimeStart - oneDay,
- canvasTimeEnd: visibleTimeEnd + oneDay,
- canvasWidth: 3000,
- visibleWidth: 1000,
- showPeriod:()=>{},
- timelineWidth:1000,
- timelineUnit:unit
- }
-
- return render(
-
- React.createRef()}
- rightSidebarWidth={0}
- >
- {children}
-
-
- )
-
-}
diff --git a/__tests__/components/Headers/SideBarHeader.test.js b/__tests__/components/Headers/SideBarHeader.test.js
index b15c13a3b..6775547c4 100644
--- a/__tests__/components/Headers/SideBarHeader.test.js
+++ b/__tests__/components/Headers/SideBarHeader.test.js
@@ -1,164 +1,159 @@
import React from 'react'
-import { render, cleanup, within } from 'react-testing-library'
-import Timeline from 'lib/Timeline'
+import { render, cleanup } from 'react-testing-library'
import DateHeader from 'lib/headers/DateHeader'
import SidebarHeader from 'lib/headers/SidebarHeader'
import TimelineHeaders from 'lib/headers/TimelineHeaders'
import 'jest-dom/extend-expect'
+import { RenderHeadersWrapper } from '../../test-utility/header-renderer'
+import {
+ renderSidebarHeaderWithCustomValues,
+ renderTwoSidebarHeadersWithCustomValues
+} from '../../test-utility/headerRenderers'
-import moment from 'moment'
+describe('Testing SidebarHeader Component', () => {
+ afterEach(cleanup)
-import { items, groups } from '../../../__fixtures__/itemsAndGroups'
+ //TODO: rename test
+ it('Given sidebarHeader When pass style with overridden (width) Then it should not override the default values', () => {
+ const { getByTestId, debug } = renderSidebarHeaderWithCustomValues({
+ props: { style: { width: 250 } }
+ })
+ const { width } = getComputedStyle(getByTestId('sidebarHeader'))
+ expect(width).not.toBe('250px')
+ })
+ it('Given sidebarHeader When pass style Then it show on the sidebar', () => {
+ const { getByTestId } = renderSidebarHeaderWithCustomValues({
+ props: { style: { color: 'white' } }
+ })
+ const { color } = getComputedStyle(getByTestId('sidebarHeader'))
+ expect(color).toBe('white')
+ })
-const defaultProps = {
- groups,
- items,
- defaultTimeStart: moment('1995-12-25').add(-12, 'hour'),
- defaultTimeEnd: moment('1995-12-25').add(12, 'hour')
-}
+ it('Given SidebarHeader When a render function Then it will be rendered', () => {
+ const renderer = jest.fn(({ getRootProps }) => {
+ return (
+
+ Left
+
+ )
+ })
+ const { getByTestId } = render(
+
+
+ {renderer}
+
+
+
+
+ )
+ expect(renderer).toHaveBeenCalled()
+ expect(getByTestId('leftSidebarHeader')).toBeInTheDocument()
+ })
+
+ it('Given SidebarHeader When passing props to SidebarHeader it should be passed to the renderProp', () => {
+ const renderer = jest.fn(({ getRootProps }) => {
+ return (
+
+ Left
+
+ )
+ })
+ const extraProps = {
+ someData: 'data'
+ }
+ const { getByTestId } = render(
+
+
+ {renderer}
+
+
+
+
+ )
+ expect(renderer).toHaveBeenCalled()
+ expect(renderer.mock.calls[0][0].data).toBe(extraProps)
+ })
-describe("Testing SidebarHeader Component", () => {
- afterEach(cleanup)
// Testing The Example In The Docs
- it("Given SidebarHeader When rendered Then it should shown correctly in the timeline", () => {
- const { container } = render(
-
+ it('Given SidebarHeader When rendered Then it should shown correctly in the timeline', () => {
+ const { getByTestId } = render(
+
{({ getRootProps }) => {
- return Left
+ return (
+
+ Left
+
+ )
}}
{({ getRootProps }) => {
- return Right
+ return (
+
+ Right
+
+ )
}}
-
+
)
- const { getByTestId } = within(container)
-
expect(getByTestId('leftSidebarHeader')).toBeInTheDocument()
expect(getByTestId('rightSidebarHeader')).toBeInTheDocument()
- expect(getByTestId('leftSidebarHeader').nextElementSibling).toHaveAttribute('data-testid', 'headerContainer')
- expect(getByTestId('rightSidebarHeader').previousElementSibling).toHaveAttribute('data-testid', 'headerContainer')
- })
-
- it("Given SidebarHeader When passing no variant prop Then it should rendered above the left sidebar", () => {
- const { getByTestId, getAllByTestId } = renderSidebarHeaderWithCustomValues()
- expect(getByTestId('sidebarHeader')).toBeInTheDocument()
- expect(getByTestId('sidebarHeader').nextElementSibling).toHaveAttribute('data-testid', 'headerContainer')
- expect(getAllByTestId('sidebarHeader')).toHaveLength(1)
-
-
- })
- it("Given SidebarHeader When passing variant prop with left value Then it should rendered above the left sidebar", () => {
- const { getByTestId, getAllByTestId } = renderSidebarHeaderWithCustomValues({ variant: "left" })
- expect(getByTestId('sidebarHeader')).toBeInTheDocument()
- expect(getByTestId('sidebarHeader').nextElementSibling).toHaveAttribute('data-testid', 'headerContainer')
- expect(getAllByTestId('sidebarHeader')).toHaveLength(1)
- })
- it("Given SidebarHeader When passing variant prop with right value Then it should rendered above the right sidebar", () => {
- const { getByTestId, getAllByTestId } = renderSidebarHeaderWithCustomValues({ variant: "right" })
- expect(getByTestId('sidebarHeader')).toBeInTheDocument()
- expect(getByTestId('sidebarHeader').previousElementSibling).toHaveAttribute('data-testid', 'headerContainer')
- expect(getAllByTestId('sidebarHeader')).toHaveLength(1)
- })
-
- it("Given SidebarHeader When passing variant prop with unusual value Then it should rendered above the left sidebar by default", () => {
- const { getByTestId } = renderSidebarHeaderWithCustomValues({ variant: "" })
- expect(getByTestId('sidebarHeader')).toBeInTheDocument()
- expect(getByTestId('sidebarHeader').nextElementSibling).toHaveAttribute('data-testid', 'headerContainer')
- })
-
- it("Given SidebarHeader When passing props to the props getter Then it should rendered correctly", () => {
- const { getByTestId } = renderSidebarHeaderWithCustomValues({ props: { style: { width: 250 } } })
- const { width } = getComputedStyle(getByTestId("sidebarHeader"))
- expect(width).toBe("250px")
- })
-
- it("Given SidebarHeader When passing children to it Then it should rendered correctly", () => {
- const { getByText } = renderSidebarHeaderWithCustomValues()
- expect(getByText("Should Be Rendred")).toBeInTheDocument()
- })
-
- it("Given sidebarheader When pass a variant and props Then it should render both correctly", () => {
- const { getByTestId } = renderSidebarHeaderWithCustomValues({ props: { style: { width: 250 }, variant: "left" } })
- const { width } = getComputedStyle(getByTestId("sidebarHeader"))
- expect(width).toBe("250px")
- expect(getByTestId('sidebarHeader').nextElementSibling).toHaveAttribute('data-testid', 'headerContainer')
+ expect(getByTestId('leftSidebarHeader').nextElementSibling).toHaveAttribute(
+ 'data-testid',
+ 'headerContainer'
+ )
+ expect(
+ getByTestId('rightSidebarHeader').previousElementSibling
+ ).toHaveAttribute('data-testid', 'headerContainer')
})
-
- it("Given two sidebarheaders When pass a variants and props Then it should render both correctly", () => {
- const { getByText } = renderTwoSidebarHeadersWithCustomValues({ props: { style: { width: 250 } } })
- const { width: leftWidth } = getComputedStyle(getByText('LeftSideBar'))
- const { width: rightWidth } = getComputedStyle(getByText('RightSideBar'))
- expect(leftWidth).toBe("250px")
- expect(rightWidth).toBe("250px")
- expect(getByText('LeftSideBar').nextElementSibling).toHaveAttribute('data-testid', 'headerContainer')
- expect(getByText('RightSideBar').previousElementSibling).toHaveAttribute('data-testid', 'headerContainer')
+ it('Given SideBarHeader When passing a react stateless component as a child Then it should render', () => {
+ const Renderer = ({ getRootProps }) => {
+ return (
+
+ Left
+
+ )
+ }
+ const { getByText } = render(
+
+
+ {Renderer}
+
+
+
+
+ )
+ expect(getByText('Left')).toBeInTheDocument()
})
-
- it('Given SidebarHeader When Pass an props obj to props renderer Then it should render it correctly', () => {
- const { getByTestId } = renderSidebarHeaderWithCustomValues({ props: { 'aria-hidden': false } })
- expect(getByTestId("sidebarHeader")).toHaveAttribute('aria-hidden')
+ it('Given SideBarHeader When passing a react stateful component as a child Then it should render', () => {
+ class Renderer extends React.Component {
+ render() {
+ const { getRootProps } = this.props
+ return (
+
+ Left
+
+ )
+ }
+ }
+ const { getByText } = render(
+
+
+ {Renderer}
+
+
+
+
+ )
+ expect(getByText('Left')).toBeInTheDocument()
})
-
})
-
-
-function renderSidebarHeaderWithCustomValues({ variant = undefined, props, rightSidebarWidth } = {}) {
- return render(
-
-
- {({ getRootProps }, extraProps) => {
- return SidebarHeader
-
Should Be Rendred
-
- }}
-
-
-
-
-
- )
-}
-
-
-function renderTwoSidebarHeadersWithCustomValues({ props, rightSidebarWidth } = {}) {
- return render(
-
-
- {({ getRootProps }) => {
- return LeftSideBar
-
Should Be Rendred
-
- }}
-
-
- {({ getRootProps }, props) => {
- return RightSideBar
-
- }}
-
-
-
-
-
- )
-}
-
diff --git a/__tests__/components/Headers/TimelineHeader.test.js b/__tests__/components/Headers/TimelineHeader.test.js
index 96ab239f0..cb66c7f5e 100644
--- a/__tests__/components/Headers/TimelineHeader.test.js
+++ b/__tests__/components/Headers/TimelineHeader.test.js
@@ -1,118 +1,82 @@
-import { render, cleanup } from 'react-testing-library'
-import Timeline from 'lib/Timeline'
+import { render } from 'react-testing-library'
import SidebarHeader from 'lib/headers/SidebarHeader'
import DateHeader from 'lib/headers/DateHeader'
import TimelineHeaders from 'lib/headers/TimelineHeaders'
import 'jest-dom/extend-expect'
+import 'react-testing-library/cleanup-after-each'
import React from 'react'
-import moment from 'moment'
-import { items, groups } from '../../../__fixtures__/itemsAndGroups'
+import { RenderHeadersWrapper } from '../../test-utility/header-renderer'
import {
- visibleTimeStart,
- visibleTimeEnd
-} from '../../../__fixtures__/stateAndProps'
-
-const defaultProps = {
- groups,
- items,
- defaultTimeStart: moment('1995-12-25').add(-12, 'hour'),
- defaultTimeEnd: moment('1995-12-25').add(12, 'hour')
-}
+ renderSidebarHeaderWithCustomValues,
+ renderTimelineWithVariantSidebar,
+ renderTimelineWithLeftAndRightSidebar
+} from '../../test-utility/headerRenderers'
describe('TimelineHeader', () => {
- beforeEach(() => {
- Element.prototype.getBoundingClientRect = jest.fn(() => {
- return {
- width: 1000,
- height: 120,
- top: 0,
- left: 0,
- bottom: 0,
- right: 0,
- }
- });
+ it('Given TimelineHeader When pass a left and right sidebars as children Then it should render a left and right sidebars', () => {
+ const { getByTestId } = renderTimelineWithLeftAndRightSidebar()
+ expect(getByTestId('left-header')).toBeInTheDocument()
+ expect(getByTestId('right-header')).toBeInTheDocument()
})
- afterEach(cleanup)
- /**
- * Testing The Default Functionality
- */
- describe('renders default headers correctly', () => {
- it('Given TimelineHeader When rendered Then it should render tow date headers by default', () => {
- const { getAllByTestId, getByTestId } = renderDefaultTimeline()
- expect(getAllByTestId('dateHeader')).toHaveLength(2)
- expect(getByTestId('headerContainer').children).toHaveLength(2)
- })
- it('Given TimelineHeader When rendered Then it should render a left sidebar by default', () => {
- const { getByTestId } = renderDefaultTimeline()
- expect(getByTestId("sidebarHeader")).toBeInTheDocument()
- })
- it('Given TimelineHeader When pass a rightsidebarWidth Then it should render two sidebar headers', () => {
- let rightSidebarWidth = 150;
- const { getAllByTestId } = renderDefaultTimeline({ rightSidebarWidth });
- const sidebarHeaders = getAllByTestId('sidebarHeader')
-
- expect(sidebarHeaders).toHaveLength(2)
- expect(sidebarHeaders[0]).toBeInTheDocument()
- expect(sidebarHeaders[1]).toBeInTheDocument()
- const { width } = getComputedStyle(sidebarHeaders[1])
- expect(width).toBe("150px")
-
+ it('Given TimelineHeader When pass calendarHeaderStyle with overridden (overflow, width) Then it should not override the default values', () => {
+ const { getByTestId } = renderTimelineWithLeftAndRightSidebar({
+ calendarHeaderStyle: { overflow: 'unset', width: 0 }
})
- it('Given TimelineHeader When rendered Then it should render a two dateHeadrs default', () => {
- const { getAllByTestId } = renderDefaultTimeline();
- const dateHeaders = getAllByTestId("dateHeader")
-
- expect(dateHeaders).toHaveLength(2)
- expect(dateHeaders[1].childElementCount).toBeGreaterThan(dateHeaders[0].childElementCount)
+ const headerContainer = getByTestId('headerContainer')
+ const { width, overflow } = getComputedStyle(headerContainer)
+ expect(overflow).not.toBe('unset')
+ expect(width).not.toBe('0px')
+ })
+ it('Given TimelineHeader When pass calendarHeaderStyle Then it be added to styles', () => {
+ const { getByTestId } = renderTimelineWithLeftAndRightSidebar({
+ calendarHeaderStyle: { color: 'white', background: 'black' }
})
+ const headerContainer = getByTestId('headerContainer')
+ const { color, background } = getComputedStyle(headerContainer)
- it("Given TimelineHeader When pass a left sidebar as a child Then it should render a left sidebar", () => {
- const { getByTestId, getAllByTestId } = renderTimelineWithVariantSidebar({ variant: "left" });
- expect(getByTestId('sidebarHeader')).toBeInTheDocument();
- expect(getAllByTestId('sidebarHeader')).toHaveLength(1)
- })
- it("Given TimelineHeader When pass a right sidebar as a child Then it should render a right sidebar", () => {
- const { getByTestId, getAllByTestId } = renderTimelineWithVariantSidebar({ variant: "right" });
- expect(getByTestId('sidebarHeader')).toBeInTheDocument();
- expect(getAllByTestId('sidebarHeader')).toHaveLength(1)
- })
- it("Given TimelineHeader When pass a left and right sidebars as children Then it should render a left and right sidebars", () => {
- const { getByTestId } = renderTimelineWithLeftAndRightSidebar();
- expect(getByTestId('left-header')).toBeInTheDocument();
- expect(getByTestId('right-header')).toBeInTheDocument();
+ expect(color).toBe('white')
+ expect(background).toBe('black')
+ })
+ it('Given TimelineHeader When pass style with overridden (display, width) Then it should not override the default values', () => {
+ const { getByTestId } = renderTimelineWithLeftAndRightSidebar({
+ style: { display: 'none', width: 0 }
})
+ const rootDiv = getByTestId('headerRootDiv')
+ const { width, display } = getComputedStyle(rootDiv)
- it("Given TimelineHeader When pass calendarHeaderStyle with overrided (overflow, width) Then it should not override the deaful values", () => {
- const { getByTestId } = renderTimelineWithLeftAndRightSidebar({ calendarHeaderStyle: { overflow: 'unset', width: 0 } });
- const headerContainer = getByTestId('headerContainer')
- const { width, overflow } = getComputedStyle(headerContainer)
-
-
- expect(overflow).not.toBe('unset')
- expect(width).not.toBe("0px")
-
+ expect(display).not.toBe('none')
+ expect(width).not.toBe('0px')
+ })
+ it('Given TimelineHeader When pass style Then it should it be added to root`s styles', () => {
+ const { getByTestId } = renderTimelineWithLeftAndRightSidebar({
+ style: { color: 'white', background: 'black' }
})
- it("Given TimelineHeader When pass rootStyle with overrided (display, width) Then it should not override the deaful values", () => {
- const { getByTestId } = renderTimelineWithLeftAndRightSidebar({ style: { display: 'none', width: 0 } });
- const rootDiv = getByTestId('headerRootDiv')
- const { width, display } = getComputedStyle(rootDiv)
-
- expect(display).not.toBe('none')
- expect(width).not.toBe("0px")
+ const rootDiv = getByTestId('headerRootDiv')
+ const { color, background } = getComputedStyle(rootDiv)
+ expect(color).toBe('white')
+ expect(background).toBe('black')
+ })
+ it('Given TimelineHeader When pass calendarHeaderClassName Then it should be applied to the date header container', () => {
+ const { getByTestId } = renderTimelineWithLeftAndRightSidebar({
+ calendarHeaderClassName: 'testClassName'
})
- it("Given TimelineHeader When pass calendarHeaderClassName Then it should be applied to the date header container", () => {
- const { getByTestId } = renderTimelineWithLeftAndRightSidebar({ calendarHeaderClassName: "testClassName" });
- expect(getByTestId("headerContainer")).toHaveClass("testClassName")
+ expect(getByTestId('headerContainer')).toHaveClass('testClassName')
+ })
+
+ it('Given TimelineHeader When pass className Then it should be applied to the root header container', () => {
+ const { getByTestId } = renderTimelineWithLeftAndRightSidebar({
+ className: 'testClassName'
})
+ expect(getByTestId('headerRootDiv')).toHaveClass('testClassName')
})
it('Given TimelineHeader When rendered Then it should render the default styles of the date header container', () => {
- const { getByTestId } = renderTimelineWithLeftAndRightSidebar();
+ const { getByTestId } = renderTimelineWithLeftAndRightSidebar()
const headerContainer = getByTestId('headerContainer')
const { overflow } = getComputedStyle(headerContainer)
expect(overflow).toBe('hidden')
@@ -120,12 +84,56 @@ describe('TimelineHeader', () => {
})
it('Given TimelineHeader When rendered Then it should render the default styles of the rootStyle', () => {
- const { getByTestId } = renderTimelineWithLeftAndRightSidebar();
+ const { getByTestId } = renderTimelineWithLeftAndRightSidebar()
const rootDiv = getByTestId('headerRootDiv')
const { width, display } = getComputedStyle(rootDiv)
expect(display).toBe('flex')
- expect(width).toBe("100%")
+ expect(width).toBe('100%')
+ })
+
+ it('Given SidebarHeader When passing no variant prop Then it should rendered above the left sidebar', () => {
+ const {
+ getByTestId,
+ getAllByTestId
+ } = renderSidebarHeaderWithCustomValues()
+ expect(getByTestId('sidebarHeader')).toBeInTheDocument()
+ expect(getByTestId('sidebarHeader').nextElementSibling).toHaveAttribute(
+ 'data-testid',
+ 'headerContainer'
+ )
+ expect(getAllByTestId('sidebarHeader')).toHaveLength(1)
+ })
+ it('Given SidebarHeader When passing variant prop with left value Then it should rendered above the left sidebar', () => {
+ const { getByTestId, getAllByTestId } = renderSidebarHeaderWithCustomValues(
+ { variant: 'left' }
+ )
+ expect(getByTestId('sidebarHeader')).toBeInTheDocument()
+ expect(getByTestId('sidebarHeader').nextElementSibling).toHaveAttribute(
+ 'data-testid',
+ 'headerContainer'
+ )
+ expect(getAllByTestId('sidebarHeader')).toHaveLength(1)
+ })
+ it('Given SidebarHeader When passing variant prop with right value Then it should rendered above the right sidebar', () => {
+ const { getByTestId, getAllByTestId } = renderSidebarHeaderWithCustomValues(
+ { variant: 'right' }
+ )
+ expect(getByTestId('sidebarHeader')).toBeInTheDocument()
+ expect(getByTestId('sidebarHeader').previousElementSibling).toHaveAttribute(
+ 'data-testid',
+ 'headerContainer'
+ )
+ expect(getAllByTestId('sidebarHeader')).toHaveLength(1)
+ })
+
+ it('Given SidebarHeader When passing variant prop with unusual value Then it should rendered above the left sidebar by default', () => {
+ const { getByTestId } = renderSidebarHeaderWithCustomValues({ variant: '' })
+ expect(getByTestId('sidebarHeader')).toBeInTheDocument()
+ expect(getByTestId('sidebarHeader').nextElementSibling).toHaveAttribute(
+ 'data-testid',
+ 'headerContainer'
+ )
})
/**
@@ -133,12 +141,7 @@ describe('TimelineHeader', () => {
*/
it('Given TimelineHeader When pass a headers as children Then it should render them correctly', () => {
const { getByText, rerender, queryByText } = render(
-
+
{({ getRootProps }) => {
@@ -156,17 +159,12 @@ describe('TimelineHeader', () => {
-
+
)
expect(getByText('Left')).toBeInTheDocument()
expect(getByText('Right')).toBeInTheDocument()
rerender(
-
+
{({ getRootProps }) => {
@@ -175,65 +173,8 @@ describe('TimelineHeader', () => {
-
+
)
expect(queryByText('Right')).toBeNull()
})
})
-
-function renderDefaultTimeline(props = {}) {
- const timelineProps = {
- ...defaultProps,
- ...props
- }
- return render(
)
-}
-
-function renderTimelineWithVariantSidebar({ props, variant } = {}) {
- const timelineProps = {
- ...defaultProps,
- ...props
- }
- return render(
-
-
-
- {({ getRootProps }) => {
- return Header
- }}
-
-
-
- )
-}
-
-
-function renderTimelineWithLeftAndRightSidebar({ props, calendarHeaderClassName, calendarHeaderStyle, style } = {}) {
-
- const timelineProps = {
- ...defaultProps,
- ...props
- }
-
- return render(
-
-
-
- {({ getRootProps }) => {
- return Right
- }}
-
-
- {({ getRootProps }) => {
- return Left
- }}
-
-
-
- )
-}
-
-
-
diff --git a/__tests__/components/Headers/defaultHeaders.js b/__tests__/components/Headers/defaultHeaders.js
new file mode 100644
index 000000000..dbd7722fe
--- /dev/null
+++ b/__tests__/components/Headers/defaultHeaders.js
@@ -0,0 +1,41 @@
+import React from 'react'
+import { render } from 'react-testing-library'
+import { items, groups } from '../../../__fixtures__/itemsAndGroups'
+import {
+ props as defaultProps
+} from '../../../__fixtures__/stateAndProps'
+import 'react-testing-library/cleanup-after-each'
+import Timeline from 'lib/Timeline'
+import 'jest-dom/extend-expect'
+
+/**
+ * Testing The Default Functionality
+ */
+describe('Renders default headers correctly', () => {
+ it('Given Timeline When not using TimelineHeaders then it should render 2 DateHeaders and a left sidebar header by default ', () => {
+ const { getAllByTestId, getByTestId } = renderDefaultTimeline();
+ expect(getAllByTestId('dateHeader')).toHaveLength(2);
+ expect(getByTestId('headerContainer').children).toHaveLength(2);
+ expect(getByTestId('sidebarHeader')).toBeInTheDocument();
+ });
+ it('Given TimelineHeader When pass a rightSidebarWidthWidth Then it should render two sidebar headers', () => {
+ let rightSidebarWidth = 150;
+ const { getAllByTestId } = renderDefaultTimeline({ rightSidebarWidth });
+ const sidebarHeaders = getAllByTestId('sidebarHeader');
+ expect(sidebarHeaders).toHaveLength(2);
+ expect(sidebarHeaders[0]).toBeInTheDocument();
+ expect(sidebarHeaders[1]).toBeInTheDocument();
+ const { width } = getComputedStyle(sidebarHeaders[1]);
+ expect(width).toBe('150px');
+ });
+});
+
+export function renderDefaultTimeline(props = {}) {
+ const timelineProps = {
+ ...defaultProps,
+ items,
+ groups,
+ ...props
+ }
+ return render(
)
+}
diff --git a/__tests__/components/Markers/TimelineMarkers.test.js b/__tests__/components/Markers/TimelineMarkers.test.js
index da00906b0..8d03a5361 100644
--- a/__tests__/components/Markers/TimelineMarkers.test.js
+++ b/__tests__/components/Markers/TimelineMarkers.test.js
@@ -3,6 +3,7 @@ import { render } from 'react-testing-library'
import 'jest-dom/extend-expect'
import TimelineMarkers from 'lib/markers/public/TimelineMarkers'
import TodayMarker from 'lib/markers/public/TodayMarker'
+import CustomMarker from 'lib/markers/public/CustomMarker'
import { RenderWrapper } from 'test-utility/marker-renderer'
describe('TimelineMarkers', () => {
@@ -23,4 +24,27 @@ describe('TimelineMarkers', () => {
)
})
+
+ it('is unsubscribed on unmounting after passing new date then hide it', ()=>{
+ const defaultCustomMarkerTestId = 'default-customer-marker-id'
+ const { queryByTestId, rerender } = render(
+
+
+
+
+ )
+
+ rerender(
+
+
+
+ )
+
+ rerender(
+
+
+ )
+
+ expect(queryByTestId(defaultCustomMarkerTestId)).not.toBeInTheDocument()
+ })
})
diff --git a/__tests__/index.js b/__tests__/index.js
index b93609565..fcb776487 100644
--- a/__tests__/index.js
+++ b/__tests__/index.js
@@ -149,7 +149,6 @@ xdescribe('Timeline', () => {
expect(typeof pluginProps.visibleTimeStart).toBe('number')
expect(typeof pluginProps.visibleTimeEnd).toBe('number')
expect(typeof pluginProps.height).toBe('number')
- expect(typeof pluginProps.headerHeight).toBe('number')
expect(typeof pluginProps.minUnit).toBe('string')
diff --git a/__tests__/test-utility/header-renderer.js b/__tests__/test-utility/header-renderer.js
new file mode 100644
index 000000000..645fb8ee0
--- /dev/null
+++ b/__tests__/test-utility/header-renderer.js
@@ -0,0 +1,53 @@
+import React from 'react'
+import TimelineMarkersRenderer from 'lib/markers/TimelineMarkersRenderer'
+import { TimelineMarkersProvider } from 'lib/markers/TimelineMarkersContext'
+import { TimelineStateProvider } from 'lib/timeline/TimelineStateContext'
+import { state } from '../../__fixtures__/stateAndProps'
+import jest from 'jest'
+import { defaultTimeSteps } from '../../src/lib/default-config'
+import { TimelineHeadersProvider } from '../../src/lib/headers/HeadersContext'
+
+// eslint-disable-next-line
+export const RenderHeadersWrapper = ({
+ children,
+ timelineState = {},
+ headersState = {},
+ showPeriod = () => {},
+ registerScroll = () => {}
+}) => {
+ const defaultTimelineState = {
+ visibleTimeStart: state.visibleTimeStart,
+ visibleTimeEnd: state.visibleTimeEnd,
+ canvasTimeStart: state.canvasTimeStart,
+ canvasTimeEnd: state.canvasTimeEnd,
+ canvasWidth: 2000,
+ showPeriod: showPeriod,
+ timelineUnit: 'day',
+ timelineWidth: 1000
+ }
+
+ const timelineStateProps = {
+ ...defaultTimelineState,
+ ...timelineState
+ }
+
+ const headersStateProps = {
+ registerScroll: registerScroll,
+ timeSteps: defaultTimeSteps,
+ leftSidebarWidth: 150,
+ rightSidebarWidth: 0,
+ ...headersState
+ }
+
+ return (
+
+
+
+
+ {children}
+
+
+
+
+ )
+}
diff --git a/__tests__/test-utility/headerRenderers.js b/__tests__/test-utility/headerRenderers.js
new file mode 100644
index 000000000..9fa305052
--- /dev/null
+++ b/__tests__/test-utility/headerRenderers.js
@@ -0,0 +1,164 @@
+import React from 'react';
+import { render } from 'react-testing-library';
+import DateHeader from 'lib/headers/DateHeader';
+import SidebarHeader from 'lib/headers/SidebarHeader';
+import TimelineHeaders from 'lib/headers/TimelineHeaders';
+import CustomHeader from 'lib/headers/CustomHeader'
+
+import { RenderHeadersWrapper } from './header-renderer';
+export function renderSidebarHeaderWithCustomValues({ variant = undefined, props, timelineState, headersState, extraProps } = {}) {
+ return render(
+
+
+ {({ getRootProps }) => {
+ return (
+ SidebarHeader
+
Should Be Rendred
+
);
+ }}
+
+
+
+
+ );
+}
+export function renderTwoSidebarHeadersWithCustomValues({ props, timelineState, headersState } = {}) {
+ return render(
+
+
+ {({ getRootProps }) => {
+ return (
+ LeftSideBar
+
Should Be Rendred
+
);
+ }}
+
+
+ {({ getRootProps, data }) => {
+ return RightSideBar
;
+ }}
+
+
+
+
+ );
+}
+
+export function renderTimelineWithLeftAndRightSidebar({
+ calendarHeaderClassName,
+ calendarHeaderStyle,
+ style,
+ className,
+ timelineState,
+ headersState
+} = {}) {
+ return render(
+
+
+
+ {({ getRootProps }) => {
+ return (
+
+ Right
+
+ )
+ }}
+
+
+ {({ getRootProps }) => {
+ return (
+
+ Left
+
+ )
+ }}
+
+
+
+ )
+}
+
+export function renderTimelineWithVariantSidebar({
+ variant,
+ timelineState,
+ headersState
+} = {}) {
+ return render(
+
+
+
+ {({ getRootProps }) => {
+ return (
+
+ Header
+
+ )
+ }}
+
+
+
+ )
+}
+
+export function getCustomHeadersInTimeline({
+ unit,
+ props,
+ intervalStyle,
+ timelineState,
+ headersState
+} = {}) {
+ return (
+
+
+
+ {(
+ {
+ headerContext: { intervals },
+ getRootProps,
+ getIntervalProps,
+ showPeriod,
+ data = { style: { height: 30 } }
+ },
+ ) => {
+ return (
+
+ {intervals.map(interval => {
+ return (
+
{
+ showPeriod(interval.startTime, interval.endTime)
+ }}
+ {...getIntervalProps({
+ interval,
+ style: intervalStyle
+ })}
+ >
+
+ {interval.startTime.format('DD/MM/YYYY')}
+
+
+ )
+ })}
+
+ )
+ }}
+
+
+
+ )
+}
diff --git a/__tests__/test-utility/index.js b/__tests__/test-utility/index.js
index 3cbac0bfb..0f5bb12a3 100644
--- a/__tests__/test-utility/index.js
+++ b/__tests__/test-utility/index.js
@@ -9,3 +9,7 @@ export function sel(selectorString) {
}
export function noop() {}
+
+export function parsePxToNumbers(value) {
+ return +value.replace('px', '')
+}
\ No newline at end of file
diff --git a/__tests__/test-utility/parse-px-to-numbers.js b/__tests__/test-utility/parse-px-to-numbers.js
new file mode 100644
index 000000000..e69de29bb
diff --git a/demo/app/demo-headers/index.js b/demo/app/demo-headers/index.js
index 9f8fc2498..efeff753e 100644
--- a/demo/app/demo-headers/index.js
+++ b/demo/app/demo-headers/index.js
@@ -203,59 +203,28 @@ export default class App extends Component {
stackItems="space"
>
-
- {({ getRootProps }) => {
- return Left
- }}
-
-
- {({ getRootProps }) => {
- return Right
- }}
-
- {
- return (
-
- {item.title}
-
- )
- }}
- />
-
-
+
-
-
+
+
{(
{
headerContext: { intervals },
getRootProps,
getIntervalProps,
- showPeriod
+ showPeriod,
+ data,
},
- props
+
) => {
+ console.log('props', data)
return (
-
+
{intervals.map(interval => {
const intervalStyle = {
- // height: 30,
lineHeight: '30px',
textAlign: 'center',
borderLeft: '1px solid black',
@@ -291,10 +260,9 @@ export default class App extends Component {
showPeriod
}) => {
return (
-
+
{intervals.map(interval => {
const intervalStyle = {
- // height: 30,
lineHeight: '30px',
textAlign: 'center',
borderLeft: '1px solid black',
@@ -330,7 +298,7 @@ export default class App extends Component {
showPeriod
}) => {
return (
-
+
{intervals.map(interval => {
const intervalStyle = {
lineHeight: '30px',
@@ -359,12 +327,13 @@ export default class App extends Component {
{
+ console.log('intervalRenderer props', data)
return (
{intervalContext.intervalText}
@@ -376,9 +345,9 @@ export default class App extends Component {
? [
,
-
+
]
: null}
diff --git a/demo/app/demo-sticky-header/index.js b/demo/app/demo-sticky-header/index.js
deleted file mode 100644
index d0685849e..000000000
--- a/demo/app/demo-sticky-header/index.js
+++ /dev/null
@@ -1,126 +0,0 @@
-import React, { Component } from 'react'
-import moment from 'moment'
-
-import Timeline from 'react-calendar-timeline'
-import containerResizeDetector from '../../../src/resize-detector/container'
-
-// you would use this in real life:
-// import containerResizeDetector from 'react-calendar-timeline/lib/resize-detector/container'
-
-import generateFakeData from '../generate-fake-data'
-
-var keys = {
- groupIdKey: 'id',
- groupTitleKey: 'title',
- groupRightTitleKey: 'rightTitle',
- itemIdKey: 'id',
- itemTitleKey: 'title',
- itemDivTitleKey: 'title',
- itemGroupKey: 'group',
- itemTimeStartKey: 'start',
- itemTimeEndKey: 'end'
-}
-
-export default class App extends Component {
- constructor(props) {
- super(props)
-
- const { groups, items } = generateFakeData()
- const defaultTimeStart = moment()
- .startOf('day')
- .toDate()
- const defaultTimeEnd = moment()
- .startOf('day')
- .add(1, 'day')
- .toDate()
- const width = 80
-
- this.state = {
- groups,
- items,
- defaultTimeStart,
- defaultTimeEnd,
- width
- }
- }
-
- render() {
- const { groups, items, defaultTimeStart, defaultTimeEnd } = this.state
-
- return (
-
- In this example we have a lot of random content above the timeline.
- Try scrolling and see how the timeline header sticks to the screen.
-
- Above The Left
}
- rightSidebarWidth={150}
- rightSidebarContent={
Above The Right
}
- canMove
- canResize="right"
- canSelect
- itemsSorted
- itemTouchSendsClick={false}
- stackItems="space"
- itemHeightRatio={0.75}
- resizeDetector={containerResizeDetector}
- defaultTimeStart={defaultTimeStart}
- defaultTimeEnd={defaultTimeEnd}
- />
-
- There is also a lot of stuff below the timeline. Watch the header fix
- itself to the bottom of the component.
-
-
- bla bla bla
-
-
- Here are random pictures of Tom Selleck:
-
-
-

-
-
-

-
-
- Here is another calendar, but this one has
stickyOffset set
- to
100, meaning that the header will stick 100px from the
- top. This is useful for example if you already have a sticky navbar.
-
-
-
Above The Left }
- rightSidebarWidth={150}
- rightSidebarContent={Above The Right
}
- canMove
- canResize="right"
- canSelect
- itemsSorted
- itemTouchSendsClick={false}
- stackItems="space"
- itemHeightRatio={0.75}
- resizeDetector={containerResizeDetector}
- defaultTimeStart={defaultTimeStart}
- defaultTimeEnd={defaultTimeEnd}
- />
-
-
- )
- }
-}
diff --git a/demo/app/index.js b/demo/app/index.js
index fbe44aeab..f853ad51c 100644
--- a/demo/app/index.js
+++ b/demo/app/index.js
@@ -11,7 +11,6 @@ const demos = {
treeGroups: require('./demo-tree-groups').default,
linkedTimelines: require('./demo-linked-timelines').default,
elementResize: require('./demo-element-resize').default,
- stickyHeader: require('./demo-sticky-header').default,
renderers: require('./demo-renderers').default,
verticalClasses: require('./demo-vertical-classes').default,
customItems: require('./demo-custom-items').default,
diff --git a/examples/README.md b/examples/README.md
index 13bdcad66..77b3b0ea8 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -40,7 +40,9 @@ You can restrict the moving and resizing of items at the item level by providing
## Right Sidebar
-Adding a right sidebar is as easy as passing in a couple of props `rightSidebarWidth` and `rightSidebarContent`. Content in the right column is populated from the `rightTitle` property on the group.
+Adding a right sidebar is as easy as passing `rightSidebarWidth`. Content in the right column is populated from the `rightTitle` property on the group.
+
+Note: If you are using Custom Headers then you need to add them with `SidebarHeader` with variant "right"
[Example Codesandbox](https://codesandbox.io/s/j3wrw6rl4v)
@@ -63,3 +65,9 @@ Note that this is the user code manipulating groups to achieve tree group functi
Using `scrollRef` you can trigger scrolling and create an animation. This is an alternative to setting `visibleStartTime` and `visibleEndTime`.
[Example Codesandbox](https://codesandbox.io/s/3kq2503y8p)
+
+## Sticky header
+
+Using `Timeline Header` you can make the header stick to the top of the page while scrolling down
+
+[Example Codesandbox](https://codesandbox.io/s/w6xvqzno4w)
diff --git a/package.json b/package.json
index ea8764ba9..cd4f933d0 100644
--- a/package.json
+++ b/package.json
@@ -140,7 +140,7 @@
"react": "^16.2.0",
"react-dom": "^16.2.0",
"react-router-dom": "^4.1.1",
- "react-testing-library": "^5.1.0",
+ "react-testing-library": "^6.0.3",
"rimraf": "^2.6.2",
"sass-loader": "^7.0.3",
"style-loader": "~0.13.0",
diff --git a/src/lib/Timeline.js b/src/lib/Timeline.js
index e059451e4..88304e797 100644
--- a/src/lib/Timeline.js
+++ b/src/lib/Timeline.js
@@ -43,11 +43,8 @@ export default class ReactCalendarTimeline extends Component {
rightSidebarWidth: PropTypes.number,
dragSnap: PropTypes.number,
minResizeWidth: PropTypes.number,
- stickyOffset: PropTypes.number,
stickyHeader: PropTypes.bool,
lineHeight: PropTypes.number,
- headerLabelGroupHeight: PropTypes.number,
- headerLabelHeight: PropTypes.number,
itemHeightRatio: PropTypes.number,
minZoom: PropTypes.number,
@@ -170,11 +167,8 @@ export default class ReactCalendarTimeline extends Component {
rightSidebarWidth: 0,
dragSnap: 1000 * 60 * 15, // 15min
minResizeWidth: 20,
- stickyOffset: 0,
stickyHeader: true,
lineHeight: 30,
- headerLabelGroupHeight: 30,
- headerLabelHeight: 30,
itemHeightRatio: 0.65,
minZoom: 60 * 60 * 1000, // 1 hour
@@ -644,6 +638,7 @@ export default class ReactCalendarTimeline extends Component {
let time = calculateTimeForXPosition(
canvasTimeStart,
+
canvasTimeEnd,
getCanvasWidth(width),
offsetX
@@ -897,7 +892,6 @@ export default class ReactCalendarTimeline extends Component {
groupHeights,
groupTops,
height,
- headerHeight,
visibleTimeStart,
visibleTimeEnd,
minUnit,
@@ -926,7 +920,6 @@ export default class ReactCalendarTimeline extends Component {
groupTops: groupTops,
selected: this.getSelected(),
height: height,
- headerHeight: headerHeight,
minUnit: minUnit,
timeSteps: timeSteps
}
@@ -955,7 +948,7 @@ export default class ReactCalendarTimeline extends Component {
return (
-
+
{this.props.rightSidebarWidth ? : null}
@@ -986,8 +979,6 @@ export default class ReactCalendarTimeline extends Component {
const {
items,
groups,
- headerLabelGroupHeight,
- headerLabelHeight,
sidebarWidth,
rightSidebarWidth,
timeSteps,
@@ -1007,7 +998,6 @@ export default class ReactCalendarTimeline extends Component {
const zoom = visibleTimeEnd - visibleTimeStart
const canvasWidth = getCanvasWidth(width)
const minUnit = getMinUnit(zoom, width, timeSteps)
- const headerHeight = headerLabelGroupHeight + headerLabelHeight
const isInteractingWithItem = !!draggingItem || !!resizingItem
@@ -1095,7 +1085,6 @@ export default class ReactCalendarTimeline extends Component {
minUnit,
timeSteps,
height,
- headerHeight
)}
{this.rows(canvasWidth, groupHeights, groups)}
{this.infoLabel()}
@@ -1107,7 +1096,6 @@ export default class ReactCalendarTimeline extends Component {
groupHeights,
groupTops,
height,
- headerHeight,
visibleTimeStart,
visibleTimeEnd,
minUnit,
diff --git a/src/lib/Timeline.scss b/src/lib/Timeline.scss
index 7fd88e0f5..93a8d58ab 100644
--- a/src/lib/Timeline.scss
+++ b/src/lib/Timeline.scss
@@ -13,10 +13,6 @@ $border-width: 1px;
$thick-border-width: 2px;
$sidebar-color: #ffffff;
$sidebar-background-color: #c52020;
-$header-color: #ffffff;
-$header-background-color: #c52020;
-$lower-header-color: #333333;
-$lower-header-background-color: #f0f0f0;
$list-item-padding: 0 4px;
$weekend: rgba(250, 246, 225, 0.5);
@@ -60,17 +56,6 @@ $weekend: rgba(250, 246, 225, 0.5);
}
}
- .rct-header-container {
- z-index: 90;
- display: flex;
- overflow: hidden;
-
- &.header-sticky {
- position: sticky;
- position: -webkit-sticky;
- }
- }
-
.rct-sidebar {
overflow: hidden;
white-space: normal; // was set to nowrap in .rct-outer
@@ -149,8 +134,39 @@ $weekend: rgba(250, 246, 225, 0.5);
background: rgba(0, 0, 0, 0.5);
color: white;
padding: 10px;
+
font-size: 20px;
border-radius: 5px;
z-index: 85;
}
+
+ .rct-dateHeader {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 100%;
+ border-bottom: 1px solid #bbb;
+ cursor: pointer;
+ font-size: 14px;
+ background-color: rgb(240, 240, 240);
+ border-left: 2px solid #bbb;
+ }
+
+ .rct-dateHeader-primary {
+ background-color: initial;
+ border-left: 1px solid #bbb;
+ border-right: 1px solid #bbb;
+ color: #fff
+ }
+
+ .rct-header-root {
+ background: #c52020;
+ border-bottom: 1px solid #bbb;
+ }
+
+ .rct-calendar-header {
+ border: 1px solid #bbb,
+
+ }
+
}
diff --git a/src/lib/headers/CustomHeader.js b/src/lib/headers/CustomHeader.js
index b1cc46103..a07bfc8c5 100644
--- a/src/lib/headers/CustomHeader.js
+++ b/src/lib/headers/CustomHeader.js
@@ -9,16 +9,17 @@ export class CustomHeader extends React.Component {
//component props
children: PropTypes.func.isRequired,
unit: PropTypes.string.isRequired,
- timeSteps: PropTypes.object.isRequired,
//Timeline context
+ timeSteps: PropTypes.object.isRequired,
visibleTimeStart: PropTypes.number.isRequired,
visibleTimeEnd: PropTypes.number.isRequired,
canvasTimeStart: PropTypes.number.isRequired,
canvasTimeEnd: PropTypes.number.isRequired,
canvasWidth: PropTypes.number.isRequired,
showPeriod: PropTypes.func.isRequired,
- props: PropTypes.object,
+ headerData: PropTypes.object,
getLeftOffsetFromDate: PropTypes.func.isRequired,
+ height: PropTypes.number.isRequired,
}
constructor(props) {
super(props)
@@ -29,13 +30,9 @@ export class CustomHeader extends React.Component {
unit,
timeSteps,
showPeriod,
- getLeftOffsetFromDate,
+ getLeftOffsetFromDate
} = props
- const ratio = this.calculateRatio(
- canvasWidth,
- canvasTimeEnd,
- canvasTimeStart
- )
+
const intervals = this.getHeaderIntervals({
canvasTimeStart,
canvasTimeEnd,
@@ -43,12 +40,11 @@ export class CustomHeader extends React.Component {
unit,
timeSteps,
showPeriod,
- getLeftOffsetFromDate,
+ getLeftOffsetFromDate
})
this.state = {
- intervals,
- ratio
+ intervals
}
}
@@ -60,7 +56,8 @@ export class CustomHeader extends React.Component {
nextProps.unit !== this.props.unit ||
nextProps.timeSteps !== this.props.timeSteps ||
nextProps.showPeriod !== this.props.showPeriod ||
- nextProps.children !== this.props.children
+ nextProps.children !== this.props.children ||
+ nextProps.headerData !== this.props.headerData
) {
return true
}
@@ -83,13 +80,9 @@ export class CustomHeader extends React.Component {
unit,
timeSteps,
showPeriod,
- getLeftOffsetFromDate,
+ getLeftOffsetFromDate
} = nextProps
- const ratio = this.calculateRatio(
- canvasWidth,
- canvasTimeEnd,
- canvasTimeStart
- )
+
const intervals = this.getHeaderIntervals({
canvasTimeStart,
canvasTimeEnd,
@@ -97,10 +90,10 @@ export class CustomHeader extends React.Component {
unit,
timeSteps,
showPeriod,
- getLeftOffsetFromDate,
+ getLeftOffsetFromDate
})
- this.setState({ intervals, ratio })
+ this.setState({ intervals })
}
}
@@ -109,7 +102,7 @@ export class CustomHeader extends React.Component {
canvasTimeEnd,
unit,
timeSteps,
- getLeftOffsetFromDate,
+ getLeftOffsetFromDate
}) => {
const intervals = []
iterateTimes(
@@ -120,37 +113,33 @@ export class CustomHeader extends React.Component {
(startTime, endTime) => {
const left = getLeftOffsetFromDate(startTime.valueOf())
const right = getLeftOffsetFromDate(endTime.valueOf())
- const width = right-left
+ const width = right - left
intervals.push({
startTime,
endTime,
labelWidth: width,
- left,
+ left
})
}
)
return intervals
}
- rootProps = {
- style: {
- position: 'relative'
- }
- }
-
getRootProps = (props = {}) => {
const { style } = props
return {
style: Object.assign({}, style ? style : {}, {
position: 'relative',
- width: this.props.canvasWidth
+ width: this.props.canvasWidth,
+ height: this.props.height,
})
}
}
getIntervalProps = (props = {}) => {
const { interval, style } = props
- if (!interval) throw new Error("you should provide interval to the prop getter")
+ if (!interval)
+ throw new Error('you should provide interval to the prop getter')
const { startTime, labelWidth, left } = interval
return {
style: this.getIntervalStyle({
@@ -159,19 +148,13 @@ export class CustomHeader extends React.Component {
labelWidth,
canvasTimeStart: this.props.canvasTimeStart,
unit: this.props.unit,
- ratio: this.state.ratio,
- left,
+ left
}),
key: `label-${startTime.valueOf()}`
}
}
- calculateRatio(canvasWidth, canvasTimeEnd, canvasTimeStart) {
- return canvasWidth / (canvasTimeEnd - canvasTimeStart)
- }
-
- getIntervalStyle = ({ startTime, canvasTimeStart, ratio, unit, left,labelWidth, style, }) => {
-
+ getIntervalStyle = ({ left, labelWidth, style }) => {
return {
...style,
left,
@@ -188,7 +171,8 @@ export class CustomHeader extends React.Component {
showPeriod,
timelineWidth,
visibleTimeStart,
- visibleTimeEnd
+ visibleTimeEnd,
+ headerData,
} = this.props
//TODO: only evaluate on changing params
return {
@@ -205,17 +189,19 @@ export class CustomHeader extends React.Component {
},
getRootProps: this.getRootProps,
getIntervalProps: this.getIntervalProps,
- showPeriod
+ showPeriod,
+ data: headerData,
}
}
render() {
const props = this.getStateAndHelpers()
- return this.props.children(props, this.props.props)
+ const Renderer = this.props.children
+ return
}
}
-const CustomHeaderWrapper = ({ children, unit, props }) => (
+const CustomHeaderWrapper = ({ children, unit, headerData, height }) => (
{({ getTimelineState, showPeriod, getLeftOffsetFromDate }) => {
const timelineState = getTimelineState()
@@ -228,8 +214,9 @@ const CustomHeaderWrapper = ({ children, unit, props }) => (
showPeriod={showPeriod}
unit={unit ? unit : timelineState.timelineUnit}
{...timelineState}
- props={props}
+ headerData={headerData}
getLeftOffsetFromDate={getLeftOffsetFromDate}
+ height={height}
/>
)}
@@ -241,7 +228,12 @@ const CustomHeaderWrapper = ({ children, unit, props }) => (
CustomHeaderWrapper.propTypes = {
children: PropTypes.func.isRequired,
unit: PropTypes.string,
- props: PropTypes.object,
+ headerData: PropTypes.object,
+ height: PropTypes.number,
+}
+
+CustomHeaderWrapper.defaultProps = {
+ height: 30,
}
export default CustomHeaderWrapper
diff --git a/src/lib/headers/DateHeader.js b/src/lib/headers/DateHeader.js
index d5a1d3962..43092824f 100644
--- a/src/lib/headers/DateHeader.js
+++ b/src/lib/headers/DateHeader.js
@@ -8,8 +8,6 @@ import Interval from './Interval'
class DateHeader extends React.PureComponent {
static propTypes = {
- primaryHeader: PropTypes.bool,
- secondaryHeader: PropTypes.bool,
unit: PropTypes.string,
style: PropTypes.object,
className: PropTypes.string,
@@ -20,34 +18,55 @@ class DateHeader extends React.PureComponent {
PropTypes.string
]).isRequired,
intervalRenderer: PropTypes.func,
- props: PropTypes.object,
+ headerData: PropTypes.object,
+ height: PropTypes.number,
}
getHeaderUnit = () => {
- if (this.props.unit) {
- return this.props.unit
- } else if (this.props.primaryHeader) {
+ if (this.props.unit === 'primaryHeader') {
return getNextUnit(this.props.timelineUnit)
+ } else if (this.props.unit) {
+ return this.props.unit
}
return this.props.timelineUnit
}
+ getRootStyle = () => {
+ return {
+ height: 30,
+ ...this.props.style
+ }
+ }
+
+ getLabelFormat(interval, unit, labelWidth) {
+ const { labelFormat } = this.props
+ if (typeof labelFormat === 'string') {
+ const startTime = interval[0]
+ return startTime.format(labelFormat)
+ } else if (typeof labelFormat === 'function') {
+ return labelFormat(interval, unit, labelWidth)
+ } else {
+ throw new Error('labelFormat should be function or string')
+ }
+ }
+
render() {
const unit = this.getHeaderUnit()
- const {props} = this.props;
+ const { headerData, height } = this.props
return (
-
+
{({
headerContext: { intervals },
getRootProps,
getIntervalProps,
- showPeriod
- }, props) => {
+ showPeriod,
+ data
+ }) => {
const unit = this.getHeaderUnit()
return (
@@ -64,11 +83,10 @@ class DateHeader extends React.PureComponent {
interval={interval}
showPeriod={showPeriod}
intervalText={intervalText}
- primaryHeader={!!this.props.primaryHeader}
- secondaryHeader={!!this.props.secondaryHeader}
+ primaryHeader={this.props.unit === 'primaryHeader'}
getIntervalProps={getIntervalProps}
intervalRenderer={this.props.intervalRenderer}
- props={props}
+ headerData={data}
/>
)
})}
@@ -78,38 +96,16 @@ class DateHeader extends React.PureComponent {
)
}
-
- getRootStyle = () => {
- return {
- height: 30,
- ...this.props.style
- }
- }
-
- getLabelFormat(interval, unit, labelWidth) {
- const { labelFormat } = this.props
- if (typeof labelFormat === 'string') {
- const startTime = interval[0]
- return startTime.format(labelFormat)
- } else if (typeof labelFormat === 'object') {
- return formatLabel(interval, unit, labelWidth, labelFormat)
- } else if (typeof labelFormat === 'function') {
- return labelFormat(interval, unit, labelWidth)
- } else {
- throw new Error('labelFormat should be function, object or string')
- }
- }
}
const DateHeaderWrapper = ({
- primaryHeader,
- secondaryHeader,
unit,
labelFormat,
style,
className,
intervalRenderer,
- props,
+ headerData,
+ height,
}) => (
{({ getTimelineState }) => {
@@ -117,14 +113,13 @@ const DateHeaderWrapper = ({
return (
)
}}
@@ -134,8 +129,6 @@ const DateHeaderWrapper = ({
DateHeaderWrapper.propTypes = {
style: PropTypes.object,
className: PropTypes.string,
- primaryHeader: PropTypes.bool,
- secondaryHeader: PropTypes.bool,
unit: PropTypes.string,
labelFormat: PropTypes.oneOfType([
PropTypes.func,
@@ -143,11 +136,11 @@ DateHeaderWrapper.propTypes = {
PropTypes.string
]),
intervalRenderer: PropTypes.func,
- props: PropTypes.object,
+ headerData: PropTypes.object,
+ height: PropTypes.number,
}
DateHeaderWrapper.defaultProps = {
- secondaryHeader: true,
labelFormat: formatLabel
}
diff --git a/src/lib/headers/Interval.js b/src/lib/headers/Interval.js
index 7da76f3a7..25abef2ea 100644
--- a/src/lib/headers/Interval.js
+++ b/src/lib/headers/Interval.js
@@ -11,30 +11,8 @@ class Interval extends React.PureComponent {
showPeriod: PropTypes.func.isRequired,
intervalText: PropTypes.string.isRequired,
primaryHeader: PropTypes.bool.isRequired,
- secondaryHeader: PropTypes.bool.isRequired,
getIntervalProps: PropTypes.func.isRequired,
- props: PropTypes.object
- }
-
- getIntervalStyle = () => {
- return {
- display: 'flex',
- alignItems: 'center',
- justifyContent: 'center',
- backgroundColor:
- this.props.secondaryHeader && !this.props.primaryHeader
- ? 'rgb(240, 240, 240)'
- : 'initial',
- height: '100%',
- borderLeft: this.props.primaryHeader
- ? '1px solid #bbb'
- : '2px solid #bbb',
- borderRight: this.props.primaryHeader ? '1px solid #bbb' : 'none',
- borderBottom: '1px solid #bbb',
- color: this.props.primaryHeader ? '#fff' : 'initial',
- cursor: 'pointer',
- fontSize: '14px'
- }
+ headerData: PropTypes.object
}
onIntervalClick = () => {
@@ -49,7 +27,7 @@ class Interval extends React.PureComponent {
}
}
- getIntervalProps = (props={}) => {
+ getIntervalProps = (props = {}) => {
return {
...this.props.getIntervalProps({
interval: this.props.interval,
@@ -60,20 +38,27 @@ class Interval extends React.PureComponent {
}
render() {
- const { intervalText, interval, intervalRenderer, props } = this.props
- if (intervalRenderer)
- return intervalRenderer({
- getIntervalProps: this.getIntervalProps,
- intervalContext: {
- interval,
- intervalText
- }
- }, props)
+ const { intervalText, interval, intervalRenderer, headerData } = this.props
+ const Renderer = intervalRenderer
+ if (Renderer) {
+ return (
+
+ )
+ }
+
return (
{intervalText}
diff --git a/src/lib/headers/SidebarHeader.js b/src/lib/headers/SidebarHeader.js
index 3ad4aa603..8f0f79b5e 100644
--- a/src/lib/headers/SidebarHeader.js
+++ b/src/lib/headers/SidebarHeader.js
@@ -9,7 +9,7 @@ class SidebarHeader extends React.PureComponent {
rightSidebarWidth: PropTypes.number,
leftSidebarWidth: PropTypes.number.isRequired,
variant: PropTypes.string,
- props: PropTypes.object
+ headerData: PropTypes.object
}
getRootProps = (props = {}) => {
@@ -20,25 +20,27 @@ class SidebarHeader extends React.PureComponent {
: this.props.leftSidebarWidth
return {
style: {
+ ...style,
width,
- ...style
}
}
}
getStateAndHelpers = () => {
return {
- getRootProps: this.getRootProps
+ getRootProps: this.getRootProps,
+ data: this.props.headerData,
}
}
render() {
const props = this.getStateAndHelpers()
- return this.props.children(props, this.props.props)
+ const Renderer = this.props.children
+ return
}
}
-const SidebarWrapper = ({ children, variant, props }) => (
+const SidebarWrapper = ({ children, variant, headerData }) => (
{({ leftSidebarWidth, rightSidebarWidth }) => {
return (
@@ -47,7 +49,7 @@ const SidebarWrapper = ({ children, variant, props }) => (
rightSidebarWidth={rightSidebarWidth}
children={children}
variant={variant}
- props={props}
+ headerData={headerData}
/>
)
}}
@@ -57,7 +59,7 @@ const SidebarWrapper = ({ children, variant, props }) => (
SidebarWrapper.propTypes = {
children: PropTypes.func.isRequired,
variant: PropTypes.string,
- props: PropTypes.object
+ headerData: PropTypes.object
}
SidebarWrapper.defaultProps = {
diff --git a/src/lib/headers/TimelineHeaders.js b/src/lib/headers/TimelineHeaders.js
index 080513253..05f0124ce 100644
--- a/src/lib/headers/TimelineHeaders.js
+++ b/src/lib/headers/TimelineHeaders.js
@@ -13,7 +13,8 @@ class TimelineHeaders extends React.PureComponent {
className: PropTypes.string,
calendarHeaderStyle: PropTypes.object,
calendarHeaderClassName: PropTypes.string,
- width: PropTypes.number.isRequired
+ width: PropTypes.number.isRequired,
+ headerRef: PropTypes.func,
}
constructor(props) {
@@ -22,8 +23,6 @@ class TimelineHeaders extends React.PureComponent {
getRootStyle = () => {
return {
- background: '#c52020',
- borderBottom: '1px solid #bbb',
...this.props.style,
display: 'flex',
width: 'max-content'
@@ -37,13 +36,18 @@ class TimelineHeaders extends React.PureComponent {
calendarHeaderStyle
} = this.props
return {
- border: '1px solid #bbb',
...calendarHeaderStyle,
overflow: 'hidden',
width: this.props.width
}
}
+ handleRootRef = (element) => {
+ if(this.props.headerRef){
+ this.props.headerRef(element)
+ }
+ }
+
render() {
let rightSidebarHeader
let leftSidebarHeader
@@ -52,27 +56,28 @@ class TimelineHeaders extends React.PureComponent {
? this.props.children.filter(c => c)
: [this.props.children]
React.Children.map(children, child => {
- if (
- child.type === SidebarHeader &&
- child.props.variant === RIGHT_VARIANT
- ) {
- rightSidebarHeader = child
- } else if (
- child.type === SidebarHeader &&
- child.props.variant === LEFT_VARIANT
- ) {
- leftSidebarHeader = child
+ if (child.type === SidebarHeader) {
+ if (child.props.variant === RIGHT_VARIANT) {
+ rightSidebarHeader = child
+ } else {
+ leftSidebarHeader = child
+ }
} else {
calendarHeaders.push(child)
}
})
return (
-
+
{leftSidebarHeader}
{calendarHeaders}
@@ -120,7 +125,8 @@ TimelineHeadersWrapper.propTypes = {
style: PropTypes.object,
className: PropTypes.string,
calendarHeaderStyle: PropTypes.object,
- calendarHeaderClassName: PropTypes.string
+ calendarHeaderClassName: PropTypes.string,
+ headerRef: PropTypes.func,
}
export default TimelineHeadersWrapper
diff --git a/src/lib/markers/TimelineMarkersContext.js b/src/lib/markers/TimelineMarkersContext.js
index f71e5bd1c..474a36e28 100644
--- a/src/lib/markers/TimelineMarkersContext.js
+++ b/src/lib/markers/TimelineMarkersContext.js
@@ -42,7 +42,7 @@ export class TimelineMarkersProvider extends React.Component {
unsubscribe: () => {
this.setState(state => {
return {
- markers: state.markers.filter(marker => marker !== newMarker)
+ markers: state.markers.filter(marker => marker.id !== newMarker.id)
}
})
},
diff --git a/yarn.lock b/yarn.lock
index 2ce970fe8..d2f8d167f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -10,10 +10,35 @@
esutils "^2.0.2"
js-tokens "^3.0.0"
+"@babel/runtime@^7.3.4", "@babel/runtime@^7.4.2":
+ version "7.4.2"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.2.tgz#f5ab6897320f16decd855eed70b705908a313fe8"
+ dependencies:
+ regenerator-runtime "^0.13.2"
+
+"@jest/types@^24.5.0":
+ version "24.5.0"
+ resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.5.0.tgz#feee214a4d0167b0ca447284e95a57aa10b3ee95"
+ dependencies:
+ "@types/istanbul-lib-coverage" "^1.1.0"
+ "@types/yargs" "^12.0.9"
+
+"@sheerun/mutationobserver-shim@^0.3.2":
+ version "0.3.2"
+ resolved "https://registry.yarnpkg.com/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.2.tgz#8013f2af54a2b7d735f71560ff360d3a8176a87b"
+
+"@types/istanbul-lib-coverage@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.0.tgz#2cc2ca41051498382b43157c8227fea60363f94a"
+
"@types/node@*":
version "9.3.0"
resolved "https://registry.yarnpkg.com/@types/node/-/node-9.3.0.tgz#3a129cda7c4e5df2409702626892cb4b96546dd5"
+"@types/yargs@^12.0.9":
+ version "12.0.10"
+ resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-12.0.10.tgz#17a8ec65cd8e88f51b418ceb271af18d3137df67"
+
"@webassemblyjs/ast@1.5.13":
version "1.5.13"
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.5.13.tgz#81155a570bd5803a30ec31436bc2c9c0ede38f25"
@@ -267,6 +292,10 @@ ansi-regex@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
+ansi-regex@^4.0.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997"
+
ansi-styles@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
@@ -685,12 +714,12 @@ babel-jest@^22.0.6:
babel-plugin-istanbul "^4.1.5"
babel-preset-jest "^22.0.6"
-babel-jest@^23.0.1:
- version "23.0.1"
- resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-23.0.1.tgz#bbad3bf523fb202da05ed0a6540b48c84eed13a6"
+babel-jest@^23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-23.6.0.tgz#a644232366557a2240a0c083da6b25786185a2f1"
dependencies:
babel-plugin-istanbul "^4.1.6"
- babel-preset-jest "^23.0.1"
+ babel-preset-jest "^23.2.0"
babel-loader@^7.1.5:
version "7.1.5"
@@ -733,9 +762,9 @@ babel-plugin-jest-hoist@^22.0.6:
version "22.0.6"
resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-22.0.6.tgz#551269ded350a15d6585da35d16d449df30d66c4"
-babel-plugin-jest-hoist@^23.0.1:
- version "23.0.1"
- resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-23.0.1.tgz#eaa11c964563aea9c21becef2bdf7853f7f3c148"
+babel-plugin-jest-hoist@^23.2.0:
+ version "23.2.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-23.2.0.tgz#e61fae05a1ca8801aadee57a6d66b8cefaf44167"
babel-plugin-react-remove-properties@^0.2.5:
version "0.2.5"
@@ -1073,11 +1102,11 @@ babel-preset-jest@^22.0.6:
babel-plugin-jest-hoist "^22.0.6"
babel-plugin-syntax-object-rest-spread "^6.13.0"
-babel-preset-jest@^23.0.1:
- version "23.0.1"
- resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-23.0.1.tgz#631cc545c6cf021943013bcaf22f45d87fe62198"
+babel-preset-jest@^23.2.0:
+ version "23.2.0"
+ resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-23.2.0.tgz#8ec7a03a138f001a1a8fb1e8113652bf1a55da46"
dependencies:
- babel-plugin-jest-hoist "^23.0.1"
+ babel-plugin-jest-hoist "^23.2.0"
babel-plugin-syntax-object-rest-spread "^6.13.0"
babel-preset-react@^6.5.0:
@@ -1120,7 +1149,7 @@ babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.26.0:
babylon "^6.18.0"
lodash "^4.17.4"
-babel-traverse@^6.18.0, babel-traverse@^6.23.1, babel-traverse@^6.24.1, babel-traverse@^6.26.0:
+babel-traverse@^6.0.0, babel-traverse@^6.18.0, babel-traverse@^6.23.1, babel-traverse@^6.24.1, babel-traverse@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee"
dependencies:
@@ -1134,7 +1163,7 @@ babel-traverse@^6.18.0, babel-traverse@^6.23.1, babel-traverse@^6.24.1, babel-tr
invariant "^2.2.2"
lodash "^4.17.4"
-babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.23.0, babel-types@^6.24.1, babel-types@^6.26.0:
+babel-types@^6.0.0, babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.23.0, babel-types@^6.24.1, babel-types@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497"
dependencies:
@@ -1297,9 +1326,9 @@ browser-process-hrtime@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-0.1.2.tgz#425d68a58d3447f02a04aa894187fce8af8b7b8e"
-browser-resolve@^1.11.2:
- version "1.11.2"
- resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.2.tgz#8ff09b0a2c421718a1051c260b32e48f442938ce"
+browser-resolve@^1.11.3:
+ version "1.11.3"
+ resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.3.tgz#9b7cbb3d0f510e4cb86bdbd796124d28b5890af6"
dependencies:
resolve "1.1.7"
@@ -2302,13 +2331,14 @@ dom-serializer@0, dom-serializer@~0.1.0:
domelementtype "~1.1.1"
entities "~1.1.1"
-dom-testing-library@^3.1.0:
- version "3.6.0"
- resolved "https://registry.yarnpkg.com/dom-testing-library/-/dom-testing-library-3.6.0.tgz#e5598fae9477f3918e22aee44f2262727203b5bd"
+dom-testing-library@^3.18.2:
+ version "3.18.2"
+ resolved "https://registry.yarnpkg.com/dom-testing-library/-/dom-testing-library-3.18.2.tgz#07d65166743ad3299b7bee5b488e9622c31241bc"
dependencies:
- mutationobserver-shim "^0.3.2"
- pretty-format "^22.4.3"
- wait-for-expect "^1.0.0"
+ "@babel/runtime" "^7.3.4"
+ "@sheerun/mutationobserver-shim" "^0.3.2"
+ pretty-format "^24.5.0"
+ wait-for-expect "^1.1.0"
domain-browser@^1.1.1:
version "1.1.7"
@@ -2758,16 +2788,16 @@ expand-range@^1.8.1:
dependencies:
fill-range "^2.1.0"
-expect@^23.1.0:
- version "23.1.0"
- resolved "https://registry.yarnpkg.com/expect/-/expect-23.1.0.tgz#bfdfd57a2a20170d875999ee9787cc71f01c205f"
+expect@^23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/expect/-/expect-23.6.0.tgz#1e0c8d3ba9a581c87bd71fb9bc8862d443425f98"
dependencies:
ansi-styles "^3.2.0"
- jest-diff "^23.0.1"
+ jest-diff "^23.6.0"
jest-get-type "^22.1.0"
- jest-matcher-utils "^23.0.1"
- jest-message-util "^23.1.0"
- jest-regex-util "^23.0.0"
+ jest-matcher-utils "^23.6.0"
+ jest-message-util "^23.4.0"
+ jest-regex-util "^23.3.0"
express@^4.16.2:
version "4.16.3"
@@ -3721,7 +3751,7 @@ invariant@^2.2.1:
dependencies:
loose-envify "^1.0.0"
-invariant@^2.2.2:
+invariant@^2.2.2, invariant@^2.2.4:
version "2.2.4"
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
dependencies:
@@ -4112,15 +4142,15 @@ istanbul-reports@^1.3.0:
dependencies:
handlebars "^4.0.3"
-jest-changed-files@^23.0.1:
- version "23.0.1"
- resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-23.0.1.tgz#f79572d0720844ea5df84c2a448e862c2254f60c"
+jest-changed-files@^23.4.2:
+ version "23.4.2"
+ resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-23.4.2.tgz#1eed688370cd5eebafe4ae93d34bb3b64968fe83"
dependencies:
throat "^4.0.0"
-jest-cli@^23.1.0:
- version "23.1.0"
- resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-23.1.0.tgz#eb8bdd4ce0d15250892e31ad9b69bc99d2a8f6bf"
+jest-cli@^23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-23.6.0.tgz#61ab917744338f443ef2baa282ddffdd658a5da4"
dependencies:
ansi-escapes "^3.0.0"
chalk "^2.0.1"
@@ -4133,23 +4163,24 @@ jest-cli@^23.1.0:
istanbul-lib-coverage "^1.2.0"
istanbul-lib-instrument "^1.10.1"
istanbul-lib-source-maps "^1.2.4"
- jest-changed-files "^23.0.1"
- jest-config "^23.1.0"
- jest-environment-jsdom "^23.1.0"
+ jest-changed-files "^23.4.2"
+ jest-config "^23.6.0"
+ jest-environment-jsdom "^23.4.0"
jest-get-type "^22.1.0"
- jest-haste-map "^23.1.0"
- jest-message-util "^23.1.0"
- jest-regex-util "^23.0.0"
- jest-resolve-dependencies "^23.0.1"
- jest-runner "^23.1.0"
- jest-runtime "^23.1.0"
- jest-snapshot "^23.0.1"
- jest-util "^23.1.0"
- jest-validate "^23.0.1"
- jest-watcher "^23.1.0"
- jest-worker "^23.0.1"
+ jest-haste-map "^23.6.0"
+ jest-message-util "^23.4.0"
+ jest-regex-util "^23.3.0"
+ jest-resolve-dependencies "^23.6.0"
+ jest-runner "^23.6.0"
+ jest-runtime "^23.6.0"
+ jest-snapshot "^23.6.0"
+ jest-util "^23.4.0"
+ jest-validate "^23.6.0"
+ jest-watcher "^23.4.0"
+ jest-worker "^23.2.0"
micromatch "^2.3.11"
node-notifier "^5.2.1"
+ prompts "^0.1.9"
realpath-native "^1.0.0"
rimraf "^2.5.4"
slash "^1.0.0"
@@ -4158,23 +4189,24 @@ jest-cli@^23.1.0:
which "^1.2.12"
yargs "^11.0.0"
-jest-config@^23.1.0:
- version "23.1.0"
- resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-23.1.0.tgz#708ca0f431d356ee424fb4895d3308006bdd8241"
+jest-config@^23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-23.6.0.tgz#f82546a90ade2d8c7026fbf6ac5207fc22f8eb1d"
dependencies:
babel-core "^6.0.0"
- babel-jest "^23.0.1"
+ babel-jest "^23.6.0"
chalk "^2.0.1"
glob "^7.1.1"
- jest-environment-jsdom "^23.1.0"
- jest-environment-node "^23.1.0"
+ jest-environment-jsdom "^23.4.0"
+ jest-environment-node "^23.4.0"
jest-get-type "^22.1.0"
- jest-jasmine2 "^23.1.0"
- jest-regex-util "^23.0.0"
- jest-resolve "^23.1.0"
- jest-util "^23.1.0"
- jest-validate "^23.0.1"
- pretty-format "^23.0.1"
+ jest-jasmine2 "^23.6.0"
+ jest-regex-util "^23.3.0"
+ jest-resolve "^23.6.0"
+ jest-util "^23.4.0"
+ jest-validate "^23.6.0"
+ micromatch "^2.3.11"
+ pretty-format "^23.6.0"
jest-diff@^22.4.3:
version "22.4.3"
@@ -4185,22 +4217,22 @@ jest-diff@^22.4.3:
jest-get-type "^22.4.3"
pretty-format "^22.4.3"
-jest-diff@^23.0.1:
- version "23.0.1"
- resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-23.0.1.tgz#3d49137cee12c320a4b4d2b4a6fa6e82d491a16a"
+jest-diff@^23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-23.6.0.tgz#1500f3f16e850bb3d71233408089be099f610c7d"
dependencies:
chalk "^2.0.1"
diff "^3.2.0"
jest-get-type "^22.1.0"
- pretty-format "^23.0.1"
+ pretty-format "^23.6.0"
jest-docblock@^21.0.0:
version "21.2.0"
resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.2.0.tgz#51529c3b30d5fd159da60c27ceedc195faf8d414"
-jest-docblock@^23.0.1:
- version "23.0.1"
- resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-23.0.1.tgz#deddd18333be5dc2415260a04ef3fce9276b5725"
+jest-docblock@^23.2.0:
+ version "23.2.0"
+ resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-23.2.0.tgz#f085e1f18548d99fdd69b20207e6fd55d91383a7"
dependencies:
detect-newline "^2.1.0"
@@ -4215,65 +4247,67 @@ jest-dom@^1.12.1:
pretty-format "^23.0.1"
redent "^2.0.0"
-jest-each@^23.1.0:
- version "23.1.0"
- resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-23.1.0.tgz#16146b592c354867a5ae5e13cdf15c6c65b696c6"
+jest-each@^23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-23.6.0.tgz#ba0c3a82a8054387016139c733a05242d3d71575"
dependencies:
chalk "^2.0.1"
- pretty-format "^23.0.1"
+ pretty-format "^23.6.0"
-jest-environment-jsdom@^23.1.0:
- version "23.1.0"
- resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-23.1.0.tgz#85929914e23bed3577dac9755f4106d0697c479c"
+jest-environment-jsdom@^23.4.0:
+ version "23.4.0"
+ resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-23.4.0.tgz#056a7952b3fea513ac62a140a2c368c79d9e6023"
dependencies:
- jest-mock "^23.1.0"
- jest-util "^23.1.0"
+ jest-mock "^23.2.0"
+ jest-util "^23.4.0"
jsdom "^11.5.1"
-jest-environment-node@^23.1.0:
- version "23.1.0"
- resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-23.1.0.tgz#452c0bf949cfcbbacda1e1762eeed70bc784c7d5"
+jest-environment-node@^23.4.0:
+ version "23.4.0"
+ resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-23.4.0.tgz#57e80ed0841dea303167cce8cd79521debafde10"
dependencies:
- jest-mock "^23.1.0"
- jest-util "^23.1.0"
+ jest-mock "^23.2.0"
+ jest-util "^23.4.0"
jest-get-type@^22.1.0, jest-get-type@^22.4.3:
version "22.4.3"
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-22.4.3.tgz#e3a8504d8479342dd4420236b322869f18900ce4"
-jest-haste-map@^23.1.0:
- version "23.1.0"
- resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-23.1.0.tgz#18e6c7d5a8d27136f91b7d9852f85de0c7074c49"
+jest-haste-map@^23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-23.6.0.tgz#2e3eb997814ca696d62afdb3f2529f5bbc935e16"
dependencies:
fb-watchman "^2.0.0"
graceful-fs "^4.1.11"
- jest-docblock "^23.0.1"
+ invariant "^2.2.4"
+ jest-docblock "^23.2.0"
jest-serializer "^23.0.1"
- jest-worker "^23.0.1"
+ jest-worker "^23.2.0"
micromatch "^2.3.11"
sane "^2.0.0"
-jest-jasmine2@^23.1.0:
- version "23.1.0"
- resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-23.1.0.tgz#4afab31729b654ddcd2b074add849396f13b30b8"
+jest-jasmine2@^23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-23.6.0.tgz#840e937f848a6c8638df24360ab869cc718592e0"
dependencies:
+ babel-traverse "^6.0.0"
chalk "^2.0.1"
co "^4.6.0"
- expect "^23.1.0"
+ expect "^23.6.0"
is-generator-fn "^1.0.0"
- jest-diff "^23.0.1"
- jest-each "^23.1.0"
- jest-matcher-utils "^23.0.1"
- jest-message-util "^23.1.0"
- jest-snapshot "^23.0.1"
- jest-util "^23.1.0"
- pretty-format "^23.0.1"
+ jest-diff "^23.6.0"
+ jest-each "^23.6.0"
+ jest-matcher-utils "^23.6.0"
+ jest-message-util "^23.4.0"
+ jest-snapshot "^23.6.0"
+ jest-util "^23.4.0"
+ pretty-format "^23.6.0"
-jest-leak-detector@^23.0.1:
- version "23.0.1"
- resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-23.0.1.tgz#9dba07505ac3495c39d3ec09ac1e564599e861a0"
+jest-leak-detector@^23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-23.6.0.tgz#e4230fd42cf381a1a1971237ad56897de7e171de"
dependencies:
- pretty-format "^23.0.1"
+ pretty-format "^23.6.0"
jest-matcher-utils@^22.4.3:
version "22.4.3"
@@ -4283,17 +4317,17 @@ jest-matcher-utils@^22.4.3:
jest-get-type "^22.4.3"
pretty-format "^22.4.3"
-jest-matcher-utils@^23.0.1:
- version "23.0.1"
- resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-23.0.1.tgz#0c6c0daedf9833c2a7f36236069efecb4c3f6e5f"
+jest-matcher-utils@^23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-23.6.0.tgz#726bcea0c5294261a7417afb6da3186b4b8cac80"
dependencies:
chalk "^2.0.1"
jest-get-type "^22.1.0"
- pretty-format "^23.0.1"
+ pretty-format "^23.6.0"
-jest-message-util@^23.1.0:
- version "23.1.0"
- resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-23.1.0.tgz#9a809ba487ecac5ce511d4e698ee3b5ee2461ea9"
+jest-message-util@^23.4.0:
+ version "23.4.0"
+ resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-23.4.0.tgz#17610c50942349508d01a3d1e0bda2c079086a9f"
dependencies:
"@babel/code-frame" "^7.0.0-beta.35"
chalk "^2.0.1"
@@ -4301,50 +4335,50 @@ jest-message-util@^23.1.0:
slash "^1.0.0"
stack-utils "^1.0.1"
-jest-mock@^23.1.0:
- version "23.1.0"
- resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-23.1.0.tgz#a381c31b121ab1f60c462a2dadb7b86dcccac487"
+jest-mock@^23.2.0:
+ version "23.2.0"
+ resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-23.2.0.tgz#ad1c60f29e8719d47c26e1138098b6d18b261134"
-jest-regex-util@^23.0.0:
- version "23.0.0"
- resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-23.0.0.tgz#dd5c1fde0c46f4371314cf10f7a751a23f4e8f76"
+jest-regex-util@^23.3.0:
+ version "23.3.0"
+ resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-23.3.0.tgz#5f86729547c2785c4002ceaa8f849fe8ca471bc5"
-jest-resolve-dependencies@^23.0.1:
- version "23.0.1"
- resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-23.0.1.tgz#d01a10ddad9152c4cecdf5eac2b88571c4b6a64d"
+jest-resolve-dependencies@^23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-23.6.0.tgz#b4526af24c8540d9a3fab102c15081cf509b723d"
dependencies:
- jest-regex-util "^23.0.0"
- jest-snapshot "^23.0.1"
+ jest-regex-util "^23.3.0"
+ jest-snapshot "^23.6.0"
-jest-resolve@^23.1.0:
- version "23.1.0"
- resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-23.1.0.tgz#b9e316eecebd6f00bc50a3960d1527bae65792d2"
+jest-resolve@^23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-23.6.0.tgz#cf1d1a24ce7ee7b23d661c33ba2150f3aebfa0ae"
dependencies:
- browser-resolve "^1.11.2"
+ browser-resolve "^1.11.3"
chalk "^2.0.1"
realpath-native "^1.0.0"
-jest-runner@^23.1.0:
- version "23.1.0"
- resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-23.1.0.tgz#fa20a933fff731a5432b3561e7f6426594fa29b5"
+jest-runner@^23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-23.6.0.tgz#3894bd219ffc3f3cb94dc48a4170a2e6f23a5a38"
dependencies:
exit "^0.1.2"
graceful-fs "^4.1.11"
- jest-config "^23.1.0"
- jest-docblock "^23.0.1"
- jest-haste-map "^23.1.0"
- jest-jasmine2 "^23.1.0"
- jest-leak-detector "^23.0.1"
- jest-message-util "^23.1.0"
- jest-runtime "^23.1.0"
- jest-util "^23.1.0"
- jest-worker "^23.0.1"
+ jest-config "^23.6.0"
+ jest-docblock "^23.2.0"
+ jest-haste-map "^23.6.0"
+ jest-jasmine2 "^23.6.0"
+ jest-leak-detector "^23.6.0"
+ jest-message-util "^23.4.0"
+ jest-runtime "^23.6.0"
+ jest-util "^23.4.0"
+ jest-worker "^23.2.0"
source-map-support "^0.5.6"
throat "^4.0.0"
-jest-runtime@^23.1.0:
- version "23.1.0"
- resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-23.1.0.tgz#b4ae0e87259ecacfd4a884b639db07cf4dd620af"
+jest-runtime@^23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-23.6.0.tgz#059e58c8ab445917cd0e0d84ac2ba68de8f23082"
dependencies:
babel-core "^6.0.0"
babel-plugin-istanbul "^4.1.6"
@@ -4353,14 +4387,14 @@ jest-runtime@^23.1.0:
exit "^0.1.2"
fast-json-stable-stringify "^2.0.0"
graceful-fs "^4.1.11"
- jest-config "^23.1.0"
- jest-haste-map "^23.1.0"
- jest-message-util "^23.1.0"
- jest-regex-util "^23.0.0"
- jest-resolve "^23.1.0"
- jest-snapshot "^23.0.1"
- jest-util "^23.1.0"
- jest-validate "^23.0.1"
+ jest-config "^23.6.0"
+ jest-haste-map "^23.6.0"
+ jest-message-util "^23.4.0"
+ jest-regex-util "^23.3.0"
+ jest-resolve "^23.6.0"
+ jest-snapshot "^23.6.0"
+ jest-util "^23.4.0"
+ jest-validate "^23.6.0"
micromatch "^2.3.11"
realpath-native "^1.0.0"
slash "^1.0.0"
@@ -4372,38 +4406,42 @@ jest-serializer@^23.0.1:
version "23.0.1"
resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-23.0.1.tgz#a3776aeb311e90fe83fab9e533e85102bd164165"
-jest-snapshot@^23.0.1:
- version "23.0.1"
- resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-23.0.1.tgz#6674fa19b9eb69a99cabecd415bddc42d6af3e7e"
+jest-snapshot@^23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-23.6.0.tgz#f9c2625d1b18acda01ec2d2b826c0ce58a5aa17a"
dependencies:
+ babel-types "^6.0.0"
chalk "^2.0.1"
- jest-diff "^23.0.1"
- jest-matcher-utils "^23.0.1"
+ jest-diff "^23.6.0"
+ jest-matcher-utils "^23.6.0"
+ jest-message-util "^23.4.0"
+ jest-resolve "^23.6.0"
mkdirp "^0.5.1"
natural-compare "^1.4.0"
- pretty-format "^23.0.1"
+ pretty-format "^23.6.0"
+ semver "^5.5.0"
-jest-util@^23.1.0:
- version "23.1.0"
- resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-23.1.0.tgz#c0251baf34644c6dd2fea78a962f4263ac55772d"
+jest-util@^23.4.0:
+ version "23.4.0"
+ resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-23.4.0.tgz#4d063cb927baf0a23831ff61bec2cbbf49793561"
dependencies:
callsites "^2.0.0"
chalk "^2.0.1"
graceful-fs "^4.1.11"
is-ci "^1.0.10"
- jest-message-util "^23.1.0"
+ jest-message-util "^23.4.0"
mkdirp "^0.5.1"
slash "^1.0.0"
source-map "^0.6.0"
-jest-validate@^23.0.1:
- version "23.0.1"
- resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-23.0.1.tgz#cd9f01a89d26bb885f12a8667715e9c865a5754f"
+jest-validate@^23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-23.6.0.tgz#36761f99d1ed33fcd425b4e4c5595d62b6597474"
dependencies:
chalk "^2.0.1"
jest-get-type "^22.1.0"
leven "^2.1.0"
- pretty-format "^23.0.1"
+ pretty-format "^23.6.0"
jest-watch-typeahead@^0.1.0:
version "0.1.0"
@@ -4416,26 +4454,26 @@ jest-watch-typeahead@^0.1.0:
string-length "^2.0.0"
strip-ansi "^4.0.0"
-jest-watcher@^23.1.0:
- version "23.1.0"
- resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-23.1.0.tgz#a8d5842e38d9fb4afff823df6abb42a58ae6cdbd"
+jest-watcher@^23.4.0:
+ version "23.4.0"
+ resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-23.4.0.tgz#d2e28ce74f8dad6c6afc922b92cabef6ed05c91c"
dependencies:
ansi-escapes "^3.0.0"
chalk "^2.0.1"
string-length "^2.0.0"
-jest-worker@^23.0.1:
- version "23.0.1"
- resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-23.0.1.tgz#9e649dd963ff4046026f91c4017f039a6aa4a7bc"
+jest-worker@^23.2.0:
+ version "23.2.0"
+ resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-23.2.0.tgz#faf706a8da36fae60eb26957257fa7b5d8ea02b9"
dependencies:
merge-stream "^1.0.1"
-jest@^23.1.0:
- version "23.1.0"
- resolved "https://registry.yarnpkg.com/jest/-/jest-23.1.0.tgz#bbb7f893100a11a742dd8bd0d047a54b0968ad1a"
+jest@^23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/jest/-/jest-23.6.0.tgz#ad5835e923ebf6e19e7a1d7529a432edfee7813d"
dependencies:
import-local "^1.0.0"
- jest-cli "^23.1.0"
+ jest-cli "^23.6.0"
js-base64@^2.1.8:
version "2.4.8"
@@ -4589,6 +4627,10 @@ kind-of@^6.0.0, kind-of@^6.0.2:
version "6.0.2"
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051"
+kleur@^2.0.1:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/kleur/-/kleur-2.0.2.tgz#b704f4944d95e255d038f0cb05fb8a602c55a300"
+
lazy-cache@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e"
@@ -5082,10 +5124,6 @@ multicast-dns@^6.0.1:
dns-packet "^1.3.1"
thunky "^1.0.2"
-mutationobserver-shim@^0.3.2:
- version "0.3.2"
- resolved "https://registry.yarnpkg.com/mutationobserver-shim/-/mutationobserver-shim-0.3.2.tgz#f4d5dae7a4971a2207914fb5a90ebd514b65acca"
-
mute-stream@0.0.7:
version "0.0.7"
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
@@ -6080,6 +6118,22 @@ pretty-format@^23.0.1:
ansi-regex "^3.0.0"
ansi-styles "^3.2.0"
+pretty-format@^23.6.0:
+ version "23.6.0"
+ resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-23.6.0.tgz#5eaac8eeb6b33b987b7fe6097ea6a8a146ab5760"
+ dependencies:
+ ansi-regex "^3.0.0"
+ ansi-styles "^3.2.0"
+
+pretty-format@^24.5.0:
+ version "24.5.0"
+ resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.5.0.tgz#cc69a0281a62cd7242633fc135d6930cd889822d"
+ dependencies:
+ "@jest/types" "^24.5.0"
+ ansi-regex "^4.0.0"
+ ansi-styles "^3.2.0"
+ react-is "^16.8.4"
+
private@^0.1.6, private@^0.1.7, private@^0.1.8:
version "0.1.8"
resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff"
@@ -6110,6 +6164,13 @@ promise@^7.1.1:
dependencies:
asap "~2.0.3"
+prompts@^0.1.9:
+ version "0.1.14"
+ resolved "https://registry.yarnpkg.com/prompts/-/prompts-0.1.14.tgz#a8e15c612c5c9ec8f8111847df3337c9cbd443b2"
+ dependencies:
+ kleur "^2.0.1"
+ sisteransi "^0.1.1"
+
prop-types@^15.5.4, prop-types@^15.6.0:
version "15.6.0"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.0.tgz#ceaf083022fc46b4a35f69e13ef75aed0d639856"
@@ -6305,6 +6366,10 @@ react-is@^16.4.1:
version "16.4.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.4.1.tgz#d624c4650d2c65dbd52c72622bbf389435d9776e"
+react-is@^16.8.4:
+ version "16.8.6"
+ resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16"
+
react-reconciler@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/react-reconciler/-/react-reconciler-0.7.0.tgz#9614894103e5f138deeeb5eabaf3ee80eb1d026d"
@@ -6346,12 +6411,12 @@ react-test-renderer@^16.0.0-0:
prop-types "^15.6.0"
react-is "^16.4.1"
-react-testing-library@^5.1.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/react-testing-library/-/react-testing-library-5.1.0.tgz#ae208d9e3b7faae233409d205e287b304ec8ffdc"
+react-testing-library@^6.0.3:
+ version "6.0.3"
+ resolved "https://registry.yarnpkg.com/react-testing-library/-/react-testing-library-6.0.3.tgz#8b5d276a353c17ce4f7486015bb7a1c8827c442c"
dependencies:
- dom-testing-library "^3.1.0"
- wait-for-expect "^1.0.0"
+ "@babel/runtime" "^7.4.2"
+ dom-testing-library "^3.18.2"
react@^16.2.0:
version "16.4.1"
@@ -6456,6 +6521,10 @@ regenerator-runtime@^0.11.0:
version "0.11.1"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
+regenerator-runtime@^0.13.2:
+ version "0.13.2"
+ resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz#32e59c9a6fb9b1a4aff09b4930ca2d4477343447"
+
regenerator-transform@^0.10.0:
version "0.10.1"
resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd"
@@ -6943,6 +7012,10 @@ signal-exit@^3.0.0, signal-exit@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
+sisteransi@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-0.1.1.tgz#5431447d5f7d1675aac667ccd0b865a4994cb3ce"
+
slash@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
@@ -7780,9 +7853,9 @@ vm-browserify@0.0.4:
dependencies:
indexof "0.0.1"
-wait-for-expect@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/wait-for-expect/-/wait-for-expect-1.0.1.tgz#73ab346ed56ed2ef66c380a59fd623755ceac0ce"
+wait-for-expect@^1.1.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/wait-for-expect/-/wait-for-expect-1.1.1.tgz#9cd10e07d52810af9e0aaf509872e38f3c3d81ae"
walker@~1.0.5:
version "1.0.7"