Skip to content

Commit

Permalink
chore: include error in onResult, change enums to string, and update …
Browse files Browse the repository at this point in the history
…tests
  • Loading branch information
yapyuyou committed Apr 21, 2024
1 parent 04e6ef7 commit 539f7e9
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 35 deletions.
2 changes: 1 addition & 1 deletion example/application/container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ const DocumentsContainer = styled.div`
const Viewer: React.FunctionComponent<ViewerProps> = ({ document }): React.ReactElement => {
const renderMethod = document.document.renderMethod?.find((method) => method.type === SVG_RENDERER_TYPE);
const isSvg = renderMethod?.type === SVG_RENDERER_TYPE;
const svgRef = useRef<HTMLIFrameElement>(null);
const svgRef = useRef<HTMLImageElement>(null);

const [toFrame, setToFrame] = useState<HostActionsHandler>();
const [height, setHeight] = useState(250);
Expand Down
17 changes: 14 additions & 3 deletions src/components/renderer/SvgRenderer.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Disable the spyOn check due to known issues with mocking fetch in jsDom env
// https://stackoverflow.com/questions/74945569/cannot-access-built-in-node-js-fetch-function-from-jest-tests
import { render } from "@testing-library/react";
import { SvgRenderer } from "./SvgRenderer";
import { DisplayResult, SvgRenderer } from "./SvgRenderer";
import fs from "fs";
import { Blob } from "buffer";
import React from "react";
Expand Down Expand Up @@ -105,12 +105,16 @@ describe("svgRenderer component", () => {
it("should render SvgModifiedTemplate when SVG at URL has been tampered with", async () => {
global.fetch = jest.fn().mockResolvedValue(tamperedMockResponse);
const svgRef = React.createRef<HTMLImageElement>();
const mockHandleResult = jest.fn();

const { findByTestId } = render(<SvgRenderer document={v4WithSvgUrlAndDigestMultibase} ref={svgRef} />);
const { findByTestId } = render(
<SvgRenderer document={v4WithSvgUrlAndDigestMultibase} ref={svgRef} onResult={mockHandleResult} />
);

const defaultTemplate = await findByTestId("default-template");
expect(defaultTemplate.textContent).toContain("The remote content for this document has been modified");
expect(defaultTemplate.textContent).toContain(`URL: “http://mockbucket.com/static/svg_test.svg”`);
expect(mockHandleResult).toHaveBeenCalledWith(DisplayResult.DIGEST_ERROR, undefined);
});

it("should render default template when document.RenderMethod is undefined", async () => {
Expand All @@ -128,12 +132,19 @@ describe("svgRenderer component", () => {
it("should render connection error template when SVG cannot be fetched", async () => {
global.fetch = jest.fn().mockResolvedValue(badMockResponse);
const svgRef = React.createRef<HTMLImageElement>();
const mockHandleResult = jest.fn();

const { findByTestId } = render(<SvgRenderer document={v4WithSvgUrlAndDigestMultibase} ref={svgRef} />);
const { findByTestId } = render(
<SvgRenderer document={v4WithSvgUrlAndDigestMultibase} ref={svgRef} onResult={mockHandleResult} />
);

const defaultTemplate = await findByTestId("default-template");
expect(defaultTemplate.textContent).toContain("This document might be having loading issues");
expect(defaultTemplate.textContent).toContain(`URL: “http://mockbucket.com/static/svg_test.svg”`);
expect(mockHandleResult).toHaveBeenCalledWith(
DisplayResult.CONNECTION_ERROR,
new Error("Failed to fetch remote SVG")
);
});
});
/* eslint-enable jest/prefer-spy-on */
50 changes: 19 additions & 31 deletions src/components/renderer/SvgRenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,29 +41,25 @@ export interface SvgRendererProps {
className?: string;
// TODO: How to handle if svg fails at img? Currently it will return twice
/** An optional callback method that returns the display result */
onResult?: (result: DisplayResult) => void;
onResult?: (result: DisplayResult, err?: Error) => void;
}

/** Indicates the result of SVG rendering */
export enum DisplayResult {
OK = 0,
DEFAULT = 1,
CONNECTION_ERROR = 2,
DIGEST_ERROR = 3,
OK = "OK",
DEFAULT = "DEFAULT",
CONNECTION_ERROR = "CONNECTION_ERROR",
DIGEST_ERROR = "DIGEST_ERROR",
}

const fetchSvg = async (svgInDoc: string, abortController: AbortController) => {
try {
const response = await fetch(svgInDoc, { signal: abortController.signal });
if (!response.ok) {
throw new Error("Failed to fetch remote SVG");
}
const blob = await response.blob();
const res = await blob.arrayBuffer();
return res;
} catch (error) {
throw new Error("Failed to fetch SVG");
const response = await fetch(svgInDoc, { signal: abortController.signal });
if (!response.ok) {
throw new Error("Failed to fetch remote SVG");
}
const blob = await response.blob();
const res = await blob.arrayBuffer();
return res;
};

// As specified in - https://w3c-ccg.github.io/vc-render-method/#svgrenderingtemplate2023
Expand Down Expand Up @@ -118,8 +114,10 @@ const SvgRenderer = React.forwardRef<HTMLImageElement, SvgRendererProps>(
});
}
})
.catch(() => {
handleResult(DisplayResult.CONNECTION_ERROR);
.catch((error) => {
if ((error as Error).name !== "AbortError") {
handleResult(DisplayResult.CONNECTION_ERROR, undefined, error);
}
});
}
return () => {
Expand All @@ -128,15 +126,12 @@ const SvgRenderer = React.forwardRef<HTMLImageElement, SvgRendererProps>(
/* eslint-disable-next-line react-hooks/exhaustive-deps */
}, [document]);

const handleResult = (result: DisplayResult, svgToSet = "") => {
const handleResult = (result: DisplayResult, svgToSet = "", error?: Error) => {
setFetchedSvgData(svgToSet);
setToDisplay(result);
setTimeout(() => {
// updateIframeHeight();
if (typeof onResult === "function") {
onResult(result);
}
}, 200); // wait for 200ms before manually updating the height
if (typeof onResult === "function") {
onResult(result, error);
}
};

const renderTemplate = (template: string, document: any) => {
Expand All @@ -147,13 +142,6 @@ const SvgRenderer = React.forwardRef<HTMLImageElement, SvgRendererProps>(

const compiledSvgData = `data:image/svg+xml,${encodeURIComponent(renderTemplate(svgFetchedData, document))}`;

// const updateIframeHeight = () => {
// if (svgRef.current) {
// const contentHeight = svgRef.current?.contentDocument?.body?.offsetHeight;
// svgRef.current.style.height = `${contentHeight}px`;
// }
// };

switch (toDisplay) {
case DisplayResult.DEFAULT:
return <NoTemplate document={document} handleObfuscation={() => null} />;
Expand Down

0 comments on commit 539f7e9

Please sign in to comment.