1import fs from 'fs'; 2import { vol } from 'memfs'; 3 4import { buildResourceItem, readResourcesXMLAsync } from '../../android/Resources'; 5import { setStringItem } from '../../android/Strings'; 6import { escapeAndroidString, format, unescapeAndroidString, writeXMLAsync } from '../XML'; 7 8jest.mock('fs'); 9 10export const sampleStringsXML = ` 11<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 12<resources> 13 <string name="app_name">exp\\'o &bo<y>'</string> 14</resources>`; 15 16describe(readResourcesXMLAsync, () => { 17 beforeAll(async () => { 18 const directoryJSON = { 19 './android/app/src/main/res/values/strings.xml': sampleStringsXML, 20 }; 21 vol.fromJSON(directoryJSON, '/app'); 22 }); 23 24 afterAll(async () => { 25 vol.reset(); 26 }); 27 28 it(`can write the escaped name and then read it back in unescaped format`, async () => { 29 const stringsPath = '/app/android/app/src/main/res/values/strings.xml'; 30 let stringsJSON = await readResourcesXMLAsync({ path: stringsPath }); 31 expect(stringsJSON.resources.string.filter((e) => e.$.name === 'app_name')[0]._).toBe( 32 `exp'o &bo<y>'` 33 ); 34 stringsJSON = setStringItem( 35 [buildResourceItem({ name: 'app_name', value: `'E&x<p>o"@\n` })], 36 stringsJSON 37 ); 38 39 // Test that it's written in escaped form 40 // expect(format(stringsJSON)).toBe(true); 41 expect(format(stringsJSON).includes(`\\'E&x<p>o\\"\\@\\n`)).toBe(true); 42 43 // And parsed in unescaped form 44 expect(stringsJSON.resources.string.filter((e) => e.$.name === 'app_name')[0]._).toBe( 45 `\\'E&x<p>o\\"\\@\\n` 46 ); 47 }); 48}); 49 50describe('read and write', () => { 51 // reading removes 52 // <?xml version="1.0" encoding="UTF-8" standalone="yes"?> 53 const example = `<resources> 54 <string name="app_name">exp\\'o</string> 55</resources>`; 56 beforeAll(async () => { 57 const directoryJSON = { 58 './android/app/src/main/res/values/strings.xml': example, 59 }; 60 vol.fromJSON(directoryJSON, '/app'); 61 }); 62 63 afterAll(async () => { 64 vol.reset(); 65 }); 66 67 it(`can write the escaped name and then read it back in unescaped format`, async () => { 68 const stringsPath = '/app/android/app/src/main/res/values/strings.xml'; 69 const stringsJSON = await readResourcesXMLAsync({ path: stringsPath }); 70 await writeXMLAsync({ path: stringsPath, xml: stringsJSON }); 71 expect(await fs.promises.readFile(stringsPath, 'utf-8')).toBe(example); 72 }); 73}); 74 75describe(escapeAndroidString, () => { 76 it(`can escape Android strings`, () => { 77 expect(escapeAndroidString(`@`)).toBe(`\\@`); 78 expect(escapeAndroidString(`'''`)).toBe(`\\'\\'\\'`); 79 expect(escapeAndroidString('"E&x<p>o"@\n\r\t')).toBe(`\\"E&x<p>o\\"\\@\\n\\r\\t`); 80 }); 81}); 82 83describe(unescapeAndroidString, () => { 84 it(`can remove escape sequences from Android strings`, () => { 85 expect(unescapeAndroidString(`test\\test`)).toBe('testtest'); 86 expect(unescapeAndroidString(`test\\'test`)).toBe("test'test"); 87 expect(unescapeAndroidString(`test\\\\'test`)).toBe("test\\'test"); 88 }); 89}); 90