-
Notifications
You must be signed in to change notification settings - Fork 133
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Proposal] Update mediaCapabilitiesProber API #1472
base: dev
Are you sure you want to change the base?
Conversation
a78ca09
to
bf9e326
Compare
bf9e326
to
52bf6ac
Compare
17e1a36
to
597dcb3
Compare
99059eb
to
538aff1
Compare
538aff1
to
0ea518d
Compare
console.log("This device is compatible with the given configuration!"); | ||
console.log("Wanted configuration:", configuration); | ||
console.log("Compatible configuration:", compatibleConfiguration); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this example is not working, configuration
and compatibleConfiguration
are not defined
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, it's directly the compatible one instead. I'll update.
const result: ISupportWithFeatures = ( | ||
globalScope as IGlobalScopeWithMSMediaKeysFeatures | ||
).MSMediaKeys.isTypeSupportedWithFeatures(type, features); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure how this API works, do you have any documentation on this one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was an old edge feature only present on MSMediaKeys
and was able to check for more precize policy support.
I also have trouble finding documentation on it today, my searches for now only lead to the RxPlayer and complaints from Netflix users :p
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TypeScript at some point had it in its type definitions: https://raw.githubusercontent.com/Microsoft/TypeScript/v2.9.2/lib/lib.es6.d.ts
Though not anymore
} | ||
} catch (err) { | ||
const error = err instanceof Error ? err : new Error("Unknown Error"); | ||
log.error("MCP: `probeHDCPPolicy` didn't succeed to create a MediaKeys", error); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From what I read, the error log here is not accurate:
We can get here if the API getStatusForPolicy
does not exist, not because the MediaKeys failed to be created.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right requestMediaKeySystemAccess
and createMediaKeys
don't even have their try/catch.
I'll fix that
try { | ||
await probeDecodingInfos(configuration); | ||
resetDecodingInfos(); | ||
} catch (error) { | ||
const message = error instanceof Error ? error.message : ""; | ||
thrownException = true; | ||
expect(message).toEqual("Not enough arguments for calling mediaCapabilites."); | ||
expect(decodingInfoStub).not.toHaveBeenCalled(); | ||
resetDecodingInfos(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remark about resetDecodingInfos()
, it can be done only once outside the try..catch
try {
await probeDecodingInfos(configuration);
} catch (error) {
const message = error instanceof Error ? error.message : "";
thrownException = true;
expect(message).toEqual("Not enough arguments for calling mediaCapabilites.");
expect(decodingInfoStub).not.toHaveBeenCalled();
}
resetDecodingInfos();
But a similar code is runned in the afterEach()
hook.
So we can delete that code from every test since it's already done in the hook and check that it works well
@@ -82,22 +80,21 @@ describe("MediaCapabilitiesProber probers - decodingInfo", () => { | |||
}, | |||
}; | |||
|
|||
expect.assertions(2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just learned about expect.assertions()
is it something that should be avoided?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like using it because it's something easy to forget about and it's not really a meaningful test beside ensuring that a code path with assertions has been taken, in which case I prefer a more explicit check like a boolean.
// eslint-disable-next-line @typescript-eslint/no-floating-promises | ||
expect(probeDecodingInfos({})).rejects.toThrowError( | ||
"MediaCapabilitiesProber >>> API_CALL: MediaCapabilities API not available", | ||
return probeDecodingInfos({}).then( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is there a return
?
Also there is jest modifier .rejects
that help with this kind of test:
await expect(probeDecodingInfos({})).rejects.toThrowError("navigator.mediaCapabilites.decodingInfo is not available");
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When tests return a promise in most testing frameworks, the test will reject when the promise rejects and resolve when the promise resolve.
I know about rejects
, and that was what was there before, but for some reason I found returning the promise more readable.
return probeDecodingInfos({}).then( | ||
() => { | ||
throw new Error("Should not succeed"); | ||
}, | ||
(err: Error) => { | ||
expect(err).toBeInstanceOf(Error); | ||
expect(err.message).toEqual( | ||
"navigator.mediaCapabilites.decodingInfo is not available", | ||
); | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
expect(probeMediaContentType({})).rejects.toThrowError( | ||
"MediaCapabilitiesProber >>> API_CALL: " + "MediaSource API not available", | ||
); | ||
expect(() => probeMediaContentType({})).toThrowError("MediaSource API not available"); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the eslint error could have been fixed by adding await
before expect
expect(() => probeMediaContentType({})).toThrowError( | ||
"MediaSource.isTypeSupported API not available", | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here
globalScope as { matchMedia: typeof globalScope.matchMedia | undefined } | ||
).matchMedia = origMatchMedia; | ||
expect(() => probeMediaDisplayInfos({})).toThrowError("matchMedia API not available"); | ||
globalScope.matchMedia = origMatchMedia; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
setting the matchMedia
API should be done in the afterEach / beforeEach hooks
support: ISupportWithFeatures, | ||
): "NotSupported" | "Unknown" | "Supported" { | ||
if (support === "") { | ||
throw new Error("Bad arguments for calling isTypeSupportedWithFeatures"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The API returns empty string if arguments are invalid ? Weird one
* @param {Object} mediaConfig | ||
* @returns {Promise.<string>} | ||
*/ | ||
async getDecodingCapabilities(mediaConfig: IMediaConfiguration): Promise<string> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't the type should be narrowed to "Supported" / "Unknown" / "NotSupported" instead of being a string ?
This reverts commit fdd172a.
0ea518d
to
a2ea9bf
Compare
After some brainstorming related to #1470, we noticed that as is, our old
mediaCapabilitiesProber
experimental tool could gain by being more flexible.Especially, the
getCompatibleDRMConfigurations
method checked multiple EMEMediaKeySystemConfiguration
at once and returned information on actual configurations compatible to them once all of them have been checked.We wondered whether this method would not be more useful by making it less powerful: we'll now only check for a single
MediaKeySystemConfiguration
per method call (and rename that method tocheckDrmConfiguration
).Doing this signals to an application that it can just combine multiple calls if it wants the old behavior (e.g. through a
Promise.all
), usePromise.race
to just obtain the first one etc. (this would still be possible with the previous API, but seemed unnatural to application developers).I also added a
timeout
argument to it, but realized that it might be very complex to maintain, as theoreticallycheckDrmConfiguration
could call multiple browser API sequentially in the future (as othermediaCapabilitiesProber
's methods are doing).In that case, where are we supposed to apply the
timeout
: to each browser API call or globally on the method?I also profited from this work to rewrite the implementation of other
mediaCapabilitiesProber
's method without changing their API, as I found that a lot of its data-processing code was unneeded and difficult to follow.