From 788cc578a8608af0d4f1fea7ee3879313311d95d Mon Sep 17 00:00:00 2001 From: Lukas Harbarth Date: Mon, 19 Feb 2024 08:07:43 +0100 Subject: [PATCH] feat(vite-ts example): add routing, e2e test, theming & data fetching example (#5502) --- .storybook/components/LabelWithWrapping.tsx | 7 + .../components/ProjectTemplate.module.css | 2 +- .storybook/components/ProjectTemplate.tsx | 23 ++- .storybook/components/index.ts | 1 + docs/ProjectTemplates.mdx | 15 +- examples/vite-ts/README.md | 25 ++- examples/vite-ts/cypress.config.ts | 10 ++ examples/vite-ts/cypress/e2e/App.cy.tsx | 9 + examples/vite-ts/cypress/support/e2e.ts | 20 +++ examples/vite-ts/package-lock.json | 41 ++++- examples/vite-ts/package.json | 7 +- examples/vite-ts/public/person.png | Bin 0 -> 41336 bytes examples/vite-ts/src/App.cy.tsx | 16 +- examples/vite-ts/src/App.tsx | 44 ----- examples/vite-ts/src/AppShell.module.css | 3 + examples/vite-ts/src/AppShell.tsx | 103 ++++++++++++ examples/vite-ts/src/ToDos.module.css | 8 + examples/vite-ts/src/ToDos.tsx | 44 +++++ examples/vite-ts/src/TodoDetails.module.css | 13 ++ examples/vite-ts/src/TodoDetails.tsx | 42 +++++ examples/vite-ts/src/index.css | 3 +- examples/vite-ts/src/main.tsx | 71 +++++++- .../src/mockImplementations/mockAPIs.ts | 21 +++ .../src/mockImplementations/mockData.ts | 156 ++++++++++++++++++ templates/vite-ts/src/App.cy.tsx | 9 +- 25 files changed, 616 insertions(+), 77 deletions(-) create mode 100644 .storybook/components/LabelWithWrapping.tsx create mode 100644 examples/vite-ts/cypress/e2e/App.cy.tsx create mode 100644 examples/vite-ts/cypress/support/e2e.ts create mode 100644 examples/vite-ts/public/person.png delete mode 100644 examples/vite-ts/src/App.tsx create mode 100644 examples/vite-ts/src/AppShell.module.css create mode 100644 examples/vite-ts/src/AppShell.tsx create mode 100644 examples/vite-ts/src/ToDos.module.css create mode 100644 examples/vite-ts/src/ToDos.tsx create mode 100644 examples/vite-ts/src/TodoDetails.module.css create mode 100644 examples/vite-ts/src/TodoDetails.tsx create mode 100644 examples/vite-ts/src/mockImplementations/mockAPIs.ts create mode 100644 examples/vite-ts/src/mockImplementations/mockData.ts diff --git a/.storybook/components/LabelWithWrapping.tsx b/.storybook/components/LabelWithWrapping.tsx new file mode 100644 index 00000000000..250b5c1bd3d --- /dev/null +++ b/.storybook/components/LabelWithWrapping.tsx @@ -0,0 +1,7 @@ +import { Label, WrappingType } from '@ui5/webcomponents-react'; +import React from 'react'; + +//mdx adds a paragraph to children if added inline, this component prevents that. +export const LabelWithWrapping = ({ children }) => { + return ; +}; diff --git a/.storybook/components/ProjectTemplate.module.css b/.storybook/components/ProjectTemplate.module.css index 9fda7587cca..96149e6a258 100644 --- a/.storybook/components/ProjectTemplate.module.css +++ b/.storybook/components/ProjectTemplate.module.css @@ -1,6 +1,6 @@ .card { width: 500px; - height: 18rem; + height: 20rem; margin-block-end: 2rem; flex-shrink: 0; } diff --git a/.storybook/components/ProjectTemplate.tsx b/.storybook/components/ProjectTemplate.tsx index d81b481ca63..371ab533016 100644 --- a/.storybook/components/ProjectTemplate.tsx +++ b/.storybook/components/ProjectTemplate.tsx @@ -25,6 +25,7 @@ interface ProjectTemplatePropTypes { children: ReactNode; deprecationNotice?: string; isTemplate?: boolean; + stackBlitzHref?: string; } addCustomCSSWithScoping( @@ -33,7 +34,18 @@ addCustomCSSWithScoping( ); export function ProjectTemplate(props: ProjectTemplatePropTypes) { - const { title, subtitle, logo, logoAttribution, isTypeScript, children, href, deprecationNotice, isTemplate } = props; + const { + title, + subtitle, + logo, + logoAttribution, + isTypeScript, + children, + href, + deprecationNotice, + isTemplate, + stackBlitzHref + } = props; return ( @@ -72,10 +84,17 @@ export function ProjectTemplate(props: ProjectTemplatePropTypes) { className={classes.deprecationNotice} /> )} - View Example + {stackBlitzHref && ( + <> + | + + View in StackBlitz + + + )} {!isTemplate && ( <>
diff --git a/.storybook/components/index.ts b/.storybook/components/index.ts index 34aeb84896d..d23a2c05d41 100644 --- a/.storybook/components/index.ts +++ b/.storybook/components/index.ts @@ -5,3 +5,4 @@ export * from './Footer'; export * from './ProductsTable'; export * from './ProjectTemplate'; export * from './TableOfContent'; +export * from './LabelWithWrapping'; diff --git a/docs/ProjectTemplates.mdx b/docs/ProjectTemplates.mdx index 3e83a9d7dd9..ac24d57bf8f 100644 --- a/docs/ProjectTemplates.mdx +++ b/docs/ProjectTemplates.mdx @@ -1,6 +1,6 @@ -import { Footer, ProjectTemplate, TableOfContent } from '@sb/components'; +import { Footer, ProjectTemplate, TableOfContent, LabelWithWrapping } from '@sb/components'; import { Meta } from '@storybook/blocks'; -import { FlexBox, FlexBoxJustifyContent, FlexBoxWrap, Label } from '@ui5/webcomponents-react'; +import { FlexBox, FlexBoxJustifyContent, FlexBoxWrap, Label, Link, WrappingType } from '@ui5/webcomponents-react'; import NextLogo from '@sb/images/logo-nextjs.svg'; import ViteLogo from '@sb/images/logo-vitejs.svg'; @@ -42,6 +42,7 @@ A curated list of minimal project templates and examples to get started using UI href={'https://github.com/SAP/ui5-webcomponents-react/tree/main/templates/vite-ts'} isTypeScript isTemplate + stackBlitzHref="https://stackblitz.com/github/SAP/ui5-webcomponents-react/tree/main/templates/vite-ts?file=src%2FApp.tsx" /> @@ -90,11 +91,21 @@ A curated list of minimal project templates and examples to get started using UI logoAttribution={'Vite.js Logo. Original Source: https://github.com/vitejs/vite/blob/main/docs/public/logo.svg '} href={'https://github.com/SAP/ui5-webcomponents-react/tree/main/examples/vite-ts'} isTypeScript + stackBlitzHref="https://stackblitz.com/github/SAP/ui5-webcomponents-react/tree/main/examples/vite-ts?file=src%2Fmain.tsx" > diff --git a/examples/vite-ts/README.md b/examples/vite-ts/README.md index 5f01e33bf9a..db7d8e39241 100644 --- a/examples/vite-ts/README.md +++ b/examples/vite-ts/README.md @@ -1,4 +1,4 @@ -# UI5 Web Components for React - Vite + TypeScript Template +# UI5 Web Components for React - Vite + TypeScript + React Router Example ## How to use this template @@ -23,13 +23,29 @@ npm run dev ## Run Tests -Run all component tests headlessly in Chrome: +Run all tests headlessly in Chrome: + +**End-to-End-Tests** + +```bash +npm run testE2E +``` + +**Component Tests** ```bash npm run test ``` -Open component tests in Chrome: +Open tests in Chrome: + +**End-to-End-Tests** + +```bash +npm run testE2E:open +``` + +**Component Tests** ```bash npm run test:open @@ -37,8 +53,9 @@ npm run test:open ## Learn More -To learn more about Vite and UI5 Web Components for React, please visit the following resources: +To learn more about Vite, React Router and UI5 Web Components for React, please visit the following resources: - [Vite Documentation](https://vitejs.dev/) +- [React Router Documentation](https://reactrouter.com/) - [UI5 Web Components Documentation](https://sap.github.io/ui5-webcomponents/) - [UI5 Web Components for React Documentation](https://sap.github.io/ui5-webcomponents-react/) diff --git a/examples/vite-ts/cypress.config.ts b/examples/vite-ts/cypress.config.ts index 7096c8cd32f..5fe6944ea6d 100644 --- a/examples/vite-ts/cypress.config.ts +++ b/examples/vite-ts/cypress.config.ts @@ -1,10 +1,20 @@ import { defineConfig } from 'cypress'; export default defineConfig({ + includeShadowDom: true, + viewportWidth: 1920, + viewportHeight: 1080, component: { devServer: { framework: 'react', bundler: 'vite' } + }, + + e2e: { + baseUrl: 'http://localhost:5173/', + setupNodeEvents(on, config) { + // implement node event listeners here + } } }); diff --git a/examples/vite-ts/cypress/e2e/App.cy.tsx b/examples/vite-ts/cypress/e2e/App.cy.tsx new file mode 100644 index 00000000000..37f23301bd5 --- /dev/null +++ b/examples/vite-ts/cypress/e2e/App.cy.tsx @@ -0,0 +1,9 @@ +// make sure to start your dev server before running e2e tests +describe('E2E tests', () => { + it('click list item', () => { + cy.visit('/'); + cy.clickUi5ListItemByText("Solve a Rubik's cube"); + cy.url().should('eq', 'http://localhost:5173/todo/5'); + cy.get('[value="Solve a Rubik\'s cube"]').should('be.visible').and('have.attr', 'ui5-input'); + }); +}); diff --git a/examples/vite-ts/cypress/support/e2e.ts b/examples/vite-ts/cypress/support/e2e.ts new file mode 100644 index 00000000000..598ab5f0d7f --- /dev/null +++ b/examples/vite-ts/cypress/support/e2e.ts @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/e2e.ts is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands'; + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/examples/vite-ts/package-lock.json b/examples/vite-ts/package-lock.json index 99dd1a2259e..42328aa41a6 100644 --- a/examples/vite-ts/package-lock.json +++ b/examples/vite-ts/package-lock.json @@ -13,7 +13,8 @@ "@ui5/webcomponents-icons": "~1.22.0", "@ui5/webcomponents-react": "~1.25.0", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "react-router-dom": "^6.22.0" }, "devDependencies": { "@types/react": "^18.0.28", @@ -1035,6 +1036,14 @@ "node": ">= 8" } }, + "node_modules/@remix-run/router": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.0.tgz", + "integrity": "sha512-HOil5aFtme37dVQTB6M34G95kPM3MMuqSmIRVCC52eKV+Y/tGSqw9P3rWhlAx6A+mz+MoX+XxsGsNJbaI5qCgQ==", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.4.1.tgz", @@ -4706,6 +4715,36 @@ "node": ">=0.10.0" } }, + "node_modules/react-router": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.22.0.tgz", + "integrity": "sha512-q2yemJeg6gw/YixRlRnVx6IRJWZD6fonnfZhN1JIOhV2iJCPeRNSH3V1ISwHf+JWcESzLC3BOLD1T07tmO5dmg==", + "dependencies": { + "@remix-run/router": "1.15.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.22.0.tgz", + "integrity": "sha512-z2w+M4tH5wlcLmH3BMMOMdrtrJ9T3oJJNsAlBJbwk+8Syxd5WFJ7J5dxMEW0/GEXD1BBis4uXRrNIz3mORr0ag==", + "dependencies": { + "@remix-run/router": "1.15.0", + "react-router": "6.22.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, "node_modules/react-table": { "version": "7.8.0", "resolved": "https://registry.npmjs.org/react-table/-/react-table-7.8.0.tgz", diff --git a/examples/vite-ts/package.json b/examples/vite-ts/package.json index 7a8b72455ee..8baac3f9fc2 100644 --- a/examples/vite-ts/package.json +++ b/examples/vite-ts/package.json @@ -7,7 +7,9 @@ "dev": "vite", "build": "tsc && vite build", "test": "cypress run --component --browser chrome", + "testE2E": "cypress run --e2e --browser chrome", "test:open": "cypress open --component --browser chrome", + "testE2E:open": "cypress open --e2e --browser chrome", "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0", "preview": "vite preview" }, @@ -17,15 +19,16 @@ "@ui5/webcomponents-icons": "~1.22.0", "@ui5/webcomponents-react": "~1.25.0", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "react-router-dom": "^6.22.0" }, "devDependencies": { "@types/react": "^18.0.28", "@types/react-dom": "^18.0.11", "@typescript-eslint/eslint-plugin": "^7.0.0", "@typescript-eslint/parser": "^7.0.0", - "@vitejs/plugin-react": "^4.2.0", "@ui5/webcomponents-cypress-commands": "^1.12.0", + "@vitejs/plugin-react": "^4.2.0", "cypress": "^13.0.0", "eslint": "^8.38.0", "eslint-plugin-react-hooks": "^4.6.0", diff --git a/examples/vite-ts/public/person.png b/examples/vite-ts/public/person.png new file mode 100644 index 0000000000000000000000000000000000000000..480658b039214ac2221cc0de2750d3fc84982223 GIT binary patch literal 41336 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 { - it('render Link component with text', () => { - cy.mount(); - cy.get('[ui5-link]').should('be.visible').and('have.text', 'Getting Started with UI5 Web Component for React'); - }); - it('type into Input component', () => { - cy.mount(); - cy.get('[ui5-input]').typeIntoUi5Input('Hello there!'); - cy.get('[ui5-label]').should('be.visible').and('have.text', 'Hello there!'); + // example for component test + it('basic', () => { + const clickSpy = cy.spy().as('clickSpy'); + cy.mount(); + cy.get('[ui5-button]').click(); + cy.get('@clickSpy').should('have.been.calledOnce'); }); }); diff --git a/examples/vite-ts/src/App.tsx b/examples/vite-ts/src/App.tsx deleted file mode 100644 index 614dcbf066e..00000000000 --- a/examples/vite-ts/src/App.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import employeeIcon from '@ui5/webcomponents-icons/dist/employee.js'; -import { - Avatar, - FlexBox, - FlexBoxAlignItems, - FlexBoxDirection, - FlexBoxJustifyContent, - Input, - InputPropTypes, - Label, - Link, - LinkDesign, - ShellBar -} from '@ui5/webcomponents-react'; -import { useState } from 'react'; - -function App() { - const [inputVal, setInputVal] = useState(''); - const handleInput: InputPropTypes['onInput'] = (e) => { - setInputVal(e.target.value ?? ''); - }; - return ( - <> - } - primaryTitle="UI5 Web Components for React Template" - profile={} - /> - - - Getting Started with UI5 Web Component for React - - - - - - ); -} - -export default App; diff --git a/examples/vite-ts/src/AppShell.module.css b/examples/vite-ts/src/AppShell.module.css new file mode 100644 index 00000000000..b6478737ab1 --- /dev/null +++ b/examples/vite-ts/src/AppShell.module.css @@ -0,0 +1,3 @@ +.popover::part(content) { + padding: 0; +} diff --git a/examples/vite-ts/src/AppShell.tsx b/examples/vite-ts/src/AppShell.tsx new file mode 100644 index 00000000000..5c78d7eb690 --- /dev/null +++ b/examples/vite-ts/src/AppShell.tsx @@ -0,0 +1,103 @@ +import navBackIcon from '@ui5/webcomponents-icons/dist/nav-back.js'; +import paletteIcon from '@ui5/webcomponents-icons/dist/palette.js'; +import { + Avatar, + Breadcrumbs, + Button, + DynamicPage, + DynamicPageTitle, + List, + ListMode, + ListPropTypes, + ResponsivePopover, + ResponsivePopoverDomRef, + ShellBar, + ShellBarItem, + ShellBarItemPropTypes, + StandardListItem +} from '@ui5/webcomponents-react'; +import { useRef, useState } from 'react'; +import { Outlet, useLocation, useMatches, useNavigate } from 'react-router-dom'; +import { SingleTodoHandle } from './main.tsx'; +import { Todo } from './mockImplementations/mockData.ts'; +import classes from './AppShell.module.css'; +import { getTheme, setTheme } from '@ui5/webcomponents-base/dist/config/Theme.js'; + +const THEMES = [ + { key: 'sap_horizon', value: 'Morning Horizon (Light)' }, + { key: 'sap_horizon_dark', value: 'Evening Horizon (Dark)' }, + { key: 'sap_horizon_hcb', value: 'Horizon High Contrast Black' }, + { key: 'sap_horizon_hcw', value: 'Horizon High Contrast White' } +]; + +function AppShell() { + const popoverRef = useRef(null); + const navigate = useNavigate(); + const location = useLocation(); + const matches = useMatches(); + const [currentTheme, setCurrentTheme] = useState(getTheme); + const detailViewMatch = matches.find((match) => Boolean(match.handle)); + const detailViewMatchHandle = detailViewMatch?.handle as SingleTodoHandle; + const detailViewMatchData = detailViewMatch?.data as Todo; + + const handleLogoClick = () => { + navigate('/'); + }; + const handleThemeSwitchItemClick: ShellBarItemPropTypes['onClick'] = (e) => { + popoverRef.current?.showAt(e.detail.targetRef); + }; + const handleThemeSwitch: ListPropTypes['onSelectionChange'] = (e) => { + const { targetItem } = e.detail; + setTheme(targetItem.dataset.key!); + setCurrentTheme(targetItem.dataset.key!); + popoverRef.current!.close(); + }; + return ( + <> + } + primaryTitle="UI5 Web Components for React Examples" + secondaryTitle="Vite.js" + profile={ + + Profile Avatar + + } + onLogoClick={handleLogoClick} + startButton={ +