Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions .github/workflows/build-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,43 @@ jobs:
- name: Run TSLint
run: |
yarn workspace @telekom/scale-components lint
type-check-react:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v3
with:
node-version: 22

- name: Restore Lerna
id: yarn-cache
uses: actions/cache@v3
with:
path: |
node_modules
*/*/node_modules
key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}

- name: Install project dependencies
if: steps.yarn-cache.outputs.cache-hit != 'true'
run: yarn

- name: Run Lerna bootstrap
if: steps.yarn-cache.outputs.cache-hit != 'true'
run: |
yarn bootstrap

- name: Build Stencil components
run: |
yarn workspace @telekom/scale-components build

- name: Build React wrappers
run: |
yarn workspace @telekom/scale-components-react build

- name: Type-check React wrapper props
run: |
yarn workspace @telekom/scale-components-react test:types
unit-tests:
runs-on: ubuntu-22.04
steps:
Expand Down
142 changes: 142 additions & 0 deletions packages/components-react/__tests__/types.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/**
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file starts with a UTF-8 BOM (U+FEFF). Please remove it to avoid invisible-character diffs and potential issues with some tooling.

Suggested change
/**
/**

Copilot uses AI. Check for mistakes.
* Type-level test for Scale React wrapper components.
* This file is type-checked only (tsc --noEmit), never executed.
* It verifies that generated React wrappers expose Stencil @Prop() as React props.
*/

import {
ScaleAlert,
ScaleButton,
ScaleTag,
ScaleTextField,
ScaleSwitch,
ScaleCheckbox,
ScaleSlider,
ScaleProgressBar,
ScaleCollapsible,
ScaleDropdownSelect,
ScaleDropdownSelectItem,
ScaleRadioButton,
ScaleRadioButtonGroup,
ScaleDatePicker,
ScaleTextarea,
ScaleRatingStars,
ScaleTelekomHeader,
ScaleTelekomNavItem,
} from '../dist/index';
import React from 'react';

// Helper: assert that a JSX expression is valid (compile-time only)
function expectValidJSX(_jsx: React.ReactElement): void {}

// --- ScaleAlert ---
expectValidJSX(<ScaleAlert variant="informational" opened headline="Test" />);
expectValidJSX(<ScaleAlert icon="info" size="small" />);

// --- ScaleButton ---
expectValidJSX(<ScaleButton variant="secondary" size="small" disabled />);
expectValidJSX(<ScaleButton type="submit">Submit</ScaleButton>);

// --- ScaleTag ---
expectValidJSX(
<ScaleTag size="small" color="green">
Active
</ScaleTag>
);
expectValidJSX(<ScaleTag dismissable type="strong" />);

// --- ScaleTextField ---
expectValidJSX(<ScaleTextField label="Name" value="John" required />);
expectValidJSX(
<ScaleTextField label="Email" type="email" helperText="Enter email" />
);

// --- ScaleSwitch ---
expectValidJSX(<ScaleSwitch label="Dark Mode" checked />);

// --- ScaleCheckbox ---
expectValidJSX(<ScaleCheckbox label="Accept terms" checked />);
expectValidJSX(<ScaleCheckbox indeterminate disabled />);

// --- ScaleSlider ---
expectValidJSX(
<ScaleSlider
label="Volume"
min={0}
max={100}
value={50}
showValue
innerAriaValueText="50%"
/>
);

// --- ScaleProgressBar ---
expectValidJSX(
<ScaleProgressBar percentage={75} percentageStart={0} showStatus />
);

// --- ScaleCollapsible ---
expectValidJSX(
<ScaleCollapsible expanded>
<div>Content</div>
</ScaleCollapsible>
);

// --- ScaleDropdownSelect + Item ---
expectValidJSX(
<ScaleDropdownSelect label="Choose" value="a">
<ScaleDropdownSelectItem value="a" selected>
Option A
</ScaleDropdownSelectItem>
<ScaleDropdownSelectItem value="b">Option B</ScaleDropdownSelectItem>
</ScaleDropdownSelect>
);

// --- ScaleRadioButtonGroup + ScaleRadioButton ---
expectValidJSX(
<ScaleRadioButtonGroup label="Choice">
<ScaleRadioButton label="Option 1" value="1" checked />
<ScaleRadioButton label="Option 2" value="2" />
</ScaleRadioButtonGroup>
);

// --- ScaleDatePicker ---
expectValidJSX(<ScaleDatePicker label="Start date" value="2026-01-01" />);

// --- ScaleTextarea ---
expectValidJSX(<ScaleTextarea label="Message" rows={5} required />);

// --- ScaleRatingStars ---
expectValidJSX(
<ScaleRatingStars
size="large"
rating={4}
max={5}
label="Rating"
ariaLabelTranslation="$value out of $max"
disabled={false}
hideLabel={false}
readonly={false}
/>
);

// --- ScaleTelekomHeader ---
expectValidJSX(
<ScaleTelekomHeader appName="My App" appNameLink="/">
<div>Nav</div>
</ScaleTelekomHeader>
);

// --- ScaleTelekomNavItem ---
expectValidJSX(
<ScaleTelekomNavItem active>
<a href="/">Home</a>
</ScaleTelekomNavItem>
);

// --- Negative tests: unknown props should NOT compile ---
// @ts-expect-error — nonExistentProp is not a valid prop
expectValidJSX(<ScaleAlert nonExistentProp="x" />);

// @ts-expect-error — nonExistentProp is not a valid prop
expectValidJSX(<ScaleButton nonExistentProp={42} />);
5 changes: 3 additions & 2 deletions packages/components-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
"zip": "zip -vr telekom-scale-components-react-$npm_package_version.zip dist/ -x '*.DS_Store'",
"clean": "rimraf dist",
"format": "prettier --write \"package.json\"",
"rollup": "rollup -c"
"rollup": "rollup -c",
"test:types": "tsc --noEmit --project tsconfig.test.json"
},
"main": "./dist/index.js",
"module": "./dist/index.es.js",
Expand Down Expand Up @@ -47,7 +48,7 @@
"typescript": "^5.8.3"
},
"dependencies": {
"@stencil/react-output-target": "^1.1.1",
"@stencil/react-output-target": "~1.5.1",
"@types/vfile-message": "^2.0.0"
},
"peerDependencies": {
Expand Down
Loading
Loading