xref: /expo/apps/test-suite/tests/FileSystem.js (revision 740b3867)
1*740b3867SJames Ide'use strict';
2*740b3867SJames Ide
3*740b3867SJames Ideexport const name = 'FileSystem';
4*740b3867SJames Ide
5*740b3867SJames Ideimport { FileSystem as FS } from 'expo';
6*740b3867SJames Ideimport { CameraRoll } from 'react-native';
7*740b3867SJames Ide
8*740b3867SJames Ideexport function test(t) {
9*740b3867SJames Ide  t.describe('FileSystem', () => {
10*740b3867SJames Ide    const throws = async run => {
11*740b3867SJames Ide      let error = null;
12*740b3867SJames Ide      try {
13*740b3867SJames Ide        await run();
14*740b3867SJames Ide      } catch (e) {
15*740b3867SJames Ide        // Uncomment to log error message.
16*740b3867SJames Ide        // const func = run.toString().match(/[A-Za-z]+\(/)[0].slice(0, -1);
17*740b3867SJames Ide        // console.log(`${func}: ${e.message}`);
18*740b3867SJames Ide        error = e;
19*740b3867SJames Ide      }
20*740b3867SJames Ide      t.expect(error).toBeTruthy();
21*740b3867SJames Ide    };
22*740b3867SJames Ide
23*740b3867SJames Ide    /*t.it(
24*740b3867SJames Ide      'delete(idempotent) -> !exists -> download(md5, uri) -> exists ' + '-> delete -> !exists',
25*740b3867SJames Ide      async () => {
26*740b3867SJames Ide        const localUri = FS.documentDirectory + 'download1.png';
27*740b3867SJames Ide
28*740b3867SJames Ide        const assertExists = async expectedToExist => {
29*740b3867SJames Ide          let { exists } = await FS.getInfoAsync(localUri);
30*740b3867SJames Ide          if (expectedToExist) {
31*740b3867SJames Ide            t.expect(exists).toBeTruthy();
32*740b3867SJames Ide          } else {
33*740b3867SJames Ide            t.expect(exists).not.toBeTruthy();
34*740b3867SJames Ide          }
35*740b3867SJames Ide        };
36*740b3867SJames Ide
37*740b3867SJames Ide        await FS.deleteAsync(localUri, { idempotent: true });
38*740b3867SJames Ide        await assertExists(false);
39*740b3867SJames Ide
40*740b3867SJames Ide        const {
41*740b3867SJames Ide          md5,
42*740b3867SJames Ide          uri,
43*740b3867SJames Ide          headers,
44*740b3867SJames Ide        } = await FS.downloadAsync(
45*740b3867SJames Ide          'https://s3-us-west-1.amazonaws.com/test-suite-data/avatar2.png',
46*740b3867SJames Ide          localUri,
47*740b3867SJames Ide          { md5: true }
48*740b3867SJames Ide        );
49*740b3867SJames Ide        t.expect(md5).toBe('1e02045c10b8f1145edc7c8375998f87');
50*740b3867SJames Ide        await assertExists(true);
51*740b3867SJames Ide        t.expect(headers['Content-Type']).toBe('image/png');
52*740b3867SJames Ide
53*740b3867SJames Ide        await FS.deleteAsync(localUri);
54*740b3867SJames Ide        await assertExists(false);
55*740b3867SJames Ide      },
56*740b3867SJames Ide      9000
57*740b3867SJames Ide    );*/
58*740b3867SJames Ide
59*740b3867SJames Ide    t.it('delete(idempotent) -> delete[error]', async () => {
60*740b3867SJames Ide      const localUri = FS.documentDirectory + 'willDelete.png';
61*740b3867SJames Ide
62*740b3867SJames Ide      await FS.deleteAsync(localUri, { idempotent: true });
63*740b3867SJames Ide
64*740b3867SJames Ide      let error;
65*740b3867SJames Ide      try {
66*740b3867SJames Ide        await FS.deleteAsync(localUri);
67*740b3867SJames Ide      } catch (e) {
68*740b3867SJames Ide        error = e;
69*740b3867SJames Ide      }
70*740b3867SJames Ide      t.expect(error.message).toMatch(/not.*found/);
71*740b3867SJames Ide    });
72*740b3867SJames Ide
73*740b3867SJames Ide    /*t.it(
74*740b3867SJames Ide      'download(md5, uri) -> read -> delete -> !exists -> read[error]',
75*740b3867SJames Ide      async () => {
76*740b3867SJames Ide        const localUri = FS.documentDirectory + 'download1.txt';
77*740b3867SJames Ide
78*740b3867SJames Ide        const {
79*740b3867SJames Ide          md5,
80*740b3867SJames Ide          uri,
81*740b3867SJames Ide        } = await FS.downloadAsync(
82*740b3867SJames Ide          'https://s3-us-west-1.amazonaws.com/test-suite-data/text-file.txt',
83*740b3867SJames Ide          localUri,
84*740b3867SJames Ide          { md5: true }
85*740b3867SJames Ide        );
86*740b3867SJames Ide        t.expect(md5).toBe('86d73d2f11e507365f7ea8e7ec3cc4cb');
87*740b3867SJames Ide
88*740b3867SJames Ide        const string = await FS.readAsStringAsync(localUri);
89*740b3867SJames Ide        t.expect(string).toBe('hello, world\nthis is a test file\n');
90*740b3867SJames Ide
91*740b3867SJames Ide        await FS.deleteAsync(localUri, { idempotent: true });
92*740b3867SJames Ide
93*740b3867SJames Ide        let error;
94*740b3867SJames Ide        try {
95*740b3867SJames Ide          await FS.readAsStringAsync(localUri);
96*740b3867SJames Ide        } catch (e) {
97*740b3867SJames Ide          error = e;
98*740b3867SJames Ide        }
99*740b3867SJames Ide        t.expect(error).toBeTruthy();
100*740b3867SJames Ide      },
101*740b3867SJames Ide      9000
102*740b3867SJames Ide    );*/
103*740b3867SJames Ide
104*740b3867SJames Ide    t.it('delete(idempotent) -> !exists -> write -> read -> write -> read', async () => {
105*740b3867SJames Ide      const localUri = FS.documentDirectory + 'write1.txt';
106*740b3867SJames Ide
107*740b3867SJames Ide      await FS.deleteAsync(localUri, { idempotent: true });
108*740b3867SJames Ide
109*740b3867SJames Ide      const { exists } = await FS.getInfoAsync(localUri);
110*740b3867SJames Ide      t.expect(exists).not.toBeTruthy();
111*740b3867SJames Ide
112*740b3867SJames Ide      const writeAndVerify = async expected => {
113*740b3867SJames Ide        await FS.writeAsStringAsync(localUri, expected);
114*740b3867SJames Ide        const string = await FS.readAsStringAsync(localUri);
115*740b3867SJames Ide        t.expect(string).toBe(expected);
116*740b3867SJames Ide      };
117*740b3867SJames Ide
118*740b3867SJames Ide      await writeAndVerify('hello, world');
119*740b3867SJames Ide      await writeAndVerify('hello, world!!!!!!');
120*740b3867SJames Ide    });
121*740b3867SJames Ide
122*740b3867SJames Ide    t.it('delete(new) -> 2 * [write -> move -> !exists(orig) -> read(new)]', async () => {
123*740b3867SJames Ide      const from = FS.documentDirectory + 'from.txt';
124*740b3867SJames Ide      const to = FS.documentDirectory + 'to.txt';
125*740b3867SJames Ide      const contents = ['contents 1', 'contents 2'];
126*740b3867SJames Ide
127*740b3867SJames Ide      await FS.deleteAsync(to, { idempotent: true });
128*740b3867SJames Ide
129*740b3867SJames Ide      // Move twice to make sure we can overwrite
130*740b3867SJames Ide      for (let i = 0; i < 2; ++i) {
131*740b3867SJames Ide        await FS.writeAsStringAsync(from, contents[i]);
132*740b3867SJames Ide
133*740b3867SJames Ide        await FS.moveAsync({ from, to });
134*740b3867SJames Ide
135*740b3867SJames Ide        const { exists } = await FS.getInfoAsync(from);
136*740b3867SJames Ide        t.expect(exists).not.toBeTruthy();
137*740b3867SJames Ide
138*740b3867SJames Ide        t.expect(await FS.readAsStringAsync(to)).toBe(contents[i]);
139*740b3867SJames Ide      }
140*740b3867SJames Ide    });
141*740b3867SJames Ide
142*740b3867SJames Ide    t.it('delete(new) -> 2 * [write -> copy -> exists(orig) -> read(new)]', async () => {
143*740b3867SJames Ide      const from = FS.documentDirectory + 'from.txt';
144*740b3867SJames Ide      const to = FS.documentDirectory + 'to.txt';
145*740b3867SJames Ide      const contents = ['contents 1', 'contents 2'];
146*740b3867SJames Ide
147*740b3867SJames Ide      await FS.deleteAsync(to, { idempotent: true });
148*740b3867SJames Ide
149*740b3867SJames Ide      // Copy twice to make sure we can overwrite
150*740b3867SJames Ide      for (let i = 0; i < 2; ++i) {
151*740b3867SJames Ide        await FS.writeAsStringAsync(from, contents[i]);
152*740b3867SJames Ide
153*740b3867SJames Ide        await FS.copyAsync({ from, to });
154*740b3867SJames Ide
155*740b3867SJames Ide        const { exists } = await FS.getInfoAsync(from);
156*740b3867SJames Ide        t.expect(exists).toBeTruthy();
157*740b3867SJames Ide
158*740b3867SJames Ide        t.expect(await FS.readAsStringAsync(to)).toBe(contents[i]);
159*740b3867SJames Ide      }
160*740b3867SJames Ide    });
161*740b3867SJames Ide
162*740b3867SJames Ide    t.it(
163*740b3867SJames Ide      'delete(dir) -> write(dir/file)[error] -> mkdir(dir) ->' +
164*740b3867SJames Ide        'mkdir(dir)[error] -> write(dir/file) -> read',
165*740b3867SJames Ide      async () => {
166*740b3867SJames Ide        let error;
167*740b3867SJames Ide        const path = FS.documentDirectory + 'dir/file';
168*740b3867SJames Ide        const dir = FS.documentDirectory + 'dir';
169*740b3867SJames Ide        const contents = 'hello, world';
170*740b3867SJames Ide
171*740b3867SJames Ide        await FS.deleteAsync(dir, { idempotent: true });
172*740b3867SJames Ide
173*740b3867SJames Ide        error = null;
174*740b3867SJames Ide        try {
175*740b3867SJames Ide          await FS.writeAsStringAsync(path, contents);
176*740b3867SJames Ide        } catch (e) {
177*740b3867SJames Ide          error = e;
178*740b3867SJames Ide        }
179*740b3867SJames Ide        t.expect(error).toBeTruthy();
180*740b3867SJames Ide
181*740b3867SJames Ide        await FS.makeDirectoryAsync(dir);
182*740b3867SJames Ide
183*740b3867SJames Ide        error = null;
184*740b3867SJames Ide        try {
185*740b3867SJames Ide          await FS.makeDirectoryAsync(dir);
186*740b3867SJames Ide        } catch (e) {
187*740b3867SJames Ide          error = e;
188*740b3867SJames Ide        }
189*740b3867SJames Ide        t.expect(error).toBeTruthy();
190*740b3867SJames Ide
191*740b3867SJames Ide        await FS.writeAsStringAsync(path, contents);
192*740b3867SJames Ide
193*740b3867SJames Ide        t.expect(await FS.readAsStringAsync(path)).toBe(contents);
194*740b3867SJames Ide      }
195*740b3867SJames Ide    );
196*740b3867SJames Ide
197*740b3867SJames Ide    t.it(
198*740b3867SJames Ide      'delete(dir) -> write(dir/dir2/file)[error] -> ' +
199*740b3867SJames Ide        'mkdir(dir/dir2, intermediates) -> ' +
200*740b3867SJames Ide        'mkdir(dir/dir2, intermediates) -> write(dir/dir2/file) -> read',
201*740b3867SJames Ide      async () => {
202*740b3867SJames Ide        let error;
203*740b3867SJames Ide        const path = FS.documentDirectory + 'dir/dir2/file';
204*740b3867SJames Ide        const dir = FS.documentDirectory + 'dir/dir2';
205*740b3867SJames Ide        const contents = 'hello, world';
206*740b3867SJames Ide
207*740b3867SJames Ide        await FS.deleteAsync(dir, { idempotent: true });
208*740b3867SJames Ide
209*740b3867SJames Ide        error = null;
210*740b3867SJames Ide        try {
211*740b3867SJames Ide          await FS.writeAsStringAsync(path, contents);
212*740b3867SJames Ide        } catch (e) {
213*740b3867SJames Ide          error = e;
214*740b3867SJames Ide        }
215*740b3867SJames Ide        t.expect(error).toBeTruthy();
216*740b3867SJames Ide
217*740b3867SJames Ide        await FS.makeDirectoryAsync(dir, {
218*740b3867SJames Ide          intermediates: true,
219*740b3867SJames Ide        });
220*740b3867SJames Ide
221*740b3867SJames Ide        error = null;
222*740b3867SJames Ide        try {
223*740b3867SJames Ide          await FS.makeDirectoryAsync(dir);
224*740b3867SJames Ide        } catch (e) {
225*740b3867SJames Ide          error = e;
226*740b3867SJames Ide        }
227*740b3867SJames Ide        t.expect(error).toBeTruthy();
228*740b3867SJames Ide
229*740b3867SJames Ide        await FS.writeAsStringAsync(path, contents);
230*740b3867SJames Ide
231*740b3867SJames Ide        t.expect(await FS.readAsStringAsync(path)).toBe(contents);
232*740b3867SJames Ide      }
233*740b3867SJames Ide    );
234*740b3867SJames Ide
235*740b3867SJames Ide    t.it(
236*740b3867SJames Ide      'delete(dir, idempotent) -> make tree -> check contents ' +
237*740b3867SJames Ide        '-> check directory listings' +
238*740b3867SJames Ide        '-> move -> check directory listings' +
239*740b3867SJames Ide        '-> copy -> check directory listings',
240*740b3867SJames Ide      async () => {
241*740b3867SJames Ide        let error;
242*740b3867SJames Ide        const dir = FS.documentDirectory + 'dir';
243*740b3867SJames Ide
244*740b3867SJames Ide        await FS.deleteAsync(dir, { idempotent: true });
245*740b3867SJames Ide
246*740b3867SJames Ide        await FS.makeDirectoryAsync(dir + '/child1', {
247*740b3867SJames Ide          intermediates: true,
248*740b3867SJames Ide        });
249*740b3867SJames Ide        await FS.makeDirectoryAsync(dir + '/child2', {
250*740b3867SJames Ide          intermediates: true,
251*740b3867SJames Ide        });
252*740b3867SJames Ide
253*740b3867SJames Ide        await FS.writeAsStringAsync(dir + '/file1', 'contents1');
254*740b3867SJames Ide        await FS.writeAsStringAsync(dir + '/file2', 'contents2');
255*740b3867SJames Ide
256*740b3867SJames Ide        await FS.writeAsStringAsync(dir + '/child1/file3', 'contents3');
257*740b3867SJames Ide
258*740b3867SJames Ide        await FS.writeAsStringAsync(dir + '/child2/file4', 'contents4');
259*740b3867SJames Ide        await FS.writeAsStringAsync(dir + '/child2/file5', 'contents5');
260*740b3867SJames Ide
261*740b3867SJames Ide        const checkContents = async (path, contents) =>
262*740b3867SJames Ide          t.expect(await FS.readAsStringAsync(path)).toBe(contents);
263*740b3867SJames Ide
264*740b3867SJames Ide        await checkContents(dir + '/file1', 'contents1');
265*740b3867SJames Ide        await checkContents(dir + '/file2', 'contents2');
266*740b3867SJames Ide        await checkContents(dir + '/child1/file3', 'contents3');
267*740b3867SJames Ide        await checkContents(dir + '/child2/file4', 'contents4');
268*740b3867SJames Ide        await checkContents(dir + '/child2/file5', 'contents5');
269*740b3867SJames Ide
270*740b3867SJames Ide        const checkDirectory = async (path, expected) => {
271*740b3867SJames Ide          const list = await FS.readDirectoryAsync(path);
272*740b3867SJames Ide          t.expect(list.sort()).toEqual(expected.sort());
273*740b3867SJames Ide        };
274*740b3867SJames Ide
275*740b3867SJames Ide        const checkRoot = async root => {
276*740b3867SJames Ide          await checkDirectory(root, ['file1', 'file2', 'child1', 'child2']);
277*740b3867SJames Ide          await checkDirectory(root + '/child1', ['file3']);
278*740b3867SJames Ide          await checkDirectory(root + '/child2', ['file4', 'file5']);
279*740b3867SJames Ide
280*740b3867SJames Ide          error = null;
281*740b3867SJames Ide          try {
282*740b3867SJames Ide            await checkDirectory(root + '/file1', ['nope']);
283*740b3867SJames Ide          } catch (e) {
284*740b3867SJames Ide            error = e;
285*740b3867SJames Ide          }
286*740b3867SJames Ide          t.expect(error).toBeTruthy();
287*740b3867SJames Ide        };
288*740b3867SJames Ide
289*740b3867SJames Ide        await checkRoot(dir);
290*740b3867SJames Ide
291*740b3867SJames Ide        await FS.deleteAsync(FS.documentDirectory + 'moved', {
292*740b3867SJames Ide          idempotent: true,
293*740b3867SJames Ide        });
294*740b3867SJames Ide        await FS.moveAsync({ from: dir, to: FS.documentDirectory + 'moved' });
295*740b3867SJames Ide        await checkRoot(FS.documentDirectory + 'moved');
296*740b3867SJames Ide        await FS.copyAsync({
297*740b3867SJames Ide          from: FS.documentDirectory + 'moved',
298*740b3867SJames Ide          to: FS.documentDirectory + 'copied',
299*740b3867SJames Ide        });
300*740b3867SJames Ide        await checkRoot(FS.documentDirectory + 'copied');
301*740b3867SJames Ide      }
302*740b3867SJames Ide    );
303*740b3867SJames Ide
304*740b3867SJames Ide    t.it(
305*740b3867SJames Ide      'delete(idempotent) -> download(md5) -> getInfo(size)',
306*740b3867SJames Ide      async () => {
307*740b3867SJames Ide        const localUri = FS.documentDirectory + 'download1.png';
308*740b3867SJames Ide
309*740b3867SJames Ide        await FS.deleteAsync(localUri, { idempotent: true });
310*740b3867SJames Ide
311*740b3867SJames Ide        const {
312*740b3867SJames Ide          md5,
313*740b3867SJames Ide        } = await FS.downloadAsync(
314*740b3867SJames Ide          'https://s3-us-west-1.amazonaws.com/test-suite-data/avatar2.png',
315*740b3867SJames Ide          localUri,
316*740b3867SJames Ide          { md5: true }
317*740b3867SJames Ide        );
318*740b3867SJames Ide        t.expect(md5).toBe('1e02045c10b8f1145edc7c8375998f87');
319*740b3867SJames Ide
320*740b3867SJames Ide        const { size, modificationTime } = await FS.getInfoAsync(localUri);
321*740b3867SJames Ide        t.expect(size).toBe(3230);
322*740b3867SJames Ide        const nowTime = 0.001 * new Date().getTime();
323*740b3867SJames Ide        t.expect(nowTime - modificationTime).toBeLessThan(3600);
324*740b3867SJames Ide
325*740b3867SJames Ide        await FS.deleteAsync(localUri);
326*740b3867SJames Ide      },
327*740b3867SJames Ide      9000
328*740b3867SJames Ide    );
329*740b3867SJames Ide
330*740b3867SJames Ide    t.it('throws out-of-scope exceptions', async () => {
331*740b3867SJames Ide      const p = FS.documentDirectory;
332*740b3867SJames Ide
333*740b3867SJames Ide      await throws(() => FS.getInfoAsync(p + '../hello/world'));
334*740b3867SJames Ide      await throws(() => FS.readAsStringAsync(p + '../hello/world'));
335*740b3867SJames Ide      await throws(() => FS.writeAsStringAsync(p + '../hello/world', ''));
336*740b3867SJames Ide      await throws(() => FS.deleteAsync(p + '../hello/world'));
337*740b3867SJames Ide      await throws(() => FS.deleteAsync(p));
338*740b3867SJames Ide      await throws(() => FS.deleteAsync(FS.cacheDirectory));
339*740b3867SJames Ide      await throws(() => FS.moveAsync({ from: p + '../a/b', to: 'c' }));
340*740b3867SJames Ide      await throws(() => FS.moveAsync({ from: 'c', to: p + '../a/b' }));
341*740b3867SJames Ide      await throws(() => FS.copyAsync({ from: p + '../a/b', to: 'c' }));
342*740b3867SJames Ide      await throws(() => FS.copyAsync({ from: 'c', to: p + '../a/b' }));
343*740b3867SJames Ide      await throws(() => FS.makeDirectoryAsync(p + '../hello/world'));
344*740b3867SJames Ide      await throws(() => FS.readDirectoryAsync(p + '../hello/world'));
345*740b3867SJames Ide      await throws(() => FS.downloadAsync('http://www.google.com', p + '../hello/world'));
346*740b3867SJames Ide      await throws(() => FS.readDirectoryAsync(p + '../'));
347*740b3867SJames Ide      await throws(() => FS.downloadAsync('http://www.google.com', p + '../hello/world'));
348*740b3867SJames Ide    });
349*740b3867SJames Ide
350*740b3867SJames Ide    t.it('missing parameters', async () => {
351*740b3867SJames Ide      const p = FS.documentDirectory + 'test';
352*740b3867SJames Ide
353*740b3867SJames Ide      await throws(() => FS.moveAsync({ from: p }));
354*740b3867SJames Ide      await throws(() => FS.moveAsync({ to: p }));
355*740b3867SJames Ide      await throws(() => FS.copyAsync({ from: p }));
356*740b3867SJames Ide      await throws(() => FS.copyAsync({ to: p }));
357*740b3867SJames Ide    });
358*740b3867SJames Ide
359*740b3867SJames Ide    t.it('can read root directories', async () => {
360*740b3867SJames Ide      await FS.readDirectoryAsync(FS.documentDirectory);
361*740b3867SJames Ide      await FS.readDirectoryAsync(FS.cacheDirectory);
362*740b3867SJames Ide    });
363*740b3867SJames Ide
364*740b3867SJames Ide    /*t.it('can copy from `CameraRoll`, verify hash, other methods restricted', async () => {
365*740b3867SJames Ide      await Promise.all(
366*740b3867SJames Ide        (await CameraRoll.getPhotos({
367*740b3867SJames Ide          first: 1,
368*740b3867SJames Ide        })).edges.map(async ({ node: { image: { uri: cameraRollUri } } }) => {
369*740b3867SJames Ide          const destinationUri = FS.documentDirectory + 'photo.jpg';
370*740b3867SJames Ide
371*740b3867SJames Ide          await throws(() => FS.readAsStringAsync(cameraRollUri));
372*740b3867SJames Ide          await throws(() => FS.writeAsStringAsync(cameraRollUri));
373*740b3867SJames Ide          await throws(() => FS.deleteAsync(cameraRollUri));
374*740b3867SJames Ide          await throws(() => FS.moveAsync({ from: cameraRollUri, to: destinationUri }));
375*740b3867SJames Ide          await throws(() => FS.copyAsync({ from: destinationUri, to: cameraRollUri }));
376*740b3867SJames Ide          await throws(() => FS.makeDirectoryAsync(cameraRollUri));
377*740b3867SJames Ide          await throws(() => FS.readDirectoryAsync(cameraRollUri));
378*740b3867SJames Ide          await throws(() => FS.downloadAsync('http://www.google.com', cameraRollUri));
379*740b3867SJames Ide
380*740b3867SJames Ide          await FS.copyAsync({ from: cameraRollUri, to: destinationUri });
381*740b3867SJames Ide
382*740b3867SJames Ide          const origInfo = await FS.getInfoAsync(cameraRollUri, {
383*740b3867SJames Ide            size: true,
384*740b3867SJames Ide            md5: true,
385*740b3867SJames Ide          });
386*740b3867SJames Ide          const copyInfo = await FS.getInfoAsync(destinationUri, {
387*740b3867SJames Ide            size: true,
388*740b3867SJames Ide            md5: true,
389*740b3867SJames Ide          });
390*740b3867SJames Ide
391*740b3867SJames Ide          t.expect(origInfo.md5).toEqual(copyInfo.md5);
392*740b3867SJames Ide          t.expect(origInfo.size).toEqual(copyInfo.size);
393*740b3867SJames Ide        })
394*740b3867SJames Ide      );
395*740b3867SJames Ide    });*/
396*740b3867SJames Ide
397*740b3867SJames Ide    t.it(
398*740b3867SJames Ide      'download(network failure)',
399*740b3867SJames Ide      async () => {
400*740b3867SJames Ide        const localUri = FS.documentDirectory + 'download1.png';
401*740b3867SJames Ide
402*740b3867SJames Ide        const assertExists = async expectedToExist => {
403*740b3867SJames Ide          let { exists } = await FS.getInfoAsync(localUri);
404*740b3867SJames Ide          if (expectedToExist) {
405*740b3867SJames Ide            t.expect(exists).toBeTruthy();
406*740b3867SJames Ide          } else {
407*740b3867SJames Ide            t.expect(exists).not.toBeTruthy();
408*740b3867SJames Ide          }
409*740b3867SJames Ide        };
410*740b3867SJames Ide
411*740b3867SJames Ide        await FS.deleteAsync(localUri, { idempotent: true });
412*740b3867SJames Ide        await assertExists(false);
413*740b3867SJames Ide
414*740b3867SJames Ide        let error;
415*740b3867SJames Ide        try {
416*740b3867SJames Ide          const { md5, uri } = await FS.downloadAsync(
417*740b3867SJames Ide            'https://nonexistent-subdomain.expo.io',
418*740b3867SJames Ide            localUri,
419*740b3867SJames Ide            { md5: true }
420*740b3867SJames Ide          );
421*740b3867SJames Ide        } catch (e) {
422*740b3867SJames Ide          error = e;
423*740b3867SJames Ide        }
424*740b3867SJames Ide        t.expect(error).toBeTruthy();
425*740b3867SJames Ide        await assertExists(false);
426*740b3867SJames Ide        await FS.deleteAsync(localUri, { idempotent: true });
427*740b3867SJames Ide      },
428*740b3867SJames Ide      9000
429*740b3867SJames Ide    );
430*740b3867SJames Ide
431*740b3867SJames Ide    t.it(
432*740b3867SJames Ide      'download(404)',
433*740b3867SJames Ide      async () => {
434*740b3867SJames Ide        const localUri = FS.documentDirectory + 'download1.png';
435*740b3867SJames Ide
436*740b3867SJames Ide        const assertExists = async expectedToExist => {
437*740b3867SJames Ide          let { exists } = await FS.getInfoAsync(localUri);
438*740b3867SJames Ide          if (expectedToExist) {
439*740b3867SJames Ide            t.expect(exists).toBeTruthy();
440*740b3867SJames Ide          } else {
441*740b3867SJames Ide            t.expect(exists).not.toBeTruthy();
442*740b3867SJames Ide          }
443*740b3867SJames Ide        };
444*740b3867SJames Ide
445*740b3867SJames Ide        await FS.deleteAsync(localUri, { idempotent: true });
446*740b3867SJames Ide        await assertExists(false);
447*740b3867SJames Ide
448*740b3867SJames Ide        const { md5, uri, status } = await FS.downloadAsync('https://expo.io/404', localUri, {
449*740b3867SJames Ide          md5: true,
450*740b3867SJames Ide        });
451*740b3867SJames Ide        await assertExists(true);
452*740b3867SJames Ide        t.expect(status).toBe(404);
453*740b3867SJames Ide
454*740b3867SJames Ide        await FS.deleteAsync(localUri);
455*740b3867SJames Ide        await assertExists(false);
456*740b3867SJames Ide      },
457*740b3867SJames Ide      9000
458*740b3867SJames Ide    );
459*740b3867SJames Ide  });
460*740b3867SJames Ide}
461