@coreui/react-pro 5.24.0 → 5.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cjs/components/calendar/CCalendar.js +4 -3
- package/dist/cjs/components/calendar/CCalendar.js.map +1 -1
- package/dist/cjs/components/date-picker/CDatePicker.d.ts +1 -1
- package/dist/cjs/components/date-picker/CDatePicker.js.map +1 -1
- package/dist/cjs/components/date-range-picker/CDateRangePicker.js +2 -0
- package/dist/cjs/components/date-range-picker/CDateRangePicker.js.map +1 -1
- package/dist/cjs/components/dropdown/CDropdown.js +1 -1
- package/dist/cjs/components/dropdown/CDropdown.js.map +1 -1
- package/dist/cjs/components/index.d.ts +1 -0
- package/dist/cjs/components/nav/CNavGroup.d.ts +3 -1
- package/dist/cjs/components/nav/CNavGroup.js +9 -5
- package/dist/cjs/components/nav/CNavGroup.js.map +1 -1
- package/dist/cjs/components/one-time-password-input/COneTimePassword.js +3 -3
- package/dist/cjs/components/one-time-password-input/COneTimePassword.js.map +1 -1
- package/dist/cjs/components/popover/CPopover.js +14 -17
- package/dist/cjs/components/popover/CPopover.js.map +1 -1
- package/dist/cjs/components/search-button/CSearchButton.d.ts +32 -0
- package/dist/cjs/components/search-button/CSearchButton.js +77 -0
- package/dist/cjs/components/search-button/CSearchButton.js.map +1 -0
- package/dist/cjs/components/search-button/index.d.ts +2 -0
- package/dist/cjs/components/search-button/types.d.ts +10 -0
- package/dist/cjs/components/search-button/utils.d.ts +11 -0
- package/dist/cjs/components/search-button/utils.js +115 -0
- package/dist/cjs/components/search-button/utils.js.map +1 -0
- package/dist/cjs/components/sidebar/CSidebarNav.d.ts +12 -0
- package/dist/cjs/components/sidebar/CSidebarNav.js +7 -2
- package/dist/cjs/components/sidebar/CSidebarNav.js.map +1 -1
- package/dist/cjs/components/smart-table/CSmartTable.js +2 -2
- package/dist/cjs/components/smart-table/CSmartTable.js.map +1 -1
- package/dist/cjs/components/smart-table/CSmartTableInterface.d.ts +2 -2
- package/dist/cjs/components/time-picker/CTimePicker.d.ts +1 -1
- package/dist/cjs/components/time-picker/CTimePicker.js +1 -1
- package/dist/cjs/components/time-picker/CTimePicker.js.map +1 -1
- package/dist/cjs/components/tooltip/CTooltip.js +14 -17
- package/dist/cjs/components/tooltip/CTooltip.js.map +1 -1
- package/dist/cjs/components/virtual-scroller/CVirtualScroller.js +11 -8
- package/dist/cjs/components/virtual-scroller/CVirtualScroller.js.map +1 -1
- package/dist/cjs/hooks/useDebouncedCallback.d.ts +1 -1
- package/dist/cjs/hooks/useDebouncedCallback.js +1 -1
- package/dist/cjs/hooks/useDebouncedCallback.js.map +1 -1
- package/dist/cjs/index.js +2 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-arrow-bottom.js +1 -1
- package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-arrow-bottom.js.map +1 -1
- package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-arrow-top.js +1 -1
- package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-arrow-top.js.map +1 -1
- package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-filter-x.js +1 -1
- package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-filter-x.js.map +1 -1
- package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-swap-vertical.js +1 -1
- package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-swap-vertical.js.map +1 -1
- package/dist/cjs/node_modules/ua-parser-js/dist/ua-parser.min.js +2 -2
- package/dist/cjs/node_modules/ua-parser-js/dist/ua-parser.min.js.map +1 -1
- package/dist/esm/components/calendar/CCalendar.js +4 -3
- package/dist/esm/components/calendar/CCalendar.js.map +1 -1
- package/dist/esm/components/date-picker/CDatePicker.d.ts +1 -1
- package/dist/esm/components/date-picker/CDatePicker.js.map +1 -1
- package/dist/esm/components/date-range-picker/CDateRangePicker.js +2 -0
- package/dist/esm/components/date-range-picker/CDateRangePicker.js.map +1 -1
- package/dist/esm/components/dropdown/CDropdown.js +1 -1
- package/dist/esm/components/dropdown/CDropdown.js.map +1 -1
- package/dist/esm/components/index.d.ts +1 -0
- package/dist/esm/components/nav/CNavGroup.d.ts +3 -1
- package/dist/esm/components/nav/CNavGroup.js +9 -5
- package/dist/esm/components/nav/CNavGroup.js.map +1 -1
- package/dist/esm/components/one-time-password-input/COneTimePassword.js +3 -3
- package/dist/esm/components/one-time-password-input/COneTimePassword.js.map +1 -1
- package/dist/esm/components/popover/CPopover.js +14 -17
- package/dist/esm/components/popover/CPopover.js.map +1 -1
- package/dist/esm/components/search-button/CSearchButton.d.ts +32 -0
- package/dist/esm/components/search-button/CSearchButton.js +75 -0
- package/dist/esm/components/search-button/CSearchButton.js.map +1 -0
- package/dist/esm/components/search-button/index.d.ts +2 -0
- package/dist/esm/components/search-button/types.d.ts +10 -0
- package/dist/esm/components/search-button/utils.d.ts +11 -0
- package/dist/esm/components/search-button/utils.js +104 -0
- package/dist/esm/components/search-button/utils.js.map +1 -0
- package/dist/esm/components/sidebar/CSidebarNav.d.ts +12 -0
- package/dist/esm/components/sidebar/CSidebarNav.js +7 -2
- package/dist/esm/components/sidebar/CSidebarNav.js.map +1 -1
- package/dist/esm/components/smart-table/CSmartTable.js +2 -2
- package/dist/esm/components/smart-table/CSmartTable.js.map +1 -1
- package/dist/esm/components/smart-table/CSmartTableInterface.d.ts +2 -2
- package/dist/esm/components/time-picker/CTimePicker.d.ts +1 -1
- package/dist/esm/components/time-picker/CTimePicker.js +1 -1
- package/dist/esm/components/time-picker/CTimePicker.js.map +1 -1
- package/dist/esm/components/tooltip/CTooltip.js +14 -17
- package/dist/esm/components/tooltip/CTooltip.js.map +1 -1
- package/dist/esm/components/virtual-scroller/CVirtualScroller.js +11 -8
- package/dist/esm/components/virtual-scroller/CVirtualScroller.js.map +1 -1
- package/dist/esm/hooks/useDebouncedCallback.d.ts +1 -1
- package/dist/esm/hooks/useDebouncedCallback.js +1 -1
- package/dist/esm/hooks/useDebouncedCallback.js.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-arrow-bottom.js +1 -1
- package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-arrow-bottom.js.map +1 -1
- package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-arrow-top.js +1 -1
- package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-arrow-top.js.map +1 -1
- package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-filter-x.js +1 -1
- package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-filter-x.js.map +1 -1
- package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-swap-vertical.js +1 -1
- package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-swap-vertical.js.map +1 -1
- package/dist/esm/node_modules/ua-parser-js/dist/ua-parser.min.js +2 -2
- package/dist/esm/node_modules/ua-parser-js/dist/ua-parser.min.js.map +1 -1
- package/package.json +7 -5
- package/src/components/autocomplete/__tests__/CAutocomplete.spec.tsx +18 -16
- package/src/components/autocomplete/__tests__/CAutocompleteOptions.spec.tsx +37 -28
- package/src/components/autocomplete/__tests__/__snapshots__/CAutocomplete.spec.tsx.snap +129 -0
- package/src/components/autocomplete/__tests__/__snapshots__/CAutocompleteOptions.spec.tsx.snap +36 -0
- package/src/components/calendar/CCalendar.tsx +5 -4
- package/src/components/calendar/__tests__/CCalendar.spec.tsx +40 -45
- package/src/components/calendar/__tests__/__snapshots__/CCalendar.spec.tsx.snap +99 -75
- package/src/components/calendar/__tests__/utils.spec.tsx +8 -18
- package/src/components/date-picker/CDatePicker.tsx +12 -13
- package/src/components/date-picker/__tests__/CDatePicker.spec.tsx +1 -1
- package/src/components/date-picker/__tests__/__snapshots__/CDatePicker.spec.tsx.snap +12 -640
- package/src/components/date-range-picker/CDateRangePicker.tsx +2 -0
- package/src/components/date-range-picker/__tests__/CDateRangePicker.spec.tsx +1 -1
- package/src/components/date-range-picker/__tests__/__snapshots__/CDateRangePicker.spec.tsx.snap +21 -1259
- package/src/components/dropdown/CDropdown.tsx +1 -1
- package/src/components/dropdown/__tests__/CDropdown.spec.tsx +1 -1
- package/src/components/dropdown/__tests__/__snapshots__/CDropdown.spec.tsx.snap +2 -2
- package/src/components/dropdown/__tests__/__snapshots__/CDropdownMenu.spec.tsx.snap +1 -1
- package/src/components/form/__tests__/CFormInput.spec.tsx +17 -20
- package/src/components/form/__tests__/__snapshots__/CFormInput.spec.tsx.snap +12 -3
- package/src/components/index.ts +1 -0
- package/src/components/loading-button/__tests__/CLoadingButton.spec.tsx +1 -1
- package/src/components/loading-button/__tests__/__snapshots__/CLoadingButton.spec.tsx.snap +4 -4
- package/src/components/multi-select/__tests__/CMultiSelect.spec.tsx +15 -61
- package/src/components/multi-select/__tests__/CMultiSelectNativeSelect.spec.tsx +4 -5
- package/src/components/multi-select/__tests__/CMultiSelectOptions.spec.tsx +4 -4
- package/src/components/multi-select/__tests__/CMultiSelectSelection.spec.tsx +7 -24
- package/src/components/multi-select/__tests__/__snapshots__/CMultiSelect.spec.tsx.snap +50 -20
- package/src/components/multi-select/__tests__/__snapshots__/CMultiSelectNativeSelect.spec.tsx.snap +0 -2
- package/src/components/multi-select/__tests__/__snapshots__/CMultiSelectOptions.spec.tsx.snap +6 -0
- package/src/components/multi-select/__tests__/__snapshots__/CMultiSelectSelection.spec.tsx.snap +11 -8
- package/src/components/nav/CNavGroup.tsx +11 -6
- package/src/components/nav/__tests__/CNavGroup.spec.tsx +29 -1
- package/src/components/nav/__tests__/__snapshots__/CNavGroup.spec.tsx.snap +1 -1
- package/src/components/offcanvas/__tests__/COffcanvas.spec.tsx +1 -0
- package/src/components/one-time-password-input/COneTimePassword.tsx +10 -11
- package/src/components/picker/__tests__/CPicker.spec.tsx +1 -1
- package/src/components/picker/__tests__/__snapshots__/CPicker.spec.tsx.snap +2 -16
- package/src/components/popover/CPopover.tsx +15 -20
- package/src/components/popover/__tests__/CPopover.spec.tsx +10 -4
- package/src/components/search-button/CSearchButton.tsx +195 -0
- package/src/components/search-button/__tests__/CSearchButton.spec.tsx +95 -0
- package/src/components/search-button/__tests__/__snapshots__/CSearchButton.spec.tsx.snap +87 -0
- package/src/components/search-button/index.ts +3 -0
- package/src/components/search-button/types.ts +10 -0
- package/src/components/search-button/utils.ts +140 -0
- package/src/components/sidebar/CSidebarNav.tsx +27 -2
- package/src/components/smart-table/CSmartTable.tsx +5 -4
- package/src/components/smart-table/CSmartTableInterface.tsx +2 -2
- package/src/components/smart-table/__tests__/CSmartTable.spec.tsx +3 -2
- package/src/components/smart-table/__tests__/__snapshots__/CSmartTable.spec.tsx.snap +7 -15
- package/src/components/stepper/__tests__/CStepper.spec.tsx +24 -21
- package/src/components/stepper/__tests__/__snapshots__/CStepper.spec.tsx.snap +295 -0
- package/src/components/tabs/__tests__/CTabContent.spec.tsx +1 -0
- package/src/components/tabs/__tests__/CTabPane.spec.tsx +1 -0
- package/src/components/time-picker/CTimePicker.tsx +6 -7
- package/src/components/time-picker/__tests__/CTimePicker.spec.tsx +10 -1
- package/src/components/time-picker/__tests__/__snapshots__/CTimePicker.spec.tsx.snap +599 -315
- package/src/components/tooltip/CTooltip.tsx +15 -20
- package/src/components/tooltip/__tests__/CTooltip.spec.tsx +6 -0
- package/src/components/virtual-scroller/CVirtualScroller.tsx +13 -14
- package/src/hooks/useDebouncedCallback.ts +7 -4
- package/dist/cjs/components/accordion/CAccordionCollapse.d.ts +0 -3
- package/dist/esm/components/accordion/CAccordionCollapse.d.ts +0 -3
- package/src/components/accordion/CAccordionCollapse.tsx +0 -20
- package/src/components/accordion/__tests__/CAccordionCollapse.spec.tsx +0 -10
- package/src/components/accordion/__tests__/__snapshots__/CAccordionCollapse.spec.tsx.snap +0 -11
- package/src/components/button/__tests__/__snapshots__/CButtonClose.spec.tsx.snap +0 -26
- package/src/components/calendar/__tests__/CCalendar.accessibility.spec.tsx +0 -595
- package/src/components/calendar/__tests__/CCalendar.comprehensive.spec.tsx +0 -402
- package/src/components/calendar/__tests__/CCalendar.edge-cases.spec.tsx +0 -416
- package/src/components/calendar/__tests__/CCalendar.interactions.spec.tsx +0 -593
- package/src/components/header/CHeaderBrand.tsx~HEAD +0 -36
- /package/src/components/calendar/__tests__/{test-setup.ts → setup.ts} +0 -0
|
@@ -1,416 +0,0 @@
|
|
|
1
|
-
import * as React from 'react'
|
|
2
|
-
import { render, screen, fireEvent, act, waitFor } from '@testing-library/react'
|
|
3
|
-
import userEvent from '@testing-library/user-event'
|
|
4
|
-
import '@testing-library/jest-dom'
|
|
5
|
-
import { CCalendar } from '../CCalendar'
|
|
6
|
-
|
|
7
|
-
describe('CCalendar Edge Cases', () => {
|
|
8
|
-
beforeEach(() => {
|
|
9
|
-
jest.clearAllMocks()
|
|
10
|
-
})
|
|
11
|
-
|
|
12
|
-
describe('Memory Management', () => {
|
|
13
|
-
it('cleans up event listeners on unmount', () => {
|
|
14
|
-
const addEventListenerSpy = jest.spyOn(document, 'addEventListener')
|
|
15
|
-
const removeEventListenerSpy = jest.spyOn(document, 'removeEventListener')
|
|
16
|
-
|
|
17
|
-
const { unmount } = render(<CCalendar />)
|
|
18
|
-
|
|
19
|
-
// Unmount the component
|
|
20
|
-
unmount()
|
|
21
|
-
|
|
22
|
-
// Verify cleanup (this is implementation dependent)
|
|
23
|
-
expect(removeEventListenerSpy).toHaveBeenCalled()
|
|
24
|
-
|
|
25
|
-
addEventListenerSpy.mockRestore()
|
|
26
|
-
removeEventListenerSpy.mockRestore()
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
it('handles rapid prop changes without memory leaks', () => {
|
|
30
|
-
const { rerender } = render(<CCalendar calendarDate="1/1/2022" />)
|
|
31
|
-
|
|
32
|
-
// Rapidly change props
|
|
33
|
-
for (let i = 1; i <= 31; i++) {
|
|
34
|
-
rerender(<CCalendar calendarDate={`1/${i}/2022`} />)
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
expect(screen.getByRole('application')).toBeInTheDocument()
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
it('handles component re-mounting', () => {
|
|
41
|
-
const { unmount, rerender } = render(<CCalendar calendarDate="1/1/2022" />)
|
|
42
|
-
|
|
43
|
-
unmount()
|
|
44
|
-
|
|
45
|
-
rerender(<CCalendar calendarDate="1/2/2022" />)
|
|
46
|
-
expect(screen.getByRole('application')).toBeInTheDocument()
|
|
47
|
-
})
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
describe('Extreme Date Values', () => {
|
|
51
|
-
it('handles dates near JavaScript Date limits', () => {
|
|
52
|
-
// JavaScript Date can handle dates from -8,640,000,000,000,000 to 8,640,000,000,000,000 milliseconds
|
|
53
|
-
// relative to January 1, 1970 UTC
|
|
54
|
-
|
|
55
|
-
// Very old date (but within JavaScript limits)
|
|
56
|
-
render(<CCalendar calendarDate="1/1/1970" />)
|
|
57
|
-
expect(screen.getByRole('application')).toBeInTheDocument()
|
|
58
|
-
|
|
59
|
-
// Very future date (but within JavaScript limits)
|
|
60
|
-
render(<CCalendar calendarDate="1/1/2030" />)
|
|
61
|
-
expect(screen.getByRole('application')).toBeInTheDocument()
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
it('handles invalid date objects gracefully', () => {
|
|
65
|
-
const invalidDate = new Date('invalid')
|
|
66
|
-
render(<CCalendar calendarDate={invalidDate} />)
|
|
67
|
-
expect(screen.getByRole('application')).toBeInTheDocument()
|
|
68
|
-
})
|
|
69
|
-
|
|
70
|
-
it('handles NaN dates gracefully', () => {
|
|
71
|
-
const nanDate = new Date(NaN)
|
|
72
|
-
render(<CCalendar calendarDate={nanDate} />)
|
|
73
|
-
expect(screen.getByRole('application')).toBeInTheDocument()
|
|
74
|
-
})
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
describe('Browser Compatibility', () => {
|
|
78
|
-
it('handles browsers without Intl support', () => {
|
|
79
|
-
const originalIntl = global.Intl
|
|
80
|
-
|
|
81
|
-
// Mock missing Intl support
|
|
82
|
-
Object.defineProperty(global, 'Intl', {
|
|
83
|
-
value: undefined,
|
|
84
|
-
writable: true
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
render(<CCalendar locale="en-US" />)
|
|
88
|
-
expect(screen.getByRole('application')).toBeInTheDocument()
|
|
89
|
-
|
|
90
|
-
// Restore Intl
|
|
91
|
-
global.Intl = originalIntl
|
|
92
|
-
})
|
|
93
|
-
|
|
94
|
-
it('handles browsers with limited Date support', () => {
|
|
95
|
-
// Mock limited Date parsing
|
|
96
|
-
const originalDateParse = Date.parse
|
|
97
|
-
Date.parse = jest.fn(() => NaN)
|
|
98
|
-
|
|
99
|
-
render(<CCalendar calendarDate="2/16/2022" />)
|
|
100
|
-
expect(screen.getByRole('application')).toBeInTheDocument()
|
|
101
|
-
|
|
102
|
-
// Restore Date.parse
|
|
103
|
-
Date.parse = originalDateParse
|
|
104
|
-
})
|
|
105
|
-
|
|
106
|
-
it('handles touch events', async () => {
|
|
107
|
-
render(<CCalendar />)
|
|
108
|
-
|
|
109
|
-
const calendar = screen.getByRole('application')
|
|
110
|
-
|
|
111
|
-
// Simulate touch events
|
|
112
|
-
fireEvent.touchStart(calendar, {
|
|
113
|
-
touches: [{ clientX: 100, clientY: 100 }]
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
fireEvent.touchEnd(calendar, {
|
|
117
|
-
changedTouches: [{ clientX: 100, clientY: 100 }]
|
|
118
|
-
})
|
|
119
|
-
|
|
120
|
-
expect(calendar).toBeInTheDocument()
|
|
121
|
-
})
|
|
122
|
-
})
|
|
123
|
-
|
|
124
|
-
describe('Error Recovery', () => {
|
|
125
|
-
it('recovers from invalid prop combinations', () => {
|
|
126
|
-
// Start date after end date
|
|
127
|
-
render(
|
|
128
|
-
<CCalendar
|
|
129
|
-
range
|
|
130
|
-
startDate="2/20/2022"
|
|
131
|
-
endDate="2/16/2022"
|
|
132
|
-
/>
|
|
133
|
-
)
|
|
134
|
-
expect(screen.getByRole('application')).toBeInTheDocument()
|
|
135
|
-
})
|
|
136
|
-
|
|
137
|
-
it('handles conflicting date constraints', () => {
|
|
138
|
-
// Min date after max date
|
|
139
|
-
render(
|
|
140
|
-
<CCalendar
|
|
141
|
-
minDate="2/20/2022"
|
|
142
|
-
maxDate="2/16/2022"
|
|
143
|
-
/>
|
|
144
|
-
)
|
|
145
|
-
expect(screen.getByRole('application')).toBeInTheDocument()
|
|
146
|
-
})
|
|
147
|
-
|
|
148
|
-
it('handles disabled date that is also selected', () => {
|
|
149
|
-
const selectedDate = new Date(2022, 1, 16)
|
|
150
|
-
render(
|
|
151
|
-
<CCalendar
|
|
152
|
-
calendarDate={selectedDate}
|
|
153
|
-
disabledDate={[selectedDate]}
|
|
154
|
-
/>
|
|
155
|
-
)
|
|
156
|
-
expect(screen.getByRole('application')).toBeInTheDocument()
|
|
157
|
-
})
|
|
158
|
-
|
|
159
|
-
it('recovers from callback errors', () => {
|
|
160
|
-
const errorCallback = jest.fn(() => {
|
|
161
|
-
throw new Error('Callback error')
|
|
162
|
-
})
|
|
163
|
-
|
|
164
|
-
// Component should still render despite callback errors
|
|
165
|
-
expect(() => {
|
|
166
|
-
render(<CCalendar onCalendarDateChange={errorCallback} />)
|
|
167
|
-
}).not.toThrow()
|
|
168
|
-
|
|
169
|
-
expect(screen.getByRole('application')).toBeInTheDocument()
|
|
170
|
-
})
|
|
171
|
-
})
|
|
172
|
-
|
|
173
|
-
describe('Performance Edge Cases', () => {
|
|
174
|
-
it('handles large number of disabled dates efficiently', () => {
|
|
175
|
-
const startTime = performance.now()
|
|
176
|
-
|
|
177
|
-
// Create array of 1000 disabled dates
|
|
178
|
-
const disabledDates = Array.from({ length: 1000 }, (_, i) =>
|
|
179
|
-
new Date(2022, 0, i + 1)
|
|
180
|
-
)
|
|
181
|
-
|
|
182
|
-
render(<CCalendar disabledDate={disabledDates} />)
|
|
183
|
-
|
|
184
|
-
const endTime = performance.now()
|
|
185
|
-
const renderTime = endTime - startTime
|
|
186
|
-
|
|
187
|
-
expect(screen.getByRole('application')).toBeInTheDocument()
|
|
188
|
-
// Should render in reasonable time (less than 1 second)
|
|
189
|
-
expect(renderTime).toBeLessThan(1000)
|
|
190
|
-
})
|
|
191
|
-
|
|
192
|
-
it('handles complex disabled date functions efficiently', () => {
|
|
193
|
-
const complexDisabledFn = (date: Date) => {
|
|
194
|
-
// Complex calculation to determine if date is disabled
|
|
195
|
-
const dayOfYear = Math.floor((date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000)
|
|
196
|
-
return dayOfYear % 7 === 0 || dayOfYear % 13 === 0
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
const startTime = performance.now()
|
|
200
|
-
render(<CCalendar disabledDate={complexDisabledFn} />)
|
|
201
|
-
const endTime = performance.now()
|
|
202
|
-
|
|
203
|
-
expect(screen.getByRole('application')).toBeInTheDocument()
|
|
204
|
-
expect(endTime - startTime).toBeLessThan(500)
|
|
205
|
-
})
|
|
206
|
-
|
|
207
|
-
it('handles rapid state updates', async () => {
|
|
208
|
-
const TestComponent = () => {
|
|
209
|
-
const [date, setDate] = React.useState<Date | null>(new Date(2022, 1, 16))
|
|
210
|
-
|
|
211
|
-
React.useEffect(() => {
|
|
212
|
-
// Rapid state updates
|
|
213
|
-
const interval = setInterval(() => {
|
|
214
|
-
setDate(prev => prev ? new Date(prev.getTime() + 86400000) : null)
|
|
215
|
-
}, 10)
|
|
216
|
-
|
|
217
|
-
setTimeout(() => clearInterval(interval), 100)
|
|
218
|
-
|
|
219
|
-
return () => clearInterval(interval)
|
|
220
|
-
}, [])
|
|
221
|
-
|
|
222
|
-
return <CCalendar calendarDate={date} />
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
render(<TestComponent />)
|
|
226
|
-
|
|
227
|
-
// Wait for rapid updates to complete
|
|
228
|
-
await waitFor(() => {
|
|
229
|
-
expect(screen.getByRole('application')).toBeInTheDocument()
|
|
230
|
-
}, { timeout: 200 })
|
|
231
|
-
})
|
|
232
|
-
})
|
|
233
|
-
|
|
234
|
-
describe('Accessibility Edge Cases', () => {
|
|
235
|
-
it('maintains focus during dynamic updates', async () => {
|
|
236
|
-
const { rerender } = render(<CCalendar />)
|
|
237
|
-
|
|
238
|
-
const calendar = screen.getByRole('application')
|
|
239
|
-
calendar.focus()
|
|
240
|
-
|
|
241
|
-
expect(calendar).toHaveFocus()
|
|
242
|
-
|
|
243
|
-
// Update props while focused
|
|
244
|
-
rerender(<CCalendar calendarDate="2/16/2022" />)
|
|
245
|
-
|
|
246
|
-
// Focus should be maintained (implementation dependent)
|
|
247
|
-
expect(screen.getByRole('application')).toBeInTheDocument()
|
|
248
|
-
})
|
|
249
|
-
|
|
250
|
-
it('handles screen reader announcements', () => {
|
|
251
|
-
const { rerender } = render(<CCalendar />)
|
|
252
|
-
|
|
253
|
-
// Change to different date
|
|
254
|
-
rerender(<CCalendar calendarDate="2/16/2022" />)
|
|
255
|
-
|
|
256
|
-
// Verify aria-live regions are updated (implementation dependent)
|
|
257
|
-
expect(screen.getByRole('application')).toBeInTheDocument()
|
|
258
|
-
})
|
|
259
|
-
|
|
260
|
-
it('handles high contrast mode', () => {
|
|
261
|
-
// Mock high contrast media query
|
|
262
|
-
Object.defineProperty(window, 'matchMedia', {
|
|
263
|
-
writable: true,
|
|
264
|
-
value: jest.fn().mockImplementation(query => ({
|
|
265
|
-
matches: query.includes('prefers-contrast: high'),
|
|
266
|
-
media: query,
|
|
267
|
-
onchange: null,
|
|
268
|
-
addListener: jest.fn(),
|
|
269
|
-
removeListener: jest.fn(),
|
|
270
|
-
addEventListener: jest.fn(),
|
|
271
|
-
removeEventListener: jest.fn(),
|
|
272
|
-
dispatchEvent: jest.fn(),
|
|
273
|
-
})),
|
|
274
|
-
})
|
|
275
|
-
|
|
276
|
-
render(<CCalendar />)
|
|
277
|
-
expect(screen.getByRole('application')).toBeInTheDocument()
|
|
278
|
-
})
|
|
279
|
-
|
|
280
|
-
it('handles reduced motion preference', () => {
|
|
281
|
-
// Mock reduced motion preference
|
|
282
|
-
Object.defineProperty(window, 'matchMedia', {
|
|
283
|
-
writable: true,
|
|
284
|
-
value: jest.fn().mockImplementation(query => ({
|
|
285
|
-
matches: query.includes('prefers-reduced-motion: reduce'),
|
|
286
|
-
media: query,
|
|
287
|
-
onchange: null,
|
|
288
|
-
addListener: jest.fn(),
|
|
289
|
-
removeListener: jest.fn(),
|
|
290
|
-
addEventListener: jest.fn(),
|
|
291
|
-
removeEventListener: jest.fn(),
|
|
292
|
-
dispatchEvent: jest.fn(),
|
|
293
|
-
})),
|
|
294
|
-
})
|
|
295
|
-
|
|
296
|
-
render(<CCalendar />)
|
|
297
|
-
expect(screen.getByRole('application')).toBeInTheDocument()
|
|
298
|
-
})
|
|
299
|
-
})
|
|
300
|
-
|
|
301
|
-
describe('Timezone Edge Cases', () => {
|
|
302
|
-
it('handles timezone changes during component lifecycle', () => {
|
|
303
|
-
const { rerender } = render(<CCalendar calendarDate="2/16/2022" />)
|
|
304
|
-
|
|
305
|
-
// Mock timezone change (this is tricky to test properly)
|
|
306
|
-
const originalDateToString = Date.prototype.toString
|
|
307
|
-
Date.prototype.toString = function() {
|
|
308
|
-
return originalDateToString.call(this).replace(/GMT[+-]\d{4}/, 'GMT+0200')
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
rerender(<CCalendar calendarDate="2/16/2022" />)
|
|
312
|
-
expect(screen.getByRole('application')).toBeInTheDocument()
|
|
313
|
-
|
|
314
|
-
// Restore original method
|
|
315
|
-
Date.prototype.toString = originalDateToString
|
|
316
|
-
})
|
|
317
|
-
|
|
318
|
-
it('handles daylight saving time boundaries', () => {
|
|
319
|
-
// Test dates around DST transitions
|
|
320
|
-
const dstDates = [
|
|
321
|
-
'3/11/2023', // Spring forward (US)
|
|
322
|
-
'3/12/2023',
|
|
323
|
-
'3/13/2023',
|
|
324
|
-
'11/4/2023', // Fall back (US)
|
|
325
|
-
'11/5/2023',
|
|
326
|
-
'11/6/2023'
|
|
327
|
-
]
|
|
328
|
-
|
|
329
|
-
dstDates.forEach(dateString => {
|
|
330
|
-
const { rerender } = render(<CCalendar calendarDate="1/1/2023" />)
|
|
331
|
-
rerender(<CCalendar calendarDate={dateString} />)
|
|
332
|
-
expect(screen.getByRole('application')).toBeInTheDocument()
|
|
333
|
-
})
|
|
334
|
-
})
|
|
335
|
-
|
|
336
|
-
it('handles system clock changes', () => {
|
|
337
|
-
// Mock system time change
|
|
338
|
-
const originalNow = Date.now
|
|
339
|
-
let mockTime = new Date('2022-02-16T12:00:00Z').getTime()
|
|
340
|
-
|
|
341
|
-
Date.now = jest.fn(() => mockTime)
|
|
342
|
-
|
|
343
|
-
render(<CCalendar />)
|
|
344
|
-
expect(screen.getByRole('application')).toBeInTheDocument()
|
|
345
|
-
|
|
346
|
-
// Simulate time jumping forward
|
|
347
|
-
mockTime += 3600000 // +1 hour
|
|
348
|
-
|
|
349
|
-
// Force re-render
|
|
350
|
-
act(() => {
|
|
351
|
-
// Component should handle time changes gracefully
|
|
352
|
-
})
|
|
353
|
-
|
|
354
|
-
expect(screen.getByRole('application')).toBeInTheDocument()
|
|
355
|
-
|
|
356
|
-
// Restore original Date.now
|
|
357
|
-
Date.now = originalNow
|
|
358
|
-
})
|
|
359
|
-
})
|
|
360
|
-
|
|
361
|
-
describe('Concurrent Mode Compatibility', () => {
|
|
362
|
-
it('handles interrupting updates gracefully', async () => {
|
|
363
|
-
const SlowComponent = ({ date }: { date: string }) => {
|
|
364
|
-
// Simulate slow rendering
|
|
365
|
-
const start = performance.now()
|
|
366
|
-
while (performance.now() - start < 5) {
|
|
367
|
-
// Busy wait for 5ms
|
|
368
|
-
}
|
|
369
|
-
return <CCalendar calendarDate={date} />
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
const { rerender } = render(<SlowComponent date="1/1/2022" />)
|
|
373
|
-
|
|
374
|
-
// Rapid updates that might be interrupted
|
|
375
|
-
rerender(<SlowComponent date="1/2/2022" />)
|
|
376
|
-
rerender(<SlowComponent date="1/3/2022" />)
|
|
377
|
-
rerender(<SlowComponent date="1/4/2022" />)
|
|
378
|
-
|
|
379
|
-
await waitFor(() => {
|
|
380
|
-
expect(screen.getByRole('application')).toBeInTheDocument()
|
|
381
|
-
})
|
|
382
|
-
})
|
|
383
|
-
})
|
|
384
|
-
|
|
385
|
-
describe('Security Edge Cases', () => {
|
|
386
|
-
it('handles XSS attempts in date strings', () => {
|
|
387
|
-
const maliciousDate = '<script>alert("xss")</script>'
|
|
388
|
-
|
|
389
|
-
expect(() => {
|
|
390
|
-
render(<CCalendar calendarDate={maliciousDate} />)
|
|
391
|
-
}).not.toThrow()
|
|
392
|
-
|
|
393
|
-
expect(screen.getByRole('application')).toBeInTheDocument()
|
|
394
|
-
|
|
395
|
-
// Verify no script tags were rendered
|
|
396
|
-
expect(document.querySelector('script')).toBeNull()
|
|
397
|
-
})
|
|
398
|
-
|
|
399
|
-
it('sanitizes user input in callbacks', () => {
|
|
400
|
-
const maliciousCallback = jest.fn((date) => {
|
|
401
|
-
// Attempt to access global objects
|
|
402
|
-
try {
|
|
403
|
-
(window as any).maliciousCode = 'executed'
|
|
404
|
-
} catch (e) {
|
|
405
|
-
// Expected to be blocked
|
|
406
|
-
}
|
|
407
|
-
})
|
|
408
|
-
|
|
409
|
-
render(<CCalendar onCalendarDateChange={maliciousCallback} />)
|
|
410
|
-
expect(screen.getByRole('application')).toBeInTheDocument()
|
|
411
|
-
|
|
412
|
-
// Verify malicious code wasn't executed
|
|
413
|
-
expect((window as any).maliciousCode).toBeUndefined()
|
|
414
|
-
})
|
|
415
|
-
})
|
|
416
|
-
})
|