xref: /expo/apps/test-suite/tests/ImagePicker.js (revision bb8f4f99)
1import Constants from 'expo-constants';
2import * as ImagePicker from 'expo-image-picker';
3import { Platform } from 'react-native';
4
5import * as TestUtils from '../TestUtils';
6import { isDeviceFarm } from '../utils/Environment';
7import { alertAndWaitForResponse } from './helpers';
8
9export const name = 'ImagePicker';
10
11export async function test({ it, beforeAll, expect, jasmine, describe, afterAll }) {
12  function testMediaObjectShape(shape, type) {
13    expect(shape).toBeDefined();
14    expect(typeof shape.cancelled).toBe('boolean');
15
16    if (!shape.cancelled) {
17      expect(typeof shape.uri).toBe('string');
18      expect(typeof shape.width).toBe('number');
19      expect(typeof shape.height).toBe('number');
20      expect(typeof shape.type).toBe('string');
21
22      expect(shape.uri).not.toBe('');
23      expect(shape.width).toBeGreaterThan(0);
24      expect(shape.height).toBeGreaterThan(0);
25
26      expect(typeof shape.type).toBe('string');
27
28      if (type) {
29        expect(shape.type).toBe(type);
30      }
31
32      if (shape.type === 'video') {
33        expect(typeof shape.duration).toBe('number');
34        expect(shape.duration).toBeGreaterThan(0);
35      }
36    }
37  }
38
39  describe(name, () => {
40    if (isDeviceFarm()) return;
41
42    let originalTimeout;
43
44    beforeAll(async () => {
45      await TestUtils.acceptPermissionsAndRunCommandAsync(() => {
46        return ImagePicker.requestMediaLibraryPermissionsAsync();
47      });
48      await TestUtils.acceptPermissionsAndRunCommandAsync(() => {
49        return ImagePicker.requestCameraPermissionsAsync();
50      });
51      originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
52      jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout * 10;
53    });
54
55    describe('launchCameraAsync', () => {
56      if (Constants.isDevice) {
57        it('launches the camera', async () => {
58          await alertAndWaitForResponse('Please take a picture for this test to pass.');
59          const image = await ImagePicker.launchCameraAsync();
60          expect(image.cancelled).toBe(false);
61          testMediaObjectShape(image);
62        });
63
64        it('cancels the camera', async () => {
65          await alertAndWaitForResponse('Please cancel the camera for this test to pass.');
66          const image = await ImagePicker.launchCameraAsync();
67          expect(image.cancelled).toBe(true);
68        });
69      } else {
70        it('natively prevents the camera from launching on a simulator', async () => {
71          let err;
72          try {
73            await ImagePicker.launchCameraAsync();
74          } catch ({ code }) {
75            err = code;
76          }
77          expect(err).toBe('CAMERA_MISSING');
78        });
79      }
80    });
81
82    describe('launchImageLibraryAsync', async () => {
83      it('mediaType: image', async () => {
84        await alertAndWaitForResponse('Please choose an image.');
85        const image = await ImagePicker.launchImageLibraryAsync({
86          mediaTypes: ImagePicker.MediaTypeOptions.Images,
87        });
88
89        testMediaObjectShape(image, 'image');
90      });
91
92      it('mediaType: video', async () => {
93        await alertAndWaitForResponse('Please choose a video.');
94        const video = await ImagePicker.launchImageLibraryAsync({
95          mediaTypes: ImagePicker.MediaTypeOptions.Videos,
96        });
97
98        testMediaObjectShape(video, 'video');
99      });
100
101      it('allows editing', async () => {
102        await alertAndWaitForResponse('Please choose an image to crop.');
103        const image = await ImagePicker.launchImageLibraryAsync({
104          mediaTypes: ImagePicker.MediaTypeOptions.Images,
105          allowsEditing: true,
106        });
107
108        testMediaObjectShape(image, 'image');
109      });
110
111      it('allows editing and returns base64', async () => {
112        await alertAndWaitForResponse('Please choose an image to crop.');
113        const image = await ImagePicker.launchImageLibraryAsync({
114          mediaTypes: ImagePicker.MediaTypeOptions.Images,
115          allowsEditing: true,
116          base64: true,
117        });
118
119        testMediaObjectShape(image, 'image');
120        if (!image.cancelled) {
121          expect(typeof image.base64).toBe('string');
122          expect(image.base64).not.toBe('');
123          expect(image.base64).not.toContain('\n');
124          expect(image.base64).not.toContain('\r');
125        }
126      });
127
128      if (Platform.OS === 'ios' && parseInt(Platform.Version, 10) > 10) {
129        it('videoExportPreset should affect video dimensions', async () => {
130          const video = await ImagePicker.launchImageLibraryAsync({
131            mediaTypes: ImagePicker.MediaTypeOptions.Videos,
132            videoExportPreset: ImagePicker.VideoExportPreset.H264_640x480,
133          });
134
135          testMediaObjectShape(video, 'video');
136
137          if (!video.cancelled) {
138            expect(video.width).toBeLessThanOrEqual(640);
139            expect(video.height).toBeLessThanOrEqual(480);
140          }
141        });
142      }
143    });
144
145    afterAll(() => {
146      jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout;
147    });
148  });
149}
150