android-emulator-webrtc 1.0.17 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +93 -204
- package/dist/components/emulator/emulator.d.ts +64 -0
- package/dist/components/emulator/emulator.js +161 -173
- package/dist/components/emulator/net/emulator_status.d.ts +45 -0
- package/dist/components/emulator/net/emulator_status.js +35 -42
- package/dist/components/emulator/net/logcat.js +37 -54
- package/dist/components/emulator/net/logger.d.ts +7 -0
- package/dist/components/emulator/net/logger.js +20 -0
- package/dist/components/emulator/net/ws_jsep_protocol_driver.d.ts +213 -0
- package/dist/components/emulator/net/ws_jsep_protocol_driver.js +640 -0
- package/dist/components/emulator/views/event_handler.d.ts +37 -0
- package/dist/components/emulator/views/event_handler.js +274 -260
- package/dist/components/emulator/views/webrtc_view.d.ts +27 -0
- package/dist/components/emulator/views/webrtc_view.js +42 -25
- package/dist/index.d.ts +8 -0
- package/dist/index.js +0 -7
- package/dist/proto/emulator_controller_pb.d.ts +1 -0
- package/dist/proto/emulator_controller_pb.js +146 -287
- package/dist/src/components/emulator/emulator.d.ts +64 -0
- package/dist/src/components/emulator/net/emulator_status.d.ts +45 -0
- package/dist/src/components/emulator/net/logger.d.ts +7 -0
- package/dist/src/components/emulator/net/ws_jsep_protocol_driver.d.ts +213 -0
- package/dist/src/components/emulator/views/event_handler.d.ts +37 -0
- package/dist/src/components/emulator/views/webrtc_view.d.ts +27 -0
- package/dist/src/index.d.ts +8 -0
- package/dist/src/proto/emulator_controller_pb.d.ts +1 -0
- package/package.json +17 -18
- package/proto/emulator_controller.proto +746 -181
- package/.vscode/launch.json +0 -21
- package/.vscode/settings.json +0 -3
- package/CONTRIBUTING.md +0 -28
- package/Makefile +0 -123
- package/android-emulator-webrtc.code-workspace +0 -7
- package/api_descriptor.pb +0 -0
- package/babel.config.js +0 -16
- package/cloudbuild.yaml +0 -41
- package/cloudbuilders/.gcloudignore +0 -1
- package/cloudbuilders/Dockerfile +0 -20
- package/cloudbuilders/README.md +0 -29
- package/cloudbuilders/cloudbuild.yaml +0 -19
- package/dist/components/emulator/net/jsep_protocol_driver.js +0 -365
- package/dist/components/emulator/views/resizing_component.js +0 -86
- package/dist/components/emulator/views/simple_png_view.js +0 -111
- package/dist/proto/emulator_controller_grpc_web_pb.js +0 -1601
- package/dist/proto/emulator_web_client.js +0 -176
- package/dist/proto/rtc_service_grpc_web_pb.js +0 -231
- package/dist/proto/rtc_service_pb.js +0 -338
- package/emulator/index.js +0 -1
- package/eslint_prefix.py +0 -37
- package/gen_md_doc.js +0 -40
- package/npmrc.enc +0 -0
- package/proto/rtc_service.proto +0 -117
- package/protoc-plugin/Makefile +0 -31
- package/protoc-plugin/grpc_generator.cc +0 -1755
- package/src/components/emulator/emulator.js +0 -217
- package/src/components/emulator/net/emulator_status.js +0 -94
- package/src/components/emulator/net/jsep_protocol_driver.js +0 -364
- package/src/components/emulator/net/logcat.js +0 -155
- package/src/components/emulator/views/event_handler.js +0 -268
- package/src/components/emulator/views/resizing_component.js +0 -65
- package/src/components/emulator/views/simple_png_view.js +0 -106
- package/src/components/emulator/views/webrtc_view.js +0 -146
- package/src/index.js +0 -20
- package/src/proto/emulator_web_client.js +0 -140
- package/test/cloudbuild.yaml +0 -41
- package/test/emulator.test.js +0 -125
- package/test/event_handler.test.js +0 -91
- package/test/fake_events.js +0 -50
- package/test/jsep_protocol_driver.test.js +0 -228
- package/test/resizing_component.test.js +0 -37
- package/test/simple_png_view.test.js +0 -145
- package/test/touch_event_handler.test.js +0 -118
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2019 The Android Open Source Project
|
|
3
|
-
*
|
|
4
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
* you may not use this file except in compliance with the License.
|
|
6
|
-
* You may obtain a copy of the License at
|
|
7
|
-
*
|
|
8
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
*
|
|
10
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
* See the License for the specific language governing permissions and
|
|
14
|
-
* limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
import PropTypes from "prop-types";
|
|
17
|
-
import React, { useEffect, useRef, useState } from "react";
|
|
18
|
-
|
|
19
|
-
const EmulatorWebrtcView = ({
|
|
20
|
-
jsep,
|
|
21
|
-
onStateChange,
|
|
22
|
-
onAudioStateChange,
|
|
23
|
-
muted,
|
|
24
|
-
volume,
|
|
25
|
-
onError,
|
|
26
|
-
}) => {
|
|
27
|
-
const [audio, setAudio] = useState(false);
|
|
28
|
-
const videoRef = useRef(null);
|
|
29
|
-
const [connect, setConnect] = useState("connecting");
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
useEffect(() => {
|
|
33
|
-
console.log("Webrtc state changed to: " + connect);
|
|
34
|
-
if (onStateChange) {
|
|
35
|
-
onStateChange(connect);
|
|
36
|
-
}
|
|
37
|
-
}, [connect]);
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
useEffect(() => {
|
|
41
|
-
console.log("Webrtc audio state changed to: " + audio);
|
|
42
|
-
if (onAudioStateChange) {
|
|
43
|
-
onAudioStateChange(audio);
|
|
44
|
-
}
|
|
45
|
-
}, [audio]);
|
|
46
|
-
|
|
47
|
-
const onDisconnect = () => {
|
|
48
|
-
setConnect("disconnected");
|
|
49
|
-
setAudio(false);
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
const onConnect = (track) => {
|
|
53
|
-
setConnect("connected");
|
|
54
|
-
const video = videoRef.current;
|
|
55
|
-
if (!video) {
|
|
56
|
-
// Component was unmounted.
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (!video.srcObject) {
|
|
61
|
-
video.srcObject = new MediaStream();
|
|
62
|
-
}
|
|
63
|
-
video.srcObject.addTrack(track);
|
|
64
|
-
if (track.kind === "audio") {
|
|
65
|
-
setAudio(true);
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
const safePlay = () => {
|
|
70
|
-
const video = videoRef.current;
|
|
71
|
-
if (!video) {
|
|
72
|
-
// Component was unmounted.
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const possiblePromise = video.play();
|
|
77
|
-
if (possiblePromise) {
|
|
78
|
-
possiblePromise
|
|
79
|
-
.then((_) => {
|
|
80
|
-
console.debug("Automatic playback started!");
|
|
81
|
-
})
|
|
82
|
-
.catch((error) => {
|
|
83
|
-
// Notify listeners that we cannot start.
|
|
84
|
-
onError(error);
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
const onCanPlay = () => {
|
|
90
|
-
safePlay();
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
const onContextMenu = (e) => {
|
|
94
|
-
e.preventDefault();
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
useEffect(() => {
|
|
98
|
-
jsep.on("connected", onConnect);
|
|
99
|
-
jsep.on("disconnected", onDisconnect);
|
|
100
|
-
jsep.startStream()
|
|
101
|
-
|
|
102
|
-
setConnect("connecting");
|
|
103
|
-
|
|
104
|
-
return () => {
|
|
105
|
-
jsep.disconnect();
|
|
106
|
-
};
|
|
107
|
-
}, []);
|
|
108
|
-
|
|
109
|
-
return (
|
|
110
|
-
<video
|
|
111
|
-
ref={videoRef}
|
|
112
|
-
style={{
|
|
113
|
-
display: "block",
|
|
114
|
-
position: "relative",
|
|
115
|
-
width: "100%",
|
|
116
|
-
height: "100%",
|
|
117
|
-
objectFit: "contain",
|
|
118
|
-
objectPosition: "center",
|
|
119
|
-
}}
|
|
120
|
-
volume={volume}
|
|
121
|
-
muted={muted}
|
|
122
|
-
onContextMenu={onContextMenu}
|
|
123
|
-
onCanPlay={onCanPlay}
|
|
124
|
-
/>
|
|
125
|
-
);
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
EmulatorWebrtcView.propTypes = {
|
|
129
|
-
jsep: PropTypes.object,
|
|
130
|
-
onStateChange: PropTypes.func,
|
|
131
|
-
onAudioStateChange: PropTypes.func,
|
|
132
|
-
muted: PropTypes.bool,
|
|
133
|
-
volume: PropTypes.number,
|
|
134
|
-
onError: PropTypes.func,
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
EmulatorWebrtcView.defaultProps = {
|
|
138
|
-
muted: true,
|
|
139
|
-
volume: 1.0,
|
|
140
|
-
onError: (e) => console.error("WebRTC error: " + e),
|
|
141
|
-
onAudioStateChange: (e) =>
|
|
142
|
-
console.log("Webrtc audio became available: " + e),
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
export default EmulatorWebrtcView;
|
|
146
|
-
|
package/src/index.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2020 The Android Open Source Project
|
|
3
|
-
*
|
|
4
|
-
* Licensed under the Apache License, Version 2.0 (the "License")
|
|
5
|
-
* you may not use this file except in compliance with the License.
|
|
6
|
-
* You may obtain a copy of the License at
|
|
7
|
-
*
|
|
8
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
*
|
|
10
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
* See the License for the specific language governing permissions and
|
|
14
|
-
* limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
import Emulator from "./components/emulator/emulator";
|
|
17
|
-
import Logcat from "./components/emulator/net/logcat";
|
|
18
|
-
import EmulatorStatus from "./components/emulator/net/emulator_status";
|
|
19
|
-
|
|
20
|
-
export { Emulator, Logcat, EmulatorStatus };
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2019 The Android Open Source Project
|
|
3
|
-
*
|
|
4
|
-
* Licensed under the Apache License, Version 2.0 (the "License")
|
|
5
|
-
* you may not use this file except in compliance with the License.
|
|
6
|
-
* You may obtain a copy of the License at
|
|
7
|
-
*
|
|
8
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
*
|
|
10
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
* See the License for the specific language governing permissions and
|
|
14
|
-
* limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
import { EmulatorControllerClient } from "../proto/emulator_controller_grpc_web_pb";
|
|
17
|
-
import { RtcClient } from "../proto/rtc_service_grpc_web_pb";
|
|
18
|
-
import { GrpcWebClientBase } from "grpc-web";
|
|
19
|
-
import { EventEmitter } from "events";
|
|
20
|
-
|
|
21
|
-
export class NopAuthenticator {
|
|
22
|
-
authHeader = () => {
|
|
23
|
-
return {};
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
unauthorized = () => { };
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* A GrcpWebClientBase that inject authentication headers and intercepts
|
|
31
|
-
* errors. If the errors are 401, the unauthorized method of the authenticator will be invoked.
|
|
32
|
-
*
|
|
33
|
-
* @export
|
|
34
|
-
* @class EmulatorWebClient
|
|
35
|
-
* @extends {GrpcWebClientBase}
|
|
36
|
-
*/
|
|
37
|
-
class EmulatorWebClient extends GrpcWebClientBase {
|
|
38
|
-
constructor(options, auth) {
|
|
39
|
-
super(options);
|
|
40
|
-
this.auth = auth;
|
|
41
|
-
this.events = new EventEmitter();
|
|
42
|
-
this.events.on("error", e => {console.log("low level gRPC error: " + JSON.stringify(e));})
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
on = (name, fn) => {
|
|
46
|
-
this.events.on(name, fn);
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
rpcCall = (method, request, metadata, methodinfo, callback) => {
|
|
50
|
-
const authHeader = this.auth.authHeader();
|
|
51
|
-
const meta = { ...metadata, ...authHeader };
|
|
52
|
-
const self = this;
|
|
53
|
-
return super.rpcCall(method, request, meta, methodinfo, (err, res) => {
|
|
54
|
-
if (err) {
|
|
55
|
-
if (err.code === 401) self.auth.unauthorized();
|
|
56
|
-
if (self.events)
|
|
57
|
-
self.events.emit("error", err);
|
|
58
|
-
}
|
|
59
|
-
if (callback) callback(err, res);
|
|
60
|
-
});
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
serverStreaming = (method, request, metadata, methodInfo) => {
|
|
64
|
-
const authHeader = this.auth.authHeader();
|
|
65
|
-
const meta = { ...metadata, ...authHeader };
|
|
66
|
-
const stream = super.serverStreaming(method, request, meta, methodInfo);
|
|
67
|
-
const self = this;
|
|
68
|
-
|
|
69
|
-
// Intercept errors.
|
|
70
|
-
stream.on("error", e => {
|
|
71
|
-
if (e.code === 401) {
|
|
72
|
-
self.auth.unauthorized();
|
|
73
|
-
}
|
|
74
|
-
self.events.emit("error", e);
|
|
75
|
-
});
|
|
76
|
-
return stream;
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* An EmulatorControllerService is an EmulatorControllerClient that inject authentication headers.
|
|
82
|
-
* You can provide your own authenticator service that must implement the following mehtods:
|
|
83
|
-
*
|
|
84
|
-
* - `authHeader()` which must return a set of headers that should be send along with a request.
|
|
85
|
-
* - `unauthorized()` a function that gets called when a 401 was received.
|
|
86
|
-
*
|
|
87
|
-
* You can use this to simplify handling authentication failures.
|
|
88
|
-
*
|
|
89
|
-
* TODO(jansene): Maybe expose error handling? That way it does
|
|
90
|
-
* not have to be repeated at every function call.
|
|
91
|
-
*
|
|
92
|
-
* @export
|
|
93
|
-
* @class EmulatorControllerService
|
|
94
|
-
* @extends {EmulatorControllerClient}
|
|
95
|
-
*/
|
|
96
|
-
export class EmulatorControllerService extends EmulatorControllerClient {
|
|
97
|
-
/**
|
|
98
|
-
*Creates an instance of EmulatorControllerService.
|
|
99
|
-
* @param {string} uri of the emulator controller endpoint.
|
|
100
|
-
* @param {Authenticator} authenticator used to authenticate with the emulator endpoint.
|
|
101
|
-
* @param onError callback that will be invoked when a low level gRPC error arises.
|
|
102
|
-
* @memberof EmulatorControllerService
|
|
103
|
-
*/
|
|
104
|
-
constructor(uri, authenticator, onError) {
|
|
105
|
-
super(uri);
|
|
106
|
-
if (!authenticator) authenticator = new NopAuthenticator();
|
|
107
|
-
this.client_ = new EmulatorWebClient({}, authenticator);
|
|
108
|
-
if (onError) this.client_.on('error', e => { onError(e); });
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* An RtcService is an RtcClient that inject authentication headers.
|
|
115
|
-
* You can provide your own authenticator service that must implement the following mehtods:
|
|
116
|
-
*
|
|
117
|
-
* - `authHeader()` which must return a set of headers that should be send along with a request.
|
|
118
|
-
* - `unauthorized()` a function that gets called when a 401 was received.
|
|
119
|
-
*
|
|
120
|
-
* You can use this to simplify handling authentication failures.
|
|
121
|
-
*
|
|
122
|
-
* @export
|
|
123
|
-
* @class EmulatorControllerService
|
|
124
|
-
* @extends {RtcClient}
|
|
125
|
-
*/
|
|
126
|
-
export class RtcService extends RtcClient {
|
|
127
|
-
/**
|
|
128
|
-
*Creates an instance of RtcService.
|
|
129
|
-
* @param {string} uri of the emulator controller endpoint.
|
|
130
|
-
* @param {Authenticator} authenticator used to authenticate with the emulator endpoint.
|
|
131
|
-
* @param onError callback that will be invoked when a low level gRPC error arises.
|
|
132
|
-
* @memberof RtcService
|
|
133
|
-
*/
|
|
134
|
-
constructor(uri, authenticator, onError) {
|
|
135
|
-
super(uri);
|
|
136
|
-
if (!authenticator) authenticator = new NopAuthenticator();
|
|
137
|
-
this.client_ = new EmulatorWebClient({}, authenticator);
|
|
138
|
-
if (onError) this.client_.on('error', e => { onError(e); });
|
|
139
|
-
}
|
|
140
|
-
}
|
package/test/cloudbuild.yaml
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
steps:
|
|
2
|
-
- name: "gcr.io/cloud-builders/gcloud"
|
|
3
|
-
args:
|
|
4
|
-
- kms
|
|
5
|
-
- decrypt
|
|
6
|
-
- --ciphertext-file=npmrc.enc
|
|
7
|
-
- --plaintext-file=/root/.npmrc
|
|
8
|
-
- --location=global
|
|
9
|
-
- --keyring=my-keyring
|
|
10
|
-
- --key=npm-key
|
|
11
|
-
volumes:
|
|
12
|
-
- name: "home"
|
|
13
|
-
path: /root/
|
|
14
|
-
- name: gcr.io/emu-dev-cts/protoc
|
|
15
|
-
args:
|
|
16
|
-
[
|
|
17
|
-
"--include_imports",
|
|
18
|
-
"--include_source_info",
|
|
19
|
-
"--proto_path",
|
|
20
|
-
"./proto",
|
|
21
|
-
"--descriptor_set_out",
|
|
22
|
-
"api_descriptor.pb",
|
|
23
|
-
"--plugin=protoc-gen-grpc-web=/protoc/bin/protoc-gen-grpc-web",
|
|
24
|
-
"--js_out=import_style=commonjs:src/proto",
|
|
25
|
-
"--grpc-web_out=import_style=commonjs,mode=grpcwebtext:src/proto",
|
|
26
|
-
"./proto/emulator_controller.proto",
|
|
27
|
-
"./proto/rtc_service.proto",
|
|
28
|
-
]
|
|
29
|
-
- name: "gcr.io/cloud-builders/npm"
|
|
30
|
-
args: ["install"]
|
|
31
|
-
- name: "gcr.io/cloud-builders/npm"
|
|
32
|
-
args: ["run", "build"]
|
|
33
|
-
- name: "gcr.io/cloud-builders/npm"
|
|
34
|
-
args: ["test"]
|
|
35
|
-
- name: "gcr.io/cloud-builders/npm"
|
|
36
|
-
args: ["publish", "/workspace", "--dry-run"]
|
|
37
|
-
env:
|
|
38
|
-
- HOME=/root/
|
|
39
|
-
volumes:
|
|
40
|
-
- name: "home"
|
|
41
|
-
path: /root/
|
package/test/emulator.test.js
DELETED
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* @jest-environment jsdom
|
|
4
|
-
*/
|
|
5
|
-
/*
|
|
6
|
-
* Copyright 2020 The Android Open Source Project
|
|
7
|
-
*
|
|
8
|
-
* Licensed under the Apache License, Version 2.0 (the "License")
|
|
9
|
-
* you may not use this file except in compliance with the License.
|
|
10
|
-
* You may obtain a copy of the License at
|
|
11
|
-
*
|
|
12
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
13
|
-
*
|
|
14
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
15
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
16
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
17
|
-
* See the License for the specific language governing permissions and
|
|
18
|
-
* limitations under the License.
|
|
19
|
-
*/
|
|
20
|
-
import "@testing-library/jest-dom";
|
|
21
|
-
import "babel-polyfill";
|
|
22
|
-
import { EventEmitter } from "events";
|
|
23
|
-
import React from "react";
|
|
24
|
-
import { render, fireEvent, screen, waitFor } from "@testing-library/react";
|
|
25
|
-
import Emulator from "../src/components/emulator/emulator";
|
|
26
|
-
import * as Proto from "../src/proto/emulator_controller_pb";
|
|
27
|
-
import * as Rtc from "../src/proto/rtc_service_pb";
|
|
28
|
-
import {
|
|
29
|
-
RtcService,
|
|
30
|
-
EmulatorControllerService,
|
|
31
|
-
} from "../src/proto/emulator_web_client";
|
|
32
|
-
|
|
33
|
-
jest.mock("../src/proto/emulator_web_client");
|
|
34
|
-
|
|
35
|
-
// See https://github.com/testing-library/react-testing-library/issues/470
|
|
36
|
-
// As well as https://github.com/facebook/react/issues/10389
|
|
37
|
-
// All because of the "muted" tag on our video element inside webrtc_view
|
|
38
|
-
const renderIgnoringUnstableFlushDiscreteUpdates = (component) => {
|
|
39
|
-
// tslint:disable: no-console
|
|
40
|
-
const originalError = console.error;
|
|
41
|
-
const error = jest.fn();
|
|
42
|
-
console.error = error;
|
|
43
|
-
const result = render(component);
|
|
44
|
-
expect(error).toHaveBeenCalledTimes(1);
|
|
45
|
-
expect(error).toHaveBeenCalledWith(
|
|
46
|
-
"Warning: unstable_flushDiscreteUpdates: Cannot flush updates when React is already rendering.%s",
|
|
47
|
-
expect.any(String)
|
|
48
|
-
);
|
|
49
|
-
console.error = originalError;
|
|
50
|
-
// tslint:enable: no-console
|
|
51
|
-
return result;
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
describe("The emulator", () => {
|
|
55
|
-
beforeEach(() => {
|
|
56
|
-
// Clear all instances and calls to constructor and all methods:
|
|
57
|
-
RtcService.mockClear();
|
|
58
|
-
EmulatorControllerService.mockClear();
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
test("Creates gRPC services", async () => {
|
|
62
|
-
render(
|
|
63
|
-
<Emulator uri="/test" width={300} height={300} />
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
expect(EmulatorControllerService).toHaveBeenCalled();
|
|
67
|
-
expect(RtcService).toHaveBeenCalled();
|
|
68
|
-
// Shipped out a gps call
|
|
69
|
-
});
|
|
70
|
-
test("Tries to establish a webrtc connection", async () => {
|
|
71
|
-
let state;
|
|
72
|
-
render(
|
|
73
|
-
<Emulator
|
|
74
|
-
uri="/test"
|
|
75
|
-
width={300}
|
|
76
|
-
height={300}
|
|
77
|
-
onStateChange={(e) => {
|
|
78
|
-
state = e;
|
|
79
|
-
}}
|
|
80
|
-
/>
|
|
81
|
-
);
|
|
82
|
-
|
|
83
|
-
await waitFor(() => state === "connecting");
|
|
84
|
-
expect(RtcService).toHaveBeenCalled();
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
test("Sends a gps location to the emulator", async () => {
|
|
88
|
-
// Let's go to Seattle!
|
|
89
|
-
render(
|
|
90
|
-
<Emulator
|
|
91
|
-
uri="/test"
|
|
92
|
-
width={300}
|
|
93
|
-
height={300}
|
|
94
|
-
gps={{ latitude: 47.6062, longitude: 122.3321 }}
|
|
95
|
-
/>
|
|
96
|
-
);
|
|
97
|
-
|
|
98
|
-
const setGps = EmulatorControllerService.mock.instances[0].setGps;
|
|
99
|
-
expect(setGps).toHaveBeenCalled();
|
|
100
|
-
|
|
101
|
-
const location = new Proto.GpsState();
|
|
102
|
-
location.setLatitude(47.6062);
|
|
103
|
-
location.setLongitude(122.3321);
|
|
104
|
-
location.setAltitude(undefined);
|
|
105
|
-
location.setBearing(undefined);
|
|
106
|
-
location.setSpeed(undefined);
|
|
107
|
-
expect(setGps).toHaveBeenCalledWith(location);
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
test("The png view requests images", async () => {
|
|
111
|
-
let pngCall = false
|
|
112
|
-
EmulatorControllerService.mockImplementation(() => {
|
|
113
|
-
return {
|
|
114
|
-
streamScreenshot: jest.fn((request) => {
|
|
115
|
-
pngCall = true
|
|
116
|
-
return { on: jest.fn(), cancel: jest.fn() };
|
|
117
|
-
}),
|
|
118
|
-
getStatus: jest.fn(() => {}),
|
|
119
|
-
};
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
render(<Emulator uri="/test" width={300} height={300} view="png" />);
|
|
123
|
-
expect(pngCall).toBeTruthy()
|
|
124
|
-
});
|
|
125
|
-
});
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @jest-environment jsdom
|
|
3
|
-
*/
|
|
4
|
-
/*
|
|
5
|
-
* Copyright 2020 The Android Open Source Project
|
|
6
|
-
*
|
|
7
|
-
* Licensed under the Apache License, Version 2.0 (the "License")
|
|
8
|
-
* you may not use this file except in compliance with the License.
|
|
9
|
-
* 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, software
|
|
14
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
-
* See the License for the specific language governing permissions and
|
|
17
|
-
* limitations under the License.
|
|
18
|
-
*/
|
|
19
|
-
import "@testing-library/jest-dom";
|
|
20
|
-
|
|
21
|
-
import React from "react";
|
|
22
|
-
import { render, fireEvent, screen } from "@testing-library/react";
|
|
23
|
-
import { fakeMouseEvent, fakeTouchEvent} from "./fake_events";
|
|
24
|
-
import withMouseKeyHandler from "../src/components/emulator/views/event_handler";
|
|
25
|
-
|
|
26
|
-
import JsepProtocol from "../src/components/emulator/net/jsep_protocol_driver";
|
|
27
|
-
import {
|
|
28
|
-
RtcService,
|
|
29
|
-
EmulatorControllerService,
|
|
30
|
-
} from "../src/proto/emulator_web_client";
|
|
31
|
-
|
|
32
|
-
jest.mock("../src/proto/emulator_web_client");
|
|
33
|
-
jest.mock("../src/proto/rtc_service_pb");
|
|
34
|
-
jest.mock("../src/proto/emulator_controller_pb");
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
class FakeEmulator extends React.Component {
|
|
38
|
-
render() {
|
|
39
|
-
return (
|
|
40
|
-
<div
|
|
41
|
-
data-testid="fake"
|
|
42
|
-
style={{ height: "200px", width: "200px", backgroundColor: "#555" }}
|
|
43
|
-
></div>
|
|
44
|
-
);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const TestView = withMouseKeyHandler(FakeEmulator);
|
|
49
|
-
describe("The event handler using a real jsep serializer", () => {
|
|
50
|
-
|
|
51
|
-
const rtcServiceInstance = new RtcService("http://foo");
|
|
52
|
-
const emulatorServiceInstance = new EmulatorControllerService("http://foo");
|
|
53
|
-
let jsep, fakeScreen;
|
|
54
|
-
|
|
55
|
-
beforeEach(() => {
|
|
56
|
-
jest.clearAllMocks();
|
|
57
|
-
jsep = new JsepProtocol(emulatorServiceInstance, rtcServiceInstance, true);
|
|
58
|
-
|
|
59
|
-
render(<TestView emulator={emulatorServiceInstance} jsep={jsep} />);
|
|
60
|
-
fakeScreen = screen.getByTestId("fake").parentElement;
|
|
61
|
-
Object.defineProperty(fakeScreen, "clientWidth", { get: () => 200 });
|
|
62
|
-
Object.defineProperty(fakeScreen, "clientHeight", { get: () => 200 });
|
|
63
|
-
|
|
64
|
-
expect(fakeScreen).toBeInTheDocument();
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
test("Forwards mouse events", () => {
|
|
68
|
-
fireEvent(fakeScreen, fakeMouseEvent("mousedown", 10, 10));
|
|
69
|
-
fireEvent(fakeScreen, fakeMouseEvent("mouseup", 20, 20));
|
|
70
|
-
|
|
71
|
-
// Shipped out a mouse event
|
|
72
|
-
expect(emulatorServiceInstance.sendMouse).toHaveBeenCalledTimes(2);
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
test("Forwards keyboard events", () => {
|
|
76
|
-
fireEvent.keyDown(fakeScreen, { key: "Enter", code: "Enter" });
|
|
77
|
-
fireEvent.keyUp(fakeScreen, { key: "Enter", code: "Enter" });
|
|
78
|
-
|
|
79
|
-
// Shipped out a keyboard event
|
|
80
|
-
expect(emulatorServiceInstance.sendKey).toHaveBeenCalledTimes(2);
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
test("Forwards touch events", () => {
|
|
84
|
-
fireEvent(fakeScreen, fakeTouchEvent("touchstart", 10, 10, 1));
|
|
85
|
-
fireEvent(fakeScreen, fakeTouchEvent("touchmove", 20, 20, 2));
|
|
86
|
-
fireEvent(fakeScreen, fakeTouchEvent("touchend", 30, 30, 0));
|
|
87
|
-
|
|
88
|
-
// Shipped out a touch event
|
|
89
|
-
expect(emulatorServiceInstance.sendTouch).toHaveBeenCalledTimes(3);
|
|
90
|
-
});
|
|
91
|
-
});
|
package/test/fake_events.js
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2021 The Android Open Source Project
|
|
3
|
-
*
|
|
4
|
-
* Licensed under the Apache License, Version 2.0 (the "License")
|
|
5
|
-
* you may not use this file except in compliance with the License.
|
|
6
|
-
* You may obtain a copy of the License at
|
|
7
|
-
*
|
|
8
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
*
|
|
10
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
* See the License for the specific language governing permissions and
|
|
14
|
-
* limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
export function fakeMouseEvent(tp, x, y, props = {}) {
|
|
17
|
-
const event = new MouseEvent(tp, {
|
|
18
|
-
bubbles: true,
|
|
19
|
-
cancelable: true,
|
|
20
|
-
...props,
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
Object.defineProperty(event, "offsetX", { get: () => x });
|
|
24
|
-
Object.defineProperty(event, "offsetY", { get: () => y });
|
|
25
|
-
return event;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export function fakeTouchEvent(tp, x, y, force, props = {}) {
|
|
29
|
-
const event = new TouchEvent(tp, {
|
|
30
|
-
bubbles: true,
|
|
31
|
-
cancelable: true,
|
|
32
|
-
...props,
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
Object.defineProperty(event, "changedTouches", {
|
|
36
|
-
get: () => [
|
|
37
|
-
{ clientX: x, clientY: y, radiusX: 4, radiusY: 4, force: force },
|
|
38
|
-
],
|
|
39
|
-
});
|
|
40
|
-
return event;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export function resize(width, height) {
|
|
44
|
-
const resizeEvent = document.createEvent("Event");
|
|
45
|
-
resizeEvent.initEvent("resize", true, true);
|
|
46
|
-
|
|
47
|
-
global.window.innerWidth = width || global.window.innerWidth;
|
|
48
|
-
global.window.innerHeight = height || global.window.innerHeight;
|
|
49
|
-
global.window.dispatchEvent(resizeEvent);
|
|
50
|
-
}
|