Skip to content

Commit 7fe7b16

Browse files
committed
Merge branch 'main' of https://github.com/kyma-project/busola into kyma-companion
2 parents b8ad577 + 86b9ab4 commit 7fe7b16

File tree

368 files changed

+7499
-6229
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

368 files changed

+7499
-6229
lines changed

.github/workflows/pull-integration-cluster-k3d.yml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,6 @@ jobs:
1616
runs-on: ubuntu-latest
1717
if: github.event.pull_request.draft == false
1818
steps:
19-
- name: Install Chrome # this step could be removed after https://github.com/cypress-io/cypress/issues/30374 is resolved
20-
shell: bash
21-
run: |
22-
wget --no-verbose -O /tmp/chrome.deb https://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-stable/google-chrome-stable_127.0.6533.119-1_amd64.deb
23-
sudo apt install --allow-downgrades -y /tmp/chrome.deb
24-
rm /tmp/chrome.deb
2519
- uses: gardenlinux/workflow-telemetry-action@v2
2620
with:
2721
comment_on_pr: false

.github/workflows/pull-integration-namespace-k3d.yml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,6 @@ jobs:
1616
runs-on: ubuntu-latest
1717
if: github.event.pull_request.draft == false
1818
steps:
19-
- name: Install Chrome
20-
shell: bash
21-
run: |
22-
wget --no-verbose -O /tmp/chrome.deb https://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-stable/google-chrome-stable_127.0.6533.119-1_amd64.deb
23-
sudo apt install --allow-downgrades -y /tmp/chrome.deb
24-
rm /tmp/chrome.deb
2519
- uses: gardenlinux/workflow-telemetry-action@v2
2620
with:
2721
comment_on_pr: false
Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
1-
name: PR Unit Tests
1+
name: PR Unit and Component Tests
22

3-
on:
3+
on:
44
pull_request:
55
types: [opened, edited, synchronize, reopened, ready_for_review]
66
paths:
7-
- ".github/workflows/pull-unit-tests.yml"
8-
- "public/**"
9-
- "src/**"
10-
- "package.json"
7+
- '.github/workflows/pull-unit-tests.yml'
8+
- 'public/**'
9+
- 'src/**'
10+
- 'backend/**'
11+
- 'package.json'
12+
- 'cypress/**'
13+
- 'cypress.config.component.ts'
1114

1215
jobs:
13-
run-unit-test:
16+
run-unit-and-component-test:
1417
runs-on: ubuntu-latest
1518
if: github.event.pull_request.draft == false
1619
steps:
@@ -27,7 +30,11 @@ jobs:
2730
run: |
2831
set -e
2932
npm ci
30-
- name: run_tests
33+
- name: run_unit_tests
3134
shell: bash
32-
run: |
35+
run: |
3336
npm run test
37+
- name: run_component_tests
38+
shell: bash
39+
run: |
40+
npm run component-test-headless

cypress.config.component.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { defineConfig } from 'cypress';
2+
3+
export default defineConfig({
4+
component: {
5+
screenshotOnRunFailure: false,
6+
includeShadowDom: true,
7+
devServer: {
8+
framework: 'react',
9+
bundler: 'vite',
10+
},
11+
specPattern: 'src/**/*.cy.{js,jsx,ts,tsx}',
12+
supportFile: 'cypress/support/component.jsx',
13+
},
14+
});
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
6+
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
7+
<title>Components App</title>
8+
</head>
9+
<body>
10+
<div data-cy-root></div>
11+
</body>
12+
</html>

cypress/support/component.jsx

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/* global Cypress */
2+
import React from 'react';
3+
import { mount } from 'cypress/react18';
4+
import { ThemeProvider } from '@ui5/webcomponents-react';
5+
import { MemoryRouter } from 'react-router-dom';
6+
import { RecoilRoot } from 'recoil';
7+
8+
import i18n from 'i18next';
9+
import { initReactI18next } from 'react-i18next';
10+
import { I18nextProvider } from 'react-i18next';
11+
12+
i18n.use(initReactI18next).init({
13+
lng: 'en',
14+
fallbackLng: false,
15+
nsSeparator: '::',
16+
defaultNS: 'translation',
17+
saveMissing: true,
18+
interpolation: {
19+
escapeValue: false,
20+
},
21+
});
22+
23+
Cypress.Commands.add(
24+
'mount',
25+
(component, { initializeRecoil, ...options } = {}) => {
26+
return mount(
27+
<RecoilRoot initializeState={initializeRecoil}>
28+
<I18nextProvider i18n={i18n}>
29+
<MemoryRouter>
30+
<ThemeProvider>{component}</ThemeProvider>
31+
</MemoryRouter>
32+
</I18nextProvider>
33+
</RecoilRoot>,
34+
options,
35+
);
36+
},
37+
);

docs/contributor/testing-strategy.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Each pull request (PR) to the repository triggers CI/CD jobs that verify the Bus
1212
- `PR Kyma Dashboard Smoke Tests Prod / run-smoke-test-prod` - Performs smoke testing for Busola with PROD environement and configuration related to the Kyma functionalities using a k3d cluster with installed Kyma.
1313
- `PR Lighthouse Test / run-lighthouse-test` - Performs performance testing for Busola - threshold for accessibility: 80, best-practices: 100.
1414
- `PR Lint Check / run-lint-check` - Performing ESlint and Prettier code quality.
15-
- `PR Unit Tests / run-unit-test` - Performs unit tests of the Busola.
15+
- `PR Unit and Component Tests / run-unit-and-component-test` - Performs unit and component tests of Busola.
1616
- `Lint Markdown Links PR / markdown-link-check` - Checks links in documentation.
1717
- `CodeQL / Analyze (javascript)` - Code quality static code check.
1818

100 KB
Loading
29.7 KB
Loading
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# Custom Busola Web Components
2+
3+
Busola provides a suite of custom web components to enhance your application's functionality.
4+
5+
## Utility Functions
6+
7+
All custom web components expose methods to dynamically update their properties, attributes, and slots after initialization.
8+
You can pass the string and boolean properties as standard HTML attributes. For example:
9+
10+
```HTML
11+
<monaco-editor read-only="true"></monaco-editor>
12+
```
13+
14+
You can pass functions, objects, and arrays using the `setProp` function. For example:
15+
16+
```JS
17+
const editor = document.querySelector('monaco-editor');
18+
editor.setProp('on-change', (value) => console.log('New content:', value));
19+
```
20+
21+
You can pass HTML elements using the `setSlot` attribute. For example:
22+
23+
```JS
24+
const dynamicPage = document.querySelector('dynamic-page-component');
25+
const customFooter = document.createElement('div');
26+
customFooter.textContent = 'Custom Footer Content';
27+
dynamicPage.setSlot('footer', customFooter);
28+
```
29+
30+
## Custom Web Components
31+
32+
- [Monaco Editor](#monaco-editor)
33+
- [Dynamic Page](#dynamic-page)
34+
35+
### Monaco Editor
36+
37+
The Monaco Editor component is a versatile code editor. It provides features such as syntax highlighting and autocompletion. It supports the following attributes and properties. Attributes correspond to camel-cased React props when accessed programmatically.
38+
39+
| Parameter | Required | Type | Description |
40+
| --------------------------------- | -------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
41+
| **value** | No | string | The initial code content displayed in the editor. Defaults to an empty string. |
42+
| **placeholder** | No | string | Specifies a short hint about the input field value. |
43+
| **language** | No | string | Specifies the programming language of the editor's content (for example, `javascript`, `json`). Defaults to `javascript`. |
44+
| **height** | No | string | Specifies the height of the component. Must include the unit (e.g., `100px`, `50vh`). |
45+
| **schema-id** | No | string | A unique identifier for the JSON schema used to enable autocompletion and validation. If not provided, autocompletion is disabled. |
46+
| **autocompletion-disabled** | No | boolean | Disables autocompletion suggestions when set to `true`. |
47+
| **read-only** | No | boolean | Specifies if the field is read-only. Defaults to `false`. |
48+
| **on-change** | No | function | Callback function triggered when the content changes. |
49+
| **on-mount** | No | function | Callback function triggered when the editor mounts. |
50+
| **on-blur** | No | function | Callback function triggered when the editor loses focus. |
51+
| **on-focus** | No | function | Callback function triggered when the editor gains focus. |
52+
| **update-value-on-parent-change** | No | boolean | Updates the editor content if the parent component changes its `value` prop. |
53+
| **options** | No | object | Custom options for configuring the Monaco Editor. Refer to the [Monaco Editor API](https://microsoft.github.io/monaco-editor/docs.html#interfaces/editor.IStandaloneEditorConstructionOptions.html) for available options. |
54+
| **error** | No | string | Displays an error message in the editor when provided. If an error is displayed, it indicates that the current input is invalid, but the previous valid input will be used by the editor. |
55+
56+
See the following example:
57+
58+
```HTML
59+
<monaco-editor
60+
value="console.log('Hello!')"
61+
language="javascript"
62+
height="200px"
63+
placeholder="Write some code..."
64+
></monaco-editor>
65+
```
66+
67+
<img src="./assets/MonacoEditor.png" alt="Example of a Monaco Editor" width="70%" style="border: 1px solid #D2D5D9">
68+
69+
### Dynamic Page
70+
71+
The Dynamic Page web component displays content on the page, consisting of a title, a header, a content area, an optional inline edit form, and a floating footer. It supports the following attributes and properties. Attributes correspond to camel-cased React props when accessed programmatically.
72+
73+
| Parameter | Required | Type | Description |
74+
| ------------------------------ | -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
75+
| **title** | No | string | The title of the page displayed in the header. |
76+
| **description** | No | string | A description displayed below the title. |
77+
| **actions** | No | node | Custom actions rendered in the header toolbar. |
78+
| **children** | No | node | Child elements or components to be rendered within the page. |
79+
| **column-wrapper-class-name** | No | string | Additional class names for the column wrapper, used for styling purposes. |
80+
| **content** | No | node | Content displayed in the main section of the page. |
81+
| **footer** | No | node | Content displayed in the footer section. |
82+
| **layout-number** | No | string | Layout identifier for column management. |
83+
| **layout-close-url** | No | string | URL to navigate to when the column layout is closed. |
84+
| **inline-edit-form** | No | function | A function defining the inline edit form. It receives the `stickyHeaderHeight` as an argument and is expected to return a HTML element. |
85+
| **show-yaml-tab** | No | boolean | Specifies whether to show a YAML editing tab. |
86+
| **protected-resource** | No | boolean | Indicates whether the resource is protected. |
87+
| **protected-resource-warning** | No | node | Warning message for protected resources. |
88+
| **class-name** | No | string | Additional class names for the component, used for custom styling. |
89+
| **custom-action-if-form-open** | No | function | Specifies a custom action triggered when a user tries to navigate out of the Edit form tab. It receives four arguments: `isResourceEdited`, `setIsResourceEdited`, `isFormOpen`, `setIsFormOpen`. |
90+
91+
#### `custom-action-if-form-open`
92+
93+
The `custom-action-if-form-open` prop in the Dynamic Page component is a customizable callback function designed to handle specific actions when a form is open. It receives four arguments:
94+
95+
| Argument | Type | Description |
96+
| ----------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------- |
97+
| **isResourceEdited** | object | Indicates if the current resource has been edited. The object has the structure: `{ isEdited: boolean; discardAction?: Function; }` |
98+
| **setIsResourceEdited** | function | A state setter function to update the `isResourceEdited` state. |
99+
| **isFormOpen** | object | Tracks the status of the inline edit form. The object has the structure: `{ formOpen: boolean; leavingForm: boolean; }` |
100+
| **setIsFormOpen** | function | A state setter function to update the `isFormOpen` state. |
101+
102+
See the following example:
103+
104+
```HTML
105+
<dynamic-page-component
106+
title="Sample Page"
107+
description="This is a dynamic page."
108+
show-yaml-tab="true"
109+
class-name="custom-page-class"
110+
>
111+
```
112+
113+
<img src="./assets/DynamicPage.png" alt="Example of a Monaco Editor" width="50%" style="border: 1px solid #D2D5D9">
114+
115+
To see an exemplary configuration of the Busola custom extension feature using web components, check files in [this](examples/../../../examples/busola-web-components/README.md) example.

0 commit comments

Comments
 (0)