tests.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. /*
  2. *
  3. * Licensed to the Apache Software Foundation (ASF) under one
  4. * or more contributor license agreements. See the NOTICE file
  5. * distributed with this work for additional information
  6. * regarding copyright ownership. The ASF licenses this file
  7. * to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance
  9. * with the License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing,
  14. * software distributed under the License is distributed on an
  15. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  16. * KIND, either express or implied. See the License for the
  17. * specific language governing permissions and limitations
  18. * under the License.
  19. *
  20. */
  21. /* eslint-env jasmine */
  22. /* global CaptureAudioOptions, CaptureImageOptions, CaptureVideoOptions, CaptureError */
  23. /* global Media, MediaFile, MediaFileData, resolveLocalFileSystemURL */
  24. exports.defineAutoTests = function () {
  25. describe('Capture (navigator.device.capture)', function () {
  26. it('capture.spec.1 should exist', function () {
  27. expect(navigator.device).toBeDefined();
  28. expect(navigator.device.capture).toBeDefined();
  29. });
  30. it('capture.spec.2 should have the correct properties ', function () {
  31. expect(navigator.device.capture.supportedAudioModes).toBeDefined();
  32. expect(navigator.device.capture.supportedImageModes).toBeDefined();
  33. expect(navigator.device.capture.supportedVideoModes).toBeDefined();
  34. });
  35. it('capture.spec.3 should contain a captureAudio function', function () {
  36. expect(navigator.device.capture.captureAudio).toBeDefined();
  37. expect(typeof navigator.device.capture.captureAudio === 'function').toBe(true);
  38. });
  39. it('capture.spec.4 should contain a captureImage function', function () {
  40. expect(navigator.device.capture.captureImage).toBeDefined();
  41. expect(typeof navigator.device.capture.captureImage === 'function').toBe(true);
  42. });
  43. it('capture.spec.5 should contain a captureVideo function', function () {
  44. expect(navigator.device.capture.captureVideo).toBeDefined();
  45. expect(typeof navigator.device.capture.captureVideo === 'function').toBe(true);
  46. });
  47. describe('CaptureAudioOptions', function () {
  48. it('capture.spec.6 CaptureAudioOptions constructor should exist', function () {
  49. var options = new CaptureAudioOptions();
  50. expect(options).toBeDefined();
  51. expect(options.limit).toBeDefined();
  52. expect(options.duration).toBeDefined();
  53. });
  54. });
  55. describe('CaptureImageOptions', function () {
  56. it('capture.spec.7 CaptureImageOptions constructor should exist', function () {
  57. var options = new CaptureImageOptions();
  58. expect(options).toBeDefined();
  59. expect(options.limit).toBeDefined();
  60. });
  61. });
  62. describe('CaptureVideoOptions', function () {
  63. it('capture.spec.8 CaptureVideoOptions constructor should exist', function () {
  64. var options = new CaptureVideoOptions();
  65. expect(options).toBeDefined();
  66. expect(options.limit).toBeDefined();
  67. expect(options.duration).toBeDefined();
  68. });
  69. });
  70. describe('CaptureError interface', function () {
  71. it('capture.spec.9 CaptureError constants should be defined', function () {
  72. expect(CaptureError.CAPTURE_INTERNAL_ERR).toBe(0);
  73. expect(CaptureError.CAPTURE_APPLICATION_BUSY).toBe(1);
  74. expect(CaptureError.CAPTURE_INVALID_ARGUMENT).toBe(2);
  75. expect(CaptureError.CAPTURE_NO_MEDIA_FILES).toBe(3);
  76. });
  77. it('capture.spec.10 CaptureError properties should exist', function () {
  78. var error = new CaptureError();
  79. expect(error).toBeDefined();
  80. expect(error.code).toBeDefined();
  81. });
  82. });
  83. describe('MediaFileData', function () {
  84. it('capture.spec.11 MediaFileData constructor should exist', function () {
  85. var fileData = new MediaFileData();
  86. expect(fileData).toBeDefined();
  87. expect(fileData.bitrate).toBeDefined();
  88. expect(fileData.codecs).toBeDefined();
  89. expect(fileData.duration).toBeDefined();
  90. expect(fileData.height).toBeDefined();
  91. expect(fileData.width).toBeDefined();
  92. });
  93. });
  94. describe('MediaFile', function () {
  95. it('capture.spec.12 MediaFile constructor should exist', function () {
  96. var fileData = new MediaFile();
  97. expect(fileData).toBeDefined();
  98. expect(fileData.name).toBeDefined();
  99. expect(fileData.type).toBeDefined();
  100. expect(fileData.lastModifiedDate).toBeDefined();
  101. expect(fileData.size).toBeDefined();
  102. });
  103. });
  104. });
  105. };
  106. /******************************************************************************/
  107. /******************************************************************************/
  108. /******************************************************************************/
  109. exports.defineManualTests = function (contentEl, createActionButton) {
  110. var pageStartTime = +new Date();
  111. function log (value) {
  112. document.getElementById('camera_status').textContent += (new Date() - pageStartTime) / 1000 + ': ' + value + '\n';
  113. console.log(value);
  114. }
  115. function captureAudioWin (mediaFiles) {
  116. var path = mediaFiles[0].fullPath;
  117. log('Audio captured: ' + path);
  118. var m = new Media(path);
  119. m.play();
  120. getFileMetadata(mediaFiles[0]);
  121. }
  122. function captureAudioFail (e) {
  123. log('Error getting audio: ' + e.code);
  124. }
  125. function getAudio () {
  126. clearStatus();
  127. var options = { limit: 1, duration: 10 };
  128. navigator.device.capture.captureAudio(captureAudioWin, captureAudioFail, options);
  129. }
  130. function captureImageWin (mediaFiles) {
  131. var path = mediaFiles[0].fullPath;
  132. // Necessary since windows doesn't allow file URLs for <img> elements
  133. if (cordova.platformId === 'windows' || cordova.platformId === 'windows8' || cordova.platformId === 'browser') { // eslint-disable-line no-undef
  134. path = mediaFiles[0].localURL;
  135. }
  136. log('Image captured: ' + path);
  137. document.getElementById('camera_image').src = path;
  138. }
  139. function captureImagesWin (mediaFiles) {
  140. var path = mediaFiles[0].fullPath;
  141. // Necessary since windows doesn't allow file URLs for <img> elements
  142. if (cordova.platformId === 'windows' || cordova.platformId === 'windows8' || cordova.platformId === 'browser') { // eslint-disable-line no-undef
  143. path = mediaFiles[0].localURL;
  144. }
  145. var path2 = mediaFiles[1].fullPath;
  146. // Necessary since windows doesn't allow file URLs for <img> elements
  147. if (cordova.platformId === 'windows' || cordova.platformId === 'windows8' || cordova.platformId === 'browser') { // eslint-disable-line no-undef
  148. path = mediaFiles[1].localURL;
  149. }
  150. var path3 = mediaFiles[2].fullPath;
  151. // Necessary since windows doesn't allow file URLs for <img> elements
  152. if (cordova.platformId === 'windows' || cordova.platformId === 'windows8' || cordova.platformId === 'browser') { // eslint-disable-line no-undef
  153. path = mediaFiles[2].localURL;
  154. }
  155. log('Image captured: ' + path);
  156. log('Image captured: ' + path2);
  157. log('Image captured: ' + path3);
  158. document.getElementById('camera_image').src = path;
  159. document.getElementById('camera_image2').src = path2;
  160. document.getElementById('camera_image3').src = path3;
  161. }
  162. function captureImageFail (e) {
  163. log('Error getting image: ' + e.code);
  164. }
  165. function getImage () {
  166. clearStatus();
  167. var options = { limit: 1 };
  168. navigator.device.capture.captureImage(captureImageWin, captureImageFail, options);
  169. }
  170. function getImages () {
  171. clearStatus();
  172. var options = { limit: 3 };
  173. navigator.device.capture.captureImage(captureImagesWin, captureImageFail, options);
  174. }
  175. function captureVideoWin (mediaFiles) {
  176. var path = mediaFiles[0].fullPath;
  177. log('Video captured: ' + path);
  178. // need to inject the video element into the html
  179. // doesn't seem to work if you have a pre-existing video element and
  180. // add in a source tag
  181. var vid = document.createElement('video');
  182. vid.id = 'theVideo';
  183. vid.width = '320';
  184. vid.height = '240';
  185. vid.controls = 'true';
  186. var source_vid = document.createElement('source');
  187. source_vid.id = 'theSource';
  188. source_vid.src = path;
  189. vid.appendChild(source_vid);
  190. document.getElementById('video_container').appendChild(vid);
  191. getFileMetadata(mediaFiles[0]);
  192. }
  193. function getFileMetadata (mediaFile) {
  194. mediaFile.getFormatData(getMetadataWin, getMetadataFail);
  195. }
  196. function getMetadataWin (metadata) {
  197. var strMetadata =
  198. 'duration = ' + metadata.duration + '\n' +
  199. 'width = ' + metadata.width + '\n' +
  200. 'height = ' + metadata.height;
  201. log(strMetadata);
  202. }
  203. function getMetadataFail (e) {
  204. log('Error getting metadata: ' + e.code);
  205. }
  206. function captureVideoFail (e) {
  207. log('Error getting video: ' + e.code);
  208. }
  209. function getVideo () {
  210. clearStatus();
  211. var options = { limit: 1, duration: 10 };
  212. navigator.device.capture.captureVideo(captureVideoWin, captureVideoFail, options);
  213. }
  214. function permissionWasNotAllowed () {
  215. log('Media has been captured. Have you forgotten to disallow camera for this app?');
  216. }
  217. function catchPermissionError (error) {
  218. if (CaptureError.CAPTURE_PERMISSION_DENIED === error.code) {
  219. log('Sucess: permission error has been detected!');
  220. } else {
  221. log('Error: another error with code: ' + error.code);
  222. }
  223. }
  224. function getVideoPermissionError () {
  225. var options = { limit: 1, duration: 10 };
  226. navigator.device.capture.captureVideo(permissionWasNotAllowed, catchPermissionError, options);
  227. }
  228. function getImagePermissionError () {
  229. var options = { limit: 1 };
  230. navigator.device.capture.captureImage(permissionWasNotAllowed, catchPermissionError, options);
  231. }
  232. function resolveMediaFileURL (mediaFile, callback) {
  233. resolveLocalFileSystemURL(mediaFile.localURL, function (entry) {
  234. log('Resolved by URL: ' + mediaFile.localURL);
  235. if (callback) callback();
  236. }, function (err) {
  237. log('Failed to resolve by URL: ' + mediaFile.localURL);
  238. log('Error: ' + JSON.stringify(err));
  239. if (callback) callback();
  240. });
  241. }
  242. function resolveMediaFile (mediaFile, callback) {
  243. resolveLocalFileSystemURL(mediaFile.fullPath, function (entry) {
  244. log('Resolved by path: ' + mediaFile.fullPath);
  245. if (callback) callback();
  246. }, function (err) {
  247. log('Failed to resolve by path: ' + mediaFile.fullPath);
  248. log('Error: ' + JSON.stringify(err));
  249. if (callback) callback();
  250. });
  251. }
  252. function resolveVideo () {
  253. clearStatus();
  254. var options = { limit: 1, duration: 5 };
  255. navigator.device.capture.captureVideo(function (mediaFiles) {
  256. captureVideoWin(mediaFiles);
  257. resolveMediaFile(mediaFiles[0], function () {
  258. resolveMediaFileURL(mediaFiles[0]);
  259. });
  260. }, captureVideoFail, options);
  261. }
  262. function clearStatus () {
  263. document.getElementById('camera_status').innerHTML = '';
  264. document.getElementById('camera_image').src = 'about:blank';
  265. document.getElementById('camera_image2').src = 'about:blank';
  266. document.getElementById('camera_image3').src = 'about:blank';
  267. }
  268. /******************************************************************************/
  269. contentEl.innerHTML = '<div id="info" style="white-space: pre-wrap">' +
  270. '<b>Status:</b> <div id="camera_status"></div>' +
  271. 'img1: <img width="100" id="camera_image">' +
  272. 'img2: <img width="100" id="camera_image2">' +
  273. 'img3: <img width="100" id="camera_image3">' +
  274. 'video: <div id="video_container"></div>' +
  275. '</div><div id="audio"></div>' +
  276. 'Expected result: Audio recorder will come up. Press record button to record for 10 seconds. Press Done. Status box will update with audio file and automatically play recording.' +
  277. '<p/> <div id="image"></div>' +
  278. 'Expected result: Status box will update with image just taken.' +
  279. '<p/> <div id="images"></div>' +
  280. 'Expected result: Status box will update with images just taken.' +
  281. '<p/> <div id="video"></div>' +
  282. 'Expected result: Record 10 second video. Status box will update with video file that you can play.' +
  283. '<p/> <div id="video_and_resolve"></div>' +
  284. 'Expected result: Record 5 second video. Status box will show that URL was resolved and video will get added at the bottom of the status box for playback.' +
  285. '<p/> <div id="prohibited_camera_video"></div>' +
  286. 'Expected result (iOS only): camera picker and alert with message that camera access is prohibited are shown. The alert has 2 buttons: OK and Settings. By click on "OK" camera is hidden, by pressing Settings it shows privacy settings for the app' +
  287. '<p/> <div id="prohibited_camera_image"></div>' +
  288. 'Expected result (iOS only): camera picker and alert with message that camera access is prohibited are shown. The alert has 2 buttons: OK and Settings. By click on "OK" camera is hidden, by pressing Settings it shows privacy settings for the app';
  289. createActionButton('Capture 10 sec of audio and play', function () {
  290. getAudio();
  291. }, 'audio');
  292. createActionButton('Capture 1 image', function () {
  293. getImage();
  294. }, 'image');
  295. createActionButton('Capture 3 images', function () {
  296. getImages();
  297. }, 'images');
  298. createActionButton('Capture 10 sec of video', function () {
  299. getVideo();
  300. }, 'video');
  301. createActionButton('Capture 5 sec of video and resolve', function () {
  302. resolveVideo();
  303. }, 'video_and_resolve');
  304. createActionButton('Disable access to Camera and click to capture video', function () {
  305. getVideoPermissionError();
  306. }, 'prohibited_camera_video');
  307. createActionButton('Disable access to Camera and click to capture image', function () {
  308. getImagePermissionError();
  309. }, 'prohibited_camera_image');
  310. };