Skip to content

Commit

Permalink
New ix react-starter (#53)
Browse files Browse the repository at this point in the history
  • Loading branch information
danielleroux authored Oct 15, 2024
1 parent e638977 commit f7152a3
Show file tree
Hide file tree
Showing 118 changed files with 7,860 additions and 16,154 deletions.
6 changes: 6 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
root = true

[*]
end_of_line = lf
indent_size = 2
max_line_length = 100
40 changes: 40 additions & 0 deletions .github/workflows/actions/install/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: "PNPM & Turbo Cache"
description: "PNPM & Turbo Cache"
runs:
using: "composite"
steps:
- uses: pnpm/action-setup@v4
name: Install pnpm
with:
run_install: false

- name: Setup Node.js environment
uses: actions/setup-node@v3
with:
node-version: lts/*
cache: "pnpm"

- name: Get pnpm store directory
run: |
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
shell: bash

- uses: actions/cache@v3
name: Setup pnpm cache
with:
path: ${{ env.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Cache turbo build setup
uses: actions/cache@v3
with:
path: .turbo
key: ${{ runner.os }}-turbo-${{ github.sha }}
restore-keys: |
${{ runner.os }}-turbo-
- name: Install dependencies
run: pnpm install
shell: bash
72 changes: 55 additions & 17 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,72 @@ name: CI

on:
push:
branches: ['main']
branches: ["main"] # remove "react-demo-app" before merge to main
pull_request:
types: [opened, synchronize]

concurrency:
group: pr-${{ github.head_ref }}
cancel-in-progress: true

jobs:
build:
name: Build
timeout-minutes: 15
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: ./.github/workflows/actions/install

- name: Build
run: pnpm build

lint:
name: Lint
timeout-minutes: 15
runs-on: ubuntu-latest

steps:
- name: Check out code
uses: actions/checkout@v3
with:
fetch-depth: 2
- uses: actions/checkout@v3
- uses: ./.github/workflows/actions/install

- uses: pnpm/action-setup@v2
with:
version: 8
- name: Lint
run: pnpm lint

- name: Setup Node.js environment
uses: actions/setup-node@v3
with:
node-version: 18
cache: 'pnpm'
unit:
name: Unit
timeout-minutes: 15
runs-on: ubuntu-latest

- name: Install dependencies
run: pnpm install
steps:
- uses: actions/checkout@v3
- uses: ./.github/workflows/actions/install
- name: Test
run: pnpm test

- name: Build
run: pnpm build
e2e:
# Depend on build job to ensure the build is completed before running E2E tests
# needs: [build]
name: E2E
timeout-minutes: 15
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- uses: ./.github/workflows/actions/install

- name: Install Playwright Browsers
run: |
cd ./apps/react-starter
pnpm playwright install chromium --with-deps
- name: E2E
run: pnpm e2e

- name: E2E Report
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v4
with:
name: react-playwright-report
path: apps/react-starter/playwright-report/
retention-days: 1
39 changes: 39 additions & 0 deletions .github/workflows/deploy-pages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Deploy GitHub Page

on:
workflow_dispatch:
inputs:
confirm_deployment:
description: "Please confirm deployment"
required: true
type: boolean

concurrency: deploy-gh-pages-${{ github.ref }}

jobs:
deploy-gh-pages:
if: ${{ inputs.confirm_deployment == true && github.repository == 'siemens/ix-starter' }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3

- uses: ./.github/workflows/actions/install

- name: Install optional theme
run: pnpm exec ix-theme-downloader
env:
CSC_TOKEN: ${{ secrets.CSC_TOKEN }}
BRAND_URL: ${{ vars.BRAND_URL }}

- name: Build React Starter
run: pnpm build
env:
REACT_BASE: /ix-starter/react-starter/
VITE_THEME: 1

- name: Deploy GitHub Pages 🚀
uses: JamesIves/github-pages-deploy-action@v4
with:
folder: ./apps/react-starter/dist
target-folder: react-starter
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
.idea
node_modules
.pnp
.pnp.js
Expand Down
1 change: 0 additions & 1 deletion .npmrc

This file was deleted.

30 changes: 28 additions & 2 deletions apps/react-starter/.gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,30 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
yarn-error.log
dist
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
*.tsbuildinfo
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
public/theme
1 change: 1 addition & 0 deletions apps/react-starter/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
9 changes: 0 additions & 9 deletions apps/react-starter/LICENSE.md

This file was deleted.

29 changes: 13 additions & 16 deletions apps/react-starter/README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
# React + TypeScript + Siemens iX + Vite
# `@siemens/ix-react` + React + Vite

This template provides a showcase setup to get React working in Vite with HMR and some ESLint rules.
## Development

## Expanding the ESLint configuration
Execute `pnpm dev`

If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
## Build

- Configure the top-level `parserOptions` property like this:
Execute `pnpm build`

```js
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
project: ['./tsconfig.json', './tsconfig.node.json'],
tsconfigRootDir: __dirname,
},
```
## Testing

- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
- Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
### Unit tests (vitest + @testing-library/react)

Execute `pnpm test`

### E2E tests (playwright)

Execute `pnpm e2e`
70 changes: 70 additions & 0 deletions apps/react-starter/e2e/devices.e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { test, expect, Page } from "@playwright/test";

async function filterDevicePageByDeviceName(page: Page, deviceName: string) {
const filter = page.getByLabel("Filter by");
const filterInput = filter.locator("input");

await filterInput.fill("Device name");

const dropdown = filter.locator("ix-dropdown");
await expect(dropdown.getByText("Categories")).toBeVisible();

await page.keyboard.press("Tab");
await page.keyboard.press("Enter");

await expect(filter.locator("ix-dropdown").getByText("Categories")).not.toBeVisible();
await expect(filter.locator("ix-dropdown").getByText("Device name")).toBeVisible();

await filterInput.fill(deviceName);
await page.keyboard.press("Enter");
await page.mouse.click(0, 0);

await expect(filter.locator("ix-dropdown")).not.toBeVisible();
}

test("filter for specific deviceName", async ({ page }) => {
await page.goto("http://localhost:5173/#/devices");

const aggrid = page.locator(".ag-root-wrapper");
const rows = aggrid.locator(".ag-center-cols-container .ag-row");

await expect(rows).toHaveCount(22, {
// AG-Grid takes some time to filter the rows
timeout: 500,
});

await filterDevicePageByDeviceName(page, "s71200");

await expect(rows).toHaveCount(1, {
// AG-Grid takes some time to filter the rows
timeout: 500,
});
});

test("add a new device", async ({ page }) => {
await page.goto("http://localhost:5173/#/devices");

const newDeviceName = "My new device";

const addDeviceButton = page.getByLabel("add device");
await addDeviceButton.click();

const modal = page.locator("ix-modal");

const device = modal.getByLabel("Device Name");
await device.fill(newDeviceName);

const okayButton = modal.getByLabel("add device");
await okayButton.click();

await expect(modal).not.toBeVisible();
// Wait for the modal to close and the animation to finish
await expect(modal).not.toBeInViewport();

await filterDevicePageByDeviceName(page, newDeviceName);

const aggrid = page.locator(".ag-root-wrapper");
const myNewRow = aggrid.getByRole("gridcell", { name: newDeviceName });

await expect(myNewRow).toBeVisible();
});
28 changes: 28 additions & 0 deletions apps/react-starter/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
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 eslintConfigPrettier from "eslint-config-prettier";

export default tseslint.config(
{ ignores: ["dist"] },
{
extends: [js.configs.recommended, ...tseslint.configs.recommended],
files: ["**/*.{ts,tsx}"],
ignores: ["**/public/**"],
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 }],
},
},
eslintConfigPrettier,
);
Loading

0 comments on commit f7152a3

Please sign in to comment.