1import { render } from '@testing-library/react'; 2import GithubSlugger from 'github-slugger'; 3import * as React from 'react'; 4 5import AppConfigSchemaPropertiesTable, { 6 formatSchema, 7 createDescription, 8 _getType, 9 Property, 10} from './AppConfigSchemaPropertiesTable'; 11 12import { HeadingManager } from '~/common/headingManager'; 13import { HeadingsContext } from '~/components/page-higher-order/withHeadingManager'; 14 15const testSchema: Record<string, Property> = { 16 name: { 17 description: 'Name of your app.', 18 type: 'string', 19 meta: { 20 bareWorkflow: "Edit the 'Display Name' field in Xcode", 21 }, 22 }, 23 androidNavigationBar: { 24 description: 'Configuration for the bottom navigation bar on Android.', 25 type: 'object', 26 properties: { 27 visible: { 28 description: 'Determines how and when the navigation bar is shown.', 29 type: 'string', 30 properties: { 31 always: { 32 description: 'Test sub-sub-property', 33 type: 'boolean', 34 }, 35 }, 36 meta: { 37 expoKit: 'Set this property using Xcode.', 38 }, 39 enum: ['leanback', 'immersive', 'sticky-immersive'], 40 }, 41 backgroundColor: { 42 description: 'Specifies the background color of the navigation bar. ', 43 type: 'string', 44 pattern: '^#|(#)\\d{6}$', 45 meta: { 46 regexHuman: "6 character long hex color string, eg: `'#000000'`", 47 }, 48 }, 49 }, 50 meta: { 51 expoKit: 'Set this property using AppConstants.java.', 52 bareWorkflow: 'Set this property using just Xcode', 53 }, 54 }, 55 intentFilters: { 56 description: 'Configuration for setting an array of custom intent filters in Android manifest.', 57 example: [ 58 { 59 autoVerify: true, 60 data: { 61 host: '*.example.com', 62 }, 63 }, 64 ], 65 exampleString: '\n [{ \n "autoVerify": true, \n "data": {"host": "*.example.com" \n } \n }]', 66 type: 'array', 67 uniqueItems: true, 68 items: { 69 type: 'object', 70 properties: { 71 autoVerify: { 72 description: 73 'You may also use an intent filter to set your app as the default handler for links', 74 type: 'boolean', 75 }, 76 data: { 77 type: ['array', 'object'], 78 items: { 79 type: 'object', 80 properties: { 81 host: { description: 'the host, e.g. `example.com`', type: 'string' }, 82 }, 83 additionalProperties: false, 84 }, 85 properties: { 86 host: { type: 'string' }, 87 }, 88 additionalProperties: false, 89 }, 90 }, 91 additionalProperties: false, 92 required: ['action'], 93 }, 94 meta: { 95 bareWorkflow: 'This is set in AndroidManifest.xml directly.', 96 }, 97 }, 98}; 99 100describe('AppConfigSchemaPropertiesTable', () => { 101 test('correctly matches snapshot', () => { 102 const { container } = render( 103 <HeadingsContext.Provider value={new HeadingManager(new GithubSlugger(), { headings: [] })}> 104 <AppConfigSchemaPropertiesTable schema={testSchema} /> 105 </HeadingsContext.Provider> 106 ); 107 expect(container).toMatchSnapshot(); 108 }); 109}); 110 111describe('formatSchema', () => { 112 const formattedSchema = formatSchema(Object.entries(testSchema)); 113 test('name is property nestingLevel 0', () => { 114 expect(formattedSchema[0].nestingLevel).toBe(0); 115 }); 116 test('androidNavigationBar is property nestingLevel 0', () => { 117 expect(formattedSchema[1].nestingLevel).toBe(0); 118 }); 119 test('visible is subproperty nestingLevel 1', () => { 120 expect(formattedSchema[2].nestingLevel).toBe(1); 121 }); 122 test('always is subproperty nestingLevel 2', () => { 123 expect(formattedSchema[3].nestingLevel).toBe(2); 124 }); 125 test('backgroundColor is subproperty nestingLevel 1', () => { 126 expect(formattedSchema[4].nestingLevel).toBe(1); 127 }); 128 test('intentFilters is property nestingLevel 0', () => { 129 expect(formattedSchema[5].nestingLevel).toBe(0); 130 }); 131 test('autoVerify is subproperty nestingLevel 1', () => { 132 expect(formattedSchema[6].nestingLevel).toBe(1); 133 }); 134 test('data is subproperty nestingLevel 1', () => { 135 expect(formattedSchema[7].nestingLevel).toBe(1); 136 }); 137 test('host is subproperty nestingLevel 2', () => { 138 expect(formattedSchema[8].nestingLevel).toBe(2); 139 }); 140}); 141 142describe('createDescription', () => { 143 test('bareWorkflow, exampleString are both added correctly to intentFilters', () => { 144 const intentFiltersObject = Object.entries(testSchema)[2]; 145 const intentFiltersObjectValue = intentFiltersObject[1] as any; 146 const result = createDescription(intentFiltersObject); 147 148 expect(result).toBe( 149 `**(${_getType(intentFiltersObjectValue)})** - ${ 150 intentFiltersObjectValue.description 151 }<bareworkflowDetails>${ 152 intentFiltersObjectValue.meta!.bareWorkflow 153 }</bareworkflowDetails>\n\n>${intentFiltersObjectValue.exampleString}` 154 ); 155 }); 156 157 test('regexHuman is added correctly to backgroundColor', () => { 158 //Note: to access this subproperty is tedious without a call to formatSchema 159 const backgroundColorObject = Object.entries(Object.values(testSchema)[1].properties!)[1]; 160 const backgroundColorObjectValue = backgroundColorObject[1]; 161 const result = createDescription(backgroundColorObject); 162 163 expect(result).toBe( 164 `**(${_getType(backgroundColorObjectValue)})** - ${ 165 backgroundColorObjectValue.description 166 }\n\n${backgroundColorObjectValue.meta!.regexHuman}` 167 ); 168 }); 169 170 test('expoKit is added correctly to visible', () => { 171 //Note: to access this subproperty is tedious without a call to formatSchema 172 const visibleObject = Object.entries(Object.values(testSchema)[1].properties!)[0]; 173 const visibleObjectValue = visibleObject[1]; 174 const result = createDescription(visibleObject); 175 176 expect(result).toBe( 177 `**(${_getType(visibleObjectValue)})** - ${visibleObjectValue.description}<expokitDetails>${ 178 visibleObjectValue.meta!.expoKit 179 }</expokitDetails>` 180 ); 181 }); 182 183 test('bareWorkflow is added correctly to name', () => { 184 const nameObject = Object.entries(testSchema)[0]; 185 const nameObjectValue = nameObject[1]; 186 const result = createDescription(nameObject); 187 188 expect(result).toBe( 189 `**(${_getType(nameObjectValue)})** - ${nameObjectValue.description}<bareworkflowDetails>${ 190 nameObjectValue.meta!.bareWorkflow 191 }</bareworkflowDetails>` 192 ); 193 }); 194 195 test('expoKit, bareWorkflow both added correctly to androidNavigationBar', () => { 196 const androidNavigationBarObject = Object.entries(testSchema)[1]; 197 const androidNavigationBarObjectValue = androidNavigationBarObject[1] as any; 198 const result = createDescription(androidNavigationBarObject); 199 200 expect(result).toBe( 201 `**(${_getType(androidNavigationBarObjectValue)})** - ${ 202 androidNavigationBarObjectValue.description 203 }<expokitDetails>${ 204 androidNavigationBarObjectValue.meta!.expoKit 205 }</expokitDetails><bareworkflowDetails>${ 206 androidNavigationBarObjectValue.meta!.bareWorkflow 207 }</bareworkflowDetails>` 208 ); 209 }); 210}); 211