Skip to content

Commit

Permalink
Merge pull request #2094 from IntersectMBO/fix/1989--mobile-cant-down…
Browse files Browse the repository at this point in the history
…load-metadata

fix(#1989): workaround for downloading metadata on iOS Safari
  • Loading branch information
MSzalowski authored Oct 1, 2024
2 parents b5384e5 + 85be603 commit 8621e64
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 16 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ changes.
### Fixed

- Add missing testIds for submitted votes [Issue 1875](https://github.com/IntersectMBO/govtool/issues/1875)
- Provide workaround for iOS for downloading metadata on iOS [Issue 1989](https://github.com/IntersectMBO/govtool/issues/1989)

### Changed

Expand Down
35 changes: 29 additions & 6 deletions govtool/frontend/src/utils/jsonUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,26 @@ import { NodeObject } from "jsonld";
* If not provided, the default name will be "data.jsonld".
*/
export const downloadJson = (json: NodeObject, fileName?: string) => {
const jsonString = `data:text/jsonld;charset=utf-8,${encodeURIComponent(
JSON.stringify(json, null, 2),
)}`;
const blob = new Blob([JSON.stringify(json, null, 2)], {
type: "application/json",
});
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = jsonString;
link.href = url;
link.download = `${fileName || "data"}.jsonld`;

link.click();
// Fallback: If iOS/Safari doesn't support `download`, open the data in a new tab
if (
navigator.userAgent.includes("Safari") &&
!navigator.userAgent.includes("Chrome")
) {
window.open(url, "_blank");
} else {
link.click();
}

document.body.removeChild(link);
URL.revokeObjectURL(url);
};

/**
Expand All @@ -30,5 +42,16 @@ export const downloadTextFile = (text: string, fileName?: string) => {
link.href = url;
link.download = `${fileName || "data"}.txt`;

link.click();
// Fallback: If iOS/Safari doesn't support `download`, open the data in a new tab
if (
navigator.userAgent.includes("Safari") &&
!navigator.userAgent.includes("Chrome")
) {
window.open(url, "_blank");
} else {
link.click();
}

document.body.removeChild(link);
URL.revokeObjectURL(url);
};
32 changes: 22 additions & 10 deletions govtool/frontend/src/utils/tests/jsonUtils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,24 @@ import { vi } from "vitest";
import { downloadJson } from "..";

describe("downloadJson", () => {
beforeEach(() => {
global.URL.createObjectURL = vi.fn(() => "mocked-url");
global.URL.revokeObjectURL = vi.fn();

// We should pass Node as an argument based on typing.
// But we are not testing this against Nodes.
/* eslint-disable @typescript-eslint/ban-ts-comment */
// @ts-expect-error
vi.spyOn(document.body, "appendChild").mockImplementation(() => undefined);
// @ts-expect-error
vi.spyOn(document.body, "removeChild").mockImplementation(() => undefined);
});

afterEach(() => {
// Restore the mocks after each test
vi.restoreAllMocks();
});

it("downloads JSON with default file name", () => {
const json = { name: "John Doe", age: 30 };
const linkMock = document.createElement("a");
Expand All @@ -12,13 +30,11 @@ describe("downloadJson", () => {

downloadJson(json);

expect(linkMock.href).toBe(
"data:text/jsonld;charset=utf-8,%7B%0A%20%20%22name%22%3A%20%22John%20Doe%22%2C%0A%20%20%22age%22%3A%2030%0A%7D",
);
expect(linkMock.href).toBe("http://localhost:3000/mocked-url");

expect(linkMock.download).toBe("data.jsonld");
expect(global.URL.createObjectURL).toHaveBeenCalled();
expect(clickMock).toHaveBeenCalled();

vi.restoreAllMocks();
});

it("downloads JSON with custom file name", () => {
Expand All @@ -31,12 +47,8 @@ describe("downloadJson", () => {

downloadJson(json, "custom");

expect(linkMock.href).toBe(
"data:text/jsonld;charset=utf-8,%7B%0A%20%20%22name%22%3A%20%22John%20Doe%22%2C%0A%20%20%22age%22%3A%2030%0A%7D",
);
expect(linkMock.href).toBe("http://localhost:3000/mocked-url");
expect(linkMock.download).toBe("custom.jsonld");
expect(clickMock).toHaveBeenCalled();

vi.restoreAllMocks();
});
});

0 comments on commit 8621e64

Please sign in to comment.