1- import { Button } from '@deriv/ui' ;
21import useApiToken from '@site/src/hooks/useApiToken' ;
32import { render , screen , cleanup } from '@site/src/test-utils' ;
43import { TTokensArrayType } from '@site/src/types' ;
54import userEvent from '@testing-library/user-event' ;
65import React from 'react' ;
76import AppForm from '..' ;
7+ import { ApplicationObject } from '@deriv/api-types' ;
8+ import useAppManager from '@site/src/hooks/useAppManager' ;
89
910jest . mock ( '@site/src/hooks/useApiToken' ) ;
1011jest . mock ( '@site/src/utils' , ( ) => ( {
1112 ...jest . requireActual ( '@site/src/utils' ) ,
1213} ) ) ;
14+ jest . mock ( '@site/src/hooks/useAppManager' ) ;
1315
1416const mockUseApiToken = useApiToken as jest . MockedFunction <
1517 ( ) => Partial < ReturnType < typeof useApiToken > >
@@ -20,32 +22,89 @@ mockUseApiToken.mockImplementation(() => ({
2022 updateCurrentToken : jest . fn ( ) ,
2123} ) ) ;
2224
23- const renderButtons = ( ) => {
24- return (
25- < div >
26- < Button role = 'submit' > Update Application </ Button >
27- </ div >
28- ) ;
29- } ;
25+ const mockUseAppManager = useAppManager as jest . MockedFunction <
26+ ( ) => Partial < ReturnType < typeof useAppManager > >
27+ > ;
28+ mockUseAppManager . mockImplementation ( ( ) => ( {
29+ apps : [ ] ,
30+ getApps : jest . fn ( ) ,
31+ } ) ) ;
3032
3133describe ( 'App Form' , ( ) => {
3234 const mockOnSubmit = jest . fn ( ) ;
3335
3436 beforeEach ( ( ) => {
35- render ( < AppForm renderButtons = { renderButtons } submit = { mockOnSubmit } /> ) ;
37+ render ( < AppForm submit = { mockOnSubmit } /> ) ;
3638 } ) ;
3739
3840 afterEach ( ( ) => {
3941 cleanup ( ) ;
4042 jest . clearAllMocks ( ) ;
4143 } ) ;
4244
45+ it ( 'Should show error message for using an appname that already exists' , async ( ) => {
46+ const fakeApps : ApplicationObject [ ] = [
47+ {
48+ active : 1 ,
49+ app_id : 12345 ,
50+ app_markup_percentage : 0 ,
51+ appstore : '' ,
52+ github : '' ,
53+ googleplay : '' ,
54+ homepage : '' ,
55+ name : 'duplicate_app' ,
56+ redirect_uri : 'https://example.com' ,
57+ scopes : [ 'read' , 'trade' , 'trading_information' ] ,
58+ verification_uri : 'https://example.com' ,
59+ last_used : '' ,
60+ } ,
61+ {
62+ active : 1 ,
63+ app_id : 12345 ,
64+ app_markup_percentage : 0 ,
65+ appstore : '' ,
66+ github : '' ,
67+ googleplay : '' ,
68+ homepage : '' ,
69+ name : 'testApp' ,
70+ redirect_uri : 'https://example.com' ,
71+ scopes : [ 'read' , 'trade' ] ,
72+ verification_uri : 'https://example.com' ,
73+ last_used : '' ,
74+ } ,
75+ ] ;
76+ const mockGetApps = jest . fn ( ) ;
77+
78+ mockUseAppManager . mockImplementation ( ( ) => ( {
79+ apps : fakeApps ,
80+ getApps : mockGetApps ,
81+ } ) ) ;
82+
83+ const submitButton = screen . getByText ( 'Register Application' ) ;
84+
85+ const tokenNameInput = screen . getByRole < HTMLInputElement > ( 'textbox' , {
86+ name : 'App name (required)' ,
87+ } ) ;
88+
89+ await userEvent . type ( tokenNameInput , 'duplicate_app' ) ;
90+
91+ await userEvent . click ( submitButton ) ;
92+
93+ await userEvent . clear ( tokenNameInput ) ;
94+
95+ await userEvent . type ( tokenNameInput , 'duplicate_app' ) ;
96+
97+ const appNameErrorText = await screen . findByText ( 'That name is taken. Choose another.' ) ;
98+
99+ expect ( appNameErrorText ) . toBeInTheDocument ( ) ;
100+ } ) ;
101+
43102 it ( 'Should show error message for having no admin token' , async ( ) => {
44103 const fakeTokens : TTokensArrayType = [
45104 {
46105 display_name : 'first' ,
47106 last_used : '' ,
48- scopes : [ 'read' , 'trade' ] ,
107+ scopes : [ 'read' , 'trade' , 'admin' ] ,
49108 token : 'first_token' ,
50109 valid_for_ip : '' ,
51110 } ,
@@ -71,8 +130,11 @@ describe('App Form', () => {
71130 } ) ;
72131
73132 it ( 'Should show error message for empty app name' , async ( ) => {
74- const submitButton = screen . getByText ( 'Update Application' ) ;
75-
133+ const submitButton = screen . getByText ( 'Register Application' ) ;
134+ const tokenNameInput = screen . getByRole < HTMLInputElement > ( 'textbox' , {
135+ name : 'App name (required)' ,
136+ } ) ;
137+ await userEvent . clear ( tokenNameInput ) ;
76138 await userEvent . click ( submitButton ) ;
77139
78140 const appNameErrorText = await screen . findByText ( 'Enter your app name.' ) ;
@@ -81,7 +143,7 @@ describe('App Form', () => {
81143 } ) ;
82144
83145 it ( 'Should show error for long app name' , async ( ) => {
84- const submitButton = screen . getByText ( 'Update Application' ) ;
146+ const submitButton = screen . getByText ( 'Register Application' ) ;
85147
86148 const tokenNameInput = screen . getByRole < HTMLInputElement > ( 'textbox' , {
87149 name : 'App name (required)' ,
@@ -99,8 +161,26 @@ describe('App Form', () => {
99161 expect ( appNameErrorText ) . toBeInTheDocument ( ) ;
100162 } ) ;
101163
164+ it ( 'Should show error for using non alphanumeric characters except underscore or space' , async ( ) => {
165+ const submitButton = screen . getByText ( 'Register Application' ) ;
166+
167+ const tokenNameInput = screen . getByRole < HTMLInputElement > ( 'textbox' , {
168+ name : 'App name (required)' ,
169+ } ) ;
170+
171+ await userEvent . type ( tokenNameInput , 'invalid-token...' ) ;
172+
173+ await userEvent . click ( submitButton ) ;
174+
175+ const appNameErrorText = await screen . findByText (
176+ 'Only alphanumeric characters with spaces and underscores are allowed. (Example: my_application)' ,
177+ ) ;
178+
179+ expect ( appNameErrorText ) . toBeInTheDocument ( ) ;
180+ } ) ;
181+
102182 it ( 'Should show error message for long app markup percentage' , async ( ) => {
103- const submitButton = screen . getByText ( 'Update Application' ) ;
183+ const submitButton = screen . getByText ( 'Register Application' ) ;
104184
105185 const appMarkupPercentageInput = screen . getByRole < HTMLInputElement > ( 'spinbutton' , {
106186 name : 'Markup percentage (optional)' ,
@@ -117,6 +197,42 @@ describe('App Form', () => {
117197 expect ( appMarkupPercentageError ) . toBeInTheDocument ( ) ;
118198 } ) ;
119199
200+ it ( 'Should show error for invalid Auth url' , async ( ) => {
201+ const submitButton = screen . getByText ( 'Register Application' ) ;
202+
203+ const authURLInput = screen . getByRole ( 'textbox' , {
204+ name : 'Authorization URL (optional)' ,
205+ } ) ;
206+
207+ await userEvent . type ( authURLInput , 'http:invalidAUTHurl.com' ) ;
208+
209+ await userEvent . click ( submitButton ) ;
210+
211+ const authURLInputError = await screen . queryByText (
212+ 'Enter a valid URL. (Example: https://www.[YourDomainName].com)' ,
213+ ) ;
214+
215+ expect ( authURLInputError ) . toBeInTheDocument ( ) ;
216+ } ) ;
217+
218+ it ( 'Should show error for invalid Verification url' , async ( ) => {
219+ const submitButton = screen . getByText ( 'Register Application' ) ;
220+
221+ const authURLInput = screen . getByRole ( 'textbox' , {
222+ name : 'Verification URL (optional)' ,
223+ } ) ;
224+
225+ await userEvent . type ( authURLInput , 'http:invalidVERIurl.com' ) ;
226+
227+ await userEvent . click ( submitButton ) ;
228+
229+ const authURLInputError = await screen . queryByText (
230+ 'Enter a valid URL. (Example: https://www.[YourDomainName].com)' ,
231+ ) ;
232+
233+ expect ( authURLInputError ) . toBeInTheDocument ( ) ;
234+ } ) ;
235+
120236 it ( 'Should show error message for wrong value' , async ( ) => {
121237 const fakeTokens : TTokensArrayType = [
122238 {
@@ -147,7 +263,7 @@ describe('App Form', () => {
147263 updateCurrentToken : jest . fn ( ) ,
148264 } ) ) ;
149265
150- const submitButton = screen . getByText ( 'Update Application' ) ;
266+ const submitButton = screen . getByText ( 'Register Application' ) ;
151267
152268 const appMarkupPercentageInput = screen . getByRole < HTMLInputElement > ( 'spinbutton' , {
153269 name : 'Markup percentage (optional)' ,
@@ -165,7 +281,7 @@ describe('App Form', () => {
165281 } ) ;
166282
167283 it ( 'Should call onSubmit on submitting the form' , async ( ) => {
168- const submitButton = screen . getByText ( 'Update Application' ) ;
284+ const submitButton = screen . getByText ( 'Register Application' ) ;
169285
170286 const selectTokenOption = screen . getByTestId ( 'select-token' ) ;
171287
@@ -193,4 +309,27 @@ describe('App Form', () => {
193309
194310 expect ( mockOnSubmit ) . toHaveBeenCalledTimes ( 1 ) ;
195311 } ) ;
312+
313+ it ( 'Should display restrictions when app name is in focus and disappear if error occurs' , async ( ) => {
314+ const submitButton = screen . getByText ( 'Register Application' ) ;
315+
316+ const tokenNameInput = screen . getByRole < HTMLInputElement > ( 'textbox' , {
317+ name : 'App name (required)' ,
318+ } ) ;
319+
320+ await userEvent . type ( tokenNameInput , 'Lorem ipsum dolor sit amet' ) ;
321+
322+ const restrictionsList = screen . queryByRole ( 'list' ) ;
323+ expect ( restrictionsList ) . toBeInTheDocument ( ) ;
324+
325+ await userEvent . clear ( tokenNameInput ) ;
326+
327+ await userEvent . type (
328+ tokenNameInput ,
329+ 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Modi corrupti neque ratione repudiandae in dolores reiciendis sequi nvrohgoih iuhwr uiwhrug uwhiog iouwhg ouwhg' ,
330+ ) ;
331+
332+ await userEvent . click ( submitButton ) ;
333+ expect ( restrictionsList ) . not . toBeInTheDocument ( ) ;
334+ } ) ;
196335} ) ;
0 commit comments