From dd2e48d857da6a21b508670e38702e48b39d932d Mon Sep 17 00:00:00 2001 From: Brandy Smith <6577830+brandyscarney@users.noreply.github.com> Date: Fri, 23 Oct 2026 15:30:56 -0400 Subject: [PATCH] chore(react): use Ionic lint and Prettier configs and replace Cypress with Playwright --- react-vite/base/.editorconfig | 16 ++++++++ react-vite/base/.gitignore | 6 +++ react-vite/base/.prettierignore | 5 +++ react-vite/base/.vscode/extensions.json | 8 ++-- react-vite/base/cypress.config.ts | 10 ----- react-vite/base/cypress/fixtures/example.json | 5 --- react-vite/base/cypress/support/commands.ts | 37 ----------------- react-vite/base/cypress/support/e2e.ts | 20 ---------- react-vite/base/eslint.config.js | 33 +++++---------- react-vite/base/package.json | 40 +++++++++++-------- react-vite/base/playwright.config.ts | 27 +++++++++++++ react-vite/base/src/App.test.tsx | 4 +- react-vite/base/src/main.tsx | 5 ++- react-vite/base/src/setupTests.ts | 33 ++++++++++----- react-vite/base/vite.config.ts | 20 ++++------ .../official/blank/cypress/e2e/test.cy.ts | 6 --- react-vite/official/blank/e2e/app.spec.ts | 6 +++ react-vite/official/blank/ionic.starter.json | 2 +- react-vite/official/blank/src/App.tsx | 3 +- .../blank/src/components/ExploreContainer.tsx | 11 +++-- react-vite/official/blank/src/pages/Home.tsx | 1 + .../official/list/cypress/e2e/test.cy.ts | 6 --- react-vite/official/list/e2e/app.spec.ts | 6 +++ react-vite/official/list/ionic.starter.json | 2 +- react-vite/official/list/src/App.tsx | 3 +- .../list/src/components/MessageListItem.tsx | 15 +++---- react-vite/official/list/src/data/messages.ts | 23 +++++------ react-vite/official/list/src/pages/Home.tsx | 20 +++++----- .../official/list/src/pages/ViewMessage.tsx | 20 +++++----- .../official/sidemenu/cypress/e2e/test.cy.ts | 6 --- react-vite/official/sidemenu/e2e/app.spec.ts | 6 +++ .../official/sidemenu/ionic.starter.json | 2 +- react-vite/official/sidemenu/src/App.tsx | 1 + .../src/components/ExploreContainer.tsx | 7 +++- .../official/sidemenu/src/components/Menu.tsx | 39 +++++++++++++----- .../official/sidemenu/src/pages/Page.tsx | 4 +- .../official/tabs/cypress/e2e/test.cy.ts | 6 --- react-vite/official/tabs/e2e/app.spec.ts | 6 +++ react-vite/official/tabs/ionic.starter.json | 2 +- react-vite/official/tabs/src/App.tsx | 5 ++- .../tabs/src/components/ExploreContainer.css | 8 ++-- .../tabs/src/components/ExploreContainer.tsx | 9 ++++- react-vite/official/tabs/src/pages/Tab1.tsx | 1 + react-vite/official/tabs/src/pages/Tab2.tsx | 1 + react-vite/official/tabs/src/pages/Tab3.tsx | 1 + 45 files changed, 263 insertions(+), 234 deletions(-) create mode 100644 react-vite/base/.editorconfig create mode 100644 react-vite/base/.prettierignore delete mode 100644 react-vite/base/cypress.config.ts delete mode 100644 react-vite/base/cypress/fixtures/example.json delete mode 100644 react-vite/base/cypress/support/commands.ts delete mode 100644 react-vite/base/cypress/support/e2e.ts create mode 100644 react-vite/base/playwright.config.ts delete mode 100644 react-vite/official/blank/cypress/e2e/test.cy.ts create mode 100644 react-vite/official/blank/e2e/app.spec.ts delete mode 100644 react-vite/official/list/cypress/e2e/test.cy.ts create mode 100644 react-vite/official/list/e2e/app.spec.ts delete mode 100644 react-vite/official/sidemenu/cypress/e2e/test.cy.ts create mode 100644 react-vite/official/sidemenu/e2e/app.spec.ts delete mode 100644 react-vite/official/tabs/cypress/e2e/test.cy.ts create mode 100644 react-vite/official/tabs/e2e/app.spec.ts diff --git a/react-vite/base/.editorconfig b/react-vite/base/.editorconfig new file mode 100644 index 000000000..59d9a3a3e --- /dev/null +++ b/react-vite/base/.editorconfig @@ -0,0 +1,16 @@ +# Editor configuration, see https://editorconfig.org +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.ts] +quote_type = single + +[*.md] +max_line_length = off +trim_trailing_whitespace = false diff --git a/react-vite/base/.gitignore b/react-vite/base/.gitignore index c5052646b..ffea9c1db 100644 --- a/react-vite/base/.gitignore +++ b/react-vite/base/.gitignore @@ -29,3 +29,9 @@ yarn-error.log* # Optional eslint cache .eslintcache + +# Playwright +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ diff --git a/react-vite/base/.prettierignore b/react-vite/base/.prettierignore new file mode 100644 index 000000000..08d41d635 --- /dev/null +++ b/react-vite/base/.prettierignore @@ -0,0 +1,5 @@ +# Prettier only reads the root .gitignore, not the ones inside the native +# projects, so ignore them here to skip Capacitor's copied web build and +# Gradle's build output. +android/ +ios/ diff --git a/react-vite/base/.vscode/extensions.json b/react-vite/base/.vscode/extensions.json index af3c0b294..e36db0847 100644 --- a/react-vite/base/.vscode/extensions.json +++ b/react-vite/base/.vscode/extensions.json @@ -1,5 +1,7 @@ { - "recommendations": [ - "Webnative.webnative" - ] + "recommendations": [ + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "Webnative.webnative" + ] } diff --git a/react-vite/base/cypress.config.ts b/react-vite/base/cypress.config.ts deleted file mode 100644 index 5d58e7ab1..000000000 --- a/react-vite/base/cypress.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { defineConfig } from "cypress"; - -export default defineConfig({ - e2e: { - baseUrl: "http://localhost:5173", - setupNodeEvents(on, config) { - // implement node event listeners here - }, - }, -}); \ No newline at end of file diff --git a/react-vite/base/cypress/fixtures/example.json b/react-vite/base/cypress/fixtures/example.json deleted file mode 100644 index 02e425437..000000000 --- a/react-vite/base/cypress/fixtures/example.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "Using fixtures to represent data", - "email": "hello@cypress.io", - "body": "Fixtures are a great way to mock data for responses to routes" -} diff --git a/react-vite/base/cypress/support/commands.ts b/react-vite/base/cypress/support/commands.ts deleted file mode 100644 index 698b01a42..000000000 --- a/react-vite/base/cypress/support/commands.ts +++ /dev/null @@ -1,37 +0,0 @@ -/// -// *********************************************** -// This example commands.ts shows you how to -// create various custom commands and overwrite -// existing commands. -// -// For more comprehensive examples of custom -// commands please read more here: -// https://on.cypress.io/custom-commands -// *********************************************** -// -// -// -- This is a parent command -- -// Cypress.Commands.add('login', (email, password) => { ... }) -// -// -// -- This is a child command -- -// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) -// -// -// -- This is a dual command -- -// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) -// -// -// -- This will overwrite an existing command -- -// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) -// -// declare global { -// namespace Cypress { -// interface Chainable { -// login(email: string, password: string): Chainable -// drag(subject: string, options?: Partial): Chainable -// dismiss(subject: string, options?: Partial): Chainable -// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable -// } -// } -// } \ No newline at end of file diff --git a/react-vite/base/cypress/support/e2e.ts b/react-vite/base/cypress/support/e2e.ts deleted file mode 100644 index f80f74f8e..000000000 --- a/react-vite/base/cypress/support/e2e.ts +++ /dev/null @@ -1,20 +0,0 @@ -// *********************************************************** -// 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') \ No newline at end of file diff --git a/react-vite/base/eslint.config.js b/react-vite/base/eslint.config.js index 0542f72c3..6c74c5e16 100644 --- a/react-vite/base/eslint.config.js +++ b/react-vite/base/eslint.config.js @@ -1,30 +1,17 @@ -import js from '@eslint/js' -import globals from 'globals' -import reactHooks from 'eslint-plugin-react-hooks' -import reactRefresh from 'eslint-plugin-react-refresh' -import tseslint from 'typescript-eslint' +import ionic from '@ionic/eslint-config/recommended.js'; +import { defineConfig } from 'eslint/config'; +import reactHooks from 'eslint-plugin-react-hooks'; +import reactRefresh from 'eslint-plugin-react-refresh'; +import globals from 'globals'; -export default tseslint.config( - { ignores: ['dist', 'cypress.config.ts'] }, +export default defineConfig([ + { ignores: ['dist/**', 'android/**', 'ios/**', 'playwright-report/**', 'test-results/**', 'blob-report/**'] }, + ionic, { - extends: [js.configs.recommended, ...tseslint.configs.recommended], files: ['**/*.{ts,tsx}'], + extends: [reactHooks.configs.flat.recommended, reactRefresh.configs.vite], languageOptions: { - ecmaVersion: 2020, globals: globals.browser, }, - plugins: { - 'react-hooks': reactHooks, - 'react-refresh': reactRefresh, - }, - rules: { - ...reactHooks.configs.recommended.rules, - 'react-refresh/only-export-components': [ - 'warn', - { allowConstantExport: true }, - ], - 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', - 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off', - }, }, -) +]); diff --git a/react-vite/base/package.json b/react-vite/base/package.json index 9732a2c58..85a8bf379 100644 --- a/react-vite/base/package.json +++ b/react-vite/base/package.json @@ -7,9 +7,14 @@ "dev": "vite", "build": "tsc && vite build", "preview": "vite preview", - "test.e2e": "cypress run", - "test.unit": "vitest", - "lint": "eslint" + "lint": "npm run eslint && npm run prettier -- --check", + "lint:fix": "npm run eslint -- --fix && npm run prettier -- --write", + "eslint": "eslint --max-warnings 0", + "prettier": "prettier \"**/*.{ts,tsx}\"", + "test": "npm run test:unit && npm run test:e2e", + "test:unit": "vitest run", + "test:unit:watch": "vitest", + "test:e2e": "playwright test" }, "dependencies": { "@ionic/react": "^9.0.0", @@ -21,25 +26,26 @@ "react-router-dom": "^6.30.0" }, "devDependencies": { - "@testing-library/dom": ">=7.21.4", - "@testing-library/jest-dom": "^5.16.5", - "@testing-library/react": "^16.2.0", - "@testing-library/user-event": "^14.4.3", + "@ionic/eslint-config": "^0.5.0", + "@ionic/prettier-config": "^4.0.0", + "@playwright/test": "^1.64.1", + "@testing-library/dom": "^10.4.2", + "@testing-library/jest-dom": "^6.9.1", + "@testing-library/react": "^16.3.3", "@types/react": "19.0.10", "@types/react-dom": "19.0.4", "@vitejs/plugin-legacy": "^8.0.0", "@vitejs/plugin-react": "^6.0.0", - "cypress": "^13.5.0", - "eslint": "^9.20.1", - "eslint-plugin-react": "^7.32.2", - "eslint-plugin-react-hooks": "^5.1.0", - "eslint-plugin-react-refresh": "^0.4.19", - "globals": "^15.15.0", - "jsdom": "^22.1.0", + "eslint": "^10.13.0", + "eslint-plugin-react-hooks": "^7.1.1", + "eslint-plugin-react-refresh": "^0.5.7", + "globals": "^17.13.0", + "jsdom": "^30.1.3", + "prettier": "^3.9.10", "terser": "^5.16.0", "typescript": "~5.9.0", - "typescript-eslint": "^8.24.0", "vite": "^8.0.0", - "vitest": "~4.0.18" - } + "vitest": "~5.0.5" + }, + "prettier": "@ionic/prettier-config" } diff --git a/react-vite/base/playwright.config.ts b/react-vite/base/playwright.config.ts new file mode 100644 index 000000000..e5db42252 --- /dev/null +++ b/react-vite/base/playwright.config.ts @@ -0,0 +1,27 @@ +import { defineConfig, devices } from '@playwright/test'; + +const baseURL = 'http://localhost:5173'; + +export default defineConfig({ + testDir: './e2e', + fullyParallel: true, + forbidOnly: !!process.env.CI, + retries: process.env.CI ? 2 : 0, + reporter: process.env.CI ? [['github'], ['html', { open: 'never' }]] : 'list', + use: { + baseURL, + trace: 'on-first-retry', + }, + projects: [ + { + name: 'Mobile Chrome', + use: { ...devices['Pixel 7'] }, + }, + ], + webServer: { + command: 'npm run dev -- --port 5173 --strictPort', + url: baseURL, + reuseExistingServer: !process.env.CI, + timeout: 120_000, + }, +}); diff --git a/react-vite/base/src/App.test.tsx b/react-vite/base/src/App.test.tsx index 8c927a8d7..5c9084896 100644 --- a/react-vite/base/src/App.test.tsx +++ b/react-vite/base/src/App.test.tsx @@ -1,5 +1,7 @@ -import React from 'react'; import { render } from '@testing-library/react'; +import React from 'react'; +import { expect, test } from 'vitest'; + import App from './App'; test('renders without crashing', () => { diff --git a/react-vite/base/src/main.tsx b/react-vite/base/src/main.tsx index fbff6c812..46e08a93d 100644 --- a/react-vite/base/src/main.tsx +++ b/react-vite/base/src/main.tsx @@ -1,5 +1,6 @@ import React from 'react'; import { createRoot } from 'react-dom/client'; + import App from './App'; const container = document.getElementById('root'); @@ -7,5 +8,5 @@ const root = createRoot(container!); root.render( - -); \ No newline at end of file + , +); diff --git a/react-vite/base/src/setupTests.ts b/react-vite/base/src/setupTests.ts index 87988d6bd..7808c1dc7 100644 --- a/react-vite/base/src/setupTests.ts +++ b/react-vite/base/src/setupTests.ts @@ -1,14 +1,25 @@ -// jest-dom adds custom jest matchers for asserting on DOM nodes. -// allows you to do things like: -// expect(element).toHaveTextContent(/react/i) -// learn more: https://github.com/testing-library/jest-dom -import '@testing-library/jest-dom/extend-expect'; +// Adds jest-dom's DOM matchers (toBeInTheDocument, toHaveTextContent, ...) to Vitest's expect. +import '@testing-library/jest-dom/vitest'; +import { cleanup } from '@testing-library/react'; +import { afterEach } from 'vitest'; -// Mock matchmedia -window.matchMedia = window.matchMedia || function() { - return { +// Testing Library only cleans up automatically when Vitest globals are enabled. +afterEach(() => { + cleanup(); +}); + +// jsdom doesn't implement matchMedia, which Ionic uses for platform and dark mode checks. +window.matchMedia = + window.matchMedia || + function (query: string): MediaQueryList { + return { matches: false, - addListener: function() {}, - removeListener: function() {} + media: query, + onchange: null, + addListener: () => undefined, + removeListener: () => undefined, + addEventListener: () => undefined, + removeEventListener: () => undefined, + dispatchEvent: () => false, + }; }; -}; diff --git a/react-vite/base/vite.config.ts b/react-vite/base/vite.config.ts index 89f5ecd22..89c00c114 100644 --- a/react-vite/base/vite.config.ts +++ b/react-vite/base/vite.config.ts @@ -1,18 +1,14 @@ -/// - -import legacy from '@vitejs/plugin-legacy' -import react from '@vitejs/plugin-react' -import { defineConfig } from 'vite' +import legacy from '@vitejs/plugin-legacy'; +import react from '@vitejs/plugin-react'; +import { defineConfig } from 'vitest/config'; // https://vitejs.dev/config/ export default defineConfig({ - plugins: [ - react(), - legacy() - ], + plugins: [react(), legacy()], test: { - globals: true, environment: 'jsdom', setupFiles: './src/setupTests.ts', - } -}) + // Playwright e2e specs live in e2e/. + include: ['src/**/*.test.{ts,tsx}'], + }, +}); diff --git a/react-vite/official/blank/cypress/e2e/test.cy.ts b/react-vite/official/blank/cypress/e2e/test.cy.ts deleted file mode 100644 index 7b9a2e029..000000000 --- a/react-vite/official/blank/cypress/e2e/test.cy.ts +++ /dev/null @@ -1,6 +0,0 @@ -describe('My First Test', () => { - it('Visits the app root url', () => { - cy.visit('/') - cy.contains('#container', 'Ready to create an app?') - }) -}) \ No newline at end of file diff --git a/react-vite/official/blank/e2e/app.spec.ts b/react-vite/official/blank/e2e/app.spec.ts new file mode 100644 index 000000000..9a3645c1f --- /dev/null +++ b/react-vite/official/blank/e2e/app.spec.ts @@ -0,0 +1,6 @@ +import { expect, test } from '@playwright/test'; + +test('visits the app root url', async ({ page }) => { + await page.goto('/'); + await expect(page.locator('#container')).toContainText('Ready to create an app?'); +}); diff --git a/react-vite/official/blank/ionic.starter.json b/react-vite/official/blank/ionic.starter.json index 5a4c10616..680603d01 100644 --- a/react-vite/official/blank/ionic.starter.json +++ b/react-vite/official/blank/ionic.starter.json @@ -7,6 +7,6 @@ "www" ], "scripts": { - "test": "npm run build && npm run test.unit -- --watch=false && npm i --no-save concurrently && ./node_modules/.bin/concurrently \"npm run dev\" \"npm run test.e2e\" --kill-others --success first" + "test": "npm run lint && npm run build && npm run test:unit && npx playwright install --with-deps chromium && npm run test:e2e" } } diff --git a/react-vite/official/blank/src/App.tsx b/react-vite/official/blank/src/App.tsx index cd8ef3f65..9e5794197 100644 --- a/react-vite/official/blank/src/App.tsx +++ b/react-vite/official/blank/src/App.tsx @@ -1,6 +1,7 @@ -import { Navigate, Route } from 'react-router-dom'; import { IonApp, IonRouterOutlet, setupIonicReact } from '@ionic/react'; import { IonReactRouter } from '@ionic/react-router'; +import { Navigate, Route } from 'react-router-dom'; + import Home from './pages/Home'; /* Core CSS required for Ionic components to work properly */ diff --git a/react-vite/official/blank/src/components/ExploreContainer.tsx b/react-vite/official/blank/src/components/ExploreContainer.tsx index 1b68a3c19..32ca296c1 100644 --- a/react-vite/official/blank/src/components/ExploreContainer.tsx +++ b/react-vite/official/blank/src/components/ExploreContainer.tsx @@ -1,12 +1,15 @@ import './ExploreContainer.css'; -interface ContainerProps { } - -const ExploreContainer: React.FC = () => { +const ExploreContainer: React.FC = () => { return (
Ready to create an app? -

Start with Ionic UI Components

+

+ Start with Ionic{' '} + + UI Components + +

); }; diff --git a/react-vite/official/blank/src/pages/Home.tsx b/react-vite/official/blank/src/pages/Home.tsx index 922267da7..b1b6224b4 100644 --- a/react-vite/official/blank/src/pages/Home.tsx +++ b/react-vite/official/blank/src/pages/Home.tsx @@ -1,4 +1,5 @@ import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar } from '@ionic/react'; + import ExploreContainer from '../components/ExploreContainer'; import './Home.css'; diff --git a/react-vite/official/list/cypress/e2e/test.cy.ts b/react-vite/official/list/cypress/e2e/test.cy.ts deleted file mode 100644 index 5f1877799..000000000 --- a/react-vite/official/list/cypress/e2e/test.cy.ts +++ /dev/null @@ -1,6 +0,0 @@ -describe('My First Test', () => { - it('Visits the app root url', () => { - cy.visit('/') - cy.contains('ion-header', 'Inbox') - }) -}) \ No newline at end of file diff --git a/react-vite/official/list/e2e/app.spec.ts b/react-vite/official/list/e2e/app.spec.ts new file mode 100644 index 000000000..c53b3b061 --- /dev/null +++ b/react-vite/official/list/e2e/app.spec.ts @@ -0,0 +1,6 @@ +import { expect, test } from '@playwright/test'; + +test('visits the app root url', async ({ page }) => { + await page.goto('/'); + await expect(page.locator('ion-header').first()).toContainText('Inbox'); +}); diff --git a/react-vite/official/list/ionic.starter.json b/react-vite/official/list/ionic.starter.json index 9e20d66ba..1d6c95d38 100644 --- a/react-vite/official/list/ionic.starter.json +++ b/react-vite/official/list/ionic.starter.json @@ -7,6 +7,6 @@ "www" ], "scripts": { - "test": "npm run build && npm run test.unit -- --watch=false && npm i --no-save concurrently && ./node_modules/.bin/concurrently \"npm run dev\" \"npm run test.e2e\" --kill-others --success first" + "test": "npm run lint && npm run build && npm run test:unit && npx playwright install --with-deps chromium && npm run test:e2e" } } diff --git a/react-vite/official/list/src/App.tsx b/react-vite/official/list/src/App.tsx index fbc89609a..604276996 100644 --- a/react-vite/official/list/src/App.tsx +++ b/react-vite/official/list/src/App.tsx @@ -1,6 +1,7 @@ -import { Navigate, Route } from 'react-router-dom'; import { IonApp, IonRouterOutlet, setupIonicReact } from '@ionic/react'; import { IonReactRouter } from '@ionic/react-router'; +import { Navigate, Route } from 'react-router-dom'; + import Home from './pages/Home'; import ViewMessage from './pages/ViewMessage'; diff --git a/react-vite/official/list/src/components/MessageListItem.tsx b/react-vite/official/list/src/components/MessageListItem.tsx index 0c030fc88..ddf6aa268 100644 --- a/react-vite/official/list/src/components/MessageListItem.tsx +++ b/react-vite/official/list/src/components/MessageListItem.tsx @@ -1,9 +1,6 @@ -import { - IonItem, - IonLabel, - IonNote - } from '@ionic/react'; -import { Message } from '../data/messages'; +import { IonItem, IonLabel, IonNote } from '@ionic/react'; + +import type { Message } from '../data/messages'; import './MessageListItem.css'; interface MessageListItemProps { @@ -23,7 +20,11 @@ const MessageListItem: React.FC = ({ message }) => {

{message.subject}

- Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore + magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla + pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id + est laborum.

diff --git a/react-vite/official/list/src/data/messages.ts b/react-vite/official/list/src/data/messages.ts index d98995845..2c4fa777d 100644 --- a/react-vite/official/list/src/data/messages.ts +++ b/react-vite/official/list/src/data/messages.ts @@ -10,53 +10,52 @@ const messages: Message[] = [ fromName: 'Matt Chorsey', subject: 'New event: Trip to Vegas', date: '9:32 AM', - id: 0 + id: 0, }, { fromName: 'Lauren Ruthford', subject: 'Long time no chat', date: '6:12 AM', - id: 1 + id: 1, }, { fromName: 'Jordan Firth', subject: 'Report Results', date: '4:55 AM', - id: 2 - + id: 2, }, { fromName: 'Bill Thomas', subject: 'The situation', date: 'Yesterday', - id: 3 + id: 3, }, { fromName: 'Joanne Pollan', subject: 'Updated invitation: Swim lessons', date: 'Yesterday', - id: 4 + id: 4, }, { fromName: 'Andrea Cornerston', subject: 'Last minute ask', date: 'Yesterday', - id: 5 + id: 5, }, { fromName: 'Moe Chamont', subject: 'Family Calendar - Version 1', date: 'Last Week', - id: 6 + id: 6, }, { fromName: 'Kelly Richardson', subject: 'Placeholder Headhots', date: 'Last Week', - id: 7 - } + id: 7, + }, ]; -export const getMessages = () => messages; +export const getMessages = (): Message[] => messages; -export const getMessage = (id: number) => messages.find(m => m.id === id); +export const getMessage = (id: number): Message | undefined => messages.find((m) => m.id === id); diff --git a/react-vite/official/list/src/pages/Home.tsx b/react-vite/official/list/src/pages/Home.tsx index 9395c4ff2..94de5a400 100644 --- a/react-vite/official/list/src/pages/Home.tsx +++ b/react-vite/official/list/src/pages/Home.tsx @@ -1,6 +1,3 @@ -import MessageListItem from '../components/MessageListItem'; -import { useState } from 'react'; -import { Message, getMessages } from '../data/messages'; import { IonContent, IonHeader, @@ -10,12 +7,17 @@ import { IonRefresherContent, IonTitle, IonToolbar, - useIonViewWillEnter + useIonViewWillEnter, } from '@ionic/react'; +import { useState } from 'react'; + +import MessageListItem from '../components/MessageListItem'; +import type { Message } from '../data/messages'; +import { getMessages } from '../data/messages'; + import './Home.css'; const Home: React.FC = () => { - const [messages, setMessages] = useState([]); useIonViewWillEnter(() => { @@ -43,14 +45,14 @@ const Home: React.FC = () => { - - Inbox - + Inbox - {messages.map(m => )} + {messages.map((m) => ( + + ))} diff --git a/react-vite/official/list/src/pages/ViewMessage.tsx b/react-vite/official/list/src/pages/ViewMessage.tsx index 526066a21..f3678a436 100644 --- a/react-vite/official/list/src/pages/ViewMessage.tsx +++ b/react-vite/official/list/src/pages/ViewMessage.tsx @@ -1,5 +1,3 @@ -import { useState } from 'react'; -import { Message, getMessage } from '../data/messages'; import { IonBackButton, IonButtons, @@ -14,10 +12,14 @@ import { useIonViewWillEnter, } from '@ionic/react'; import { personCircle } from 'ionicons/icons'; +import { useState } from 'react'; import { useParams } from 'react-router'; + +import { getMessage } from '../data/messages'; +import type { Message } from '../data/messages'; import './ViewMessage.css'; -function ViewMessage() { +function ViewMessage(): React.JSX.Element { const [message, setMessage] = useState(); const { id = '' } = useParams<{ id: string }>(); @@ -57,13 +59,11 @@ function ViewMessage() {

{message.subject}

- Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do - eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut - enim ad minim veniam, quis nostrud exercitation ullamco laboris - nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor - in reprehenderit in voluptate velit esse cillum dolore eu fugiat - nulla pariatur. Excepteur sint occaecat cupidatat non proident, - sunt in culpa qui officia deserunt mollit anim id est laborum. + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip + ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu + fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum.

diff --git a/react-vite/official/sidemenu/cypress/e2e/test.cy.ts b/react-vite/official/sidemenu/cypress/e2e/test.cy.ts deleted file mode 100644 index 4f3230bb4..000000000 --- a/react-vite/official/sidemenu/cypress/e2e/test.cy.ts +++ /dev/null @@ -1,6 +0,0 @@ -describe('My First Test', () => { - it('Visits the app root url', () => { - cy.visit('/folder/Inbox') - cy.contains('#container', 'Inbox') - }) -}) diff --git a/react-vite/official/sidemenu/e2e/app.spec.ts b/react-vite/official/sidemenu/e2e/app.spec.ts new file mode 100644 index 000000000..11cd138af --- /dev/null +++ b/react-vite/official/sidemenu/e2e/app.spec.ts @@ -0,0 +1,6 @@ +import { expect, test } from '@playwright/test'; + +test('visits the app root url', async ({ page }) => { + await page.goto('/'); + await expect(page.locator('#container')).toContainText('Inbox'); +}); diff --git a/react-vite/official/sidemenu/ionic.starter.json b/react-vite/official/sidemenu/ionic.starter.json index 0ca129de2..824dc06e5 100644 --- a/react-vite/official/sidemenu/ionic.starter.json +++ b/react-vite/official/sidemenu/ionic.starter.json @@ -7,6 +7,6 @@ "www" ], "scripts": { - "test": "npm run build && npm run test.unit -- --watch=false && npm i --no-save concurrently && ./node_modules/.bin/concurrently \"npm run dev\" \"npm run test.e2e\" --kill-others --success first" + "test": "npm run lint && npm run build && npm run test:unit && npx playwright install --with-deps chromium && npm run test:e2e" } } diff --git a/react-vite/official/sidemenu/src/App.tsx b/react-vite/official/sidemenu/src/App.tsx index a2d8897e1..732108c97 100644 --- a/react-vite/official/sidemenu/src/App.tsx +++ b/react-vite/official/sidemenu/src/App.tsx @@ -1,6 +1,7 @@ import { IonApp, IonRouterOutlet, IonSplitPane, setupIonicReact } from '@ionic/react'; import { IonReactRouter } from '@ionic/react-router'; import { Navigate, Route } from 'react-router-dom'; + import Menu from './components/Menu'; import Page from './pages/Page'; diff --git a/react-vite/official/sidemenu/src/components/ExploreContainer.tsx b/react-vite/official/sidemenu/src/components/ExploreContainer.tsx index 0711cabd7..bae1316c7 100644 --- a/react-vite/official/sidemenu/src/components/ExploreContainer.tsx +++ b/react-vite/official/sidemenu/src/components/ExploreContainer.tsx @@ -8,7 +8,12 @@ const ExploreContainer: React.FC = ({ name }) => { return (
{name} -

Explore UI Components

+

+ Explore{' '} + + UI Components + +

); }; diff --git a/react-vite/official/sidemenu/src/components/Menu.tsx b/react-vite/official/sidemenu/src/components/Menu.tsx index 563ee6277..b2195e7d4 100644 --- a/react-vite/official/sidemenu/src/components/Menu.tsx +++ b/react-vite/official/sidemenu/src/components/Menu.tsx @@ -9,9 +9,22 @@ import { IonMenuToggle, IonNote, } from '@ionic/react'; - +import { + archiveOutline, + archiveSharp, + bookmarkOutline, + heartOutline, + heartSharp, + mailOutline, + mailSharp, + paperPlaneOutline, + paperPlaneSharp, + trashOutline, + trashSharp, + warningOutline, + warningSharp, +} from 'ionicons/icons'; import { useLocation } from 'react-router-dom'; -import { archiveOutline, archiveSharp, bookmarkOutline, heartOutline, heartSharp, mailOutline, mailSharp, paperPlaneOutline, paperPlaneSharp, trashOutline, trashSharp, warningOutline, warningSharp } from 'ionicons/icons'; import './Menu.css'; interface AppPage { @@ -26,38 +39,38 @@ const appPages: AppPage[] = [ title: 'Inbox', url: '/folder/Inbox', iosIcon: mailOutline, - mdIcon: mailSharp + mdIcon: mailSharp, }, { title: 'Outbox', url: '/folder/Outbox', iosIcon: paperPlaneOutline, - mdIcon: paperPlaneSharp + mdIcon: paperPlaneSharp, }, { title: 'Favorites', url: '/folder/Favorites', iosIcon: heartOutline, - mdIcon: heartSharp + mdIcon: heartSharp, }, { title: 'Archived', url: '/folder/Archived', iosIcon: archiveOutline, - mdIcon: archiveSharp + mdIcon: archiveSharp, }, { title: 'Trash', url: '/folder/Trash', iosIcon: trashOutline, - mdIcon: trashSharp + mdIcon: trashSharp, }, { title: 'Spam', url: '/folder/Spam', iosIcon: warningOutline, - mdIcon: warningSharp - } + mdIcon: warningSharp, + }, ]; const labels = ['Family', 'Friends', 'Notes', 'Work', 'Travel', 'Reminders']; @@ -74,7 +87,13 @@ const Menu: React.FC = () => { {appPages.map((appPage, index) => { return ( - + diff --git a/react-vite/official/sidemenu/src/pages/Page.tsx b/react-vite/official/sidemenu/src/pages/Page.tsx index 627630aea..6001fd25d 100644 --- a/react-vite/official/sidemenu/src/pages/Page.tsx +++ b/react-vite/official/sidemenu/src/pages/Page.tsx @@ -1,11 +1,11 @@ import { IonButtons, IonContent, IonHeader, IonMenuButton, IonPage, IonTitle, IonToolbar } from '@ionic/react'; import { useParams } from 'react-router'; + import ExploreContainer from '../components/ExploreContainer'; import './Page.css'; const Page: React.FC = () => { - - const { name = '' } = useParams<{ name: string; }>(); + const { name = '' } = useParams<{ name: string }>(); return ( diff --git a/react-vite/official/tabs/cypress/e2e/test.cy.ts b/react-vite/official/tabs/cypress/e2e/test.cy.ts deleted file mode 100644 index f6b655f3b..000000000 --- a/react-vite/official/tabs/cypress/e2e/test.cy.ts +++ /dev/null @@ -1,6 +0,0 @@ -describe('My First Test', () => { - it('Visits the app root url', () => { - cy.visit('/') - cy.contains('ion-content', 'Tab 1 page') - }) -}) \ No newline at end of file diff --git a/react-vite/official/tabs/e2e/app.spec.ts b/react-vite/official/tabs/e2e/app.spec.ts new file mode 100644 index 000000000..338de5e3e --- /dev/null +++ b/react-vite/official/tabs/e2e/app.spec.ts @@ -0,0 +1,6 @@ +import { expect, test } from '@playwright/test'; + +test('visits the app root url', async ({ page }) => { + await page.goto('/'); + await expect(page.locator('ion-content')).toContainText('Tab 1 page'); +}); diff --git a/react-vite/official/tabs/ionic.starter.json b/react-vite/official/tabs/ionic.starter.json index b5ad2db75..8088c9a9a 100644 --- a/react-vite/official/tabs/ionic.starter.json +++ b/react-vite/official/tabs/ionic.starter.json @@ -7,6 +7,6 @@ "www" ], "scripts": { - "test": "npm run build && npm run test.unit -- --watch=false && npm i --no-save concurrently && ./node_modules/.bin/concurrently \"npm run dev\" \"npm run test.e2e\" --kill-others --success first" + "test": "npm run lint && npm run build && npm run test:unit && npx playwright install --with-deps chromium && npm run test:e2e" } } diff --git a/react-vite/official/tabs/src/App.tsx b/react-vite/official/tabs/src/App.tsx index caeef6078..cc143edff 100644 --- a/react-vite/official/tabs/src/App.tsx +++ b/react-vite/official/tabs/src/App.tsx @@ -1,4 +1,3 @@ -import { Navigate, Route } from 'react-router-dom'; import { IonApp, IonIcon, @@ -7,10 +6,12 @@ import { IonTabBar, IonTabButton, IonTabs, - setupIonicReact + setupIonicReact, } from '@ionic/react'; import { IonReactRouter } from '@ionic/react-router'; import { ellipse, square, triangle } from 'ionicons/icons'; +import { Navigate, Route } from 'react-router-dom'; + import Tab1 from './pages/Tab1'; import Tab2 from './pages/Tab2'; import Tab3 from './pages/Tab3'; diff --git a/react-vite/official/tabs/src/components/ExploreContainer.css b/react-vite/official/tabs/src/components/ExploreContainer.css index e99f514fb..c2c47cfa2 100644 --- a/react-vite/official/tabs/src/components/ExploreContainer.css +++ b/react-vite/official/tabs/src/components/ExploreContainer.css @@ -1,4 +1,4 @@ -.container { +#container { text-align: center; position: absolute; left: 0; @@ -7,18 +7,18 @@ transform: translateY(-50%); } -.container strong { +#container strong { font-size: 20px; line-height: 26px; } -.container p { +#container p { font-size: 16px; line-height: 22px; color: #8c8c8c; margin: 0; } -.container a { +#container a { text-decoration: none; } \ No newline at end of file diff --git a/react-vite/official/tabs/src/components/ExploreContainer.tsx b/react-vite/official/tabs/src/components/ExploreContainer.tsx index 354df7b7b..bae1316c7 100644 --- a/react-vite/official/tabs/src/components/ExploreContainer.tsx +++ b/react-vite/official/tabs/src/components/ExploreContainer.tsx @@ -6,9 +6,14 @@ interface ContainerProps { const ExploreContainer: React.FC = ({ name }) => { return ( -
+
{name} -

Explore UI Components

+

+ Explore{' '} + + UI Components + +

); }; diff --git a/react-vite/official/tabs/src/pages/Tab1.tsx b/react-vite/official/tabs/src/pages/Tab1.tsx index 97aa72d86..5a49b4db1 100644 --- a/react-vite/official/tabs/src/pages/Tab1.tsx +++ b/react-vite/official/tabs/src/pages/Tab1.tsx @@ -1,4 +1,5 @@ import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar } from '@ionic/react'; + import ExploreContainer from '../components/ExploreContainer'; import './Tab1.css'; diff --git a/react-vite/official/tabs/src/pages/Tab2.tsx b/react-vite/official/tabs/src/pages/Tab2.tsx index 05458aa0a..fdc2d9f4f 100644 --- a/react-vite/official/tabs/src/pages/Tab2.tsx +++ b/react-vite/official/tabs/src/pages/Tab2.tsx @@ -1,4 +1,5 @@ import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar } from '@ionic/react'; + import ExploreContainer from '../components/ExploreContainer'; import './Tab2.css'; diff --git a/react-vite/official/tabs/src/pages/Tab3.tsx b/react-vite/official/tabs/src/pages/Tab3.tsx index 3a29b8a5c..143f7f2d0 100644 --- a/react-vite/official/tabs/src/pages/Tab3.tsx +++ b/react-vite/official/tabs/src/pages/Tab3.tsx @@ -1,4 +1,5 @@ import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar } from '@ionic/react'; + import ExploreContainer from '../components/ExploreContainer'; import './Tab3.css';