From 2e4f55707db1755a94145df84f268895fa507d7c Mon Sep 17 00:00:00 2001 From: Mateusz Kwasniewski Date: Tue, 20 Jun 2023 11:34:27 +0200 Subject: [PATCH] feat: store playground settings in local storage (#4012) --- .../Playground/AdvancedPlayground.test.tsx | 64 +++++++++++++++++++ .../Playground/AdvancedPlayground.tsx | 50 +++++++++++---- .../PlaygroundEnvironmentDiffTable.test.tsx | 2 +- 3 files changed, 101 insertions(+), 15 deletions(-) create mode 100644 frontend/src/component/playground/Playground/AdvancedPlayground.test.tsx diff --git a/frontend/src/component/playground/Playground/AdvancedPlayground.test.tsx b/frontend/src/component/playground/Playground/AdvancedPlayground.test.tsx new file mode 100644 index 0000000000..e0927bc9b6 --- /dev/null +++ b/frontend/src/component/playground/Playground/AdvancedPlayground.test.tsx @@ -0,0 +1,64 @@ +import { screen } from '@testing-library/react'; +import { render } from 'utils/testRenderer'; +import { UIProviderContainer } from '../../providers/UIProvider/UIProviderContainer'; +import AdvancedPlayground from './AdvancedPlayground'; +import { createLocalStorage } from 'utils/createLocalStorage'; + +const testComponent = ( + + ( +
+
+ {JSON.stringify(props.projects)} +
+
+ {JSON.stringify(props.environments)} +
+
{JSON.stringify(props.context)}
+
+ )} + /> +
+); + +afterEach(() => { + const { setValue } = createLocalStorage('AdvancedPlayground:v1', {}); + setValue({}); +}); + +test('should fetch initial form data from local storage', async () => { + const { setValue } = createLocalStorage('AdvancedPlayground:v1', {}); + setValue({ + projects: ['projectA', 'projectB'], + environments: ['development', 'production'], + context: { userId: '1' }, + }); + + render(testComponent); + + expect(screen.getByText('Unleash playground')).toBeInTheDocument(); + expect(screen.getByText('["projectA","projectB"]')).toBeInTheDocument(); + expect( + screen.getByText('["development","production"]') + ).toBeInTheDocument(); + expect(screen.getByText('{"userId":"1"}')).toBeInTheDocument(); +}); + +test('should fetch initial form data from url', async () => { + const { setValue } = createLocalStorage('AdvancedPlayground:v1', {}); + setValue({ + projects: ['projectA', 'projectB'], + environments: ['development', 'production'], + context: { userId: '1' }, + }); + + render(testComponent, { + route: '/playground?context=customContext&environments=customEnv&projects=urlProject&sort=name', + }); + + expect(screen.getByText('Unleash playground')).toBeInTheDocument(); + expect(screen.getByText('["urlProject"]')).toBeInTheDocument(); + expect(screen.getByText('["customEnv"]')).toBeInTheDocument(); + expect(screen.getByText('"customContext"')).toBeInTheDocument(); +}); diff --git a/frontend/src/component/playground/Playground/AdvancedPlayground.tsx b/frontend/src/component/playground/Playground/AdvancedPlayground.tsx index ff1142a930..963f4472b7 100644 --- a/frontend/src/component/playground/Playground/AdvancedPlayground.tsx +++ b/frontend/src/component/playground/Playground/AdvancedPlayground.tsx @@ -1,6 +1,6 @@ import { FormEventHandler, useEffect, useState, VFC } from 'react'; import { useSearchParams } from 'react-router-dom'; -import { Box, Paper, useMediaQuery, useTheme } from '@mui/material'; +import { Box, Paper, useTheme } from '@mui/material'; import { PageContent } from 'component/common/PageContent/PageContent'; import { PageHeader } from 'component/common/PageHeader/PageHeader'; import useToast from 'hooks/useToast'; @@ -20,28 +20,48 @@ import { PlaygroundGuidancePopper } from './PlaygroundGuidancePopper/PlaygroundG import Loader from '../../common/Loader/Loader'; import { AdvancedPlaygroundResultsTable } from './AdvancedPlaygroundResultsTable/AdvancedPlaygroundResultsTable'; import { AdvancedPlaygroundResponseSchema } from 'openapi'; +import { createLocalStorage } from 'utils/createLocalStorage'; + +export const AdvancedPlayground: VFC<{ + FormComponent?: typeof PlaygroundForm; +}> = ({ FormComponent = PlaygroundForm }) => { + const defaultSettings: { + projects: string[]; + environments: string[]; + context?: string; + } = { projects: [], environments: [] }; + const { value, setValue } = createLocalStorage( + 'AdvancedPlayground:v1', + defaultSettings + ); -export const AdvancedPlayground: VFC<{}> = () => { const { environments: availableEnvironments } = useEnvironments(); const theme = useTheme(); const matches = true; - const [environments, setEnvironments] = useState([]); - const [projects, setProjects] = useState([]); - const [context, setContext] = useState(); + const [environments, setEnvironments] = useState( + value.environments + ); + const [projects, setProjects] = useState(value.projects); + const [context, setContext] = useState(value.context); const [results, setResults] = useState< AdvancedPlaygroundResponseSchema | undefined >(); const { setToastData } = useToast(); const [searchParams, setSearchParams] = useSearchParams(); + const searchParamsLength = Array.from(searchParams.entries()).length; const { evaluateAdvancedPlayground, loading } = usePlaygroundApi(); useEffect(() => { - setEnvironments([resolveDefaultEnvironment(availableEnvironments)]); + if (environments.length === 0) { + setEnvironments([resolveDefaultEnvironment(availableEnvironments)]); + } }, [availableEnvironments]); useEffect(() => { - loadInitialValuesFromUrl(); + if (searchParamsLength > 0) { + loadInitialValuesFromUrl(); + } }, []); const loadInitialValuesFromUrl = () => { @@ -129,12 +149,14 @@ export const AdvancedPlayground: VFC<{}> = () => { const onSubmit: FormEventHandler = async event => { event.preventDefault(); - await evaluatePlaygroundContext( - environments, - projects, - context, - setURLParameters - ); + await evaluatePlaygroundContext(environments, projects, context, () => { + setURLParameters(); + setValue({ + environments, + projects, + context, + }); + }); }; const setURLParameters = () => { @@ -201,7 +223,7 @@ export const AdvancedPlayground: VFC<{}> = () => { top: 0, }} > - { +test('should render environment diff table', async () => { render(