cozy-ui 113.7.1 → 113.9.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/.nvmrc +1 -1
- package/CHANGELOG.md +15 -0
- package/assets/icons/ui/number.svg +1 -0
- package/jest.config.js +1 -2
- package/package.json +2 -8
- package/react/AppSections/components/AppsSection.spec.jsx +10 -19
- package/react/AppSections/index.spec.jsx +98 -77
- package/react/ContactsList/ContactRow.spec.js +28 -53
- package/react/DateMonthPicker/index.spec.jsx +17 -45
- package/react/Field/index.spec.js +28 -5
- package/react/Figure/Figure.spec.jsx +9 -4
- package/react/Figure/__snapshots__/Figure.spec.jsx.snap +289 -225
- package/react/FileInput/index.jsx +1 -0
- package/react/FileInput/index.spec.jsx +16 -38
- package/react/Icon/Readme.md +5 -1
- package/react/Icons/Number.jsx +16 -0
- package/react/Popup/index.spec.jsx +90 -41
- package/react/QualificationIconStack/Readme.md +14 -0
- package/react/QualificationIconStack/index.jsx +132 -0
- package/react/deprecated/ViewStack/example.jsx +1 -1
- package/react/hooks/useClientErrors.spec.jsx +16 -24
- package/react/providers/I18n/index.spec.jsx +13 -5
- package/react/providers/I18n/withLocales.spec.jsx +4 -4
- package/transpiled/react/FileInput/index.js +2 -1
- package/transpiled/react/Icon/icons-sprite.js +1 -1
- package/transpiled/react/Icons/Number.js +15 -0
- package/transpiled/react/QualificationIconStack/index.js +132 -0
- package/transpiled/react/deprecated/ViewStack/example.js +1 -1
- package/react/AppSections/__snapshots__/index.spec.jsx.snap +0 -1843
- package/react/AppSections/components/__snapshots__/AppsSection.spec.jsx.snap +0 -41
- package/react/ContactsList/__snapshots__/ContactRow.spec.js.snap +0 -69
- package/react/FileInput/__snapshots__/index.spec.jsx.snap +0 -86
- package/react/Input/__snapshots__/index.spec.jsx.snap +0 -11
- package/react/Input/index.spec.jsx +0 -12
- package/react/__snapshots__/examples.spec.jsx.snap +0 -3720
- package/react/deprecated/ActionMenu/__snapshots__/index.spec.jsx.snap +0 -157
- package/react/deprecated/ActionMenu/index.spec.jsx +0 -115
- package/react/deprecated/Alerter/__snapshots__/alerter.spec.js.snap +0 -88
- package/react/deprecated/Alerter/alerter.spec.js +0 -78
- package/react/deprecated/InfosCarrousel/index.spec.jsx +0 -71
- package/react/deprecated/Modal/index.spec.jsx +0 -70
- package/react/deprecated/ViewStack/index.spec.jsx +0 -64
- package/react/examples.spec.jsx +0 -67
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { fireEvent, render, screen } from '@testing-library/react'
|
|
1
2
|
import uniqueId from 'lodash/uniqueId'
|
|
2
3
|
import React from 'react'
|
|
3
4
|
|
|
@@ -20,66 +21,43 @@ describe('FileInput component', () => {
|
|
|
20
21
|
})
|
|
21
22
|
|
|
22
23
|
it('should render a file selector', () => {
|
|
23
|
-
|
|
24
|
+
render(
|
|
24
25
|
<FileInput onChange={onChangeSpy}>
|
|
25
26
|
<span>Click me</span>
|
|
26
27
|
</FileInput>
|
|
27
|
-
)
|
|
28
|
-
expect(component).toMatchSnapshot()
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
it('should render a default file selector', () => {
|
|
32
|
-
const component = shallow(
|
|
33
|
-
<FileInput hidden={false} onChange={onChangeSpy} />
|
|
34
|
-
).getElement()
|
|
35
|
-
expect(component).toMatchSnapshot()
|
|
36
|
-
})
|
|
28
|
+
)
|
|
37
29
|
|
|
38
|
-
|
|
39
|
-
const component = shallow(
|
|
40
|
-
<FileInput disabled onChange={onChangeSpy}>
|
|
41
|
-
<span>Click me</span>
|
|
42
|
-
</FileInput>
|
|
43
|
-
).getElement()
|
|
44
|
-
expect(component).toMatchSnapshot()
|
|
45
|
-
})
|
|
30
|
+
const button = screen.getByText('Click me')
|
|
46
31
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
<FileInput accept="image/*" onChange={onChangeSpy}>
|
|
50
|
-
<span>Click me</span>
|
|
51
|
-
</FileInput>
|
|
52
|
-
).getElement()
|
|
53
|
-
expect(component).toMatchSnapshot()
|
|
32
|
+
expect(button).toBeInTheDocument()
|
|
33
|
+
expect(screen.getByTestId('file-input')).toBeInTheDocument()
|
|
54
34
|
})
|
|
55
35
|
|
|
56
36
|
it('should process selected file on change', () => {
|
|
57
37
|
const filelist = [pic1]
|
|
58
|
-
|
|
38
|
+
render(
|
|
59
39
|
<FileInput accept="image/*" onChange={onChangeSpy}>
|
|
60
40
|
<span>Click me</span>
|
|
61
41
|
</FileInput>
|
|
62
42
|
)
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
})
|
|
43
|
+
|
|
44
|
+
const input = screen.getByTestId('file-input')
|
|
45
|
+
fireEvent.change(input, { target: { files: filelist } })
|
|
46
|
+
|
|
68
47
|
expect(onChangeSpy).toHaveBeenCalledWith(pic1)
|
|
69
48
|
})
|
|
70
49
|
|
|
71
50
|
it('should process selected files on change if it is multiple', () => {
|
|
72
51
|
const filelist = [pic1, pic2]
|
|
73
|
-
|
|
52
|
+
render(
|
|
74
53
|
<FileInput accept="image/*" multiple onChange={onChangeSpy}>
|
|
75
54
|
<span>Click me</span>
|
|
76
55
|
</FileInput>
|
|
77
56
|
)
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
})
|
|
57
|
+
|
|
58
|
+
const input = screen.getByTestId('file-input')
|
|
59
|
+
fireEvent.change(input, { target: { files: filelist } })
|
|
60
|
+
|
|
83
61
|
expect(onChangeSpy).toHaveBeenCalledWith([pic1, pic2])
|
|
84
62
|
})
|
|
85
63
|
})
|
package/react/Icon/Readme.md
CHANGED
|
@@ -233,6 +233,7 @@ import New from 'cozy-ui/transpiled/react/Icons/New'
|
|
|
233
233
|
import Next from 'cozy-ui/transpiled/react/Icons/Next'
|
|
234
234
|
import Note from 'cozy-ui/transpiled/react/Icons/Note'
|
|
235
235
|
import NotificationEmail from 'cozy-ui/transpiled/react/Icons/NotificationEmail'
|
|
236
|
+
import Number from 'cozy-ui/transpiled/react/Icons/Number'
|
|
236
237
|
import Offline from 'cozy-ui/transpiled/react/Icons/Offline'
|
|
237
238
|
import Online from 'cozy-ui/transpiled/react/Icons/Online'
|
|
238
239
|
import Openapp from 'cozy-ui/transpiled/react/Icons/Openapp'
|
|
@@ -501,6 +502,7 @@ const icons = [
|
|
|
501
502
|
Next,
|
|
502
503
|
Note,
|
|
503
504
|
NotificationEmail,
|
|
505
|
+
Number,
|
|
504
506
|
Offline,
|
|
505
507
|
Online,
|
|
506
508
|
Openapp,
|
|
@@ -692,6 +694,7 @@ import FileTypeCodeIcon from 'cozy-ui/transpiled/react/Icons/FileTypeCode'
|
|
|
692
694
|
import FileTypeFilesIcon from 'cozy-ui/transpiled/react/Icons/FileTypeFiles'
|
|
693
695
|
import FileTypeFolderIcon from 'cozy-ui/transpiled/react/Icons/FileTypeFolder'
|
|
694
696
|
import FileTypeImageIcon from 'cozy-ui/transpiled/react/Icons/FileTypeImage'
|
|
697
|
+
import FileTypeNoteIcon from 'cozy-ui/transpiled/react/Icons/FileTypeNote'
|
|
695
698
|
import FileTypePdfIcon from 'cozy-ui/transpiled/react/Icons/FileTypePdf'
|
|
696
699
|
import FileTypeSheetIcon from 'cozy-ui/transpiled/react/Icons/FileTypeSheet'
|
|
697
700
|
import FileTypeSlideIcon from 'cozy-ui/transpiled/react/Icons/FileTypeSlide'
|
|
@@ -731,6 +734,7 @@ const icons = [
|
|
|
731
734
|
FileTypeFilesIcon,
|
|
732
735
|
FileTypeFolderIcon,
|
|
733
736
|
FileTypeImageIcon,
|
|
737
|
+
FileTypeNoteIcon,
|
|
734
738
|
FileTypePdfIcon,
|
|
735
739
|
FileTypeSheetIcon,
|
|
736
740
|
FileTypeSlideIcon,
|
|
@@ -935,7 +939,7 @@ import Typography from 'cozy-ui/transpiled/react/Typography'
|
|
|
935
939
|
|
|
936
940
|
const colors = ['#297EF2', '#08b442', '#B449E7', '#F52D2D', '#FF962F']
|
|
937
941
|
let i = 0
|
|
938
|
-
const availableIcons = ['album-add','album-remove','album','answer','apple','archive','arrowUp','attachment','attention','bank-check','bank','banking-add','banking','bell','benefit','bike','bill','bottom','browser-brave','browser-chrome','browser-duckduckgo','browser-edge','browser-edge-chromium','browser-firefox','browser-ie','browser-opera','browser-safari','burger','bus','calendar','camera','car','carbonCopy','carpooling','categories','certified','check-circle','check-list','check-square','check','checkbox','chess','child','circle-filled','clock','clock-outline','cloud-happy','cloud-plus-outlined','cloud','collect','cocktail','comment','company','compare','compass','connector','contract','contrast','copy','cozy-circle','cozy-laugh', 'cozy-lock', 'cozy-text', 'cozy-release', 'credit-card-add','credit-card','credit','crop','cross-circle-outline','cross-circle','cross-medium','cross-small','cross','cube','dash','dashboard','data-control','debit','devices','dots','down','download','drawing-arrow-up','dropdown-close','dropdown-open','dropdown','dropup','electric-bike','electric-car','electric-scooter','email-notification','email','eu','euro','exchange','eye-closed','eye','face-id','file-add','file-duotone','file-new','file-none','file-outline','file','filter','fingerprint','fitness','flag-outlined','flag','flash-auto','flashlight','folder-add','folder-moveto','folder-open','folder','forbidden','from-user','gear','globe','gouv','graph-circle','grid','group-list','groups','growth','hand','heart','help','help-outlined','history','home','hourglass','image','info-outlined','info','justice','key','label-outlined','laudry','laptop','left','library','lightbulb','lightning','link-out','link','list','list-min','location','lock', 'lock-screen', 'logout','magic-trick','magnet','magnifier','merge','moped','mosaic-min','motorcycle','mountain','movement-in','movement-out','mouvement','moveto','multi-files','music','new','next','note','notification-email','offline','online', 'openapp', 'openwith','palette','paper','paperplane','password','pen','people','percent-circle','percent','personal-data','phone-download','phone-upload','phone','pie-chart','pin','plane','plus-small','plus', 'pop-inside', 'previous','printer','qualify','radio-checked','radio-unchecked','refresh','relationship','remboursement','rename','repare','reply','restaurant','restore-straight','restore','right','rise','rotate-left','rotate-right','sad-cozy','safe','school','scooter','select-all','server','setting','share-circle','share','shield','shop','sound','spinner','sport-bag','stack','star','star-outline','stats','stop', 'subway', 'support', 'swap', 'sync-cozy','sync','tab','tag','target','task','team','telecom','telephone','text','text-info','to-the-cloud','top','train','tram','trash','trophy', 'uncloud', 'unknow','unlink','unlock','up','upload','videos','walk','wallet-add','wallet-new','wallet','warn','warning-circle','warning','water','wrench-circle','work']
|
|
942
|
+
const availableIcons = ['album-add','album-remove','album','answer','apple','archive','arrowUp','attachment','attention','bank-check','bank','banking-add','banking','bell','benefit','bike','bill','bottom','browser-brave','browser-chrome','browser-duckduckgo','browser-edge','browser-edge-chromium','browser-firefox','browser-ie','browser-opera','browser-safari','burger','bus','calendar','camera','car','carbonCopy','carpooling','categories','certified','check-circle','check-list','check-square','check','checkbox','chess','child','circle-filled','clock','clock-outline','cloud-happy','cloud-plus-outlined','cloud','collect','cocktail','comment','company','compare','compass','connector','contract','contrast','copy','cozy-circle','cozy-laugh', 'cozy-lock', 'cozy-text', 'cozy-release', 'credit-card-add','credit-card','credit','crop','cross-circle-outline','cross-circle','cross-medium','cross-small','cross','cube','dash','dashboard','data-control','debit','devices','dots','down','download','drawing-arrow-up','dropdown-close','dropdown-open','dropdown','dropup','electric-bike','electric-car','electric-scooter','email-notification','email','eu','euro','exchange','eye-closed','eye','face-id','file-add','file-duotone','file-new','file-none','file-outline','file','filter','fingerprint','fitness','flag-outlined','flag','flash-auto','flashlight','folder-add','folder-moveto','folder-open','folder','forbidden','from-user','gear','globe','gouv','graph-circle','grid','group-list','groups','growth','hand','heart','help','help-outlined','history','home','hourglass','image','info-outlined','info','justice','key','label-outlined','laudry','laptop','left','library','lightbulb','lightning','link-out','link','list','list-min','location','lock', 'lock-screen', 'logout','magic-trick','magnet','magnifier','merge','moped','mosaic-min','motorcycle','mountain','movement-in','movement-out','mouvement','moveto','multi-files','music','new','next','note','notification-email','number','offline','online', 'openapp', 'openwith','palette','paper','paperplane','password','pen','people','percent-circle','percent','personal-data','phone-download','phone-upload','phone','pie-chart','pin','plane','plus-small','plus', 'pop-inside', 'previous','printer','qualify','radio-checked','radio-unchecked','refresh','relationship','remboursement','rename','repare','reply','restaurant','restore-straight','restore','right','rise','rotate-left','rotate-right','sad-cozy','safe','school','scooter','select-all','server','setting','share-circle','share','shield','shop','sound','spinner','sport-bag','stack','star','star-outline','stats','stop', 'subway', 'support', 'swap', 'sync-cozy','sync','tab','tag','target','task','team','telecom','telephone','text','text-info','to-the-cloud','top','train','tram','trash','trophy', 'uncloud', 'unknow','unlink','unlock','up','upload','videos','walk','wallet-add','wallet-new','wallet','warn','warning-circle','warning','water','wrench-circle','work']
|
|
939
943
|
;
|
|
940
944
|
<div style={{ fontSize: '2rem', display: 'grid', gridTemplateColumns: 'repeat(6, 1fr)' }}>
|
|
941
945
|
<Sprite />
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Automatically created, please run `scripts/generate-svgr-icon.sh assets/icons/ui/number.svg` to regenerate;
|
|
2
|
+
import React from 'react'
|
|
3
|
+
|
|
4
|
+
function SvgNumber(props) {
|
|
5
|
+
return (
|
|
6
|
+
<svg viewBox="0 0 16 16" {...props}>
|
|
7
|
+
<path
|
|
8
|
+
fillRule="evenodd"
|
|
9
|
+
clipRule="evenodd"
|
|
10
|
+
d="M4 12V4h-.452l-.117.024-2.73 1.177v1.883l1.323-.54V12H4zm11.245-7.363C14.8 4.21 14.192 4 13.44 4c-.437 0-.84.096-1.204.29a2.155 2.155 0 00-.864.816c-.17.29-.27.61-.298.957l-.021.527h2.08v-.318l.004-.09a.507.507 0 01.11-.28.276.276 0 01.233-.11c.111 0 .184.035.248.116.077.097.12.252.12.472 0 .24-.045.418-.128.54-.05.073-.118.111-.232.123l-.09.005h-.994v1.757h1.021l.08.004c.301.03.434.238.434.742 0 .228-.05.395-.144.512-.08.1-.178.144-.325.144-.108 0-.188-.04-.265-.137a.647.647 0 01-.132-.337l-.023-.431H11v.318l.007.206c.04.607.265 1.116.673 1.513.453.44 1.042.661 1.75.661.751 0 1.374-.22 1.85-.663.48-.446.72-1.04.72-1.762 0-.447-.098-.843-.296-1.182l-.094-.145-.107-.134a1.798 1.798 0 00-.252-.235l-.008-.006.014-.01.128-.133c.082-.092.157-.192.225-.3a2 2 0 00.305-1.07c0-.714-.222-1.296-.67-1.723zm-5.83-.007C8.996 4.208 8.417 4 7.696 4c-.475 0-.907.118-1.289.354a2.37 2.37 0 00-.888.99 2.98 2.98 0 00-.3 1.123L5.2 7.03h2.05v-.322l.004-.157c.015-.25.066-.44.146-.568.077-.122.157-.17.271-.17.096 0 .152.033.204.12.076.127.12.323.12.59 0 .192-.049.397-.148.618-.085.19-.211.41-.378.66L7.331 8 5.33 10.57V12h4.87v-1.815H8.05l.573-.824.185-.226c.417-.519.722-.98.906-1.374.215-.462.323-.923.323-1.38 0-.739-.205-1.328-.623-1.751z"
|
|
11
|
+
/>
|
|
12
|
+
</svg>
|
|
13
|
+
)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export default SvgNumber
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { render, fireEvent } from '@testing-library/react'
|
|
2
2
|
import React from 'react'
|
|
3
3
|
|
|
4
4
|
import { isMobileApp } from 'cozy-device-helper'
|
|
@@ -17,35 +17,56 @@ const props = {
|
|
|
17
17
|
height: '200'
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
this.source = options.source ||
|
|
20
|
+
class MessageEventMock extends Event {
|
|
21
|
+
constructor(options = {}, mock) {
|
|
22
|
+
super('message', options)
|
|
23
|
+
this.source = options.source || mock
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
class LoadStartEventMock extends Event {
|
|
28
|
+
constructor(url) {
|
|
29
|
+
super('loadstart')
|
|
30
|
+
this.url = url
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
class ExitEventMock extends Event {
|
|
35
|
+
constructor() {
|
|
36
|
+
super('exit')
|
|
24
37
|
}
|
|
25
38
|
}
|
|
26
39
|
|
|
27
40
|
describe('Popup', () => {
|
|
28
|
-
|
|
29
|
-
|
|
41
|
+
const setup = ({ mockAddEventListener = true }) => {
|
|
42
|
+
const popupMock = new EventTarget()
|
|
43
|
+
|
|
44
|
+
isMobileApp.mockReturnValue(false)
|
|
30
45
|
|
|
31
46
|
jest.spyOn(global, 'open').mockReturnValue(popupMock)
|
|
32
47
|
jest.spyOn(global, 'addEventListener')
|
|
33
|
-
})
|
|
34
48
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
})
|
|
49
|
+
if (mockAddEventListener) {
|
|
50
|
+
popupMock.addEventListener = jest.fn()
|
|
51
|
+
}
|
|
39
52
|
|
|
40
|
-
beforeEach(() => {
|
|
41
|
-
isMobileApp.mockReturnValue(false)
|
|
42
|
-
popupMock.addEventListener = jest.fn()
|
|
43
53
|
popupMock.close = jest.fn()
|
|
44
54
|
popupMock.focus = jest.fn()
|
|
45
55
|
popupMock.closed = false
|
|
46
56
|
props.onClose = jest.fn()
|
|
47
57
|
props.onMessage = jest.fn()
|
|
48
58
|
props.onMobileUrlChange = jest.fn()
|
|
59
|
+
|
|
60
|
+
return popupMock
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
beforeAll(() => {
|
|
64
|
+
jest.useFakeTimers()
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
afterAll(() => {
|
|
68
|
+
global.open.mockRestore()
|
|
69
|
+
global.addEventListener.mockRestore()
|
|
49
70
|
})
|
|
50
71
|
|
|
51
72
|
afterEach(() => {
|
|
@@ -54,7 +75,10 @@ describe('Popup', () => {
|
|
|
54
75
|
})
|
|
55
76
|
|
|
56
77
|
it('should open new window', () => {
|
|
57
|
-
|
|
78
|
+
const popupMock = setup({})
|
|
79
|
+
|
|
80
|
+
render(<Popup {...props} />)
|
|
81
|
+
|
|
58
82
|
expect(global.open).toHaveBeenCalledWith(
|
|
59
83
|
props.initialUrl,
|
|
60
84
|
props.title,
|
|
@@ -64,66 +88,91 @@ describe('Popup', () => {
|
|
|
64
88
|
})
|
|
65
89
|
|
|
66
90
|
it('should subscribe to message events', () => {
|
|
67
|
-
|
|
91
|
+
setup({})
|
|
92
|
+
|
|
93
|
+
render(<Popup {...props} />)
|
|
94
|
+
|
|
68
95
|
expect(global.addEventListener).toHaveBeenCalledWith(
|
|
69
96
|
'message',
|
|
70
|
-
|
|
97
|
+
expect.any(Function)
|
|
71
98
|
)
|
|
72
99
|
})
|
|
73
100
|
|
|
74
101
|
it('should subcribe to mobile events', () => {
|
|
102
|
+
const popupMock = setup({})
|
|
75
103
|
isMobileApp.mockReturnValue(true)
|
|
76
|
-
|
|
104
|
+
|
|
105
|
+
render(<Popup {...props} />)
|
|
106
|
+
|
|
77
107
|
expect(popupMock.addEventListener).toHaveBeenCalledWith(
|
|
78
108
|
'loadstart',
|
|
79
|
-
|
|
109
|
+
expect.any(Function)
|
|
80
110
|
)
|
|
81
111
|
expect(popupMock.addEventListener).toHaveBeenCalledWith(
|
|
82
112
|
'exit',
|
|
83
|
-
|
|
113
|
+
expect.any(Function)
|
|
84
114
|
)
|
|
85
115
|
})
|
|
86
116
|
|
|
87
|
-
describe('monitorClosing', () => {
|
|
88
|
-
it('should detect closing', () => {
|
|
89
|
-
const wrapper = shallow(<Popup {...props} />)
|
|
90
|
-
jest.spyOn(wrapper.instance(), 'handleClose')
|
|
91
|
-
popupMock.closed = true
|
|
92
|
-
jest.runAllTimers()
|
|
93
|
-
expect(wrapper.instance().handleClose).toHaveBeenCalled()
|
|
94
|
-
})
|
|
95
|
-
})
|
|
96
|
-
|
|
97
117
|
describe('handleClose', () => {
|
|
98
118
|
it('should call onClose', () => {
|
|
99
|
-
const
|
|
100
|
-
|
|
119
|
+
const popupMock = setup({
|
|
120
|
+
mockAddEventListener: false
|
|
121
|
+
})
|
|
122
|
+
isMobileApp.mockReturnValue(true)
|
|
123
|
+
|
|
124
|
+
render(<Popup {...props} />)
|
|
125
|
+
|
|
126
|
+
const messageEvent = new ExitEventMock()
|
|
127
|
+
fireEvent(popupMock, messageEvent)
|
|
128
|
+
|
|
101
129
|
expect(props.onClose).toHaveBeenCalled()
|
|
102
130
|
})
|
|
103
131
|
})
|
|
104
132
|
|
|
105
133
|
describe('handleMessage', () => {
|
|
106
134
|
it('should call onMessage', () => {
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
135
|
+
const popupMock = setup({
|
|
136
|
+
mockAddEventListener: false
|
|
137
|
+
})
|
|
138
|
+
isMobileApp.mockReturnValue(true)
|
|
139
|
+
|
|
140
|
+
render(<Popup {...props} />)
|
|
141
|
+
|
|
142
|
+
const messageEvent = new MessageEventMock({}, popupMock)
|
|
143
|
+
fireEvent(window, messageEvent)
|
|
144
|
+
|
|
110
145
|
expect(props.onMessage).toHaveBeenCalledWith(messageEvent)
|
|
111
146
|
})
|
|
112
147
|
|
|
113
148
|
it('should ignore messageEvent from another window ', () => {
|
|
114
|
-
|
|
149
|
+
setup({
|
|
150
|
+
mockAddEventListener: false
|
|
151
|
+
})
|
|
152
|
+
isMobileApp.mockReturnValue(true)
|
|
153
|
+
|
|
154
|
+
render(<Popup {...props} />)
|
|
155
|
+
|
|
115
156
|
const messageEvent = new MessageEventMock({ source: {} })
|
|
116
|
-
|
|
157
|
+
fireEvent(window, messageEvent)
|
|
158
|
+
|
|
117
159
|
expect(props.onMessage).not.toHaveBeenCalled()
|
|
118
160
|
})
|
|
119
161
|
})
|
|
120
162
|
|
|
121
163
|
describe('handleLoadStart', () => {
|
|
122
164
|
it('should call onMobileUrlChange', () => {
|
|
123
|
-
const
|
|
165
|
+
const popupMock = setup({
|
|
166
|
+
mockAddEventListener: false
|
|
167
|
+
})
|
|
168
|
+
isMobileApp.mockReturnValue(true)
|
|
169
|
+
|
|
170
|
+
render(<Popup {...props} />)
|
|
171
|
+
|
|
124
172
|
const url = 'https://cozy.io'
|
|
125
|
-
const
|
|
126
|
-
|
|
173
|
+
const messageEvent = new LoadStartEventMock(url)
|
|
174
|
+
fireEvent(popupMock, messageEvent)
|
|
175
|
+
|
|
127
176
|
expect(props.onMobileUrlChange).toHaveBeenCalledWith(expect.any(URL))
|
|
128
177
|
expect(props.onMobileUrlChange).toHaveBeenCalledWith(new URL(url))
|
|
129
178
|
})
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
```jsx
|
|
2
|
+
import QualificationIconStack from 'cozy-ui/transpiled/react/QualificationIconStack'
|
|
3
|
+
|
|
4
|
+
;
|
|
5
|
+
|
|
6
|
+
<>
|
|
7
|
+
<QualificationIconStack className="u-mr-1" />
|
|
8
|
+
<QualificationIconStack className="u-mr-1" qualification="isp_invoice" />
|
|
9
|
+
<QualificationIconStack className="u-mr-1" qualification="phone_invoice" />
|
|
10
|
+
<QualificationIconStack className="u-mr-1" qualification="family_record_book" />
|
|
11
|
+
<QualificationIconStack className="u-mr-1" theme="identity" />
|
|
12
|
+
<QualificationIconStack theme="transport" />
|
|
13
|
+
</>
|
|
14
|
+
```
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import PropTypes from 'prop-types'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
|
|
4
|
+
import { getIconByLabel } from 'cozy-client/dist/models/document/qualification'
|
|
5
|
+
|
|
6
|
+
import Icon from '../Icon'
|
|
7
|
+
import IconStack from '../IconStack'
|
|
8
|
+
import BankIcon from '../Icons/Bank'
|
|
9
|
+
import BankCheckIcon from '../Icons/BankCheck'
|
|
10
|
+
import BenefitIcon from '../Icons/Benefit'
|
|
11
|
+
import BillIcon from '../Icons/Bill'
|
|
12
|
+
import CarIcon from '../Icons/Car'
|
|
13
|
+
import ChessIcon from '../Icons/Chess'
|
|
14
|
+
import ChildIcon from '../Icons/Child'
|
|
15
|
+
import DotsIcon from '../Icons/Dots'
|
|
16
|
+
import EmailIcon from '../Icons/Email'
|
|
17
|
+
import EuroIcon from '../Icons/Euro'
|
|
18
|
+
import ExchangeIcon from '../Icons/Exchange'
|
|
19
|
+
import FileDuotoneIcon from '../Icons/FileDuotone'
|
|
20
|
+
import FileTypeNoteIcon from '../Icons/FileTypeNote'
|
|
21
|
+
import FitnessIcon from '../Icons/Fitness'
|
|
22
|
+
import GlobeIcon from '../Icons/Globe'
|
|
23
|
+
import GouvIcon from '../Icons/Gouv'
|
|
24
|
+
import HeartIcon from '../Icons/Heart'
|
|
25
|
+
import HomeIcon from '../Icons/Home'
|
|
26
|
+
import ImageIcon from '../Icons/Image'
|
|
27
|
+
import JusticeIcon from '../Icons/Justice'
|
|
28
|
+
import LaudryIcon from '../Icons/Laudry'
|
|
29
|
+
import LightningIcon from '../Icons/Lightning'
|
|
30
|
+
import PeopleIcon from '../Icons/People'
|
|
31
|
+
import PlaneIcon from '../Icons/Plane'
|
|
32
|
+
import RemboursementIcon from '../Icons/Remboursement'
|
|
33
|
+
import RestaurantIcon from '../Icons/Restaurant'
|
|
34
|
+
import SchoolIcon from '../Icons/School'
|
|
35
|
+
import ShopIcon from '../Icons/Shop'
|
|
36
|
+
import TeamIcon from '../Icons/Team'
|
|
37
|
+
import TelecomIcon from '../Icons/Telecom'
|
|
38
|
+
import TelephoneIcon from '../Icons/Telephone'
|
|
39
|
+
import WaterIcon from '../Icons/Water'
|
|
40
|
+
import WorkIcon from '../Icons/Work'
|
|
41
|
+
|
|
42
|
+
// this is a copy of FileDuotone without the flap and with a white background
|
|
43
|
+
function FileDuotoneWhite(props) {
|
|
44
|
+
return (
|
|
45
|
+
<svg viewBox="0 0 26 32" {...props}>
|
|
46
|
+
<g fillRule="evenodd">
|
|
47
|
+
<path
|
|
48
|
+
d="M0 2.002C0 .896.89 0 1.997 0H19l7 7v22.996A2 2 0 0124.003 32H1.997A1.995 1.995 0 010 29.998C.048 16 0 16 0 2.002z"
|
|
49
|
+
fill="#ffffff"
|
|
50
|
+
/>
|
|
51
|
+
</g>
|
|
52
|
+
</svg>
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const IconByLabel = {
|
|
57
|
+
'bank-check': BankCheckIcon,
|
|
58
|
+
bank: BankIcon,
|
|
59
|
+
benefit: BenefitIcon,
|
|
60
|
+
bill: BillIcon,
|
|
61
|
+
car: CarIcon,
|
|
62
|
+
chess: ChessIcon,
|
|
63
|
+
child: ChildIcon,
|
|
64
|
+
dots: DotsIcon,
|
|
65
|
+
email: EmailIcon,
|
|
66
|
+
euro: EuroIcon,
|
|
67
|
+
exchange: ExchangeIcon,
|
|
68
|
+
'file-type-note': FileTypeNoteIcon,
|
|
69
|
+
fitness: FitnessIcon,
|
|
70
|
+
globe: GlobeIcon,
|
|
71
|
+
gouv: GouvIcon,
|
|
72
|
+
heart: HeartIcon,
|
|
73
|
+
home: HomeIcon,
|
|
74
|
+
image: ImageIcon,
|
|
75
|
+
justice: JusticeIcon,
|
|
76
|
+
laudry: LaudryIcon,
|
|
77
|
+
lightning: LightningIcon,
|
|
78
|
+
people: PeopleIcon,
|
|
79
|
+
plane: PlaneIcon,
|
|
80
|
+
remboursement: RemboursementIcon,
|
|
81
|
+
restaurant: RestaurantIcon,
|
|
82
|
+
school: SchoolIcon,
|
|
83
|
+
shop: ShopIcon,
|
|
84
|
+
team: TeamIcon,
|
|
85
|
+
telecom: TelecomIcon,
|
|
86
|
+
telephone: TelephoneIcon,
|
|
87
|
+
water: WaterIcon,
|
|
88
|
+
work: WorkIcon
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const themeIconByLabel = {
|
|
92
|
+
identity: 'people',
|
|
93
|
+
family: 'team',
|
|
94
|
+
work_study: 'work',
|
|
95
|
+
health: 'heart',
|
|
96
|
+
home: 'home',
|
|
97
|
+
transport: 'car',
|
|
98
|
+
activity: 'chess',
|
|
99
|
+
finance: 'bank',
|
|
100
|
+
invoice: 'bill',
|
|
101
|
+
others: 'dots'
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const QualificationIconStack = ({ theme, qualification, ...props }) => {
|
|
105
|
+
const ForegroundIcon = qualification
|
|
106
|
+
? IconByLabel[getIconByLabel(qualification)]
|
|
107
|
+
: theme
|
|
108
|
+
? IconByLabel[themeIconByLabel[theme]]
|
|
109
|
+
: null
|
|
110
|
+
|
|
111
|
+
return (
|
|
112
|
+
<IconStack
|
|
113
|
+
{...props}
|
|
114
|
+
backgroundIcon={
|
|
115
|
+
<>
|
|
116
|
+
<Icon className="u-pos-absolute" icon={FileDuotoneWhite} size={32} />
|
|
117
|
+
<Icon icon={FileDuotoneIcon} color="#E049BF" size={32} />
|
|
118
|
+
</>
|
|
119
|
+
}
|
|
120
|
+
foregroundIcon={<Icon icon={ForegroundIcon} color="#E049BF" size={16} />}
|
|
121
|
+
/>
|
|
122
|
+
)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
QualificationIconStack.propTypes = {
|
|
126
|
+
/** The name of the qualification (isp\_invoice, family\_record\_book, etc.) */
|
|
127
|
+
qualification: PropTypes.string,
|
|
128
|
+
/** The name of the qualification theme (indentity, family, etc.) */
|
|
129
|
+
theme: PropTypes.string
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export default QualificationIconStack
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { screen, render, act } from '@testing-library/react'
|
|
2
|
+
import { renderHook } from '@testing-library/react-hooks'
|
|
3
3
|
import React from 'react'
|
|
4
4
|
|
|
5
|
-
import { CozyProvider } from 'cozy-client'
|
|
6
5
|
import { FetchError } from 'cozy-stack-client'
|
|
7
6
|
|
|
8
7
|
import useClientErrors from './useClientErrors'
|
|
8
|
+
import DemoProvider from '../providers/DemoProvider'
|
|
9
9
|
|
|
10
10
|
function createCozyClient() {
|
|
11
11
|
return {
|
|
@@ -14,9 +14,15 @@ function createCozyClient() {
|
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
jest.mock('../deprecated/QuotaAlert', () => ({ onClose }) => (
|
|
18
|
+
<>
|
|
19
|
+
QuotaAlert <button onClick={onClose}>Dismiss</button>
|
|
20
|
+
</>
|
|
21
|
+
))
|
|
22
|
+
|
|
17
23
|
function createWrapper(client = createCozyClient()) {
|
|
18
24
|
function Wrapper({ children }) {
|
|
19
|
-
return <
|
|
25
|
+
return <DemoProvider client={client}>{children}</DemoProvider>
|
|
20
26
|
}
|
|
21
27
|
return Wrapper
|
|
22
28
|
}
|
|
@@ -27,7 +33,7 @@ function renderWrappedHook(client) {
|
|
|
27
33
|
}
|
|
28
34
|
|
|
29
35
|
function wrappedShallow(tree, client) {
|
|
30
|
-
return
|
|
36
|
+
return render(tree, { wrapper: createWrapper(client) })
|
|
31
37
|
}
|
|
32
38
|
|
|
33
39
|
describe('useClientErrors', () => {
|
|
@@ -47,14 +53,12 @@ describe('useClientErrors', () => {
|
|
|
47
53
|
it('displays nothing by default', () => {
|
|
48
54
|
const { result } = renderWrappedHook()
|
|
49
55
|
const { ClientErrors } = result.current
|
|
50
|
-
|
|
51
|
-
|
|
56
|
+
wrappedShallow(<ClientErrors />)
|
|
57
|
+
|
|
58
|
+
expect(screen.queryByText('QuotaAlert')).not.toBeInTheDocument()
|
|
52
59
|
})
|
|
53
60
|
|
|
54
61
|
describe('for quota errors', () => {
|
|
55
|
-
const findQuotaAlert = node => {
|
|
56
|
-
return node.at(0).dive()
|
|
57
|
-
}
|
|
58
62
|
const setup = async () => {
|
|
59
63
|
const client = createCozyClient()
|
|
60
64
|
const response = new Response(null, {
|
|
@@ -81,21 +85,9 @@ describe('useClientErrors', () => {
|
|
|
81
85
|
}
|
|
82
86
|
|
|
83
87
|
it('displays a a QuotaAlert', async () => {
|
|
84
|
-
|
|
85
|
-
expect(node).toHaveLength(1)
|
|
86
|
-
expect(findQuotaAlert(node).type().name).toEqual('QuotaAlert')
|
|
87
|
-
})
|
|
88
|
-
|
|
89
|
-
it('can be dismissed', async () => {
|
|
90
|
-
const { node, result, client } = await setup()
|
|
91
|
-
const quotaAlert = findQuotaAlert(node)
|
|
92
|
-
const onClose = quotaAlert.props().onClose
|
|
93
|
-
act(() => onClose())
|
|
88
|
+
await setup()
|
|
94
89
|
|
|
95
|
-
|
|
96
|
-
const { ClientErrors } = result.current
|
|
97
|
-
const updatedNode = wrappedShallow(<ClientErrors />, client)
|
|
98
|
-
expect(updatedNode.at(0).length).toBe(0)
|
|
90
|
+
expect(screen.queryByText('QuotaAlert')).toBeInTheDocument()
|
|
99
91
|
})
|
|
100
92
|
})
|
|
101
93
|
})
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { render, fireEvent } from '@testing-library/react'
|
|
1
|
+
import { render, fireEvent, screen } from '@testing-library/react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
import React, { useState } from 'react'
|
|
4
4
|
|
|
@@ -34,23 +34,31 @@ I18nHelloWorldOldAPI.contextTypes = {
|
|
|
34
34
|
|
|
35
35
|
describe('new context api', () => {
|
|
36
36
|
it('should provide t and f and lang through useI18n hook', () => {
|
|
37
|
-
|
|
37
|
+
render(
|
|
38
38
|
<I18n lang="en" dictRequire={() => locales}>
|
|
39
39
|
<I18nHelloWorldHook />
|
|
40
40
|
</I18n>
|
|
41
41
|
)
|
|
42
|
-
expect(
|
|
42
|
+
expect(
|
|
43
|
+
screen.getByText('Hello World !', { exact: false })
|
|
44
|
+
).toBeInTheDocument()
|
|
45
|
+
expect(screen.getByText('6 Jan', { exact: false })).toBeInTheDocument()
|
|
46
|
+
expect(screen.getByText('en', { exact: false })).toBeInTheDocument()
|
|
43
47
|
})
|
|
44
48
|
})
|
|
45
49
|
|
|
46
50
|
describe('old context api', () => {
|
|
47
51
|
it('should provide t and f and lang through old context API', () => {
|
|
48
|
-
|
|
52
|
+
render(
|
|
49
53
|
<I18n lang="en" dictRequire={() => locales}>
|
|
50
54
|
<I18nHelloWorldOldAPI />
|
|
51
55
|
</I18n>
|
|
52
56
|
)
|
|
53
|
-
expect(
|
|
57
|
+
expect(
|
|
58
|
+
screen.getByText('Hello World !', { exact: false })
|
|
59
|
+
).toBeInTheDocument()
|
|
60
|
+
expect(screen.getByText('6 Jan', { exact: false })).toBeInTheDocument()
|
|
61
|
+
expect(screen.getByText('en', { exact: false })).toBeInTheDocument()
|
|
54
62
|
})
|
|
55
63
|
})
|
|
56
64
|
|