diff --git a/src/panel/components/PropView.spec.tsx b/src/panel/components/PropView.spec.tsx index 04f47c1..b62c15a 100644 --- a/src/panel/components/PropView.spec.tsx +++ b/src/panel/components/PropView.spec.tsx @@ -3,22 +3,26 @@ import { mount } from "enzyme"; import { PropView } from "./PropView"; import { useSelectedBrickContext } from "../libs/SelectedBrickContext"; import { PropList } from "./PropList"; +import { Button } from "@blueprintjs/core"; +import { DehydratedBrickInfo } from "../../shared/interfaces"; jest.mock("../libs/SelectedBrickContext"); (useSelectedBrickContext as jest.Mock).mockReturnValue({ selectedBrick: null }); -const mockEval = jest.fn((string: string, fn: Function): void => { - fn({ - info: { - properties: { - quality: "good", +const mockEval = jest.fn( + (string: string, fn: (brickInfo: DehydratedBrickInfo) => void): void => { + fn({ + info: { + properties: { + quality: "good", + }, + events: [["click", { action: "console.log" }]], }, - events: [["click", { action: "console.log" }]], - }, - repo: [], - }); -}); + repo: [], + }); + } +); (window as any).chrome = { devtools: { @@ -58,4 +62,17 @@ describe("PropView", () => { (useSelectedBrickContext as jest.Mock).mockReset(); }); + + it("should work when copy properties", () => { + const selectedBrick = { + uid: 1, + }; + (useSelectedBrickContext as jest.Mock).mockReturnValue({ selectedBrick }); + const wrapper = mount(); + document.execCommand = jest.fn().mockReturnValue(true); + document.removeEventListener = jest.fn(); + wrapper.find(Button).simulate("click"); + expect(document.execCommand).toBeCalledWith("copy"); + expect(document.removeEventListener).toHaveBeenCalled(); + }); }); diff --git a/src/panel/components/PropView.tsx b/src/panel/components/PropView.tsx index dff9808..e2f21ee 100644 --- a/src/panel/components/PropView.tsx +++ b/src/panel/components/PropView.tsx @@ -1,11 +1,25 @@ import React from "react"; -import { Tag } from "@blueprintjs/core"; +import { Tag, Button, Tooltip } from "@blueprintjs/core"; import { useSelectedBrickContext } from "../libs/SelectedBrickContext"; import { HOOK_NAME } from "../../shared/constants"; import { BrickInfo, DehydratedBrickInfo } from "../../shared/interfaces"; import { hydrate } from "../libs/hydrate"; import { PropList } from "./PropList"; +const copyToClipboard = (text: string): void => { + // istanbul ignore next + const listener = (e: ClipboardEvent) => { + e.stopPropagation(); + const clipboard = e.clipboardData; + clipboard.clearData(); + clipboard.setData("text", text); + e.preventDefault(); + }; + document.addEventListener("copy", listener); + document.execCommand("copy"); + document.removeEventListener("copy", listener); +}; + function isNotEmpty(object: any[] | Record): boolean { return object ? (Array.isArray(object) ? object : Object.keys(object)).length > 0 @@ -42,6 +56,15 @@ export function PropView(): React.ReactElement { return null; } + const handleCopyProps = () => { + try { + const propsText = JSON.stringify(brickInfo.properties, null, 2); + copyToClipboard(propsText); + } catch (error) { + // do nothing + } + }; + return (
@@ -51,6 +74,17 @@ export function PropView(): React.ReactElement {
{tag} + {key === "properties" && ( + +