rx-player
Version:
Canal+ HTML5 Video Player
789 lines (754 loc) • 31 kB
text/typescript
import { describe, afterEach, it, expect, vi } from "vitest";
import assert from "../../../../utils/assert";
import type IContentDecryptor from "../../content_decryptor";
import type { ContentDecryptorState as IContentDecryptorState } from "../../types";
import {
formatFakeChallengeFromInitData,
MediaKeySessionImpl,
MediaKeysImpl,
mockCompat,
} from "./utils";
describe("decrypt - global tests - init data", () => {
/** Default video element used in our tests. */
const videoElt = document.createElement("video");
const mockGetLicense = vi.fn().mockImplementation(() => {
return new Promise(() => {
/* noop */
});
});
/** Default keySystems configuration used in our tests. */
const ksConfig = [{ type: "com.widevine.alpha", getLicense: mockGetLicense }];
afterEach(() => {
vi.resetAllMocks();
vi.resetModules();
});
it("should create a session and generate a request when init data is sent through the arguments", async () => {
// == mocks ==
const { mockGenerateKeyRequest } = mockCompat();
const mediaKeySession = new MediaKeySessionImpl();
const mockCreateSession = vi
.spyOn(MediaKeysImpl.prototype, "createSession")
.mockReturnValue(mediaKeySession);
const ContentDecryptorState = (await vi.importActual("../../types"))
.ContentDecryptorState as typeof IContentDecryptorState;
const ContentDecryptor = (await vi.importActual("../../content_decryptor"))
.default as typeof IContentDecryptor;
const getEmeApiImplementation = (await import("../../../../compat/eme")).default;
return new Promise<void>((res, rej) => {
// == vars ==
const initData = new Uint8Array([54, 55, 75]);
// == test ==
const eme = getEmeApiImplementation("auto");
assert(eme !== null, "Expected to have an EME implementation");
const contentDecryptor = new ContentDecryptor(eme, videoElt, ksConfig);
contentDecryptor.addEventListener(
"stateChange",
(newState: IContentDecryptorState) => {
if (newState !== ContentDecryptorState.WaitingForAttachment) {
rej(new Error(`Unexpected state: ${newState}`));
}
contentDecryptor.removeEventListener("stateChange");
contentDecryptor.attach();
},
);
contentDecryptor.onInitializationData({
type: "cenc",
values: [{ systemId: "15", data: initData }],
});
setTimeout(() => {
try {
expect(mockCreateSession).toHaveBeenCalledTimes(1);
expect(mockCreateSession).toHaveBeenCalledWith("temporary");
expect(mockGenerateKeyRequest).toHaveBeenCalledTimes(1);
expect(mockGenerateKeyRequest).toHaveBeenCalledWith(
mediaKeySession,
"cenc",
initData,
);
expect(mockGetLicense).toHaveBeenCalledTimes(1);
// TODO there's seem to be an issue with how vitest check Uint8Array
// equality
expect(mockGetLicense).toHaveBeenCalledWith(
formatFakeChallengeFromInitData(initData, "cenc"),
"license-request",
);
res();
} catch (err) {
rej(err);
}
}, 100);
});
});
it("should ignore init data already sent through the argument", async () => {
// == mocks ==
const { mockGenerateKeyRequest } = mockCompat();
const mediaKeySession = new MediaKeySessionImpl();
const mockCreateSession = vi
.spyOn(MediaKeysImpl.prototype, "createSession")
.mockReturnValue(mediaKeySession);
const ContentDecryptorState = (await vi.importActual("../../types"))
.ContentDecryptorState as typeof IContentDecryptorState;
const ContentDecryptor = (await vi.importActual("../../content_decryptor"))
.default as typeof IContentDecryptor;
const getEmeApiImplementation = (await import("../../../../compat/eme")).default;
return new Promise<void>((res, rej) => {
// == vars ==
const initData = new Uint8Array([54, 55, 75]);
// == test ==
const eme = getEmeApiImplementation("auto");
assert(eme !== null, "Expected to have an EME implementation");
const contentDecryptor = new ContentDecryptor(eme, videoElt, ksConfig);
contentDecryptor.addEventListener(
"stateChange",
(newState: IContentDecryptorState) => {
if (newState !== ContentDecryptorState.WaitingForAttachment) {
rej(new Error(`Unexpected state: ${newState}`));
}
contentDecryptor.removeEventListener("stateChange");
contentDecryptor.attach();
},
);
contentDecryptor.onInitializationData({
type: "cenc",
values: [{ systemId: "15", data: initData }],
});
contentDecryptor.onInitializationData({
type: "cenc",
values: [{ systemId: "15", data: initData }],
});
setTimeout(() => {
contentDecryptor.onInitializationData({
type: "cenc",
values: [{ systemId: "15", data: initData }],
});
}, 5);
setTimeout(() => {
try {
expect(mockCreateSession).toHaveBeenCalledTimes(1);
expect(mockCreateSession).toHaveBeenCalledWith("temporary");
expect(mockGenerateKeyRequest).toHaveBeenCalledTimes(1);
expect(mockGenerateKeyRequest).toHaveBeenCalledWith(
mediaKeySession,
"cenc",
initData,
);
expect(mockGetLicense).toHaveBeenCalledTimes(1);
// TODO there's seem to be an issue with how vitest check Uint8Array
// equality
expect(mockGetLicense).toHaveBeenCalledWith(
formatFakeChallengeFromInitData(initData, "cenc"),
"license-request",
);
res();
} catch (err) {
rej(err);
}
}, 100);
});
});
it("should create multiple sessions for multiple sent init data when unknown", async () => {
// == mocks ==
const { mockGenerateKeyRequest } = mockCompat();
const mediaKeySessions = [
new MediaKeySessionImpl(),
new MediaKeySessionImpl(),
new MediaKeySessionImpl(),
];
let createSessionCallIdx = 0;
const mockCreateSession = vi
.spyOn(MediaKeysImpl.prototype, "createSession")
.mockImplementation(() => mediaKeySessions[createSessionCallIdx++]);
const ContentDecryptorState = (await vi.importActual("../../types"))
.ContentDecryptorState as typeof IContentDecryptorState;
const ContentDecryptor = (await vi.importActual("../../content_decryptor"))
.default as typeof IContentDecryptor;
const getEmeApiImplementation = (await import("../../../../compat/eme")).default;
return new Promise<void>((res, rej) => {
// == vars ==
const initDatas = [
new Uint8Array([54, 55, 75]),
new Uint8Array([87, 32]),
new Uint8Array([87, 77]),
];
// == test ==
const eme = getEmeApiImplementation("auto");
assert(eme !== null, "Expected to have an EME implementation");
const contentDecryptor = new ContentDecryptor(eme, videoElt, ksConfig);
contentDecryptor.addEventListener(
"stateChange",
(newState: IContentDecryptorState) => {
if (newState !== ContentDecryptorState.WaitingForAttachment) {
rej(new Error(`Unexpected state: ${newState}`));
}
contentDecryptor.removeEventListener("stateChange");
contentDecryptor.attach();
},
);
contentDecryptor.onInitializationData({
type: "cenc",
values: [{ systemId: "15", data: initDatas[0] }],
});
contentDecryptor.onInitializationData({
type: "cenc",
values: [{ systemId: "15", data: initDatas[1] }],
});
contentDecryptor.onInitializationData({
type: "cenc",
values: [{ systemId: "15", data: initDatas[0] }],
});
setTimeout(() => {
contentDecryptor.onInitializationData({
type: "cenc",
values: [{ systemId: "15", data: initDatas[2] }],
});
});
setTimeout(() => {
contentDecryptor.onInitializationData({
type: "cenc",
values: [{ systemId: "15", data: initDatas[1] }],
});
}, 5);
setTimeout(() => {
try {
expect(mockCreateSession).toHaveBeenCalledTimes(3);
expect(mockCreateSession).toHaveBeenNthCalledWith(1, "temporary");
expect(mockCreateSession).toHaveBeenNthCalledWith(2, "temporary");
expect(mockCreateSession).toHaveBeenNthCalledWith(3, "temporary");
expect(mockGenerateKeyRequest).toHaveBeenCalledTimes(3);
expect(mockGenerateKeyRequest).toHaveBeenNthCalledWith(
1,
mediaKeySessions[0],
"cenc",
initDatas[0],
);
expect(mockGenerateKeyRequest).toHaveBeenNthCalledWith(
2,
mediaKeySessions[1],
"cenc",
initDatas[1],
);
expect(mockGenerateKeyRequest).toHaveBeenNthCalledWith(
3,
mediaKeySessions[2],
"cenc",
initDatas[2],
);
expect(mockGetLicense).toHaveBeenCalledTimes(3);
// TODO there's seem to be an issue with how vitest check Uint8Array
// equality
expect(mockGetLicense).toHaveBeenNthCalledWith(
1,
formatFakeChallengeFromInitData(initDatas[0], "cenc"),
"license-request",
);
expect(mockGetLicense).toHaveBeenNthCalledWith(
2,
formatFakeChallengeFromInitData(initDatas[1], "cenc"),
"license-request",
);
expect(mockGetLicense).toHaveBeenNthCalledWith(
3,
formatFakeChallengeFromInitData(initDatas[2], "cenc"),
"license-request",
);
res();
} catch (err) {
rej(err);
}
}, 100);
});
});
it("should create multiple sessions for multiple sent init data types", async () => {
// == mocks ==
const { mockGenerateKeyRequest } = mockCompat();
const mediaKeySessions = [new MediaKeySessionImpl(), new MediaKeySessionImpl()];
let createSessionCallIdx = 0;
const mockCreateSession = vi
.spyOn(MediaKeysImpl.prototype, "createSession")
.mockImplementation(() => mediaKeySessions[createSessionCallIdx++]);
const ContentDecryptorState = (await vi.importActual("../../types"))
.ContentDecryptorState as typeof IContentDecryptorState;
const ContentDecryptor = (await vi.importActual("../../content_decryptor"))
.default as typeof IContentDecryptor;
const getEmeApiImplementation = (await import("../../../../compat/eme")).default;
return new Promise<void>((res, rej) => {
// == vars ==
const initData = new Uint8Array([54, 55, 75]);
// == test ==
const eme = getEmeApiImplementation("auto");
assert(eme !== null, "Expected to have an EME implementation");
const contentDecryptor = new ContentDecryptor(eme, videoElt, ksConfig);
contentDecryptor.addEventListener(
"stateChange",
(newState: IContentDecryptorState) => {
if (newState !== ContentDecryptorState.WaitingForAttachment) {
rej(new Error(`Unexpected state: ${newState}`));
}
contentDecryptor.removeEventListener("stateChange");
contentDecryptor.attach();
},
);
contentDecryptor.onInitializationData({
type: "cenc",
values: [{ systemId: "15", data: initData }],
});
contentDecryptor.onInitializationData({
type: "cenc2",
values: [{ systemId: "15", data: initData }],
});
setTimeout(() => {
try {
expect(mockCreateSession).toHaveBeenCalledTimes(2);
expect(mockCreateSession).toHaveBeenNthCalledWith(1, "temporary");
expect(mockCreateSession).toHaveBeenNthCalledWith(2, "temporary");
expect(mockGenerateKeyRequest).toHaveBeenCalledTimes(2);
expect(mockGenerateKeyRequest).toHaveBeenNthCalledWith(
1,
mediaKeySessions[0],
"cenc",
initData,
);
expect(mockGenerateKeyRequest).toHaveBeenNthCalledWith(
2,
mediaKeySessions[1],
"cenc2",
initData,
);
expect(mockGetLicense).toHaveBeenCalledTimes(2);
// TODO there's seem to be an issue with how vitest check Uint8Array
// equality
expect(mockGetLicense).toHaveBeenNthCalledWith(
1,
formatFakeChallengeFromInitData(initData, "cenc"),
"license-request",
);
expect(mockGetLicense).toHaveBeenNthCalledWith(
2,
formatFakeChallengeFromInitData(initData, "cenc2"),
"license-request",
);
res();
} catch (err) {
rej(err);
}
}, 100);
});
});
it("should create a session and generate a request when init data is received from the browser", async () => {
// == mocks ==
const { mockGenerateKeyRequest, eventTriggers, mockGetInitData } = mockCompat();
const mediaKeySession = new MediaKeySessionImpl();
const mockCreateSession = vi
.spyOn(MediaKeysImpl.prototype, "createSession")
.mockReturnValue(mediaKeySession);
const ContentDecryptorState = (await vi.importActual("../../types"))
.ContentDecryptorState as typeof IContentDecryptorState;
const ContentDecryptor = (await vi.importActual("../../content_decryptor"))
.default as typeof IContentDecryptor;
const getEmeApiImplementation = (await import("../../../../compat/eme")).default;
return new Promise<void>((res, rej) => {
// == vars ==
const initData = new Uint8Array([54, 55, 75]);
// == test ==
const eme = getEmeApiImplementation("auto");
assert(eme !== null, "Expected to have an EME implementation");
const contentDecryptor = new ContentDecryptor(eme, videoElt, ksConfig);
contentDecryptor.addEventListener(
"stateChange",
(newState: IContentDecryptorState) => {
if (newState !== ContentDecryptorState.WaitingForAttachment) {
rej(new Error(`Unexpected state: ${newState}`));
}
contentDecryptor.removeEventListener("stateChange");
contentDecryptor.attach();
},
);
const initDataEvent = {
type: "cenc",
values: [{ systemId: "15", data: initData }],
};
eventTriggers.triggerEncrypted(videoElt, initDataEvent);
setTimeout(() => {
try {
expect(mockGetInitData).toHaveBeenCalledTimes(1);
expect(mockGetInitData).toHaveBeenCalledWith(initDataEvent);
expect(mockCreateSession).toHaveBeenCalledTimes(1);
expect(mockCreateSession).toHaveBeenCalledWith("temporary");
expect(mockGenerateKeyRequest).toHaveBeenCalledTimes(1);
expect(mockGenerateKeyRequest).toHaveBeenCalledWith(
mediaKeySession,
"cenc",
initData,
);
expect(mockGetLicense).toHaveBeenCalledTimes(1);
// TODO there's seem to be an issue with how vitest check Uint8Array
// equality
expect(mockGetLicense).toHaveBeenCalledWith(
formatFakeChallengeFromInitData(initData, "cenc"),
"license-request",
);
res();
} catch (err) {
rej(err);
}
}, 100);
});
});
it("should ignore init data already received through the browser", async () => {
// == mocks ==
const { mockGenerateKeyRequest, eventTriggers, mockGetInitData } = mockCompat();
const mediaKeySession = new MediaKeySessionImpl();
const mockCreateSession = vi
.spyOn(MediaKeysImpl.prototype, "createSession")
.mockReturnValue(mediaKeySession);
const ContentDecryptorState = (await vi.importActual("../../types"))
.ContentDecryptorState as typeof IContentDecryptorState;
const ContentDecryptor = (await vi.importActual("../../content_decryptor"))
.default as typeof IContentDecryptor;
const getEmeApiImplementation = (await import("../../../../compat/eme")).default;
return new Promise<void>((res, rej) => {
// == vars ==
const initData = new Uint8Array([54, 55, 75]);
// == test ==
const eme = getEmeApiImplementation("auto");
assert(eme !== null, "Expected to have an EME implementation");
const contentDecryptor = new ContentDecryptor(eme, videoElt, ksConfig);
contentDecryptor.addEventListener(
"stateChange",
(newState: IContentDecryptorState) => {
if (newState !== ContentDecryptorState.WaitingForAttachment) {
rej(new Error(`Unexpected state: ${newState}`));
}
contentDecryptor.removeEventListener("stateChange");
contentDecryptor.attach();
},
);
const initDataEvent = {
type: "cenc",
values: [{ systemId: "15", data: initData }],
};
eventTriggers.triggerEncrypted(videoElt, initDataEvent);
eventTriggers.triggerEncrypted(videoElt, initDataEvent);
setTimeout(() => {
eventTriggers.triggerEncrypted(videoElt, initDataEvent);
}, 5);
setTimeout(() => {
try {
expect(mockGetInitData).toHaveBeenCalledTimes(3);
expect(mockGetInitData).toHaveBeenNthCalledWith(1, initDataEvent);
expect(mockGetInitData).toHaveBeenNthCalledWith(2, initDataEvent);
expect(mockGetInitData).toHaveBeenNthCalledWith(3, initDataEvent);
expect(mockCreateSession).toHaveBeenCalledTimes(1);
expect(mockCreateSession).toHaveBeenCalledWith("temporary");
expect(mockGenerateKeyRequest).toHaveBeenCalledTimes(1);
expect(mockGenerateKeyRequest).toHaveBeenCalledWith(
mediaKeySession,
"cenc",
initData,
);
expect(mockGetLicense).toHaveBeenCalledTimes(1);
// TODO there's seem to be an issue with how vitest check Uint8Array
// equality
expect(mockGetLicense).toHaveBeenCalledWith(
formatFakeChallengeFromInitData(initData, "cenc"),
"license-request",
);
res();
} catch (err) {
rej(err);
}
}, 100);
});
});
it("should create multiple sessions for multiple received init data when unknown", async () => {
// == mocks ==
const { mockGenerateKeyRequest, eventTriggers, mockGetInitData } = mockCompat();
const mediaKeySessions = [
new MediaKeySessionImpl(),
new MediaKeySessionImpl(),
new MediaKeySessionImpl(),
];
let createSessionCallIdx = 0;
const mockCreateSession = vi
.spyOn(MediaKeysImpl.prototype, "createSession")
.mockImplementation(() => mediaKeySessions[createSessionCallIdx++]);
const ContentDecryptorState = (await vi.importActual("../../types"))
.ContentDecryptorState as typeof IContentDecryptorState;
const ContentDecryptor = (await vi.importActual("../../content_decryptor"))
.default as typeof IContentDecryptor;
const getEmeApiImplementation = (await import("../../../../compat/eme")).default;
return new Promise<void>((res, rej) => {
// == vars ==
const initDatas = [
new Uint8Array([54, 55, 75]),
new Uint8Array([87, 32]),
new Uint8Array([87, 77]),
];
const initDataEvents = [
{ type: "cenc", values: [{ systemId: "15", data: initDatas[0] }] },
{ type: "cenc", values: [{ systemId: "15", data: initDatas[1] }] },
{ type: "cenc", values: [{ systemId: "15", data: initDatas[2] }] },
];
// == test ==
const eme = getEmeApiImplementation("auto");
assert(eme !== null, "Expected to have an EME implementation");
const contentDecryptor = new ContentDecryptor(eme, videoElt, ksConfig);
contentDecryptor.addEventListener(
"stateChange",
(newState: IContentDecryptorState) => {
if (newState !== ContentDecryptorState.WaitingForAttachment) {
rej(new Error(`Unexpected state: ${newState}`));
}
contentDecryptor.removeEventListener("stateChange");
contentDecryptor.attach();
},
);
eventTriggers.triggerEncrypted(videoElt, initDataEvents[0]);
eventTriggers.triggerEncrypted(videoElt, initDataEvents[1]);
eventTriggers.triggerEncrypted(videoElt, initDataEvents[0]);
setTimeout(() => {
eventTriggers.triggerEncrypted(videoElt, initDataEvents[2]);
});
setTimeout(() => {
eventTriggers.triggerEncrypted(videoElt, initDataEvents[1]);
}, 5);
setTimeout(() => {
try {
expect(mockGetInitData).toHaveBeenCalledTimes(5);
expect(mockGetInitData).toHaveBeenNthCalledWith(1, initDataEvents[0]);
expect(mockGetInitData).toHaveBeenNthCalledWith(2, initDataEvents[1]);
expect(mockGetInitData).toHaveBeenNthCalledWith(3, initDataEvents[0]);
expect(mockGetInitData).toHaveBeenNthCalledWith(4, initDataEvents[2]);
expect(mockGetInitData).toHaveBeenNthCalledWith(5, initDataEvents[1]);
expect(mockCreateSession).toHaveBeenCalledTimes(3);
expect(mockCreateSession).toHaveBeenNthCalledWith(1, "temporary");
expect(mockCreateSession).toHaveBeenNthCalledWith(2, "temporary");
expect(mockCreateSession).toHaveBeenNthCalledWith(3, "temporary");
expect(mockGenerateKeyRequest).toHaveBeenCalledTimes(3);
expect(mockGenerateKeyRequest).toHaveBeenNthCalledWith(
1,
mediaKeySessions[0],
"cenc",
initDatas[0],
);
expect(mockGenerateKeyRequest).toHaveBeenNthCalledWith(
2,
mediaKeySessions[1],
"cenc",
initDatas[1],
);
expect(mockGenerateKeyRequest).toHaveBeenNthCalledWith(
3,
mediaKeySessions[2],
"cenc",
initDatas[2],
);
expect(mockGetLicense).toHaveBeenCalledTimes(3);
// TODO there's seem to be an issue with how vitest check Uint8Array
// equality
expect(mockGetLicense).toHaveBeenNthCalledWith(
1,
formatFakeChallengeFromInitData(initDatas[0], "cenc"),
"license-request",
);
expect(mockGetLicense).toHaveBeenNthCalledWith(
2,
formatFakeChallengeFromInitData(initDatas[1], "cenc"),
"license-request",
);
expect(mockGetLicense).toHaveBeenNthCalledWith(
3,
formatFakeChallengeFromInitData(initDatas[2], "cenc"),
"license-request",
);
res();
} catch (err) {
rej(err);
}
}, 100);
});
});
it("should create multiple sessions for multiple received init data types", async () => {
// == mocks ==
const { mockGenerateKeyRequest, eventTriggers, mockGetInitData } = mockCompat();
const mediaKeySessions = [new MediaKeySessionImpl(), new MediaKeySessionImpl()];
let createSessionCallIdx = 0;
const mockCreateSession = vi
.spyOn(MediaKeysImpl.prototype, "createSession")
.mockImplementation(() => mediaKeySessions[createSessionCallIdx++]);
const ContentDecryptorState = (await vi.importActual("../../types"))
.ContentDecryptorState as typeof IContentDecryptorState;
const ContentDecryptor = (await vi.importActual("../../content_decryptor"))
.default as typeof IContentDecryptor;
const getEmeApiImplementation = (await import("../../../../compat/eme")).default;
return new Promise<void>((res, rej) => {
// == vars ==
const initData = new Uint8Array([54, 55, 75]);
const initDataEvents = [
{ type: "cenc", values: [{ systemId: "15", data: initData }] },
{ type: "cenc2", values: [{ systemId: "15", data: initData }] },
];
// == test ==
const eme = getEmeApiImplementation("auto");
assert(eme !== null, "Expected to have an EME implementation");
const contentDecryptor = new ContentDecryptor(eme, videoElt, ksConfig);
contentDecryptor.addEventListener(
"stateChange",
(newState: IContentDecryptorState) => {
if (newState !== ContentDecryptorState.WaitingForAttachment) {
rej(new Error(`Unexpected state: ${newState}`));
}
contentDecryptor.removeEventListener("stateChange");
contentDecryptor.attach();
},
);
eventTriggers.triggerEncrypted(videoElt, initDataEvents[0]);
eventTriggers.triggerEncrypted(videoElt, initDataEvents[1]);
setTimeout(() => {
try {
expect(mockGetInitData).toHaveBeenCalledTimes(2);
expect(mockGetInitData).toHaveBeenNthCalledWith(1, initDataEvents[0]);
expect(mockGetInitData).toHaveBeenNthCalledWith(2, initDataEvents[1]);
expect(mockCreateSession).toHaveBeenCalledTimes(2);
expect(mockCreateSession).toHaveBeenNthCalledWith(1, "temporary");
expect(mockCreateSession).toHaveBeenNthCalledWith(2, "temporary");
expect(mockGenerateKeyRequest).toHaveBeenCalledTimes(2);
expect(mockGenerateKeyRequest).toHaveBeenNthCalledWith(
1,
mediaKeySessions[0],
"cenc",
initData,
);
expect(mockGenerateKeyRequest).toHaveBeenNthCalledWith(
2,
mediaKeySessions[1],
"cenc2",
initData,
);
expect(mockGetLicense).toHaveBeenCalledTimes(2);
// TODO there's seem to be an issue with how vitest check Uint8Array
// equality
expect(mockGetLicense).toHaveBeenNthCalledWith(
1,
formatFakeChallengeFromInitData(initData, "cenc"),
"license-request",
);
expect(mockGetLicense).toHaveBeenNthCalledWith(
2,
formatFakeChallengeFromInitData(initData, "cenc2"),
"license-request",
);
res();
} catch (err) {
rej(err);
}
}, 100);
});
});
it("should consider sent event through arguments and received events through the browser the same way", async () => {
// == mocks ==
const { mockGenerateKeyRequest, eventTriggers, mockGetInitData } = mockCompat();
const mediaKeySessions = [
new MediaKeySessionImpl(),
new MediaKeySessionImpl(),
new MediaKeySessionImpl(),
];
let createSessionCallIdx = 0;
const mockCreateSession = vi
.spyOn(MediaKeysImpl.prototype, "createSession")
.mockImplementation(() => mediaKeySessions[createSessionCallIdx++]);
const ContentDecryptorState = (await vi.importActual("../../types"))
.ContentDecryptorState as typeof IContentDecryptorState;
const ContentDecryptor = (await vi.importActual("../../content_decryptor"))
.default as typeof IContentDecryptor;
const getEmeApiImplementation = (await import("../../../../compat/eme")).default;
return new Promise<void>((res, rej) => {
// == vars ==
const initDatas = [
new Uint8Array([54, 55, 75]),
new Uint8Array([87, 32]),
new Uint8Array([87, 77]),
];
const initDataEvents = [
{ type: "cenc", values: [{ systemId: "15", data: initDatas[0] }] },
{ type: "cenc", values: [{ systemId: "15", data: initDatas[1] }] },
{ type: "cenc", values: [{ systemId: "15", data: initDatas[2] }] },
];
// == test ==
const eme = getEmeApiImplementation("auto");
assert(eme !== null, "Expected to have an EME implementation");
const contentDecryptor = new ContentDecryptor(eme, videoElt, ksConfig);
contentDecryptor.addEventListener(
"stateChange",
(newState: IContentDecryptorState) => {
if (newState !== ContentDecryptorState.WaitingForAttachment) {
rej(new Error(`Unexpected state: ${newState}`));
}
contentDecryptor.removeEventListener("stateChange");
contentDecryptor.attach();
},
);
eventTriggers.triggerEncrypted(videoElt, initDataEvents[0]);
contentDecryptor.onInitializationData(initDataEvents[1]);
eventTriggers.triggerEncrypted(videoElt, initDataEvents[1]);
eventTriggers.triggerEncrypted(videoElt, initDataEvents[0]);
setTimeout(() => {
contentDecryptor.onInitializationData(initDataEvents[0]);
eventTriggers.triggerEncrypted(videoElt, initDataEvents[2]);
});
setTimeout(() => {
try {
expect(mockGetInitData).toHaveBeenCalledTimes(4);
expect(mockGetInitData).toHaveBeenNthCalledWith(1, initDataEvents[0]);
expect(mockGetInitData).toHaveBeenNthCalledWith(2, initDataEvents[1]);
expect(mockGetInitData).toHaveBeenNthCalledWith(3, initDataEvents[0]);
expect(mockGetInitData).toHaveBeenNthCalledWith(4, initDataEvents[2]);
expect(mockCreateSession).toHaveBeenCalledTimes(3);
expect(mockCreateSession).toHaveBeenNthCalledWith(1, "temporary");
expect(mockCreateSession).toHaveBeenNthCalledWith(2, "temporary");
expect(mockCreateSession).toHaveBeenNthCalledWith(3, "temporary");
expect(mockGenerateKeyRequest).toHaveBeenCalledTimes(3);
expect(mockGenerateKeyRequest).toHaveBeenNthCalledWith(
1,
mediaKeySessions[0],
"cenc",
initDatas[0],
);
expect(mockGenerateKeyRequest).toHaveBeenNthCalledWith(
2,
mediaKeySessions[1],
"cenc",
initDatas[1],
);
expect(mockGenerateKeyRequest).toHaveBeenNthCalledWith(
3,
mediaKeySessions[2],
"cenc",
initDatas[2],
);
expect(mockGetLicense).toHaveBeenCalledTimes(3);
// TODO there's seem to be an issue with how vitest check Uint8Array
// equality
expect(mockGetLicense).toHaveBeenNthCalledWith(
1,
formatFakeChallengeFromInitData(initDatas[0], "cenc"),
"license-request",
);
expect(mockGetLicense).toHaveBeenNthCalledWith(
2,
formatFakeChallengeFromInitData(initDatas[1], "cenc"),
"license-request",
);
expect(mockGetLicense).toHaveBeenNthCalledWith(
3,
formatFakeChallengeFromInitData(initDatas[2], "cenc"),
"license-request",
);
res();
} catch (err) {
rej(err);
}
}, 100);
});
});
});