1
- import { render , screen } from '@testing-library/react' ;
1
+ import { fireEvent , render , screen } from '@testing-library/react' ;
2
2
import { type Mock , beforeEach , describe , expect , it , vi } from 'vitest' ;
3
3
import '@testing-library/jest-dom' ;
4
4
import { getSlicedAddress } from '../utils/getSlicedAddress' ;
@@ -14,74 +14,117 @@ vi.mock('../utils/getSlicedAddress', () => ({
14
14
} ) ) ;
15
15
16
16
vi . mock ( './IdentityProvider' , ( ) => ( {
17
- useIdentityContext : vi . fn ( ) ,
17
+ useIdentityContext : vi . fn ( ( ) => ( {
18
+ address : undefined ,
19
+ ensName : undefined ,
20
+ loading : false ,
21
+ error : null ,
22
+ } ) ) ,
18
23
} ) ) ;
19
24
20
25
const useIdentityContextMock = mock ( useIdentityContext ) ;
21
26
22
27
const mockGetSlicedAddress = ( addr : string ) =>
23
28
`${ addr . slice ( 0 , 5 ) } ...${ addr . slice ( - 4 ) } ` ;
24
29
30
+ const mockClipboard = {
31
+ writeText : vi . fn ( ) . mockResolvedValue ( undefined ) ,
32
+ } ;
33
+
34
+ Object . defineProperty ( navigator , 'clipboard' , {
35
+ value : mockClipboard ,
36
+ configurable : true ,
37
+ } ) ;
38
+
25
39
describe ( 'Address component' , ( ) => {
26
40
const testIdentityProviderAddress = '0xIdentityAddress' ;
27
41
const testAddressComponentAddress =
28
42
'0x1234567890abcdef1234567890abcdef12345678' ;
29
43
30
44
beforeEach ( ( ) => {
31
45
vi . clearAllMocks ( ) ;
46
+ mockClipboard . writeText . mockClear ( ) ;
47
+ useIdentityContextMock . mockReturnValue ( {
48
+ address : undefined ,
49
+ ensName : undefined ,
50
+ loading : false ,
51
+ error : null ,
52
+ } ) ;
32
53
} ) ;
33
54
34
55
it ( 'should console.error and return null when no address is provided' , ( ) => {
35
- vi . mocked ( useIdentityContext ) . mockReturnValue ( { } ) ;
56
+ useIdentityContextMock . mockReturnValue ( {
57
+ address : undefined ,
58
+ ensName : undefined ,
59
+ loading : false ,
60
+ error : null ,
61
+ } ) ;
62
+
36
63
const consoleErrorSpy = vi
37
64
. spyOn ( console , 'error' )
38
65
. mockImplementation ( ( ) => { } ) ;
39
66
const { container } = render ( < Address /> ) ;
67
+
40
68
expect ( consoleErrorSpy ) . toHaveBeenCalledWith (
41
69
'Address: an Ethereum address must be provided to the Identity or Address component.' ,
42
70
) ;
43
71
expect ( container . firstChild ) . toBeNull ( ) ;
72
+
73
+ consoleErrorSpy . mockRestore ( ) ;
44
74
} ) ;
45
75
46
76
it ( 'renders the sliced address when address supplied to Identity' , ( ) => {
47
77
useIdentityContextMock . mockReturnValue ( {
48
78
address : testAddressComponentAddress ,
79
+ ensName : undefined ,
80
+ loading : false ,
81
+ error : null ,
49
82
} ) ;
50
83
( getSlicedAddress as Mock ) . mockReturnValue (
51
84
mockGetSlicedAddress ( testAddressComponentAddress ) ,
52
85
) ;
53
86
54
- const { getByText } = render ( < Address /> ) ;
87
+ render ( < Address /> ) ;
88
+ expect ( getSlicedAddress ) . toHaveBeenCalledWith ( testAddressComponentAddress ) ;
55
89
expect (
56
- getByText ( mockGetSlicedAddress ( testAddressComponentAddress ) ) ,
90
+ screen . getByText ( mockGetSlicedAddress ( testAddressComponentAddress ) ) ,
57
91
) . toBeInTheDocument ( ) ;
58
92
} ) ;
59
93
60
- it ( 'renders the sliced address when address supplied to Identity' , ( ) => {
61
- useIdentityContextMock . mockReturnValue ( { } ) ;
94
+ it ( 'renders the sliced address when address supplied directly to component' , ( ) => {
95
+ useIdentityContextMock . mockReturnValue ( {
96
+ address : undefined ,
97
+ ensName : undefined ,
98
+ loading : false ,
99
+ error : null ,
100
+ } ) ;
62
101
( getSlicedAddress as Mock ) . mockReturnValue (
63
102
mockGetSlicedAddress ( testAddressComponentAddress ) ,
64
103
) ;
65
104
66
- const { getByText } = render (
67
- < Address address = { testAddressComponentAddress } /> ,
68
- ) ;
105
+ render ( < Address address = { testAddressComponentAddress } /> ) ;
106
+ expect ( getSlicedAddress ) . toHaveBeenCalledWith ( testAddressComponentAddress ) ;
69
107
expect (
70
- getByText ( mockGetSlicedAddress ( testAddressComponentAddress ) ) ,
108
+ screen . getByText ( mockGetSlicedAddress ( testAddressComponentAddress ) ) ,
71
109
) . toBeInTheDocument ( ) ;
72
110
} ) ;
73
111
74
- it ( 'displays sliced address when ENS name is not available and isSliced is set to true' , ( ) => {
75
- useIdentityContextMock . mockReturnValue ( { } ) ;
112
+ it ( 'displays sliced address when ENS name is not available and isSliced is true' , ( ) => {
113
+ useIdentityContextMock . mockReturnValue ( {
114
+ address : undefined ,
115
+ ensName : undefined ,
116
+ loading : false ,
117
+ error : null ,
118
+ } ) ;
76
119
( getSlicedAddress as Mock ) . mockReturnValue (
77
120
mockGetSlicedAddress ( testAddressComponentAddress ) ,
78
121
) ;
79
122
80
123
render ( < Address address = { testAddressComponentAddress } isSliced = { true } /> ) ;
124
+ expect ( getSlicedAddress ) . toHaveBeenCalledWith ( testAddressComponentAddress ) ;
81
125
expect (
82
126
screen . getByText ( mockGetSlicedAddress ( testAddressComponentAddress ) ) ,
83
127
) . toBeInTheDocument ( ) ;
84
- expect ( getSlicedAddress ) . toHaveBeenCalledWith ( testAddressComponentAddress ) ;
85
128
} ) ;
86
129
87
130
it ( 'displays full address when isSliced is false and ENS name is not available' , ( ) => {
@@ -91,7 +134,7 @@ describe('Address component', () => {
91
134
expect ( getSlicedAddress ) . not . toHaveBeenCalled ( ) ;
92
135
} ) ;
93
136
94
- it ( 'use identity context address if provided' , ( ) => {
137
+ it ( 'uses identity context address if provided' , ( ) => {
95
138
useIdentityContextMock . mockReturnValue ( {
96
139
address : testIdentityProviderAddress ,
97
140
} ) ;
@@ -100,12 +143,78 @@ describe('Address component', () => {
100
143
expect ( getSlicedAddress ) . not . toHaveBeenCalled ( ) ;
101
144
} ) ;
102
145
103
- it ( 'use component address over identity context if both are provided' , ( ) => {
146
+ it ( 'prioritizes component address over identity context address if both are provided' , ( ) => {
104
147
useIdentityContextMock . mockReturnValue ( {
105
148
address : testIdentityProviderAddress ,
106
149
} ) ;
107
150
render ( < Address address = { testAddressComponentAddress } isSliced = { false } /> ) ;
108
151
expect ( screen . getByText ( testAddressComponentAddress ) ) . toBeInTheDocument ( ) ;
109
152
expect ( getSlicedAddress ) . not . toHaveBeenCalled ( ) ;
110
153
} ) ;
154
+
155
+ describe ( 'clipboard functionality' , ( ) => {
156
+ const testAddress = '0x1234567890abcdef' ;
157
+
158
+ beforeEach ( ( ) => {
159
+ vi . clearAllMocks ( ) ;
160
+ useIdentityContextMock . mockReturnValue ( {
161
+ address : undefined ,
162
+ ensName : undefined ,
163
+ loading : false ,
164
+ error : null ,
165
+ } ) ;
166
+ } ) ;
167
+
168
+ it ( 'copies address to clipboard on click' , ( ) => {
169
+ render ( < Address address = { testAddress } /> ) ;
170
+ const element = screen . getByTestId ( 'ockAddress' ) ;
171
+ fireEvent . click ( element ) ;
172
+ expect ( mockClipboard . writeText ) . toHaveBeenCalledWith ( testAddress ) ;
173
+ } ) ;
174
+
175
+ it ( 'shows Copied text after clicking' , async ( ) => {
176
+ render ( < Address address = { testAddress } /> ) ;
177
+ const element = screen . getByTestId ( 'ockAddress' ) ;
178
+
179
+ const tooltipSpan = element . querySelector ( 'span' ) ;
180
+ expect ( tooltipSpan ) . toHaveTextContent ( 'Copy' ) ;
181
+
182
+ fireEvent . click ( element ) ;
183
+
184
+ await vi . waitFor ( ( ) => {
185
+ expect ( tooltipSpan ) . toHaveTextContent ( 'Copied' ) ;
186
+ } ) ;
187
+ } ) ;
188
+
189
+ it ( 'handles clipboard error' , async ( ) => {
190
+ mockClipboard . writeText . mockRejectedValueOnce ( new Error ( 'Failed' ) ) ;
191
+ const consoleSpy = vi
192
+ . spyOn ( console , 'error' )
193
+ . mockImplementation ( ( ) => { } ) ;
194
+
195
+ render ( < Address address = { testAddress } /> ) ;
196
+ const element = screen . getByTestId ( 'ockAddress' ) ;
197
+ fireEvent . click ( element ) ;
198
+
199
+ await vi . waitFor ( ( ) => {
200
+ expect ( consoleSpy ) . toHaveBeenCalled ( ) ;
201
+ } ) ;
202
+
203
+ consoleSpy . mockRestore ( ) ;
204
+ } ) ;
205
+
206
+ it ( 'copies on Enter key' , ( ) => {
207
+ render ( < Address address = { testAddress } /> ) ;
208
+ const element = screen . getByTestId ( 'ockAddress' ) ;
209
+ fireEvent . keyDown ( element , { key : 'Enter' } ) ;
210
+ expect ( mockClipboard . writeText ) . toHaveBeenCalledWith ( testAddress ) ;
211
+ } ) ;
212
+
213
+ it ( 'copies on Space key' , ( ) => {
214
+ render ( < Address address = { testAddress } /> ) ;
215
+ const element = screen . getByTestId ( 'ockAddress' ) ;
216
+ fireEvent . keyDown ( element , { key : ' ' } ) ;
217
+ expect ( mockClipboard . writeText ) . toHaveBeenCalledWith ( testAddress ) ;
218
+ } ) ;
219
+ } ) ;
111
220
} ) ;
0 commit comments