From 7bebdaa298dcfa1f130d9d7410daeb9f96b4464d Mon Sep 17 00:00:00 2001 From: Lucas Date: Mon, 18 Mar 2024 14:36:52 +0800 Subject: [PATCH] test: add SvgRenderer test --- package.json | 2 +- src/components/renderer/SvgRenderer.test.tsx | 72 +++++++++++++++++++ src/components/renderer/SvgRenderer.tsx | 21 ++++-- .../renderer/fixtures/example_cert.svg | 12 ++++ 4 files changed, 100 insertions(+), 7 deletions(-) create mode 100644 src/components/renderer/SvgRenderer.test.tsx create mode 100644 src/components/renderer/fixtures/example_cert.svg diff --git a/package.json b/package.json index ef62d44..e5ecc3c 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "lint:fix": "npm run lint -- --fix", "storybook": "storybook dev -p 6006", "storybook:build": "storybook build -o docs", - "test": "jest --ci", + "test": "jest --ci SvgRenderer", "test:coverage": "npm run test -- --coverage", "test:watch": "npm run test -- --watch", "semantic-release": "semantic-release" diff --git a/src/components/renderer/SvgRenderer.test.tsx b/src/components/renderer/SvgRenderer.test.tsx new file mode 100644 index 0000000..c202bfa --- /dev/null +++ b/src/components/renderer/SvgRenderer.test.tsx @@ -0,0 +1,72 @@ +// Valid / Invalid urls +// v4 with Svg url with response and multibase +// v4 with Svg data and multibase +// v4 with Svg url with tampered response and no multibase +// v4 with Svg url with bad response and multibase +// v4 with Svg url with tampered response and multibase +// v4 with tampered Svg data +// v2 with Svg url with response and multibase + +// import React from "react"; +import { v4 } from "@govtechsg/open-attestation"; +import { render } from "@testing-library/react"; +import { SvgRenderer } from "./SvgRenderer"; +import fs from "fs"; +// import { UnsupportedRenderer } from "./UnsupportedRenderer"; + +const v4WithSvgUrlAndDigestMultibase = { + // TODO: Update type to v4.OpenAttestationDocument + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json", + ], + issuer: { + id: "did:ethr:0xB26B4941941C51a4885E5B7D3A1B861E54405f90", + type: "OpenAttestationIssuer", + name: "Government Technology Agency of Singapore (GovTech)", + identityProof: { identityProofType: v4.IdentityProofType.DNSDid, identifier: "example.openattestation.com" }, + }, + credentialStatus: { type: "OpenAttestationCredentialStatus", credentialStatusType: v4.CredentialStatusType.None }, + renderMethod: { + id: "http://mockbucket.com/static/svg_test.svg", + type: "SvgRenderingTemplate2023", + name: "SVG Certificate", + digestMultibase: "z2Z98fDGXMKgjxZpWNFBE2c8fRPH5dQ9Zc2Y15vDHLHdm", + url: "https://ignorethisurlthisisjusttopasstheschemacheck.com", + renderMethodType: v4.RenderMethodType.EmbeddedRenderer, + }, + credentialSubject: { + id: "urn:uuid:a013fb9d-bb03-4056-b696-05575eceaf42", + type: ["SvgExample"], + course: { name: "SVG Basics Workshop", fromDate: "01/01/2024", endDate: "16/01/2024" }, + recipient: { name: "TAN CHEN CHEN" }, + }, +}; + +describe("component SvgRenderer with 200 response", () => { + // const mockBlob = jest.fn().mockResolvedValueOnce({ + // arrayBuffer: jest.fn().mockResolvedValueOnce("your array buffer data"), + // }); + + const mockSvg = fs.readFileSync("./src/components/renderer/fixtures/example_cert.svg"); + const mockBlob = jest.fn().mockResolvedValue(new Blob([mockSvg], { type: "image/svg+xml" })); + const mockResponse = { blob: mockBlob }; + global.fetch = jest.fn().mockResolvedValueOnce(mockResponse); + + it("should render correctly", () => { + const svgRef = { + current: null, + }; + + const svgUrl = v4WithSvgUrlAndDigestMultibase.renderMethod.id; + + const { getByText } = render( + + ); + // const { getByText } = render( + // + // ); + // expect(getByText("Rendering of this type of attachment is not supported.")).toBeDefined(); + // expect(getByText("Please check your mime-type: application/epub+zip")).toBeDefined(); + }); +}); diff --git a/src/components/renderer/SvgRenderer.tsx b/src/components/renderer/SvgRenderer.tsx index df5a4ad..167f5ba 100644 --- a/src/components/renderer/SvgRenderer.tsx +++ b/src/components/renderer/SvgRenderer.tsx @@ -1,7 +1,9 @@ import { OpenAttestationDocument, v4 } from "@govtechsg/open-attestation"; -import { base58btc } from "multiformats/bases/base58"; -import { Digest } from "multiformats/dist/src/hashes/digest"; -import { sha256 } from "multiformats/hashes/sha2"; +import { bases, hashes, digest } from "multiformats/basics"; +// import { basics } from "multiformats" +// import { Digest } from "multiformats/hashes/digest"; +// import { sha256 } from "multiformats/hashes/sha2"; +// import { base58btc } from "multiformats/bases/base58"; import React, { CSSProperties, FunctionComponent, useEffect, useState } from "react"; import { renderToStaticMarkup } from "react-dom/server"; import { ConnectionFailureTemplate } from "../../DefaultTemplate"; @@ -16,6 +18,7 @@ interface SvgRendererProps { className?: string; sandbox?: string; onConnected?: () => void; // Optional call method to call once svg is loaded + useWithoutV4?: boolean; } export const SvgRenderer: FunctionComponent = ({ svgOrUrl, @@ -25,12 +28,18 @@ export const SvgRenderer: FunctionComponent = ({ className, sandbox = "allow-same-origin", onConnected, + useWithoutV4 = false, }) => { const [buffer, setBuffer] = useState(); const [svgData, setSvgData] = useState(""); const [isError, setIsError] = useState(false); const [source, setSource] = useState(""); - const docAsAny = document as any; // TODO: update type to v4.OpenAttestationDocument + let docAsAny: any; + if (useWithoutV4) { + docAsAny = document as any; + } else { + docAsAny = document as any; // TODO: update type to v4.OpenAttestationDocument + } // 1. Fetch svg data from url if needed, if not directly proceed to checksum useEffect(() => { @@ -67,9 +76,9 @@ export const SvgRenderer: FunctionComponent = ({ const text = new TextDecoder().decode(svgUint8Array); if (digestMultibaseInDoc) { - const shaDigest = sha256.digest(svgUint8Array) as Promise>; + const shaDigest = hashes.sha256.digest(svgUint8Array) as Promise>; shaDigest.then((res: any) => { - const recomputedDigestMultibase = base58btc.encode(res.digest); + const recomputedDigestMultibase = bases.base58btc.encode(res.digest); console.log(`Original checksum is`, digestMultibaseInDoc); console.log(`Recomputed checksum is`, recomputedDigestMultibase); if (recomputedDigestMultibase === digestMultibaseInDoc) { diff --git a/src/components/renderer/fixtures/example_cert.svg b/src/components/renderer/fixtures/example_cert.svg new file mode 100644 index 0000000..33f2a81 --- /dev/null +++ b/src/components/renderer/fixtures/example_cert.svg @@ -0,0 +1,12 @@ + + + + + +CERTIFICATEOF COMPLETION +awarded to +{{recipient.name}} +for successfully completing +{{course.name}}{{course.fromDate}} - {{course.endDate}} + +