1import { vol } from 'memfs'; 2 3import { writeXMLAsync } from '../../utils/XML'; 4import { buildResourceItem, readResourcesXMLAsync } from '../Resources'; 5import { 6 getProjectStylesXMLPathAsync, 7 getStyleParent, 8 getStylesItem, 9 removeStylesItem, 10 setStylesItem, 11} from '../Styles'; 12jest.mock('fs'); 13 14const mockStyles = ` 15<?xml 16 version="1.0" 17 encoding="UTF-8" 18 standalone="yes" 19?> 20<resources> 21 <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> 22 <item name="android:textColor">#000000</item> 23 <item name="android:windowTranslucentStatus">true</item> 24 <item name="colorPrimary">@color/colorPrimary</item> 25 </style> 26 <style name="Theme.App.SplashScreen" parent="AppTheme"> 27 <item name="android:windowBackground">@drawable/splashscreen</item> 28 </style> 29</resources>`; 30 31describe('Styles', () => { 32 beforeAll(async () => { 33 const directoryJSON = { 34 './app/android/app/src/main/res/values/styles.xml': mockStyles, 35 './empty/android/app/src/main/res/values/styles.xml': '<resources></resources>', 36 }; 37 vol.fromJSON(directoryJSON, '/'); 38 }); 39 afterAll(async () => { 40 vol.reset(); 41 }); 42 43 it(`sets a style on an empty resource item`, async () => { 44 const stylesPath = await getProjectStylesXMLPathAsync('/empty')!; 45 const xml = await readResourcesXMLAsync({ path: stylesPath }); 46 const parent = { name: 'AppTheme', parent: 'Theme.AppCompat.Light.NoActionBar' }; 47 setStylesItem({ 48 xml, 49 parent, 50 item: buildResourceItem({ name: 'android:textColor', value: '#fff000' }), 51 }); 52 await writeXMLAsync({ path: stylesPath, xml }); 53 54 const modifiedXml = await readResourcesXMLAsync({ path: stylesPath }); 55 56 expect(getStyleParent(modifiedXml, parent)).toStrictEqual({ 57 $: { name: 'AppTheme', parent: 'Theme.AppCompat.Light.NoActionBar' }, 58 item: [{ $: { name: 'android:textColor' }, _: '#fff000' }], 59 }); 60 }); 61 it(`changes the value of a style`, async () => { 62 const stylesPath = await getProjectStylesXMLPathAsync('/app')!; 63 const xml = await readResourcesXMLAsync({ path: stylesPath }); 64 const parent = { name: 'Theme.App.SplashScreen', parent: 'AppTheme' }; 65 setStylesItem({ 66 xml, 67 parent, 68 item: buildResourceItem({ name: 'android:textColor', value: '#ffffff' }), 69 }); 70 await writeXMLAsync({ path: stylesPath, xml }); 71 72 const modifiedXml = await readResourcesXMLAsync({ path: stylesPath }); 73 74 expect(getStyleParent(modifiedXml, parent)).toStrictEqual({ 75 $: { name: 'Theme.App.SplashScreen', parent: 'AppTheme' }, 76 item: [ 77 { $: { name: 'android:windowBackground' }, _: '@drawable/splashscreen' }, 78 { 79 $: { 80 name: 'android:textColor', 81 }, 82 _: '#ffffff', 83 }, 84 ], 85 }); 86 }); 87 88 it(`removes a value`, async () => { 89 const stylesPath = await getProjectStylesXMLPathAsync('/app')!; 90 const xml = await readResourcesXMLAsync({ path: stylesPath }); 91 const parent = { name: 'Theme.App.SplashScreen', parent: 'AppTheme' }; 92 expect(getStylesItem({ xml, parent, name: 'android:textColor' })).toStrictEqual({ 93 $: { 94 name: 'android:textColor', 95 }, 96 _: '#ffffff', 97 }); 98 99 removeStylesItem({ 100 xml, 101 parent, 102 name: 'android:textColor', 103 }); 104 expect(getStylesItem({ xml, parent, name: 'android:textColor' })).toBe(null); 105 }); 106}); 107