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