4
4
* (c) 2024 Feedzai, Rights Reserved.
5
5
*/
6
6
import React from "react" ;
7
- import { useAutoId } from "src/hooks" ;
7
+ import { useAutoId , generateFallbackId , generateUUIDFragment , initializeState } from "src/hooks" ;
8
8
9
- function DemoComponent ( { value = null , prefix } : { value ?: string | null ; prefix ?: string } ) {
9
+ function DemoComponent ( { value, prefix } : { value ?: string | null ; prefix ?: string } ) {
10
10
const firstId = useAutoId ( value , prefix ) ;
11
11
const secondId = useAutoId ( ) ;
12
12
return (
@@ -21,88 +21,132 @@ function FallbackDemo({
21
21
value = "feedzai-fallback-id" ,
22
22
prefix,
23
23
} : {
24
- value ?: string | null ;
24
+ value ?: string ;
25
25
prefix ?: string ;
26
26
} ) {
27
27
const id = useAutoId ( value , prefix ) ;
28
28
return < h1 id = { id } > Feedzai</ h1 > ;
29
29
}
30
30
31
+ describe ( "generateFallbackId" , ( ) => {
32
+ it ( "generates a fallback ID" , ( ) => {
33
+ const id = generateFallbackId ( ) ;
34
+ expect ( id ) . to . exist ;
35
+ expect ( typeof id ) . to . equal ( "string" ) ;
36
+ } ) ;
37
+ } ) ;
38
+
39
+ describe ( "generateUUIDFragment" , ( ) => {
40
+ it ( "generates a UUID fragment" , ( ) => {
41
+ const id = generateUUIDFragment ( ) ;
42
+ expect ( id ) . to . exist ;
43
+ expect ( typeof id ) . to . equal ( "string" ) ;
44
+ expect ( id . length ) . to . equal ( 8 ) ;
45
+ } ) ;
46
+
47
+ it ( "generates a UUID fragment of a given length" , ( ) => {
48
+ const id = generateUUIDFragment ( 16 ) ;
49
+ expect ( id ) . to . exist ;
50
+ expect ( typeof id ) . to . equal ( "string" ) ;
51
+ expect ( id . length ) . to . equal ( 16 ) ;
52
+ } ) ;
53
+ } ) ;
54
+
55
+ describe ( "initializeState" , ( ) => {
56
+ it ( "generates a UUID fragment if no ID is provided" , ( ) => {
57
+ // @ts -expect-error - This is a test for the fallback behavior
58
+ const id = initializeState ( ) ;
59
+ expect ( id ) . to . exist ;
60
+ expect ( typeof id ) . to . equal ( "string" ) ;
61
+ } ) ;
62
+
63
+ it ( "generates a UUID fragment of a given length if no ID is provided" , ( ) => {
64
+ const id = initializeState ( undefined , { length : 16 } ) ;
65
+ expect ( id ) . to . exist ;
66
+ expect ( typeof id ) . to . equal ( "string" ) ;
67
+ expect ( id . length ) . to . equal ( 16 ) ;
68
+ } ) ;
69
+
70
+ it ( "returns the provided ID if it is a string" , ( ) => {
71
+ const id = initializeState ( "feedzai-id" ) ;
72
+ expect ( id ) . to . equal ( "feedzai-id" ) ;
73
+ } ) ;
74
+ } ) ;
75
+
31
76
describe ( "useAutoId" , ( ) => {
32
- context ( "React pre-useId" , ( ) => {
77
+ it ( "generates a prefixed fallback ID" , ( ) => {
78
+ cy . mount ( < DemoComponent prefix = "fdz-prefix" /> ) ;
79
+
80
+ console . log ( process . env . NODE_ENV ) ;
81
+
82
+ cy . findByText ( "A paragraph" )
83
+ . invoke ( "attr" , "id" )
84
+ . should ( "match" , / ^ f d z - p r e f i x - - : ? [ a - z 0 - 9 : ] + : ? $ / ) ;
85
+ } ) ;
86
+
87
+ context ( "React <18 (no useId support)" , ( ) => {
33
88
beforeEach ( ( ) => {
34
- // Mock React.useId to be undefined
35
89
cy . stub ( React , "useId" ) . as ( "useIdStub" ) . value ( undefined ) ;
36
90
} ) ;
37
91
38
- it ( "should generate a unique ID value " , ( ) => {
92
+ it ( "generates unique IDs using fallback generator " , ( ) => {
39
93
cy . mount ( < DemoComponent /> ) ;
40
94
41
95
cy . findByText ( "A paragraph" )
42
96
. invoke ( "attr" , "id" )
43
- . then ( ( idOne ) => {
44
- cy . findByText ( "An inline span element" ) . invoke ( "attr" , "id" ) . should ( "not.equal" , idOne ) ;
45
- } ) ;
46
- } ) ;
47
-
48
- it ( "should generate a prefixed unique ID value" , ( ) => {
49
- const expected = "feedzai-a-prefix" ;
50
- cy . mount ( < DemoComponent value = { undefined } prefix = { expected } /> ) ;
97
+ . then ( ( firstId ) => {
98
+ expect ( firstId ) . to . exist ;
51
99
52
- cy . findByText ( "A paragraph" ) . invoke ( "attr" , "id" ) . should ( "contain" , expected ) ;
100
+ cy . findByText ( "An inline span element" )
101
+ . invoke ( "attr" , "id" )
102
+ . should ( "exist" )
103
+ . and ( "not.equal" , firstId ) ;
104
+ } ) ;
53
105
} ) ;
54
106
55
- it ( "uses a fallback ID" , ( ) => {
107
+ it ( "uses a static fallback ID if provided " , ( ) => {
56
108
cy . mount ( < FallbackDemo /> ) ;
57
109
58
110
cy . findByText ( "Feedzai" ) . should ( "have.id" , "feedzai-fallback-id" ) ;
59
111
} ) ;
60
112
61
- it ( "should return a prefixed fallback ID" , ( ) => {
62
- cy . mount ( < FallbackDemo prefix = "js-prefix" value = "423696e5 " /> ) ;
113
+ it ( "applies a prefix to the custom fallback ID" , ( ) => {
114
+ cy . mount ( < FallbackDemo value = "423696e5" prefix = "js-prefix " /> ) ;
63
115
64
116
cy . findByText ( "Feedzai" ) . should ( "have.id" , "js-prefix--423696e5" ) ;
65
117
} ) ;
66
118
} ) ;
67
119
68
- context ( "React 18+ with useId" , ( ) => {
69
- const GENERATED_ID = ":r0:" ;
70
-
71
- beforeEach ( ( ) => {
72
- // Mock React.useId to return a predictable value
73
- cy . stub ( React , "useId" ) . as ( "useIdStub" ) . returns ( GENERATED_ID ) ;
74
- } ) ;
75
-
76
- it ( "should use React.useId for generating IDs" , ( ) => {
120
+ context ( "React 18+ (with useId)" , ( ) => {
121
+ it ( "uses React.useId to generate consistent IDs" , ( ) => {
77
122
cy . mount ( < DemoComponent /> ) ;
78
123
79
- cy . findByText ( "A paragraph" ) . invoke ( "attr" , "id" ) . should ( "equal" , GENERATED_ID ) ;
80
- cy . findByText ( "An inline span element" ) . invoke ( "attr" , "id" ) . should ( "equal" , GENERATED_ID ) ;
81
- cy . get ( "@useIdStub" ) . should ( "be.calledTwice" ) ;
124
+ cy . findByText ( "A paragraph" )
125
+ . invoke ( "attr" , "id" )
126
+ . should ( "match" , / ^ : ? [ a - z 0 - 9 : ] + : ? $ / ) ;
127
+ cy . findByText ( "An inline span element" )
128
+ . invoke ( "attr" , "id" )
129
+ . should ( "match" , / ^ : ? [ a - z 0 - 9 : ] + : ? $ / ) ;
82
130
} ) ;
83
131
84
- it ( "should generate a prefixed unique ID value using React.useId" , ( ) => {
85
- const expected = "feedzai-a-prefix" ;
86
- cy . mount ( < DemoComponent value = { undefined } prefix = { expected } /> ) ;
132
+ it ( "applies prefix to ID generated by React.useId" , ( ) => {
133
+ cy . mount ( < DemoComponent prefix = "fdz-js-prefix" /> ) ;
87
134
88
135
cy . findByText ( "A paragraph" )
89
136
. invoke ( "attr" , "id" )
90
- . should ( "equal" , `${ expected } --${ GENERATED_ID } ` ) ;
91
- cy . get ( "@useIdStub" ) . should ( "be.called" ) ;
137
+ . should ( "match" , / ^ f d z - j s - p r e f i x - - : ? [ a - z 0 - 9 : ] + : ? $ / ) ;
92
138
} ) ;
93
139
94
- it ( "uses a fallback ID even when React.useId is available " , ( ) => {
140
+ it ( "uses static fallback ID when explicitly provided " , ( ) => {
95
141
cy . mount ( < FallbackDemo /> ) ;
96
142
97
143
cy . findByText ( "Feedzai" ) . should ( "have.id" , "feedzai-fallback-id" ) ;
98
- cy . get ( "@useIdStub" ) . should ( "not.be.called" ) ;
99
144
} ) ;
100
145
101
- it ( "should return a prefixed fallback ID and not use React. useId" , ( ) => {
102
- cy . mount ( < FallbackDemo prefix = "js-prefix" value = "423696e5 " /> ) ;
146
+ it ( "applies prefix to provided fallback ID (ignoring useId) " , ( ) => {
147
+ cy . mount ( < FallbackDemo value = "423696e5" prefix = "fdz-js-prefix " /> ) ;
103
148
104
- cy . findByText ( "Feedzai" ) . should ( "have.id" , "js-prefix--423696e5" ) ;
105
- cy . get ( "@useIdStub" ) . should ( "not.be.called" ) ;
149
+ cy . findByText ( "Feedzai" ) . should ( "have.id" , "fdz-js-prefix--423696e5" ) ;
106
150
} ) ;
107
151
} ) ;
108
152
} ) ;
0 commit comments