rx-player
Version:
Canal+ HTML5 Video Player
235 lines (222 loc) • 8.48 kB
text/typescript
import { describe, beforeEach, it, expect, vi } from "vitest";
import type IParseContentProtection from "../ContentProtection";
function testStringAttribute(attributeName: string, variableName?: string): void {
const _variableName = variableName ?? attributeName;
it(`should correctly parse a ContentProtection element with a correct ${attributeName} attribute`, async () => {
const parseContentProtection = (await vi.importActual("../ContentProtection"))
.default as typeof IParseContentProtection;
const element1 = new DOMParser().parseFromString(
`<ContentProtection ${attributeName}="foobar" />`,
"text/xml",
).childNodes[0] as Element;
expect(parseContentProtection(element1)).toEqual([
{ attributes: { [_variableName]: "foobar" }, children: { cencPssh: [] } },
[],
]);
const element2 = new DOMParser().parseFromString(
`<ContentProtection ${attributeName}="" />`,
"text/xml",
).childNodes[0] as Element;
expect(parseContentProtection(element2)).toEqual([
{ attributes: { [_variableName]: "" }, children: { cencPssh: [] } },
[],
]);
});
}
describe("DASH Node Parsers - ContentProtection", () => {
beforeEach(() => {
vi.resetModules();
});
it("should correctly parse a ContentProtection element without attributes", async () => {
const parseContentProtection = (await vi.importActual("../ContentProtection"))
.default as typeof IParseContentProtection;
const element = new DOMParser().parseFromString("<ContentProtection />", "text/xml")
.childNodes[0] as Element;
expect(parseContentProtection(element)).toEqual([
{ attributes: {}, children: { cencPssh: [] } },
[],
]);
});
testStringAttribute("schemeIdUri");
testStringAttribute("value");
it("should correctly parse a ContentProtection element with a correct cenc:default_KID attribute", async () => {
const keyId = new Uint8Array([0, 1, 2, 3]);
const mockHexToBytes = vi.fn().mockImplementation(() => {
return keyId;
});
vi.doMock("../../../../../../utils/string_parsing", () => ({
hexToBytes: mockHexToBytes,
}));
const parseContentProtection = (await vi.importActual("../ContentProtection"))
.default as typeof IParseContentProtection;
const element1 = new DOMParser()
.parseFromString(
`<?xml version="1.0" encoding="utf-8"?>
<MPD
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:mpeg:dash:schema:mpd:2011"
xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd"
xmlns:cenc="urn:mpeg:cenc:2013"
xmlns:mspr="urn:microsoft:playready"
xmlns:scte35="urn:scte:scte35:2014:xml+bin">
<ContentProtection cenc:default_KID="dead-beef" />
</MPD>
`,
"text/xml",
)
.getElementsByTagName("ContentProtection")[0];
expect(parseContentProtection(element1)).toEqual([
{ attributes: { keyId }, children: { cencPssh: [] } },
[],
]);
expect(mockHexToBytes).toHaveBeenCalledTimes(1);
expect(mockHexToBytes).toHaveBeenCalledWith("deadbeef");
});
it("should correctly parse a ContentProtection with every attributes", async () => {
const keyId = new Uint8Array([0, 1, 2, 3]);
const mockHexToBytes = vi.fn().mockImplementation(() => {
return keyId;
});
vi.doMock("../../../../../../utils/string_parsing", () => ({
hexToBytes: mockHexToBytes,
}));
const parseContentProtection = (await vi.importActual("../ContentProtection"))
.default as typeof IParseContentProtection;
const element = new DOMParser()
.parseFromString(
`<?xml version="1.0" encoding="utf-8"?>
<MPD
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:mpeg:dash:schema:mpd:2011"
xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd"
xmlns:cenc="urn:mpeg:cenc:2013"
xmlns:mspr="urn:microsoft:playready"
xmlns:scte35="urn:scte:scte35:2014:xml+bin">
<ContentProtection
schemeIdUri="foo"
value="bar"
cenc:default_KID="dead-beef"
/>
</MPD>
`,
"text/xml",
)
.getElementsByTagName("ContentProtection")[0];
expect(parseContentProtection(element)).toEqual([
{
attributes: { keyId, schemeIdUri: "foo", value: "bar" },
children: { cencPssh: [] },
},
[],
]);
});
it("should correctly parse a ContentProtection with cenc:pssh children", async () => {
const parseContentProtection = (await vi.importActual("../ContentProtection"))
.default as typeof IParseContentProtection;
const element = new DOMParser()
.parseFromString(
`<?xml version="1.0" encoding="utf-8"?>
<MPD
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:mpeg:dash:schema:mpd:2011"
xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd"
xmlns:cenc="urn:mpeg:cenc:2013"
xmlns:mspr="urn:microsoft:playready"
xmlns:scte35="urn:scte:scte35:2014:xml+bin">
<ContentProtection>
<cenc:pssh>AABBCC</cenc:pssh>
<cenc:pssh>AAABAC</cenc:pssh>
</ContentProtection>
</MPD>
`,
"text/xml",
)
.getElementsByTagName("ContentProtection")[0];
expect(parseContentProtection(element)).toEqual([
{
attributes: {},
children: {
cencPssh: [new Uint8Array([0, 0, 65, 8]), new Uint8Array([0, 0, 1, 0])],
},
},
[],
]);
});
it("should correctly parse a ContentProtection with both cenc:pssh children and every attributes", async () => {
const keyId = new Uint8Array([0, 1, 2, 3]);
const mockHexToBytes = vi.fn().mockImplementation(() => {
return keyId;
});
vi.doMock("../../../../../../utils/string_parsing", () => ({
hexToBytes: mockHexToBytes,
}));
const parseContentProtection = (await vi.importActual("../ContentProtection"))
.default as typeof IParseContentProtection;
const element = new DOMParser()
.parseFromString(
`<?xml version="1.0" encoding="utf-8"?>
<MPD
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:mpeg:dash:schema:mpd:2011"
xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd"
xmlns:cenc="urn:mpeg:cenc:2013"
xmlns:mspr="urn:microsoft:playready"
xmlns:scte35="urn:scte:scte35:2014:xml+bin">
<ContentProtection
schemeIdUri="foo"
value="bar"
cenc:default_KID="dead-beef"
>
<cenc:pssh>AABBCC</cenc:pssh>
<cenc:pssh>AAABAC</cenc:pssh>
</ContentProtection>
</MPD>
`,
"text/xml",
)
.getElementsByTagName("ContentProtection")[0];
expect(parseContentProtection(element)).toEqual([
{
attributes: { keyId, schemeIdUri: "foo", value: "bar" },
children: {
cencPssh: [new Uint8Array([0, 0, 65, 8]), new Uint8Array([0, 0, 1, 0])],
},
},
[],
]);
});
it("should return a warning if one of the cenc:pssh is invalid base64", async () => {
const parseContentProtection = (await vi.importActual("../ContentProtection"))
.default as typeof IParseContentProtection;
const element = new DOMParser()
.parseFromString(
`<?xml version="1.0" encoding="utf-8"?>
<MPD
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:mpeg:dash:schema:mpd:2011"
xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd"
xmlns:cenc="urn:mpeg:cenc:2013"
xmlns:mspr="urn:microsoft:playready"
xmlns:scte35="urn:scte:scte35:2014:xml+bin">
<ContentProtection>
<cenc:pssh>AA!BCC</cenc:pssh>
<cenc:pssh>AAABAC</cenc:pssh>
</ContentProtection>
</MPD>
`,
"text/xml",
)
.getElementsByTagName("ContentProtection")[0];
const parsed = parseContentProtection(element);
expect(parsed[0]).toEqual({
attributes: {},
children: { cencPssh: [new Uint8Array([0, 0, 1, 0])] },
});
expect(parsed[1]).not.toBe(null);
expect(parsed[1]).toHaveLength(1);
expect(parsed[1][0]).toBeInstanceOf(Error);
expect(parsed[1][0].message).toEqual(
'`cenc:pssh` is not a valid base64 string: "AA!BCC"',
);
});
});