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 function testResultShape(result, type) { 39 expect(result.canceled).toBe(false); 40 41 for (const asset of result.assets) { 42 testMediaObjectShape(asset, type); 43 } 44 } 45 46 describe(name, () => { 47 if (isDeviceFarm()) return; 48 49 let originalTimeout; 50 51 beforeAll(async () => { 52 await TestUtils.acceptPermissionsAndRunCommandAsync(() => { 53 return ImagePicker.requestMediaLibraryPermissionsAsync(); 54 }); 55 await TestUtils.acceptPermissionsAndRunCommandAsync(() => { 56 return ImagePicker.requestCameraPermissionsAsync(); 57 }); 58 originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL; 59 jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout * 10; 60 }); 61 62 describe('launchCameraAsync', () => { 63 if (Constants.isDevice) { 64 it('launches the camera', async () => { 65 await alertAndWaitForResponse('Please take a picture for this test to pass.'); 66 const result = await ImagePicker.launchCameraAsync(); 67 68 testResultShape(result); 69 }); 70 71 it('cancels the camera', async () => { 72 await alertAndWaitForResponse('Please cancel the camera for this test to pass.'); 73 const result = await ImagePicker.launchCameraAsync(); 74 expect(result.canceled).toBe(true); 75 expect(result.assets).toBe(null); 76 }); 77 } else { 78 it('natively prevents the camera from launching on a simulator', async () => { 79 let err; 80 try { 81 await ImagePicker.launchCameraAsync(); 82 } catch ({ code }) { 83 err = code; 84 } 85 expect(err).toBe('CAMERA_MISSING'); 86 }); 87 } 88 }); 89 90 describe('launchImageLibraryAsync', async () => { 91 it('mediaType: image', async () => { 92 await alertAndWaitForResponse('Please choose an image.'); 93 const result = await ImagePicker.launchImageLibraryAsync({ 94 mediaTypes: ImagePicker.MediaTypeOptions.Images, 95 }); 96 testResultShape(result, 'image'); 97 }); 98 99 it('mediaType: video', async () => { 100 await alertAndWaitForResponse('Please choose a video.'); 101 const result = await ImagePicker.launchImageLibraryAsync({ 102 mediaTypes: ImagePicker.MediaTypeOptions.Videos, 103 }); 104 testResultShape(result, 'video'); 105 }); 106 107 it('allows editing', async () => { 108 await alertAndWaitForResponse('Please choose an image to crop.'); 109 const result = await ImagePicker.launchImageLibraryAsync({ 110 mediaTypes: ImagePicker.MediaTypeOptions.Images, 111 allowsEditing: true, 112 }); 113 testResultShape(result, 'image'); 114 }); 115 116 it('allows editing and returns base64', async () => { 117 await alertAndWaitForResponse('Please choose an image to crop.'); 118 const result = await ImagePicker.launchImageLibraryAsync({ 119 mediaTypes: ImagePicker.MediaTypeOptions.Images, 120 allowsEditing: true, 121 base64: true, 122 }); 123 124 testResultShape(result, 'image'); 125 126 for (const image of result.assets) { 127 expect(typeof image.base64).toBe('string'); 128 expect(image.base64).not.toBe(''); 129 expect(image.base64).not.toContain('\n'); 130 expect(image.base64).not.toContain('\r'); 131 } 132 }); 133 134 if (Platform.OS === 'ios' && parseInt(Platform.Version, 10) > 10) { 135 it('videoExportPreset should affect video dimensions', async () => { 136 const result = await ImagePicker.launchImageLibraryAsync({ 137 mediaTypes: ImagePicker.MediaTypeOptions.Videos, 138 videoExportPreset: ImagePicker.VideoExportPreset.H264_640x480, 139 }); 140 141 testResultShape(result, 'video'); 142 143 for (const video of result.assets) { 144 expect(video.width).toBeLessThanOrEqual(640); 145 expect(video.height).toBeLessThanOrEqual(480); 146 } 147 }); 148 } 149 }); 150 151 afterAll(() => { 152 jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout; 153 }); 154 }); 155} 156