From 6777d04f30fffbe63352dbb5ec09089bcfaee15b Mon Sep 17 00:00:00 2001 From: wadjih-bencheikh18 Date: Tue, 3 Jan 2023 01:43:46 +0100 Subject: [PATCH 1/3] feat: implement createSVG to render react-plot svg in server-side --- src/createSVG.ts | 7 +++++++ src/index.ts | 2 ++ tests/serverside.test.tsx | 15 +++++++++++---- tests/utils.tsx | 40 ++++++++++++++++++++++++++++++++++----- 4 files changed, 55 insertions(+), 9 deletions(-) create mode 100644 src/createSVG.ts diff --git a/src/createSVG.ts b/src/createSVG.ts new file mode 100644 index 00000000..89f2c13b --- /dev/null +++ b/src/createSVG.ts @@ -0,0 +1,7 @@ +import { createElement } from 'react'; +import { renderToString } from 'react-dom/server'; +import { PlotObject, PlotObjectProps } from './components/PlotObject'; +export function createSVG(param: PlotObjectProps) { + const plot = createElement(PlotObject, param); + return renderToString(plot); +} diff --git a/src/index.ts b/src/index.ts index 7073e29b..a940e0fa 100644 --- a/src/index.ts +++ b/src/index.ts @@ -38,3 +38,5 @@ export { usePlotControls, usePlotEvents, } from './contexts/plotController/plotControllerContext'; + +export * from './createSVG'; diff --git a/tests/serverside.test.tsx b/tests/serverside.test.tsx index 811dacf3..8840b044 100644 --- a/tests/serverside.test.tsx +++ b/tests/serverside.test.tsx @@ -1,8 +1,15 @@ import { test, expect } from '@playwright/experimental-ct-react'; -import { ServerSide } from './utils'; +import { InfraredPlotTest, ServerSide } from './utils'; test('should render a plot in server-side mode', async ({ mount }) => { - const plot = await mount(); - const html = await plot.innerHTML(); - expect(html).toContain('svg'); + const serverPlot = await mount(); + const clientPlot = await mount(); + const ServerHtml = await serverPlot.innerHTML(); + const ClientHtml = await clientPlot.innerHTML(); + expect(ServerHtml).toBe(ClientHtml); + + // compare screen shots + const serverImage = await serverPlot.screenshot(); + const clientImage = await clientPlot.screenshot(); + expect(serverImage).toStrictEqual(clientImage); }); diff --git a/tests/utils.tsx b/tests/utils.tsx index e6069be9..8d785f94 100644 --- a/tests/utils.tsx +++ b/tests/utils.tsx @@ -1,7 +1,8 @@ -import { ReactNode, useState } from 'react'; -import { renderToStaticMarkup } from 'react-dom/server'; +import { ReactNode, useState, useEffect } from 'react'; +import { hydrate } from 'react-dom'; +import { PlotObject, PlotObjectPlot } from 'react-plot'; -import { Annotations, Plot, ScatterSeries } from '../src'; +import { Annotations, createSVG, Plot, ScatterSeries } from '../src'; import { Arrow } from '../src/components/Annotations/Arrow'; import { DirectedEllipse } from '../src/components/Annotations/DirectedEllipse'; import infrared from '../stories/data/infrared.json'; @@ -14,9 +15,38 @@ interface ChildrenProps { export function DefaultPlotTest({ children }: ChildrenProps) { return {children}; } +const plot: PlotObjectPlot = { + dimensions: DEFAULT_PLOT_CONFIG, + axes: [ + { + type: 'main', + position: 'bottom', + }, + { + type: 'main', + position: 'left', + }, + ], + content: [ + { + type: 'line', + data: infrared, + }, + ], +}; export function ServerSide() { - const html = renderToStaticMarkup(); - return
; + const [result, setResult] = useState(null); + + useEffect(() => { + const html = createSVG({ plot }); + const rootElement = document.getElementById('root'); + if (rootElement === null) throw new Error('Root element not found'); + rootElement.innerHTML = html; + const result = hydrate(, rootElement); + setResult(result); + }); + + return result; } export function InfraredPlotTest({ children }: ChildrenProps) { return ( From 0b72081d771ade2ae277e3fb78cbdbcf6cb0aa0a Mon Sep 17 00:00:00 2001 From: wadjih-bencheikh18 Date: Tue, 3 Jan 2023 02:23:48 +0100 Subject: [PATCH 2/3] fix: eslint --- .eslintrc.yml | 1 + src/createSVG.ts | 2 ++ tests/serverside.test.tsx | 1 + tests/utils.tsx | 12 +++++++++--- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.eslintrc.yml b/.eslintrc.yml index f65f43d3..70a0b06e 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -4,3 +4,4 @@ extends: rules: '@typescript-eslint/no-dynamic-delete': off 'import/namespace': off + 'jest/no-standalone-expect': off diff --git a/src/createSVG.ts b/src/createSVG.ts index 89f2c13b..58512250 100644 --- a/src/createSVG.ts +++ b/src/createSVG.ts @@ -1,6 +1,8 @@ import { createElement } from 'react'; import { renderToString } from 'react-dom/server'; + import { PlotObject, PlotObjectProps } from './components/PlotObject'; + export function createSVG(param: PlotObjectProps) { const plot = createElement(PlotObject, param); return renderToString(plot); diff --git a/tests/serverside.test.tsx b/tests/serverside.test.tsx index 8840b044..4f606acc 100644 --- a/tests/serverside.test.tsx +++ b/tests/serverside.test.tsx @@ -1,4 +1,5 @@ import { test, expect } from '@playwright/experimental-ct-react'; + import { InfraredPlotTest, ServerSide } from './utils'; test('should render a plot in server-side mode', async ({ mount }) => { diff --git a/tests/utils.tsx b/tests/utils.tsx index 8d785f94..a1da49a3 100644 --- a/tests/utils.tsx +++ b/tests/utils.tsx @@ -1,8 +1,14 @@ import { ReactNode, useState, useEffect } from 'react'; import { hydrate } from 'react-dom'; -import { PlotObject, PlotObjectPlot } from 'react-plot'; -import { Annotations, createSVG, Plot, ScatterSeries } from '../src'; +import { + PlotObject, + PlotObjectPlot, + Annotations, + createSVG, + Plot, + ScatterSeries, +} from '../src'; import { Arrow } from '../src/components/Annotations/Arrow'; import { DirectedEllipse } from '../src/components/Annotations/DirectedEllipse'; import infrared from '../stories/data/infrared.json'; @@ -44,7 +50,7 @@ export function ServerSide() { rootElement.innerHTML = html; const result = hydrate(, rootElement); setResult(result); - }); + }, []); return result; } From 3524084b1454c873b73fed7cfc1465001eee264d Mon Sep 17 00:00:00 2001 From: wadjih-bencheikh18 Date: Tue, 3 Jan 2023 02:30:21 +0100 Subject: [PATCH 3/3] fix: eslint error --- tests/utils.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/utils.tsx b/tests/utils.tsx index a1da49a3..682bc725 100644 --- a/tests/utils.tsx +++ b/tests/utils.tsx @@ -45,7 +45,7 @@ export function ServerSide() { useEffect(() => { const html = createSVG({ plot }); - const rootElement = document.getElementById('root'); + const rootElement = document.querySelector('root'); if (rootElement === null) throw new Error('Root element not found'); rootElement.innerHTML = html; const result = hydrate(, rootElement);