1import { ExpoConfig } from '@expo/config-types'; 2import { fs, vol } from 'memfs'; 3import * as path from 'path'; 4 5import { 6 getNotificationColor, 7 getNotificationIcon, 8 NOTIFICATION_ICON_COLOR, 9 setNotificationIconAsync, 10 setNotificationIconColorAsync, 11} from '../withNotificationsAndroid'; 12 13function getDirFromFS(fsJSON: Record<string, string | null>, rootDir: string) { 14 return Object.entries(fsJSON) 15 .filter(([path, value]) => value !== null && path.startsWith(rootDir)) 16 .reduce<Record<string, string>>( 17 (acc, [path, fileContent]) => ({ 18 ...acc, 19 [path.substring(rootDir.length).startsWith('/') 20 ? path.substring(rootDir.length + 1) 21 : path.substring(rootDir.length)]: fileContent, 22 }), 23 {} 24 ); 25} 26 27const SAMPLE_COLORS_XML = `<?xml version="1.0" encoding="utf-8"?> 28 <resources> 29 <!-- Below line is handled by '@expo/configure-splash-screen' command and it's discouraged to modify it manually --> 30 <color name="splashscreen_background">#FFFFFF</color> 31 </resources> 32 `; 33 34jest.mock('fs'); 35 36const fsReal = jest.requireActual('fs') as typeof fs; 37 38const LIST_OF_GENERATED_NOTIFICATION_FILES = [ 39 'android/app/src/main/res/drawable-mdpi/notification_icon.png', 40 'android/app/src/main/res/drawable-hdpi/notification_icon.png', 41 'android/app/src/main/res/drawable-xhdpi/notification_icon.png', 42 'android/app/src/main/res/drawable-xxhdpi/notification_icon.png', 43 'android/app/src/main/res/drawable-xxxhdpi/notification_icon.png', 44 'android/app/src/main/res/values/colors.xml', 45 'assets/notificationIcon.png', 46]; 47const iconPath = path.resolve(__dirname, './fixtures/icon.png'); 48const projectRoot = '/app'; 49 50describe('Android notifications configuration', () => { 51 beforeAll(async () => { 52 const icon = fsReal.readFileSync(iconPath); 53 vol.fromJSON( 54 { './android/app/src/main/res/values/colors.xml': SAMPLE_COLORS_XML }, 55 projectRoot 56 ); 57 setUpDrawableDirectories(); 58 vol.mkdirpSync('/app/assets'); 59 vol.writeFileSync('/app/assets/notificationIcon.png', icon); 60 61 const expoConfig: ExpoConfig = { 62 slug: 'testproject', 63 version: '1', 64 name: 'testproject', 65 platforms: ['ios', 'android'], 66 notification: { 67 icon: '/app/assets/notificationIcon.png', 68 color: '#00ff00', 69 }, 70 }; 71 await setNotificationIconAsync(expoConfig, projectRoot); 72 await setNotificationIconColorAsync(expoConfig, projectRoot); 73 }); 74 75 afterAll(() => { 76 jest.unmock('@expo/image-utils'); 77 jest.unmock('fs'); 78 vol.reset(); 79 }); 80 81 it(`returns null if no config provided`, () => { 82 expect(getNotificationIcon({} as ExpoConfig)).toBeNull(); 83 expect(getNotificationColor({} as ExpoConfig)).toBeNull(); 84 }); 85 86 it(`returns config if provided`, () => { 87 expect(getNotificationIcon({ notification: { icon: './myIcon.png' } } as ExpoConfig)).toMatch( 88 './myIcon.png' 89 ); 90 expect(getNotificationColor({ notification: { color: '#123456' } } as ExpoConfig)).toMatch( 91 '#123456' 92 ); 93 }); 94 it('writes to colors.xml correctly', () => { 95 const after = getDirFromFS(vol.toJSON(), projectRoot); 96 expect(after['android/app/src/main/res/values/colors.xml']).toContain( 97 `<color name="${NOTIFICATION_ICON_COLOR}">#00ff00</color>` 98 ); 99 }); 100 it('writes all the image files expected', async () => { 101 const after = getDirFromFS(vol.toJSON(), projectRoot); 102 Object.keys(after).forEach(path => { 103 expect(LIST_OF_GENERATED_NOTIFICATION_FILES).toContain(path); 104 }); 105 }); 106}); 107 108function setUpDrawableDirectories() { 109 vol.mkdirpSync('/app/android/app/src/main/res/drawable-mdpi'); 110 vol.mkdirpSync('/app/android/app/src/main/res/drawable-hdpi'); 111 vol.mkdirpSync('/app/android/app/src/main/res/drawable-xhdpi'); 112 vol.mkdirpSync('/app/android/app/src/main/res/drawable-xxhdpi'); 113 vol.mkdirpSync('/app/android/app/src/main/res/drawable-xxxhdpi'); 114} 115