blob: 4c8ccc12c9481ea76a8fffaf9ce02e0c90c0180b [file] [edit]
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>MediaStreamTrackState enum: readyState only ever returns "live" or "ended"</title>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script>
// MediaCapture-Main §"MediaStreamTrackState" enum:
// https://w3c.github.io/mediacapture-main/#dom-mediastreamtrackstate
//
// enum MediaStreamTrackState {
// "live",
// "ended"
// };
//
// MediaStreamTrack.readyState (a MediaStreamTrackState getter) must
// return only one of these two values. There is no script API to "prove"
// the enum is closed (we can't enumerate the enum from script), but we
// can assert that every observable transition produces a value in the
// allowed set — which is the strongest assertion script-side testing
// supports for an IDL enum.
const VALID = ["live", "ended"];
function assertValidState(track, label) {
assert_in_array(track.readyState, VALID,
`${label}: readyState is one of ${JSON.stringify(VALID)}`);
}
promise_test(async test => {
// Newly created from getUserMedia.
const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true });
test.add_cleanup(() => stream.getTracks().forEach(t => t.stop()));
for (const t of stream.getTracks())
assertValidState(t, `fresh ${t.kind} track`);
// After stop().
for (const t of stream.getTracks()) {
t.stop();
assertValidState(t, `stopped ${t.kind} track`);
assert_equals(t.readyState, "ended", "stopped track is in 'ended' state");
}
}, "readyState is in MediaStreamTrackState enum after creation and after stop()");
promise_test(async test => {
// Clones of live and ended tracks must also yield valid states.
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
test.add_cleanup(() => stream.getTracks().forEach(t => t.stop()));
const original = stream.getVideoTracks()[0];
const cloneOfLive = original.clone();
test.add_cleanup(() => cloneOfLive.stop());
assertValidState(cloneOfLive, "clone of live track");
assert_equals(cloneOfLive.readyState, "live",
"clone of a live track is also live");
original.stop();
const cloneOfEnded = original.clone();
assertValidState(cloneOfEnded, "clone of ended track");
assert_equals(cloneOfEnded.readyState, "ended",
"clone of an ended track is also ended");
}, "readyState is in MediaStreamTrackState enum after cloning live and ended tracks");
promise_test(async test => {
// Verify that JSON serialization round-trips the enum string verbatim
// (no extra modifier characters or stringification artifacts that
// would imply a different underlying type).
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
test.add_cleanup(() => stream.getTracks().forEach(t => t.stop()));
const track = stream.getAudioTracks()[0];
const round = JSON.parse(JSON.stringify({ s: track.readyState }));
assert_equals(typeof round.s, "string",
"readyState round-trips as a string");
assert_in_array(round.s, VALID,
"readyState round-trip value is in the spec-mandated enum set");
}, "readyState stringifies and round-trips as an enum-set value");
</script>
</head>
<body></body>
</html>