Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

Commit 57fb51f

Browse files
bselwefelangel
andauthored
[camera] Introduce camera_web package (#4151)
This first version is a no-op implementation of the platform_interface, but is the initial step to bring over the implementation from the Photobooth into flutter/plugins. Won't be published (for now). Co-authored-by: Felix Angelov <[email protected]>
1 parent f726c31 commit 57fb51f

17 files changed

+718
-0
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
## 0.1.0
2+
3+
* Initial release

packages/camera/camera_web/LICENSE

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
Copyright 2013 The Flutter Authors. All rights reserved.
2+
3+
Redistribution and use in source and binary forms, with or without modification,
4+
are permitted provided that the following conditions are met:
5+
6+
* Redistributions of source code must retain the above copyright
7+
notice, this list of conditions and the following disclaimer.
8+
* Redistributions in binary form must reproduce the above
9+
copyright notice, this list of conditions and the following
10+
disclaimer in the documentation and/or other materials provided
11+
with the distribution.
12+
* Neither the name of Google Inc. nor the names of its
13+
contributors may be used to endorse or promote products derived
14+
from this software without specific prior written permission.
15+
16+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
23+
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

packages/camera/camera_web/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Camera Web Plugin
2+
3+
A Flutter plugin for Web allowing access to the device cameras.
4+
5+
*Note*: This plugin is under development.
6+
7+
In order to use this plugin, your app should depend both on `camera` and `camera_web`. This is a temporary solution until a plugin is released.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Testing
2+
3+
This package uses `package:integration_test` to run its tests in a web browser.
4+
5+
See [Plugin Tests > Web Tests](https://github.com/flutter/flutter/wiki/Plugin-Tests#web-tests)
6+
in the Flutter wiki for instructions to setup and run the tests in this package.
7+
8+
Check [flutter.dev > Integration testing](https://flutter.dev/docs/testing/integration-tests)
9+
for more info.
Lines changed: 314 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,314 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'dart:html';
6+
7+
import 'package:camera_platform_interface/camera_platform_interface.dart';
8+
import 'package:camera_web/camera_web.dart';
9+
import 'package:flutter/services.dart';
10+
import 'package:flutter_test/flutter_test.dart';
11+
import 'package:integration_test/integration_test.dart';
12+
import 'package:mocktail/mocktail.dart';
13+
14+
import 'helpers/helpers.dart';
15+
16+
void main() {
17+
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
18+
19+
group('CameraPlugin', () {
20+
const cameraId = 0;
21+
22+
late Window window;
23+
late Navigator navigator;
24+
late MediaDevices mediaDevices;
25+
late VideoElement videoElement;
26+
27+
setUp(() async {
28+
window = MockWindow();
29+
navigator = MockNavigator();
30+
mediaDevices = MockMediaDevices();
31+
videoElement = VideoElement()
32+
..src =
33+
'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4'
34+
..preload = 'true'
35+
..width = 10
36+
..height = 10;
37+
38+
when(() => window.navigator).thenReturn(navigator);
39+
when(() => navigator.mediaDevices).thenReturn(mediaDevices);
40+
when(
41+
() => mediaDevices.getUserMedia(any()),
42+
).thenAnswer((_) async => videoElement.captureStream());
43+
44+
CameraPlatform.instance = CameraPlugin()..window = window;
45+
});
46+
47+
testWidgets('CameraPlugin is the live instance', (tester) async {
48+
expect(CameraPlatform.instance, isA<CameraPlugin>());
49+
});
50+
51+
testWidgets('availableCameras throws UnimplementedError', (tester) async {
52+
expect(
53+
() => CameraPlatform.instance.availableCameras(),
54+
throwsUnimplementedError,
55+
);
56+
});
57+
58+
testWidgets('createCamera throws UnimplementedError', (tester) async {
59+
expect(
60+
() => CameraPlatform.instance.createCamera(
61+
CameraDescription(
62+
name: 'name',
63+
lensDirection: CameraLensDirection.external,
64+
sensorOrientation: 0,
65+
),
66+
ResolutionPreset.medium,
67+
),
68+
throwsUnimplementedError,
69+
);
70+
});
71+
72+
testWidgets('initializeCamera throws UnimplementedError', (tester) async {
73+
expect(
74+
() => CameraPlatform.instance.initializeCamera(cameraId),
75+
throwsUnimplementedError,
76+
);
77+
});
78+
79+
testWidgets('lockCaptureOrientation throws UnimplementedError',
80+
(tester) async {
81+
expect(
82+
() => CameraPlatform.instance.lockCaptureOrientation(
83+
cameraId,
84+
DeviceOrientation.landscapeLeft,
85+
),
86+
throwsUnimplementedError,
87+
);
88+
});
89+
90+
testWidgets('unlockCaptureOrientation throws UnimplementedError',
91+
(tester) async {
92+
expect(
93+
() => CameraPlatform.instance.unlockCaptureOrientation(cameraId),
94+
throwsUnimplementedError,
95+
);
96+
});
97+
98+
testWidgets('takePicture throws UnimplementedError', (tester) async {
99+
expect(
100+
() => CameraPlatform.instance.takePicture(cameraId),
101+
throwsUnimplementedError,
102+
);
103+
});
104+
105+
testWidgets('prepareForVideoRecording throws UnimplementedError',
106+
(tester) async {
107+
expect(
108+
() => CameraPlatform.instance.prepareForVideoRecording(),
109+
throwsUnimplementedError,
110+
);
111+
});
112+
113+
testWidgets('startVideoRecording throws UnimplementedError',
114+
(tester) async {
115+
expect(
116+
() => CameraPlatform.instance.startVideoRecording(cameraId),
117+
throwsUnimplementedError,
118+
);
119+
});
120+
121+
testWidgets('stopVideoRecording throws UnimplementedError', (tester) async {
122+
expect(
123+
() => CameraPlatform.instance.stopVideoRecording(cameraId),
124+
throwsUnimplementedError,
125+
);
126+
});
127+
128+
testWidgets('pauseVideoRecording throws UnimplementedError',
129+
(tester) async {
130+
expect(
131+
() => CameraPlatform.instance.pauseVideoRecording(cameraId),
132+
throwsUnimplementedError,
133+
);
134+
});
135+
136+
testWidgets('resumeVideoRecording throws UnimplementedError',
137+
(tester) async {
138+
expect(
139+
() => CameraPlatform.instance.resumeVideoRecording(cameraId),
140+
throwsUnimplementedError,
141+
);
142+
});
143+
144+
testWidgets('setFlashMode throws UnimplementedError', (tester) async {
145+
expect(
146+
() => CameraPlatform.instance.setFlashMode(
147+
cameraId,
148+
FlashMode.auto,
149+
),
150+
throwsUnimplementedError,
151+
);
152+
});
153+
154+
testWidgets('setExposureMode throws UnimplementedError', (tester) async {
155+
expect(
156+
() => CameraPlatform.instance.setExposureMode(
157+
cameraId,
158+
ExposureMode.auto,
159+
),
160+
throwsUnimplementedError,
161+
);
162+
});
163+
164+
testWidgets('setExposurePoint throws UnimplementedError', (tester) async {
165+
expect(
166+
() => CameraPlatform.instance.setExposurePoint(
167+
cameraId,
168+
const Point(0, 0),
169+
),
170+
throwsUnimplementedError,
171+
);
172+
});
173+
174+
testWidgets('getMinExposureOffset throws UnimplementedError',
175+
(tester) async {
176+
expect(
177+
() => CameraPlatform.instance.getMinExposureOffset(cameraId),
178+
throwsUnimplementedError,
179+
);
180+
});
181+
182+
testWidgets('getMaxExposureOffset throws UnimplementedError',
183+
(tester) async {
184+
expect(
185+
() => CameraPlatform.instance.getMaxExposureOffset(cameraId),
186+
throwsUnimplementedError,
187+
);
188+
});
189+
190+
testWidgets('getExposureOffsetStepSize throws UnimplementedError',
191+
(tester) async {
192+
expect(
193+
() => CameraPlatform.instance.getExposureOffsetStepSize(cameraId),
194+
throwsUnimplementedError,
195+
);
196+
});
197+
198+
testWidgets('setExposureOffset throws UnimplementedError', (tester) async {
199+
expect(
200+
() => CameraPlatform.instance.setExposureOffset(
201+
cameraId,
202+
0,
203+
),
204+
throwsUnimplementedError,
205+
);
206+
});
207+
208+
testWidgets('setFocusMode throws UnimplementedError', (tester) async {
209+
expect(
210+
() => CameraPlatform.instance.setFocusMode(
211+
cameraId,
212+
FocusMode.auto,
213+
),
214+
throwsUnimplementedError,
215+
);
216+
});
217+
218+
testWidgets('setFocusPoint throws UnimplementedError', (tester) async {
219+
expect(
220+
() => CameraPlatform.instance.setFocusPoint(
221+
cameraId,
222+
const Point(0, 0),
223+
),
224+
throwsUnimplementedError,
225+
);
226+
});
227+
228+
testWidgets('getMaxZoomLevel throws UnimplementedError', (tester) async {
229+
expect(
230+
() => CameraPlatform.instance.getMaxZoomLevel(cameraId),
231+
throwsUnimplementedError,
232+
);
233+
});
234+
235+
testWidgets('getMinZoomLevel throws UnimplementedError', (tester) async {
236+
expect(
237+
() => CameraPlatform.instance.getMinZoomLevel(cameraId),
238+
throwsUnimplementedError,
239+
);
240+
});
241+
242+
testWidgets('setZoomLevel throws UnimplementedError', (tester) async {
243+
expect(
244+
() => CameraPlatform.instance.setZoomLevel(
245+
cameraId,
246+
1.0,
247+
),
248+
throwsUnimplementedError,
249+
);
250+
});
251+
252+
testWidgets('buildPreview throws UnimplementedError', (tester) async {
253+
expect(
254+
() => CameraPlatform.instance.buildPreview(cameraId),
255+
throwsUnimplementedError,
256+
);
257+
});
258+
259+
testWidgets('dispose throws UnimplementedError', (tester) async {
260+
expect(
261+
() => CameraPlatform.instance.dispose(cameraId),
262+
throwsUnimplementedError,
263+
);
264+
});
265+
266+
group('events', () {
267+
testWidgets('onCameraInitialized throws UnimplementedError',
268+
(tester) async {
269+
expect(
270+
() => CameraPlatform.instance.onCameraInitialized(cameraId),
271+
throwsUnimplementedError,
272+
);
273+
});
274+
275+
testWidgets('onCameraResolutionChanged throws UnimplementedError',
276+
(tester) async {
277+
expect(
278+
() => CameraPlatform.instance.onCameraResolutionChanged(cameraId),
279+
throwsUnimplementedError,
280+
);
281+
});
282+
283+
testWidgets('onCameraClosing throws UnimplementedError', (tester) async {
284+
expect(
285+
() => CameraPlatform.instance.onCameraClosing(cameraId),
286+
throwsUnimplementedError,
287+
);
288+
});
289+
290+
testWidgets('onCameraError throws UnimplementedError', (tester) async {
291+
expect(
292+
() => CameraPlatform.instance.onCameraError(cameraId),
293+
throwsUnimplementedError,
294+
);
295+
});
296+
297+
testWidgets('onVideoRecordedEvent throws UnimplementedError',
298+
(tester) async {
299+
expect(
300+
() => CameraPlatform.instance.onVideoRecordedEvent(cameraId),
301+
throwsUnimplementedError,
302+
);
303+
});
304+
305+
testWidgets('onDeviceOrientationChanged throws UnimplementedError',
306+
(tester) async {
307+
expect(
308+
() => CameraPlatform.instance.onDeviceOrientationChanged(),
309+
throwsUnimplementedError,
310+
);
311+
});
312+
});
313+
});
314+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
export 'mocks.dart';
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'dart:html';
6+
7+
import 'package:mocktail/mocktail.dart';
8+
9+
class MockWindow extends Mock implements Window {}
10+
11+
class MockNavigator extends Mock implements Navigator {}
12+
13+
class MockMediaDevices extends Mock implements MediaDevices {}
14+
15+
/// A fake [DomException] that returns the provided [errorName].
16+
class FakeDomException extends Fake implements DomException {
17+
FakeDomException(this.errorName);
18+
19+
final String errorName;
20+
21+
@override
22+
String get name => errorName;
23+
}

0 commit comments

Comments
 (0)