1
1
import React from 'react' ;
2
2
import { render , fireEvent } from '@testing-library/react-native' ;
3
- import { Linking } from 'react-native' ;
3
+ import { Linking , Text , View } from 'react-native' ;
4
4
import { SnapUILink } from './SnapUILink' ;
5
- import ButtonLink from '../../../component-library/components/Buttons/Button/variants/ButtonLink' ;
6
5
import Icon , {
7
6
IconColor ,
8
7
IconName ,
9
8
IconSize ,
10
9
} from '../../../component-library/components/Icons/Icon' ;
11
- import { TextColor } from '../../../component-library/components/Texts/Text' ;
12
10
13
11
jest . mock ( 'react-native/Libraries/Linking/Linking' , ( ) => ( {
14
12
openURL : jest . fn ( ) ,
@@ -25,14 +23,19 @@ describe('SnapUILink', () => {
25
23
} ;
26
24
27
25
it ( 'renders correctly with valid props' , ( ) => {
28
- const { UNSAFE_getByType } = render ( < SnapUILink { ...validProps } /> ) ;
26
+ const { UNSAFE_getByType, getByTestId } = render (
27
+ < SnapUILink { ...validProps } /> ,
28
+ ) ;
29
29
30
- const button = UNSAFE_getByType ( ButtonLink ) ;
30
+ const linkText = getByTestId ( 'snaps-ui-link' ) ;
31
+ const spacer = UNSAFE_getByType ( View ) ;
31
32
const icon = UNSAFE_getByType ( Icon ) ;
32
33
33
- expect ( button ) . toBeTruthy ( ) ;
34
- expect ( button . props . testID ) . toBe ( 'snaps-ui-link' ) ;
35
- expect ( button . props . color ) . toBe ( TextColor . Info ) ;
34
+ expect ( linkText ) . toBeTruthy ( ) ;
35
+ expect ( linkText . props . children [ 0 ] ) . toBe ( 'Visit MetaMask' ) ;
36
+ expect ( spacer ) . toBeTruthy ( ) ;
37
+ expect ( spacer . props . style ) . toEqual ( { width : 4 } ) ;
38
+ expect ( linkText . props . accessibilityRole ) . toBe ( 'link' ) ;
36
39
expect ( icon . props . name ) . toBe ( IconName . Export ) ;
37
40
expect ( icon . props . color ) . toBe ( IconColor . Primary ) ;
38
41
expect ( icon . props . size ) . toBe ( IconSize . Sm ) ;
@@ -41,8 +44,8 @@ describe('SnapUILink', () => {
41
44
it ( 'opens URL when pressed with valid https URL' , ( ) => {
42
45
const { getByTestId } = render ( < SnapUILink { ...validProps } /> ) ;
43
46
44
- const button = getByTestId ( 'snaps-ui-link' ) ;
45
- fireEvent . press ( button ) ;
47
+ const link = getByTestId ( 'snaps-ui-link' ) ;
48
+ fireEvent . press ( link ) ;
46
49
47
50
expect ( Linking . openURL ) . toHaveBeenCalledWith ( validProps . href ) ;
48
51
expect ( Linking . openURL ) . toHaveBeenCalledTimes ( 1 ) ;
@@ -56,12 +59,88 @@ describe('SnapUILink', () => {
56
59
57
60
const { getByTestId } = render ( < SnapUILink { ...invalidProps } /> ) ;
58
61
59
- const button = getByTestId ( 'snaps-ui-link' ) ;
62
+ const link = getByTestId ( 'snaps-ui-link' ) ;
60
63
61
64
expect ( ( ) => {
62
- fireEvent . press ( button ) ;
65
+ fireEvent . press ( link ) ;
63
66
} ) . toThrow ( 'Invalid URL' ) ;
64
67
65
68
expect ( Linking . openURL ) . not . toHaveBeenCalled ( ) ;
66
69
} ) ;
70
+
71
+ it ( 'can be nested inside another Text component' , ( ) => {
72
+ const { toJSON } = render (
73
+ < Text >
74
+ Before < SnapUILink href = "https://metamask.io" > MetaMask</ SnapUILink > { ' ' }
75
+ After
76
+ </ Text > ,
77
+ ) ;
78
+
79
+ const textContent = JSON . stringify ( toJSON ( ) ) ;
80
+ expect ( textContent ) . toContain ( 'Before' ) ;
81
+ expect ( textContent ) . toContain ( 'MetaMask' ) ;
82
+ expect ( textContent ) . toContain ( 'After' ) ;
83
+ } ) ;
84
+
85
+ it ( 'handles array children correctly' , ( ) => {
86
+ const { getByTestId } = render (
87
+ < SnapUILink href = "https://metamask.io" >
88
+ { 'Part 1 ' }
89
+ { 'Part 2' }
90
+ </ SnapUILink > ,
91
+ ) ;
92
+
93
+ const link = getByTestId ( 'snaps-ui-link' ) ;
94
+ const childrenArray = link . props . children ;
95
+ const textContent = childrenArray [ 0 ] . toString ( ) ;
96
+
97
+ expect ( textContent ) . toBe ( 'Part 1 ,Part 2' ) ;
98
+ } ) ;
99
+
100
+ it ( 'renders correctly with complex children' , ( ) => {
101
+ const { UNSAFE_getAllByType, toJSON } = render (
102
+ < SnapUILink href = "https://metamask.io" >
103
+ Normal text
104
+ { /* eslint-disable-next-line react-native/no-inline-styles */ }
105
+ < Text style = { { fontWeight : 'bold' } } > Bold text</ Text >
106
+ </ SnapUILink > ,
107
+ ) ;
108
+
109
+ const textContent = JSON . stringify ( toJSON ( ) ) ;
110
+ expect ( textContent ) . toContain ( 'Normal text' ) ;
111
+ expect ( textContent ) . toContain ( 'Bold text' ) ;
112
+
113
+ // Should have our Icon plus any Text components
114
+ const allIcons = UNSAFE_getAllByType ( Icon ) ;
115
+ expect ( allIcons . length ) . toBe ( 1 ) ;
116
+ } ) ;
117
+
118
+ it ( 'validates URL format correctly' , ( ) => {
119
+ // Valid HTTPS URL
120
+ expect ( ( ) => {
121
+ fireEvent . press (
122
+ render (
123
+ < SnapUILink href = "https://example.com" > Link</ SnapUILink > ,
124
+ ) . getByTestId ( 'snaps-ui-link' ) ,
125
+ ) ;
126
+ } ) . not . toThrow ( ) ;
127
+
128
+ // Invalid HTTP URL
129
+ expect ( ( ) => {
130
+ fireEvent . press (
131
+ render (
132
+ < SnapUILink href = "http://example.com" > Link</ SnapUILink > ,
133
+ ) . getByTestId ( 'snaps-ui-link' ) ,
134
+ ) ;
135
+ } ) . toThrow ( 'Invalid URL' ) ;
136
+
137
+ // Invalid non-HTTP URL
138
+ expect ( ( ) => {
139
+ fireEvent . press (
140
+ render (
141
+ < SnapUILink href = "ftp://example.com" > Link</ SnapUILink > ,
142
+ ) . getByTestId ( 'snaps-ui-link' ) ,
143
+ ) ;
144
+ } ) . toThrow ( 'Invalid URL' ) ;
145
+ } ) ;
67
146
} ) ;
0 commit comments