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