Skip to content

Commit

Permalink
feat(frontend): add wizard layout and architecture (#3521)
Browse files Browse the repository at this point in the history
* feat(frontend): add wizard layout and architecture

* add home icon

* fix cypress tests
  • Loading branch information
jorgeepc authored Jan 12, 2024
1 parent dc5f609 commit 40e6e84
Show file tree
Hide file tree
Showing 25 changed files with 410 additions and 70 deletions.
2 changes: 1 addition & 1 deletion web/cypress/e2e/Home/CancelTest.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
describe('Cancel Create test', () => {
beforeEach(() => cy.visit('/'));
beforeEach(() => cy.visit('/tests'));

it('should cancel a create test flow', () => {
cy.openTestCreationModal();
Expand Down
2 changes: 1 addition & 1 deletion web/cypress/e2e/Home/CreateTest.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ describe('Create test', () => {
beforeEach(() => {
cy.interceptHomeApiCall();
cy.enableDemo();
cy.visit('/');
cy.visit('/tests');
});
afterEach(() => cy.deleteTest(true));

Expand Down
2 changes: 1 addition & 1 deletion web/cypress/e2e/Home/CreateTestFromCurl.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {POKEMON_HTTP_ENDPOINT} from '../constants/Test';
describe('Create test from CURL Command', () => {
beforeEach(() => {
cy.enableDemo();
cy.visit('/');
cy.visit('/tests');
});

it('should create a basic GET test', () => {
Expand Down
2 changes: 1 addition & 1 deletion web/cypress/e2e/Home/CreateTestFromPostman.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
describe('Create test from Postman Collection', () => {
beforeEach(() => {
cy.enableDemo();
cy.visit('/');
cy.visit('/tests');
});

it('should create a basic GET test', () => {
Expand Down
2 changes: 1 addition & 1 deletion web/cypress/e2e/Home/CreateTestWithAuthentication.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ describe('Create test with authentication', () => {
beforeEach(() => {
cy.interceptHomeApiCall();
cy.enableDemo();
cy.visit('/');
cy.visit('/tests');
});

it('should create a basic GET test with api key authentication method', () => {
Expand Down
4 changes: 2 additions & 2 deletions web/cypress/e2e/Home/ShowTestList.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
describe('Home', () => {
beforeEach(() => cy.visit('/'));
beforeEach(() => cy.visit('/tests'));

it('should render the layout', () => {
cy.get('[data-cy=menu-link]').should('be.visible');
Expand All @@ -12,7 +12,7 @@ describe('Home', () => {

it('should run a test from the home page', () => {
cy.createTest();
cy.visit('/');
cy.visit('/tests');
cy.get('[data-cy^=test-run-button]:not([data-cy*=button-00])', {timeout: 10000}).first().click();
cy.location('href').should('match', /\/test\/.*/i);
cy.deleteTest();
Expand Down
2 changes: 1 addition & 1 deletion web/cypress/e2e/VariableSet/VariableSet.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ describe('VariableSets', () => {
it.only('should create a test using variables from variableSet', () => {
createVariableSet(variableSet1);

cy.visit('/');
cy.visit('/tests');
cy.interceptHomeApiCall();

// Select created variableSet
Expand Down
12 changes: 6 additions & 6 deletions web/cypress/support/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ export const getComparatorListId = (number: number) => `#assertion-form_assertio
export const getValueFromList = (number: number) => `.cm-tooltip-autocomplete li:nth-child(${number})`;

Cypress.Commands.add('createMultipleTestRuns', (id: string, count: number) => {
cy.visit('/');
cy.visit('/tests');

for (let i = 0; i < count; i += 1) {
cy.get(`[data-cy=test-run-button-${id}]`).click();
cy.matchTestRunPageUrl();

cy.visit('/');
cy.visit('/tests');
}
});

Expand All @@ -33,7 +33,7 @@ Cypress.Commands.add('deleteTest', (shouldIntercept = false) => {
if (shouldIntercept) {
cy.interceptHomeApiCall();
}
cy.visit(`/`);
cy.visit('/tests');
cy.wait('@testList');
cy.get('[data-cy=test-list]').should('exist', {timeout: 10000});
cy.get(`[data-cy=test-actions-button-${localTestId}]`, {timeout: 10000}).should('be.visible');
Expand Down Expand Up @@ -195,7 +195,7 @@ Cypress.Commands.add('createTest', () => {
cy.enableDemo();
cy.interceptHomeApiCall();
cy.clearLocalStorage();
cy.visit('/');
cy.visit('/tests');
cy.clearLocalStorage();
cy.openTestCreationModal();
cy.clickNextOnCreateTestWizard();
Expand Down Expand Up @@ -260,7 +260,7 @@ Cypress.Commands.add('deleteTestSuite', () => {
});

Cypress.Commands.add('enableDemo', () => {
cy.visit(`/settings`);
cy.visit('/settings');

cy.get('[id*=tab-demo]').click();
cy.get('#demo_pokeshop_enabled').then(element => {
Expand All @@ -272,6 +272,6 @@ Cypress.Commands.add('enableDemo', () => {
cy.get('[data-cy=demo-form-save-button]').click();
}

cy.visit(`/`);
cy.visit('/tests');
});
});
119 changes: 64 additions & 55 deletions web/src/components/Layout/Layout.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {AppstoreAddOutlined, ClusterOutlined, GlobalOutlined, SettingOutlined} from '@ant-design/icons';
import {AppstoreAddOutlined, ClusterOutlined, GlobalOutlined, HomeOutlined, SettingOutlined} from '@ant-design/icons';
import {Menu} from 'antd';
import {Outlet, useLocation} from 'react-router-dom';

Expand All @@ -14,6 +14,7 @@ import VariableSetProvider from 'providers/VariableSet';
import {useSettingsValues} from 'providers/SettingsValues/SettingsValues.provider';
import MissingVariablesModalProvider from 'providers/MissingVariablesModal/MissingVariablesModal.provider';
import NotificationProvider from 'providers/Notification/Notification.provider';
import WizardProvider from 'providers/Wizard';
import {ConfigMode} from 'types/DataStore.types';
import * as S from './Layout.styled';
import MenuBottom from './MenuBottom';
Expand All @@ -27,18 +28,24 @@ interface IProps {
const menuItems = [
{
key: '0',
icon: <HomeOutlined />,
label: <Link to="/">Home</Link>,
path: '/',
},
{
key: '1',
icon: <ClusterOutlined />,
label: <Link to="/">Tests</Link>,
label: <Link to="/tests">Tests</Link>,
path: '/tests',
},
{
key: '1',
key: '2',
icon: <AppstoreAddOutlined />,
label: <Link to="/testsuites">Test Suites</Link>,
path: '/testsuites',
},
{
key: '2',
key: '3',
icon: <GlobalOutlined />,
label: <Link to="/variablesets">Variable Sets</Link>,
path: '/variablesets',
Expand All @@ -62,61 +69,63 @@ const Layout = ({hasMenu = false}: IProps) => {

return (
<NotificationProvider>
<MissingVariablesModalProvider>
<FileViewerModalProvider>
<ConfirmationModalProvider>
<VariableSetProvider>
<GuidedTourProvider>
<CreateTestProvider>
<S.Layout hasSider>
{hasMenu && (
<S.Sider width={256}>
<S.LogoContainer>
<Link to="/">
<img alt="Tracetest logo" src={logoAsset} />
</Link>
</S.LogoContainer>
<WizardProvider>
<MissingVariablesModalProvider>
<FileViewerModalProvider>
<ConfirmationModalProvider>
<VariableSetProvider>
<GuidedTourProvider>
<CreateTestProvider>
<S.Layout hasSider>
{hasMenu && (
<S.Sider width={256}>
<S.LogoContainer>
<Link to="/">
<img alt="Tracetest logo" src={logoAsset} />
</Link>
</S.LogoContainer>

<S.SiderContent>
<S.MenuContainer>
<Menu
defaultSelectedKeys={[
menuItems.findIndex(value => value.path === pathname).toString() || '0',
]}
items={menuItems}
mode="inline"
theme="dark"
/>
</S.MenuContainer>
<S.SiderContent>
<S.MenuContainer>
<Menu
defaultSelectedKeys={[
menuItems.findIndex(value => value.path === pathname).toString() || '0',
]}
items={menuItems}
mode="inline"
theme="dark"
/>
</S.MenuContainer>

<S.MenuContainer>
<MenuBottom />
<Menu
defaultSelectedKeys={[
footerMenuItems.findIndex(value => value.path === pathname).toString() || '0',
]}
items={footerMenuItems}
mode="inline"
theme="dark"
/>
</S.MenuContainer>
</S.SiderContent>
</S.Sider>
)}
<S.MenuContainer>
<MenuBottom />
<Menu
defaultSelectedKeys={[
footerMenuItems.findIndex(value => value.path === pathname).toString() || '0',
]}
items={footerMenuItems}
mode="inline"
theme="dark"
/>
</S.MenuContainer>
</S.SiderContent>
</S.Sider>
)}

<S.Layout>
<Header hasLogo={!hasMenu} isNoTracingMode={isNoTracingMode && !isLoading} />
<S.Content $hasMenu={hasMenu}>
<Outlet />
</S.Content>
<S.Layout>
<Header hasLogo={!hasMenu} isNoTracingMode={isNoTracingMode && !isLoading} />
<S.Content $hasMenu={hasMenu}>
<Outlet />
</S.Content>
</S.Layout>
</S.Layout>
</S.Layout>
</CreateTestProvider>
</GuidedTourProvider>
</VariableSetProvider>
</ConfirmationModalProvider>
</FileViewerModalProvider>
</MissingVariablesModalProvider>
</CreateTestProvider>
</GuidedTourProvider>
</VariableSetProvider>
</ConfirmationModalProvider>
</FileViewerModalProvider>
</MissingVariablesModalProvider>
</WizardProvider>
</NotificationProvider>
);
};
Expand Down
4 changes: 3 additions & 1 deletion web/src/components/Router/Router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import TestSuiteRunOverview from 'pages/TestSuiteRunOverview';
import TestSuiteRunAutomate from 'pages/TestSuiteRunAutomate';
import AutomatedTestRun from 'pages/AutomatedTestRun';
import CreateTest from 'pages/CreateTest';
import Wizard from 'pages/Wizard';
import {useDashboard} from 'providers/Dashboard/Dashboard.provider';

const Router = () => {
Expand All @@ -20,7 +21,8 @@ const Router = () => {
return (
<Routes>
<Route element={<Layout hasMenu />}>
<Route path="/" element={<Home />} />
<Route path="/" element={<Wizard />} />
<Route path="/tests" element={<Home />} />
<Route path="/testsuites" element={<TestSuites />} />
<Route path="/variablesets" element={<VariableSet />} />
<Route path="/settings" element={<Settings />} />
Expand Down
17 changes: 17 additions & 0 deletions web/src/components/Wizard/Header/Header.styled.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {Typography} from 'antd';
import styled from 'styled-components';

export const Container = styled.div`
padding: 16px;
border-bottom: 1px solid ${({theme}) => theme.color.border};
`;

export const Title = styled(Typography.Title)`
&& {
margin-bottom: 12px;
}
`;

export const Text = styled(Typography.Text)`
font-size: ${({theme}) => theme.size.sm};
`;
23 changes: 23 additions & 0 deletions web/src/components/Wizard/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import {Progress} from 'antd';
import * as S from './Header.styled';

function calculatePercent(activeStep: number, totalSteps: number) {
return Math.round((activeStep / totalSteps) * 100);
}

interface IProps {
activeStep: number;
totalSteps: number;
}

const Header = ({activeStep, totalSteps}: IProps) => (
<S.Container>
<S.Title>🚀 Setup guide</S.Title>
<Progress percent={calculatePercent(activeStep, totalSteps)} showInfo={false} />
<S.Text>
{activeStep} of {totalSteps} steps completed
</S.Text>
</S.Container>
);

export default Header;
2 changes: 2 additions & 0 deletions web/src/components/Wizard/Header/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// eslint-disable-next-line no-restricted-exports
export {default} from './Header';
19 changes: 19 additions & 0 deletions web/src/components/Wizard/StepFactory/StepFactory.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import {IWizardStep, IWizardStepComponentMap} from 'types/Wizard.types';

const StepComponentMap: IWizardStepComponentMap = {
Step1: () => <div>Step 1</div>,
Step2: () => <div>Step 1</div>,
Step3: () => <div>Step 3</div>,
};

interface IProps {
step: IWizardStep;
}

const StepFactory = ({step: {component}}: IProps) => {
const Step = StepComponentMap[component];

return <Step />;
};

export default StepFactory;
2 changes: 2 additions & 0 deletions web/src/components/Wizard/StepFactory/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// eslint-disable-next-line no-restricted-exports
export {default} from './StepFactory';
24 changes: 24 additions & 0 deletions web/src/components/Wizard/Steps/StepTab.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import {CheckOutlined} from '@ant-design/icons';
import {IWizardStep} from 'types/Wizard.types';
import * as S from './Steps.styled';

interface IProps {
index: number;
isActive: boolean;
step: IWizardStep;
}

const StepTab = ({index, isActive, step}: IProps) => (
<S.StepTabContainer $isActive={isActive}>
{step.status === 'complete' ? (
<S.StepTabCheck>
<CheckOutlined />
</S.StepTabCheck>
) : (
<S.StepTabNumber>{index}</S.StepTabNumber>
)}
<S.StepTabTitle $isActive={isActive}>{step.name}</S.StepTabTitle>
</S.StepTabContainer>
);

export default StepTab;
Loading

0 comments on commit 40e6e84

Please sign in to comment.