xref: /expo/apps/test-suite/tests/FileSystem.js (revision d12a8680)
1740b3867SJames Ide'use strict';
2740b3867SJames Ide
3a47a1472SVille Immonenimport { Asset } from 'expo-asset';
4a47a1472SVille Immonenimport * as FS from 'expo-file-system';
58cb96155SEvan Baconimport Constants from 'expo-constants';
68cb96155SEvan Baconimport { Platform } from '@unimodules/core';
767f55e2bSStanisław Chmiela
867f55e2bSStanisław Chmielaexport const name = 'FileSystem';
9740b3867SJames Ide
108cb96155SEvan Baconexport async function test({ describe, expect, it, ...t }) {
118cb96155SEvan Bacon  describe('FileSystem', () => {
12740b3867SJames Ide    const throws = async run => {
13740b3867SJames Ide      let error = null;
14740b3867SJames Ide      try {
15740b3867SJames Ide        await run();
16740b3867SJames Ide      } catch (e) {
17740b3867SJames Ide        error = e;
18740b3867SJames Ide      }
198cb96155SEvan Bacon      expect(error).toBeTruthy();
20740b3867SJames Ide    };
21740b3867SJames Ide
228cb96155SEvan Bacon    if (Constants.appOwnership === 'expo') {
238cb96155SEvan Bacon      describe('managed workflow', () => {
248cb96155SEvan Bacon        it('throws out-of-scope exceptions', async () => {
258cb96155SEvan Bacon          const p = FS.documentDirectory;
268cb96155SEvan Bacon
278cb96155SEvan Bacon          await throws(() => FS.getInfoAsync(p + '../hello/world'));
288cb96155SEvan Bacon          await throws(() => FS.readAsStringAsync(p + '../hello/world'));
298cb96155SEvan Bacon          await throws(() => FS.writeAsStringAsync(p + '../hello/world', ''));
308cb96155SEvan Bacon          await throws(() => FS.deleteAsync(p + '../hello/world'));
318cb96155SEvan Bacon          await throws(() => FS.deleteAsync(p));
328cb96155SEvan Bacon          await throws(() => FS.deleteAsync(FS.cacheDirectory));
338cb96155SEvan Bacon          await throws(() => FS.moveAsync({ from: p + '../a/b', to: 'c' }));
348cb96155SEvan Bacon          await throws(() => FS.moveAsync({ from: 'c', to: p + '../a/b' }));
358cb96155SEvan Bacon          await throws(() => FS.copyAsync({ from: p + '../a/b', to: 'c' }));
368cb96155SEvan Bacon          await throws(() => FS.copyAsync({ from: 'c', to: p + '../a/b' }));
378cb96155SEvan Bacon          await throws(() => FS.makeDirectoryAsync(p + '../hello/world'));
388cb96155SEvan Bacon          await throws(() => FS.readDirectoryAsync(p + '../hello/world'));
398cb96155SEvan Bacon          await throws(() => FS.downloadAsync('http://www.google.com', p + '../hello/world'));
408cb96155SEvan Bacon          await throws(() => FS.readDirectoryAsync(p + '../'));
418cb96155SEvan Bacon          await throws(() => FS.downloadAsync('http://www.google.com', p + '../hello/world'));
428cb96155SEvan Bacon        });
438cb96155SEvan Bacon      });
448cb96155SEvan Bacon    }
458cb96155SEvan Bacon
468cb96155SEvan Bacon    if (Platform.OS === 'web') {
478cb96155SEvan Bacon      // Web doesn't support FileSystem
488cb96155SEvan Bacon      return;
498cb96155SEvan Bacon    }
508cb96155SEvan Bacon
518cb96155SEvan Bacon    it(
52740b3867SJames Ide      'delete(idempotent) -> !exists -> download(md5, uri) -> exists ' + '-> delete -> !exists',
53740b3867SJames Ide      async () => {
54740b3867SJames Ide        const localUri = FS.documentDirectory + 'download1.png';
55740b3867SJames Ide
56740b3867SJames Ide        const assertExists = async expectedToExist => {
57740b3867SJames Ide          let { exists } = await FS.getInfoAsync(localUri);
58740b3867SJames Ide          if (expectedToExist) {
598cb96155SEvan Bacon            expect(exists).toBeTruthy();
60740b3867SJames Ide          } else {
618cb96155SEvan Bacon            expect(exists).not.toBeTruthy();
62740b3867SJames Ide          }
63740b3867SJames Ide        };
64740b3867SJames Ide
65740b3867SJames Ide        await FS.deleteAsync(localUri, { idempotent: true });
66740b3867SJames Ide        await assertExists(false);
67740b3867SJames Ide
68*d12a8680SŁukasz Kosmaty        const {
69*d12a8680SŁukasz Kosmaty          md5,
70*d12a8680SŁukasz Kosmaty          headers,
71*d12a8680SŁukasz Kosmaty        } = await FS.downloadAsync(
72740b3867SJames Ide          'https://s3-us-west-1.amazonaws.com/test-suite-data/avatar2.png',
73740b3867SJames Ide          localUri,
74740b3867SJames Ide          { md5: true }
75740b3867SJames Ide        );
768cb96155SEvan Bacon        expect(md5).toBe('1e02045c10b8f1145edc7c8375998f87');
77740b3867SJames Ide        await assertExists(true);
788cb96155SEvan Bacon        expect(headers['Content-Type']).toBe('image/png');
79740b3867SJames Ide
80740b3867SJames Ide        await FS.deleteAsync(localUri);
81740b3867SJames Ide        await assertExists(false);
82740b3867SJames Ide      },
83740b3867SJames Ide      9000
84fec220cbSSergei Chestakov    );
85740b3867SJames Ide
868cb96155SEvan Bacon    it('Can read/write Base64', async () => {
872bd74c95SEvan Bacon      const asset = await Asset.fromModule(require('../assets/icons/app.png'));
882bd74c95SEvan Bacon      await asset.downloadAsync();
892bd74c95SEvan Bacon
9067f55e2bSStanisław Chmiela      for (let startingPosition = 0; startingPosition < 3; startingPosition++) {
912bd74c95SEvan Bacon        const options = {
92fec220cbSSergei Chestakov          encoding: FS.EncodingType.Base64,
9367f55e2bSStanisław Chmiela          position: startingPosition,
9467f55e2bSStanisław Chmiela          length: startingPosition + 1,
952bd74c95SEvan Bacon        };
962bd74c95SEvan Bacon
972bd74c95SEvan Bacon        const b64 = await FS.readAsStringAsync(asset.localUri, options);
988cb96155SEvan Bacon        expect(b64).toBeDefined();
998cb96155SEvan Bacon        expect(typeof b64).toBe('string');
1008cb96155SEvan Bacon        expect(b64.length % 4).toBe(0);
1012bd74c95SEvan Bacon
1022bd74c95SEvan Bacon        const localUri = FS.documentDirectory + 'b64.png';
1032bd74c95SEvan Bacon
104fec220cbSSergei Chestakov        await FS.writeAsStringAsync(localUri, b64, { encoding: FS.EncodingType.Base64 });
1052bd74c95SEvan Bacon
1068cb96155SEvan Bacon        expect(await FS.readAsStringAsync(localUri, { encoding: FS.EncodingType.Base64 })).toBe(
10767f55e2bSStanisław Chmiela          b64
10867f55e2bSStanisław Chmiela        );
1092bd74c95SEvan Bacon      }
1102bd74c95SEvan Bacon    });
1112bd74c95SEvan Bacon
1128cb96155SEvan Bacon    it('delete(idempotent) -> delete[error]', async () => {
113740b3867SJames Ide      const localUri = FS.documentDirectory + 'willDelete.png';
114740b3867SJames Ide
115740b3867SJames Ide      await FS.deleteAsync(localUri, { idempotent: true });
116740b3867SJames Ide
117740b3867SJames Ide      let error;
118740b3867SJames Ide      try {
119740b3867SJames Ide        await FS.deleteAsync(localUri);
120740b3867SJames Ide      } catch (e) {
121740b3867SJames Ide        error = e;
122740b3867SJames Ide      }
1238cb96155SEvan Bacon      expect(error.message).toMatch(/not.*found/);
124740b3867SJames Ide    });
125740b3867SJames Ide
1268cb96155SEvan Bacon    it('download(md5, uri) -> read -> delete -> !exists -> read[error]', async () => {
127740b3867SJames Ide      const localUri = FS.documentDirectory + 'download1.txt';
128740b3867SJames Ide
129*d12a8680SŁukasz Kosmaty      const {
130*d12a8680SŁukasz Kosmaty        md5,
131*d12a8680SŁukasz Kosmaty      } = await FS.downloadAsync(
132740b3867SJames Ide        'https://s3-us-west-1.amazonaws.com/test-suite-data/text-file.txt',
133740b3867SJames Ide        localUri,
134740b3867SJames Ide        { md5: true }
135740b3867SJames Ide      );
1368cb96155SEvan Bacon      expect(md5).toBe('86d73d2f11e507365f7ea8e7ec3cc4cb');
137740b3867SJames Ide
138740b3867SJames Ide      const string = await FS.readAsStringAsync(localUri);
1398cb96155SEvan Bacon      expect(string).toBe('hello, world\nthis is a test file\n');
140740b3867SJames Ide
141740b3867SJames Ide      await FS.deleteAsync(localUri, { idempotent: true });
142740b3867SJames Ide
143740b3867SJames Ide      let error;
144740b3867SJames Ide      try {
145740b3867SJames Ide        await FS.readAsStringAsync(localUri);
146740b3867SJames Ide      } catch (e) {
147740b3867SJames Ide        error = e;
148740b3867SJames Ide      }
1498cb96155SEvan Bacon      expect(error).toBeTruthy();
1508cb96155SEvan Bacon    }, 9000);
151740b3867SJames Ide
1528cb96155SEvan Bacon    it('delete(idempotent) -> !exists -> write -> read -> write -> read', async () => {
153740b3867SJames Ide      const localUri = FS.documentDirectory + 'write1.txt';
154740b3867SJames Ide
155740b3867SJames Ide      await FS.deleteAsync(localUri, { idempotent: true });
156740b3867SJames Ide
157740b3867SJames Ide      const { exists } = await FS.getInfoAsync(localUri);
1588cb96155SEvan Bacon      expect(exists).not.toBeTruthy();
159740b3867SJames Ide
160740b3867SJames Ide      const writeAndVerify = async expected => {
161740b3867SJames Ide        await FS.writeAsStringAsync(localUri, expected);
162740b3867SJames Ide        const string = await FS.readAsStringAsync(localUri);
1638cb96155SEvan Bacon        expect(string).toBe(expected);
164740b3867SJames Ide      };
165740b3867SJames Ide
166740b3867SJames Ide      await writeAndVerify('hello, world');
167740b3867SJames Ide      await writeAndVerify('hello, world!!!!!!');
168740b3867SJames Ide    });
169740b3867SJames Ide
1708cb96155SEvan Bacon    it('delete(new) -> 2 * [write -> move -> !exists(orig) -> read(new)]', async () => {
171740b3867SJames Ide      const from = FS.documentDirectory + 'from.txt';
172740b3867SJames Ide      const to = FS.documentDirectory + 'to.txt';
173740b3867SJames Ide      const contents = ['contents 1', 'contents 2'];
174740b3867SJames Ide
175740b3867SJames Ide      await FS.deleteAsync(to, { idempotent: true });
176740b3867SJames Ide
177740b3867SJames Ide      // Move twice to make sure we can overwrite
178740b3867SJames Ide      for (let i = 0; i < 2; ++i) {
179740b3867SJames Ide        await FS.writeAsStringAsync(from, contents[i]);
180740b3867SJames Ide
181740b3867SJames Ide        await FS.moveAsync({ from, to });
182740b3867SJames Ide
183740b3867SJames Ide        const { exists } = await FS.getInfoAsync(from);
1848cb96155SEvan Bacon        expect(exists).not.toBeTruthy();
185740b3867SJames Ide
1868cb96155SEvan Bacon        expect(await FS.readAsStringAsync(to)).toBe(contents[i]);
187740b3867SJames Ide      }
188740b3867SJames Ide    });
189740b3867SJames Ide
1908cb96155SEvan Bacon    it('delete(new) -> 2 * [write -> copy -> exists(orig) -> read(new)]', async () => {
191740b3867SJames Ide      const from = FS.documentDirectory + 'from.txt';
192740b3867SJames Ide      const to = FS.documentDirectory + 'to.txt';
193740b3867SJames Ide      const contents = ['contents 1', 'contents 2'];
194740b3867SJames Ide
195740b3867SJames Ide      await FS.deleteAsync(to, { idempotent: true });
196740b3867SJames Ide
197740b3867SJames Ide      // Copy twice to make sure we can overwrite
198740b3867SJames Ide      for (let i = 0; i < 2; ++i) {
199740b3867SJames Ide        await FS.writeAsStringAsync(from, contents[i]);
200740b3867SJames Ide
201740b3867SJames Ide        await FS.copyAsync({ from, to });
202740b3867SJames Ide
203740b3867SJames Ide        const { exists } = await FS.getInfoAsync(from);
2048cb96155SEvan Bacon        expect(exists).toBeTruthy();
205740b3867SJames Ide
2068cb96155SEvan Bacon        expect(await FS.readAsStringAsync(to)).toBe(contents[i]);
207740b3867SJames Ide      }
208740b3867SJames Ide    });
209740b3867SJames Ide
2108cb96155SEvan Bacon    it(
211740b3867SJames Ide      'delete(dir) -> write(dir/file)[error] -> mkdir(dir) ->' +
212740b3867SJames Ide        'mkdir(dir)[error] -> write(dir/file) -> read',
213740b3867SJames Ide      async () => {
214740b3867SJames Ide        let error;
215740b3867SJames Ide        const path = FS.documentDirectory + 'dir/file';
216740b3867SJames Ide        const dir = FS.documentDirectory + 'dir';
217740b3867SJames Ide        const contents = 'hello, world';
218740b3867SJames Ide
219740b3867SJames Ide        await FS.deleteAsync(dir, { idempotent: true });
220740b3867SJames Ide
221740b3867SJames Ide        error = null;
222740b3867SJames Ide        try {
223740b3867SJames Ide          await FS.writeAsStringAsync(path, contents);
224740b3867SJames Ide        } catch (e) {
225740b3867SJames Ide          error = e;
226740b3867SJames Ide        }
2278cb96155SEvan Bacon        expect(error).toBeTruthy();
228740b3867SJames Ide
229740b3867SJames Ide        await FS.makeDirectoryAsync(dir);
230740b3867SJames Ide
231740b3867SJames Ide        error = null;
232740b3867SJames Ide        try {
233740b3867SJames Ide          await FS.makeDirectoryAsync(dir);
234740b3867SJames Ide        } catch (e) {
235740b3867SJames Ide          error = e;
236740b3867SJames Ide        }
2378cb96155SEvan Bacon        expect(error).toBeTruthy();
238740b3867SJames Ide
239740b3867SJames Ide        await FS.writeAsStringAsync(path, contents);
240740b3867SJames Ide
2418cb96155SEvan Bacon        expect(await FS.readAsStringAsync(path)).toBe(contents);
242740b3867SJames Ide      }
243740b3867SJames Ide    );
244740b3867SJames Ide
2458cb96155SEvan Bacon    it(
246740b3867SJames Ide      'delete(dir) -> write(dir/dir2/file)[error] -> ' +
247740b3867SJames Ide        'mkdir(dir/dir2, intermediates) -> ' +
248740b3867SJames Ide        'mkdir(dir/dir2, intermediates) -> write(dir/dir2/file) -> read',
249740b3867SJames Ide      async () => {
250740b3867SJames Ide        let error;
251740b3867SJames Ide        const path = FS.documentDirectory + 'dir/dir2/file';
252740b3867SJames Ide        const dir = FS.documentDirectory + 'dir/dir2';
253740b3867SJames Ide        const contents = 'hello, world';
254740b3867SJames Ide
255740b3867SJames Ide        await FS.deleteAsync(dir, { idempotent: true });
256740b3867SJames Ide
257740b3867SJames Ide        error = null;
258740b3867SJames Ide        try {
259740b3867SJames Ide          await FS.writeAsStringAsync(path, contents);
260740b3867SJames Ide        } catch (e) {
261740b3867SJames Ide          error = e;
262740b3867SJames Ide        }
2638cb96155SEvan Bacon        expect(error).toBeTruthy();
264740b3867SJames Ide
265740b3867SJames Ide        await FS.makeDirectoryAsync(dir, {
266740b3867SJames Ide          intermediates: true,
267740b3867SJames Ide        });
268740b3867SJames Ide
269740b3867SJames Ide        error = null;
270740b3867SJames Ide        try {
271740b3867SJames Ide          await FS.makeDirectoryAsync(dir);
272740b3867SJames Ide        } catch (e) {
273740b3867SJames Ide          error = e;
274740b3867SJames Ide        }
2758cb96155SEvan Bacon        expect(error).toBeTruthy();
276740b3867SJames Ide
2776cfa9c5fSSergei Chestakov        error = null;
2786cfa9c5fSSergei Chestakov        try {
2796cfa9c5fSSergei Chestakov          await FS.makeDirectoryAsync(dir, {
2806cfa9c5fSSergei Chestakov            intermediates: true,
2816cfa9c5fSSergei Chestakov          });
2826cfa9c5fSSergei Chestakov        } catch (e) {
2836cfa9c5fSSergei Chestakov          error = e;
2846cfa9c5fSSergei Chestakov        }
2858cb96155SEvan Bacon        expect(error).toBe(null);
2866cfa9c5fSSergei Chestakov
287740b3867SJames Ide        await FS.writeAsStringAsync(path, contents);
288740b3867SJames Ide
2898cb96155SEvan Bacon        expect(await FS.readAsStringAsync(path)).toBe(contents);
290740b3867SJames Ide      }
291740b3867SJames Ide    );
292740b3867SJames Ide
293*d12a8680SŁukasz Kosmaty    it('getInfo(dirPath)', async () => {
294*d12a8680SŁukasz Kosmaty      const dir = FS.documentDirectory + 'dir';
295*d12a8680SŁukasz Kosmaty      const path = FS.documentDirectory + 'dir/file.txt';
296*d12a8680SŁukasz Kosmaty
297*d12a8680SŁukasz Kosmaty      await FS.deleteAsync(dir, { idempotent: true });
298*d12a8680SŁukasz Kosmaty      await FS.makeDirectoryAsync(dir, {
299*d12a8680SŁukasz Kosmaty        intermediates: true,
300*d12a8680SŁukasz Kosmaty      });
301*d12a8680SŁukasz Kosmaty      await FS.writeAsStringAsync(path, 'Expo is awesome ������');
302*d12a8680SŁukasz Kosmaty      const info = await FS.getInfoAsync(dir);
303*d12a8680SŁukasz Kosmaty
304*d12a8680SŁukasz Kosmaty      expect(info).toBeDefined();
305*d12a8680SŁukasz Kosmaty      expect(info.exists).toBe(true);
306*d12a8680SŁukasz Kosmaty      expect(info.isDirectory).toBe(true);
307*d12a8680SŁukasz Kosmaty      expect(info.size).toBe(28);
308*d12a8680SŁukasz Kosmaty    });
309*d12a8680SŁukasz Kosmaty
310fec220cbSSergei Chestakov    /*
311fec220cbSSergei Chestakov    This test fails in CI because of an exception being thrown by deleteAsync in the nativeModule.
312fec220cbSSergei Chestakov    I traced it down to the FileUtils.forceDelete call here:
313fec220cbSSergei Chestakov    https://github.com/expo/expo/blob/bcd136b096df84e0b0f72a15acbda45491de8201/packages/expo-file-system/android/src/main/java/expo/modules/filesystem/FileSystemModule.java#L294
3148cb96155SEvan Bacon    it(
315740b3867SJames Ide      'delete(dir, idempotent) -> make tree -> check contents ' +
316740b3867SJames Ide        '-> check directory listings' +
317740b3867SJames Ide        '-> move -> check directory listings' +
318740b3867SJames Ide        '-> copy -> check directory listings',
319740b3867SJames Ide      async () => {
320740b3867SJames Ide        let error;
321740b3867SJames Ide        const dir = FS.documentDirectory + 'dir';
322740b3867SJames Ide
323740b3867SJames Ide        await FS.deleteAsync(dir, { idempotent: true });
324740b3867SJames Ide
325740b3867SJames Ide        await FS.makeDirectoryAsync(dir + '/child1', {
326740b3867SJames Ide          intermediates: true,
327740b3867SJames Ide        });
328740b3867SJames Ide        await FS.makeDirectoryAsync(dir + '/child2', {
329740b3867SJames Ide          intermediates: true,
330740b3867SJames Ide        });
331740b3867SJames Ide
332740b3867SJames Ide        await FS.writeAsStringAsync(dir + '/file1', 'contents1');
333740b3867SJames Ide        await FS.writeAsStringAsync(dir + '/file2', 'contents2');
334740b3867SJames Ide
335740b3867SJames Ide        await FS.writeAsStringAsync(dir + '/child1/file3', 'contents3');
336740b3867SJames Ide
337740b3867SJames Ide        await FS.writeAsStringAsync(dir + '/child2/file4', 'contents4');
338740b3867SJames Ide        await FS.writeAsStringAsync(dir + '/child2/file5', 'contents5');
339740b3867SJames Ide
340740b3867SJames Ide        const checkContents = async (path, contents) =>
3418cb96155SEvan Bacon          expect(await FS.readAsStringAsync(path)).toBe(contents);
342740b3867SJames Ide
343740b3867SJames Ide        await checkContents(dir + '/file1', 'contents1');
344740b3867SJames Ide        await checkContents(dir + '/file2', 'contents2');
345740b3867SJames Ide        await checkContents(dir + '/child1/file3', 'contents3');
346740b3867SJames Ide        await checkContents(dir + '/child2/file4', 'contents4');
347740b3867SJames Ide        await checkContents(dir + '/child2/file5', 'contents5');
348740b3867SJames Ide
349740b3867SJames Ide        const checkDirectory = async (path, expected) => {
350740b3867SJames Ide          const list = await FS.readDirectoryAsync(path);
3518cb96155SEvan Bacon          expect(list.sort()).toEqual(expected.sort());
352740b3867SJames Ide        };
353740b3867SJames Ide
354740b3867SJames Ide        const checkRoot = async root => {
355740b3867SJames Ide          await checkDirectory(root, ['file1', 'file2', 'child1', 'child2']);
356740b3867SJames Ide          await checkDirectory(root + '/child1', ['file3']);
357740b3867SJames Ide          await checkDirectory(root + '/child2', ['file4', 'file5']);
358740b3867SJames Ide
359740b3867SJames Ide          error = null;
360740b3867SJames Ide          try {
361740b3867SJames Ide            await checkDirectory(root + '/file1', ['nope']);
362740b3867SJames Ide          } catch (e) {
363740b3867SJames Ide            error = e;
364740b3867SJames Ide          }
3658cb96155SEvan Bacon          expect(error).toBeTruthy();
366740b3867SJames Ide        };
367740b3867SJames Ide
368740b3867SJames Ide        await checkRoot(dir);
369740b3867SJames Ide
370740b3867SJames Ide        await FS.deleteAsync(FS.documentDirectory + 'moved', {
371740b3867SJames Ide          idempotent: true,
372740b3867SJames Ide        });
373740b3867SJames Ide        await FS.moveAsync({ from: dir, to: FS.documentDirectory + 'moved' });
374740b3867SJames Ide        await checkRoot(FS.documentDirectory + 'moved');
375740b3867SJames Ide        await FS.copyAsync({
376740b3867SJames Ide          from: FS.documentDirectory + 'moved',
377740b3867SJames Ide          to: FS.documentDirectory + 'copied',
378740b3867SJames Ide        });
379740b3867SJames Ide        await checkRoot(FS.documentDirectory + 'copied');
380740b3867SJames Ide      }
381740b3867SJames Ide    );
382fec220cbSSergei Chestakov    */
383740b3867SJames Ide
3848cb96155SEvan Bacon    it('delete(idempotent) -> download(md5) -> getInfo(size)', async () => {
385740b3867SJames Ide      const localUri = FS.documentDirectory + 'download1.png';
386740b3867SJames Ide
387740b3867SJames Ide      await FS.deleteAsync(localUri, { idempotent: true });
388740b3867SJames Ide
389*d12a8680SŁukasz Kosmaty      const {
390*d12a8680SŁukasz Kosmaty        md5,
391*d12a8680SŁukasz Kosmaty      } = await FS.downloadAsync(
392740b3867SJames Ide        'https://s3-us-west-1.amazonaws.com/test-suite-data/avatar2.png',
393740b3867SJames Ide        localUri,
394740b3867SJames Ide        { md5: true }
395740b3867SJames Ide      );
3968cb96155SEvan Bacon      expect(md5).toBe('1e02045c10b8f1145edc7c8375998f87');
397740b3867SJames Ide
398740b3867SJames Ide      const { size, modificationTime } = await FS.getInfoAsync(localUri);
3998cb96155SEvan Bacon      expect(size).toBe(3230);
400740b3867SJames Ide      const nowTime = 0.001 * new Date().getTime();
4018cb96155SEvan Bacon      expect(nowTime - modificationTime).toBeLessThan(3600);
402740b3867SJames Ide
403740b3867SJames Ide      await FS.deleteAsync(localUri);
4048cb96155SEvan Bacon    }, 30000);
405740b3867SJames Ide
4068cb96155SEvan Bacon    it('missing parameters', async () => {
407740b3867SJames Ide      const p = FS.documentDirectory + 'test';
408740b3867SJames Ide
409740b3867SJames Ide      await throws(() => FS.moveAsync({ from: p }));
410740b3867SJames Ide      await throws(() => FS.moveAsync({ to: p }));
411740b3867SJames Ide      await throws(() => FS.copyAsync({ from: p }));
412740b3867SJames Ide      await throws(() => FS.copyAsync({ to: p }));
413740b3867SJames Ide    });
414740b3867SJames Ide
4158cb96155SEvan Bacon    it('can read root directories', async () => {
416740b3867SJames Ide      await FS.readDirectoryAsync(FS.documentDirectory);
417740b3867SJames Ide      await FS.readDirectoryAsync(FS.cacheDirectory);
418740b3867SJames Ide    });
419740b3867SJames Ide
4208cb96155SEvan Bacon    it('download(network failure)', async () => {
421740b3867SJames Ide      const localUri = FS.documentDirectory + 'download1.png';
422740b3867SJames Ide
423740b3867SJames Ide      const assertExists = async expectedToExist => {
424740b3867SJames Ide        let { exists } = await FS.getInfoAsync(localUri);
425740b3867SJames Ide        if (expectedToExist) {
4268cb96155SEvan Bacon          expect(exists).toBeTruthy();
427740b3867SJames Ide        } else {
4288cb96155SEvan Bacon          expect(exists).not.toBeTruthy();
429740b3867SJames Ide        }
430740b3867SJames Ide      };
431740b3867SJames Ide
432740b3867SJames Ide      await FS.deleteAsync(localUri, { idempotent: true });
433740b3867SJames Ide      await assertExists(false);
434740b3867SJames Ide
435740b3867SJames Ide      let error;
436740b3867SJames Ide      try {
4373ba2b94bSŁukasz Kosmaty        await FS.downloadAsync('https://nonexistent-subdomain.expo.io', localUri, {
4383ba2b94bSŁukasz Kosmaty          md5: true,
4393ba2b94bSŁukasz Kosmaty          sessionType: FS.FileSystemSessionType.FOREGROUND,
4403ba2b94bSŁukasz Kosmaty        });
441740b3867SJames Ide      } catch (e) {
442740b3867SJames Ide        error = e;
443740b3867SJames Ide      }
4448cb96155SEvan Bacon      expect(error).toBeTruthy();
445740b3867SJames Ide      await assertExists(false);
446740b3867SJames Ide      await FS.deleteAsync(localUri, { idempotent: true });
4478cb96155SEvan Bacon    }, 30000);
448740b3867SJames Ide
4498cb96155SEvan Bacon    it('download(404)', async () => {
450740b3867SJames Ide      const localUri = FS.documentDirectory + 'download1.png';
451740b3867SJames Ide
452740b3867SJames Ide      const assertExists = async expectedToExist => {
453740b3867SJames Ide        let { exists } = await FS.getInfoAsync(localUri);
454740b3867SJames Ide        if (expectedToExist) {
4558cb96155SEvan Bacon          expect(exists).toBeTruthy();
456740b3867SJames Ide        } else {
4578cb96155SEvan Bacon          expect(exists).not.toBeTruthy();
458740b3867SJames Ide        }
459740b3867SJames Ide      };
460740b3867SJames Ide
461740b3867SJames Ide      await FS.deleteAsync(localUri, { idempotent: true });
462740b3867SJames Ide      await assertExists(false);
463740b3867SJames Ide
464fec220cbSSergei Chestakov      const { status } = await FS.downloadAsync('https://expo.io/404', localUri, {
465740b3867SJames Ide        md5: true,
466740b3867SJames Ide      });
467740b3867SJames Ide      await assertExists(true);
4688cb96155SEvan Bacon      expect(status).toBe(404);
469740b3867SJames Ide
470740b3867SJames Ide      await FS.deleteAsync(localUri);
471740b3867SJames Ide      await assertExists(false);
4728cb96155SEvan Bacon    }, 30000);
473d7aba270SDominik Sokal
4748cb96155SEvan Bacon    it('download(nonexistent local path)', async () => {
475d7aba270SDominik Sokal      try {
476d7aba270SDominik Sokal        const remoteUrl = 'https://s3-us-west-1.amazonaws.com/test-suite-data/avatar2.png';
477d7aba270SDominik Sokal        const localUri = FS.documentDirectory + 'doesnt/exists/download1.png';
478d7aba270SDominik Sokal        await FS.downloadAsync(remoteUrl, localUri);
479d7aba270SDominik Sokal      } catch (err) {
4808cb96155SEvan Bacon        expect(err.message).toMatch(/Directory for .* doesn't exist/);
481d7aba270SDominik Sokal      }
4828cb96155SEvan Bacon    }, 30000);
483d7aba270SDominik Sokal
4848cb96155SEvan Bacon    it('mkdir(multi-level) + download(multi-level local path)', async () => {
485d7aba270SDominik Sokal      const remoteUrl = 'https://s3-us-west-1.amazonaws.com/test-suite-data/avatar2.png';
486d7aba270SDominik Sokal      const localDirUri = FS.documentDirectory + 'foo/bar/baz';
487d7aba270SDominik Sokal      const localFileUri = localDirUri + 'download1.png';
488d7aba270SDominik Sokal
489d7aba270SDominik Sokal      await FS.makeDirectoryAsync(localDirUri, { intermediates: true });
490d7aba270SDominik Sokal
491d7aba270SDominik Sokal      await FS.downloadAsync(remoteUrl, localFileUri);
4928cb96155SEvan Bacon    }, 30000);
493740b3867SJames Ide  });
494740b3867SJames Ide}
495