import { describe, beforeEach, it, expect, vi } from "vitest"; import type { ITNode } from "../../../../../../utils/xml-parser"; import { parseXml } from "../../../../../../utils/xml-parser"; import type IContentProtection 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 IContentProtection; const element1 = parseXml( ``, )[0] as ITNode; expect(parseContentProtection(element1)).toEqual([ { attributes: { [_variableName]: "foobar" }, children: { cencPssh: [] } }, [], ]); const element2 = parseXml(``)[0] as ITNode; 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 IContentProtection; const element = parseXml("")[0] as ITNode; 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 IContentProtection; const element1 = parseXml( '', )[0] as ITNode; 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 IContentProtection; const element = parseXml( ``, )[0] as ITNode; 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 IContentProtection; const element = parseXml( ` AABBCC AAABAC `, )[0] as ITNode; 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 IContentProtection; const element = parseXml( ` AABBCC AAABAC `, )[0] as ITNode; 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 IContentProtection; const element = parseXml( ` AA!BCC AAABAC `, )[0] as ITNode; 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"', ); }); });