@scm-manager/ui-core 4.0.0-REACT19-20250917-125211 → 4.0.0-REACT19-20250922-115826

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,174 +1,27 @@
1
1
  yarn run v1.22.22
2
- $ jest
3
- PASS src/base/helpers/useDocumentTitle.test.ts (11.461 s)
4
- PASS src/base/shortcuts/iterator/keyboardIterator.test.tsx (11.454 s)
5
- PASS src/base/text/textSplitAndReplace.test.ts (13.412 s)
6
- ----------------------------------------|---------|----------|---------|---------|-------------------
7
- File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
8
- ----------------------------------------|---------|----------|---------|---------|-------------------
9
- All files | 2.29 | 2.15 | 1.32 | 2.26 |
10
- src | 0 | 0 | 0 | 0 |
11
- index.ts | 0 | 0 | 0 | 0 |
12
- src/base | 0 | 0 | 0 | 0 |
13
- index.ts | 0 | 0 | 0 | 0 |
14
- src/base/buttons | 0 | 0 | 0 | 0 |
15
- Button.stories.tsx | 0 | 100 | 0 | 0 | 141-229
16
- Button.tsx | 0 | 0 | 0 | 0 | 27-231
17
- Icon.tsx | 0 | 0 | 0 | 0 | 38-39
18
- index.ts | 0 | 0 | 0 | 0 |
19
- src/base/forms | 0 | 0 | 0 | 0 |
20
- AddListEntryForm.tsx | 0 | 0 | 0 | 0 | 27-97
21
- ConfigurationForm.tsx | 0 | 0 | 0 | 0 | 40-47
22
- Form.stories.tsx | 0 | 100 | 0 | 0 | 477-756
23
- Form.tsx | 0 | 0 | 0 | 0 | 32-171
24
- FormPathContext.tsx | 0 | 0 | 0 | 0 | 19-64
25
- FormRow.tsx | 0 | 0 | 0 | 0 | 22-23
26
- ScmFormContext.tsx | 0 | 100 | 0 | 0 | 27-37
27
- ScmFormListContext.tsx | 0 | 0 | 0 | 0 | 24-57
28
- helpers.ts | 0 | 0 | 0 | 0 | 21-61
29
- index.ts | 0 | 100 | 100 | 0 | 53-64
30
- resourceHooks.ts | 0 | 0 | 0 | 0 | 23-151
31
- variants.ts | 0 | 0 | 0 | 0 | 17-19
32
- src/base/forms/base | 0 | 0 | 0 | 0 |
33
- Control.tsx | 0 | 100 | 0 | 0 | 24-25
34
- ExpandableText.tsx | 0 | 100 | 0 | 0 | 40-41
35
- Field.tsx | 0 | 0 | 0 | 0 | 20-25
36
- src/base/forms/base/field-message | 0 | 100 | 0 | 0 |
37
- FieldMessage.tsx | 0 | 100 | 0 | 0 | 23-24
38
- src/base/forms/base/help | 0 | 100 | 0 | 0 |
39
- Help.tsx | 0 | 100 | 0 | 0 | 21-22
40
- src/base/forms/base/label | 0 | 0 | 0 | 0 |
41
- Label.tsx | 0 | 0 | 0 | 0 | 20-25
42
- src/base/forms/checkbox | 0 | 0 | 0 | 0 |
43
- Checkbox.tsx | 0 | 0 | 0 | 0 | 23-62
44
- CheckboxField.tsx | 0 | 100 | 0 | 0 | 24-25
45
- ControlledCheckboxField.tsx | 0 | 0 | 0 | 0 | 46-61
46
- src/base/forms/chip-input | 0 | 0 | 0 | 0 |
47
- ChipInputField.stories.tsx | 0 | 0 | 0 | 0 | 77-147
48
- ChipInputField.tsx | 0 | 0 | 0 | 0 | 31-152
49
- ControlledChipInputField.tsx | 0 | 0 | 0 | 0 | 59-83
50
- src/base/forms/combobox | 0 | 0 | 0 | 0 |
51
- Combobox.stories.tsx | 0 | 100 | 0 | 0 | 128-144
52
- Combobox.tsx | 0 | 0 | 0 | 0 | 24-205
53
- ComboboxField.tsx | 0 | 0 | 0 | 0 | 30-41
54
- ControlledComboboxField.tsx | 0 | 0 | 0 | 0 | 52-74
55
- src/base/forms/headless-chip-input | 0 | 0 | 0 | 0 |
56
- ChipInput.tsx | 0 | 0 | 0 | 0 | 48-221
57
- src/base/forms/input | 0 | 0 | 0 | 0 |
58
- ControlledInputField.tsx | 0 | 0 | 0 | 0 | 48-63
59
- ControlledSecretConfirmationField.tsx | 0 | 0 | 0 | 0 | 55-113
60
- Input.tsx | 0 | 100 | 0 | 0 | 28-29
61
- InputField.tsx | 0 | 0 | 0 | 0 | 45-63
62
- Textarea.tsx | 0 | 100 | 0 | 0 | 28-29
63
- src/base/forms/list | 0 | 0 | 0 | 0 |
64
- ControlledList.tsx | 0 | 0 | 0 | 0 | 47-68
65
- src/base/forms/misc | 0 | 100 | 0 | 0 |
66
- RequiredMarker.tsx | 0 | 100 | 0 | 0 | 19-20
67
- src/base/forms/radio-button | 0 | 0 | 0 | 0 |
68
- ControlledRadioGroupField.tsx | 0 | 0 | 0 | 0 | 51-65
69
- RadioButton.stories.tsx | 0 | 100 | 0 | 0 | 236-379
70
- RadioButton.tsx | 0 | 0 | 0 | 0 | 25-103
71
- RadioButtonContext.tsx | 0 | 100 | 0 | 0 | 27-34
72
- RadioGroup.tsx | 0 | 0 | 0 | 0 | 31-36
73
- RadioGroupField.tsx | 0 | 0 | 0 | 0 | 35-36
74
- src/base/forms/select | 0 | 0 | 0 | 0 |
75
- ControlledSelectField.tsx | 0 | 0 | 0 | 0 | 45-58
76
- Select.tsx | 0 | 0 | 0 | 0 | 33-38
77
- SelectField.tsx | 0 | 0 | 0 | 0 | 38-41
78
- src/base/forms/table | 0 | 0 | 0 | 0 |
79
- ControlledColumn.tsx | 0 | 0 | 0 | 0 | 31-38
80
- ControlledTable.tsx | 0 | 0 | 0 | 0 | 49-84
81
- src/base/helpers | 0 | 0 | 0 | 0 |
82
- devbuild.ts | 0 | 0 | 0 | 0 | 17-35
83
- index.ts | 0 | 0 | 0 | 0 |
84
- useAriaId.tsx | 0 | 0 | 0 | 0 | 19-22
85
- useDocumentTitle.ts | 0 | 0 | 0 | 0 | 29-52
86
- src/base/layout | 0 | 100 | 100 | 0 |
87
- index.ts | 0 | 100 | 100 | 0 | 44-80
88
- src/base/layout/_helpers | 0 | 0 | 0 | 0 |
89
- with-classes.tsx | 0 | 0 | 0 | 0 | 27-38
90
- src/base/layout/card | 0 | 0 | 0 | 0 |
91
- Card.stories.tsx | 0 | 100 | 0 | 0 | 126-147
92
- Card.tsx | 0 | 0 | 0 | 0 | 21-59
93
- CardDetail.tsx | 0 | 0 | 0 | 0 | 24-175
94
- CardRow.tsx | 0 | 100 | 0 | 0 | 26-37
95
- CardTitle.tsx | 0 | 0 | 0 | 0 | 41-42
96
- src/base/layout/card-list | 0 | 100 | 0 | 0 |
97
- CardList.stories.tsx | 0 | 100 | 0 | 0 | 205-279
98
- CardList.tsx | 0 | 100 | 0 | 0 | 29-63
99
- src/base/layout/collapsible | 0 | 0 | 0 | 0 |
100
- Collapsible.stories.tsx | 0 | 100 | 0 | 0 | 44-61
101
- Collapsible.tsx | 0 | 0 | 0 | 0 | 24-68
102
- src/base/layout/tabs | 0 | 0 | 0 | 0 |
103
- TabTrigger.tsx | 0 | 100 | 0 | 0 | 27-28
104
- Tabs.stories.tsx | 0 | 100 | 0 | 0 | 50-69
105
- Tabs.tsx | 0 | 0 | 0 | 0 | 26-37
106
- TabsContent.tsx | 0 | 100 | 100 | 0 | 23
107
- TabsList.tsx | 0 | 100 | 0 | 0 | 27-28
108
- src/base/layout/templates/data-page | 0 | 0 | 0 | 0 |
109
- DataPage.stories.tsx | 0 | 100 | 0 | 0 | 215-322
110
- DataPageHeader.tsx | 0 | 0 | 0 | 0 | 27-89
111
- src/base/misc | 0 | 0 | 0 | 0 |
112
- Image.tsx | 0 | 0 | 0 | 0 | 22-23
113
- Level.tsx | 0 | 0 | 0 | 0 | 26-27
114
- Loading.tsx | 0 | 100 | 0 | 0 | 23-36
115
- SubSubtitle.tsx | 0 | 0 | 0 | 0 | 22-23
116
- Subtitle.tsx | 0 | 0 | 0 | 0 | 22-23
117
- Title.tsx | 0 | 0 | 0 | 0 | 27-44
118
- index.ts | 0 | 0 | 0 | 0 |
119
- src/base/notifications | 0 | 0 | 0 | 0 |
120
- BackendErrorNotification.tsx | 0 | 0 | 0 | 0 | 26-136
121
- ErrorNotification.tsx | 0 | 0 | 0 | 0 | 28-63
122
- Notification.tsx | 0 | 0 | 0 | 0 | 29-32
123
- index.tsx | 0 | 0 | 0 | 0 |
124
- src/base/overlays | 0 | 100 | 100 | 0 |
125
- index.ts | 0 | 100 | 100 | 0 | 23-32
126
- src/base/overlays/dialog | 0 | 0 | 0 | 0 |
127
- Dialog.stories.tsx | 0 | 100 | 0 | 0 | 69-86
128
- Dialog.tsx | 0 | 0 | 0 | 0 | 25-49
129
- src/base/overlays/menu | 0 | 0 | 0 | 0 |
130
- Menu.stories.tsx | 0 | 100 | 0 | 0 | 79-103
131
- Menu.tsx | 0 | 0 | 0 | 0 | 37-185
132
- MenuTrigger.tsx | 0 | 100 | 0 | 0 | 29-43
133
- src/base/overlays/popover | 0 | 100 | 0 | 0 |
134
- Popover.stories.tsx | 0 | 100 | 0 | 0 | 21-46
135
- Popover.tsx | 0 | 100 | 0 | 0 | 23-63
136
- src/base/overlays/tooltip | 0 | 0 | 0 | 0 |
137
- ExpandableHint.tsx | 0 | 0 | 0 | 0 | 29-59
138
- Tooltip.examples.js | 0 | 100 | 100 | 0 | 18-25
139
- Tooltip.tsx | 0 | 100 | 0 | 0 | 22-62
140
- src/base/shortcuts | 0 | 0 | 0 | 0 |
141
- index.ts | 0 | 0 | 0 | 0 |
142
- usePauseShortcuts.ts | 0 | 0 | 0 | 0 | 27-33
143
- useShortcut.ts | 0 | 0 | 0 | 0 | 76-99
144
- useShortcutDocs.tsx | 0 | 100 | 0 | 0 | 25-44
145
- src/base/shortcuts/iterator | 0 | 0 | 0 | 0 |
146
- callbackIterator.ts | 0 | 0 | 0 | 0 | 19-252
147
- keyboardIterator.tsx | 0 | 0 | 0 | 0 | 28-193
148
- src/base/status | 0 | 0 | 0 | 0 |
149
- StatusIcon.stories.tsx | 0 | 100 | 0 | 0 | 71-106
150
- StatusIcon.tsx | 0 | 0 | 0 | 0 | 21-109
151
- index.ts | 0 | 0 | 0 | 0 |
152
- src/base/text | 56.52 | 66.66 | 45.45 | 55.55 |
153
- SplitAndReplace.stories.tsx | 0 | 100 | 0 | 0 | 82-141
154
- SplitAndReplace.tsx | 0 | 0 | 0 | 0 | 32-52
155
- index.ts | 0 | 0 | 0 | 0 |
156
- textSplitAndReplace.ts | 100 | 100 | 100 | 100 |
157
- src/routing | 0 | 0 | 0 | 0 |
158
- admin.ts | 0 | 100 | 100 | 0 | 17-35
159
- group.ts | 0 | 100 | 100 | 0 | 17-20
160
- help.ts | 0 | 100 | 100 | 0 | 17-19
161
- import.ts | 0 | 100 | 100 | 0 | 17
162
- index.ts | 0 | 0 | 0 | 0 |
163
- me.ts | 0 | 100 | 100 | 0 | 17-19
164
- namespace.ts | 0 | 0 | 0 | 0 | 21-51
165
- repository.ts | 0 | 0 | 0 | 0 | 21-89
166
- user.ts | 0 | 100 | 100 | 0 | 17-20
167
- ----------------------------------------|---------|----------|---------|---------|-------------------
2
+ $ vitest
168
3
 
169
- Test Suites: 3 passed, 3 total
170
- Tests: 9 passed, 9 total
171
- Snapshots: 0 total
172
- Time: 39.418 s
173
- Ran all test suites.
174
- Done in 41.46s.
4
+  RUN  v3.2.4 /tmp/workspace/manager_feature_react-19-upgrade/scm-ui/ui-core
5
+ Coverage enabled with v8
6
+
7
+ ✓ src/base/text/textSplitAndReplace.test.ts (7 tests) 48ms
8
+ stderr | src/base/helpers/useDocumentTitle.test.tsx > useDocumentTitle > should set document title
9
+ react-i18next:: You will need to pass in an i18next instance by using initReactI18next
10
+
11
+ ✓ src/base/helpers/useDocumentTitle.test.tsx (4 tests) 254ms
12
+ ✓ src/base/shortcuts/iterator/keyboardIterator.test.tsx (17 tests) 921ms
13
+
14
+  Test Files  3 passed (3)
15
+  Tests  28 passed (28)
16
+  Start at  11:34:11
17
+  Duration  11.77s (transform 1.39s, setup 0ms, collect 5.73s, tests 1.22s, environment 11.48s, prepare 2.79s)
18
+
19
+ JUNIT report written to /tmp/workspace/manager_feature_react-19-upgrade/scm-ui/build/jest-reports/TEST-vitest-report.xml
20
+  % Coverage report from v8
21
+ ----------|---------|----------|---------|---------|-------------------
22
+ File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
23
+ ----------|---------|----------|---------|---------|-------------------
24
+ All files | 0 | 100 | 100 | 0 |
25
+ index.ts | 0 | 100 | 100 | 0 | 17-18
26
+ ----------|---------|----------|---------|---------|-------------------
27
+ Done in 14.80s.
@@ -1,3 +1,3 @@
1
1
  yarn run v1.22.22
2
2
  $ tsc
3
- Done in 32.49s.
3
+ Done in 29.23s.
@@ -5,7 +5,7 @@ import { Button } from "../src";
5
5
 
6
6
  # Buttons
7
7
 
8
- The `@scm-manager/ui-buttons` library provides [atoms](https://atomicdesign.bradfrost.com/chapter-2/#atoms) implemented
8
+ The buttons directory in the `@scm-manager/ui-core` library provides [atoms](https://atomicdesign.bradfrost.com/chapter-2/#atoms) implemented
9
9
  as minimal wrappers around native html elements styled to match the general SCM-Manager aesthetic.
10
10
 
11
11
  ## Components
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@scm-manager/ui-core",
3
- "version": "4.0.0-REACT19-20250917-125211",
3
+ "version": "4.0.0-REACT19-20250922-115826",
4
4
  "main": "./src/index.ts",
5
5
  "license": "AGPL-3.0-only",
6
6
  "scripts": {
7
+ "test": "vitest",
7
8
  "typecheck": "tsc",
8
9
  "storybook": "storybook dev -p 6006",
9
- "build-storybook": "storybook build",
10
- "test": "jest"
10
+ "build-storybook": "storybook build"
11
11
  },
12
12
  "peerDependencies": {
13
13
  "@headlessui/react": "^2.2.7",
@@ -30,7 +30,7 @@
30
30
  "@radix-ui/react-tabs": "^1.0.4",
31
31
  "@radix-ui/react-tooltip": "1.0.2",
32
32
  "@radix-ui/react-visually-hidden": "^1.0.3",
33
- "@scm-manager/ui-api": "4.0.0-REACT19-20250917-125211",
33
+ "@scm-manager/ui-api": "4.0.0-REACT19-20250922-115826",
34
34
  "mousetrap": "1.6.5"
35
35
  },
36
36
  "devDependencies": {
@@ -39,7 +39,7 @@
39
39
  "@scm-manager/eslint-config": "^2.18.2",
40
40
  "@scm-manager/prettier-config": "^2.12.0",
41
41
  "@scm-manager/tsconfig": "^2.12.0",
42
- "@scm-manager/ui-types": "4.0.0-REACT19-20250917-125211",
42
+ "@scm-manager/ui-types": "4.0.0-REACT19-20250922-115826",
43
43
  "@storybook/addon-actions": "^9.0.8",
44
44
  "@storybook/addon-docs": "^9.1.5",
45
45
  "@storybook/addon-essentials": "^9.0.0-alpha.12",
@@ -51,15 +51,17 @@
51
51
  "@tanstack/react-query-devtools": "4.40.1",
52
52
  "@types/mousetrap": "1.6.5",
53
53
  "@vitejs/plugin-react": "^5.0.2",
54
+ "@vitest/coverage-v8": "^3.2.4",
54
55
  "babel-loader": "^8.2.5",
56
+ "ci-info": "^4.3.1",
55
57
  "html-webpack-plugin": "^5.5.0",
56
58
  "i18next": "21",
57
59
  "i18next-fetch-backend": "4",
58
- "jest-extended": "3.1.0",
59
60
  "mini-css-extract-plugin": "^2.4.3",
60
61
  "minimatch": "^10.0.3",
61
62
  "storybook-addon-pseudo-states": "^9.1.5",
62
- "vite": "^7.1.4",
63
+ "vite": "7.1.5",
64
+ "vitest": "^3.2.4",
63
65
  "webpack": "^5.72.0"
64
66
  },
65
67
  "prettier": "@scm-manager/prettier-config",
@@ -68,11 +70,5 @@
68
70
  },
69
71
  "publishConfig": {
70
72
  "access": "public"
71
- },
72
- "jest": {
73
- "preset": "@scm-manager/jest-preset",
74
- "setupFilesAfterEnv": [
75
- "jest-extended/all"
76
- ]
77
73
  }
78
74
  }
@@ -14,6 +14,9 @@
14
14
  * along with this program. If not, see https://www.gnu.org/licenses/.
15
15
  */
16
16
 
17
+ import React from "react";
18
+ import { render } from "@testing-library/react";
19
+
17
20
  export const isDevBuild = () =>
18
21
  ((window as unknown as { scmStage: string }).scmStage || "").toUpperCase() !== "PRODUCTION";
19
22
 
@@ -34,3 +37,13 @@ const normalizeTestId = (testId?: string) => {
34
37
  }
35
38
  return id;
36
39
  };
40
+
41
+ export const renderTestHook = <T,>(hook: () => T, wrapper?: React.ComponentType<{ children?: React.ReactNode }>) => {
42
+ let result = undefined as unknown as T;
43
+ function HookComponent() {
44
+ result = hook();
45
+ return null;
46
+ }
47
+ const { unmount } = render(<HookComponent />, { wrapper });
48
+ return { result, unmount };
49
+ };
@@ -14,33 +14,26 @@
14
14
  * along with this program. If not, see https://www.gnu.org/licenses/.
15
15
  */
16
16
 
17
- //TODO Fix renderHook import
18
- //import { renderHook } from "@testing-library/react-hooks";
19
17
  import { Repository } from "@scm-manager/ui-types";
20
18
  import { binder } from "@scm-manager/ui-extensions";
21
19
  import useDocumentTitle, { useDocumentTitleForRepository } from "./useDocumentTitle";
20
+ import { renderTestHook } from "./devbuild";
22
21
 
23
- describe("Temporary test to be removed", () => {
24
- it("true", () => {
25
- expect(true).toBeTrue();
26
- });
27
- });
28
-
29
- /*describe("useDocumentTitle", () => {
22
+ describe("useDocumentTitle", () => {
30
23
  it("should set document title", () => {
31
- renderHook(() => useDocumentTitle("Part1", "Part2"));
24
+ renderTestHook(() => useDocumentTitle("Part1", "Part2"));
32
25
  expect(document.title).toBe("Part1 - Part2 - documentTitle.suffix");
33
26
  });
34
27
 
35
28
  it("should append title if extension is a string", () => {
36
29
  binder.getExtension = () => ({ documentTitle: "myInstance" });
37
- renderHook(() => useDocumentTitle("Part1", "Part2"));
30
+ renderTestHook(() => useDocumentTitle("Part1", "Part2"));
38
31
  expect(document.title).toBe("Part1 - Part2 - documentTitle.suffix (myInstance)");
39
32
  });
40
33
 
41
34
  it("should modify title if extension is a function", () => {
42
35
  binder.getExtension = () => ({ documentTitle: (title: string) => `Modified: ${title}` });
43
- renderHook(() => useDocumentTitle("Part1", "Part2"));
36
+ renderTestHook(() => useDocumentTitle("Part1", "Part2"));
44
37
  expect(document.title).toBe("Modified: Part1 - Part2 - documentTitle.suffix");
45
38
  });
46
39
  });
@@ -50,7 +43,7 @@ describe("useDocumentTitleForRepository", () => {
50
43
 
51
44
  it("should set the document title for a repository", () => {
52
45
  binder.getExtension = () => ({ documentTitle: (title: string) => `Repository: ${title}` });
53
- renderHook(() => useDocumentTitleForRepository(repository, "Part1", "Part2"));
46
+ renderTestHook(() => useDocumentTitleForRepository(repository, "Part1", "Part2"));
54
47
  expect(document.title).toBe("Repository: Part1 - Part2 - namespace/name - documentTitle.suffix");
55
48
  });
56
- });*/
49
+ });
@@ -14,28 +14,20 @@
14
14
  * along with this program. If not, see https://www.gnu.org/licenses/.
15
15
  */
16
16
 
17
- //TODO Fix renderHook import
18
- //import { renderHook } from "@testing-library/react-hooks";
19
17
  import React, { FC, ReactNode } from "react";
18
+ import { render } from "@testing-library/react";
19
+ import Mousetrap from "mousetrap";
20
+ import { renderTestHook } from "../../helpers/devbuild";
21
+ import { ShortcutDocsContextProvider } from "../useShortcutDocs";
20
22
  import {
21
23
  KeyboardIteratorContextProvider,
22
24
  KeyboardSubIterator,
23
25
  KeyboardSubIteratorContextProvider,
24
26
  useKeyboardIteratorItem,
25
27
  } from "./keyboardIterator";
26
- import { render } from "@testing-library/react";
27
- import { ShortcutDocsContextProvider } from "../useShortcutDocs";
28
- import Mousetrap from "mousetrap";
29
- import "jest-extended";
30
-
31
- describe("Temporary test to be removed", () => {
32
- it("true", () => {
33
- expect(true).toBeTrue();
34
- });
35
- });
36
28
 
37
- /*jest.mock("react-i18next", () => ({
38
- useTranslation: () => [jest.fn()],
29
+ vi.mock("react-i18next", () => ({
30
+ useTranslation: () => [vi.fn()],
39
31
  }));
40
32
 
41
33
  const Wrapper: FC<{ initialIndex?: number; children?: ReactNode }> = ({ children, initialIndex }) => {
@@ -50,10 +42,13 @@ const DocsWrapper: FC<{ children?: ReactNode }> = ({ children }) => (
50
42
  <ShortcutDocsContextProvider>{children}</ShortcutDocsContextProvider>
51
43
  );
52
44
 
53
- const createWrapper =
54
- (initialIndex?: number): FC<{ children?: ReactNode }> =>
55
- ({ children }) =>
56
- <Wrapper initialIndex={initialIndex}>{children}</Wrapper>;
45
+ const createWrapper = (initialIndex?: number): FC<{ children?: ReactNode }> => {
46
+ const Component: FC<{ children?: ReactNode }> = ({ children }) => (
47
+ <Wrapper initialIndex={initialIndex}>{children}</Wrapper>
48
+ );
49
+ Component.displayName = "CreateWrapper";
50
+ return Component;
51
+ };
57
52
 
58
53
  const Item: FC<{ callback: () => void }> = ({ callback }) => {
59
54
  useKeyboardIteratorItem(callback);
@@ -74,36 +69,33 @@ describe("shortcutIterator", () => {
74
69
  beforeEach(() => Mousetrap.reset());
75
70
 
76
71
  it("should not call callback upon registration", () => {
77
- const callback = jest.fn();
72
+ const callback = vi.fn();
78
73
 
79
- renderHook(() => useKeyboardIteratorItem(callback), {
80
- wrapper: Wrapper,
81
- });
74
+ renderTestHook(() => useKeyboardIteratorItem(callback), Wrapper);
82
75
 
83
76
  expect(callback).not.toHaveBeenCalled();
84
77
  });
85
78
 
86
79
  it("should not throw if not inside keyboard iterator context", () => {
87
- const callback = jest.fn();
80
+ const callback = vi.fn();
88
81
 
89
- const { result, unmount } = renderHook(() => useKeyboardIteratorItem(callback), {
90
- wrapper: DocsWrapper,
91
- });
92
-
93
- unmount();
82
+ const callHook = () => {
83
+ const { unmount } = renderTestHook(() => useKeyboardIteratorItem(callback), DocsWrapper);
84
+ unmount();
85
+ };
94
86
 
95
- expect(result.error).toBeUndefined();
87
+ expect(callHook).not.toThrow();
96
88
  });
97
89
 
98
90
  it("should call first callback upon pressing forward in initial state", async () => {
99
- const callback = jest.fn();
100
- const callback2 = jest.fn();
101
- const callback3 = jest.fn();
91
+ const callback = vi.fn();
92
+ const callback2 = vi.fn();
93
+ const callback3 = vi.fn();
102
94
 
103
95
  render(
104
96
  <Wrapper>
105
97
  <List callbacks={[callback, callback2, callback3]} />
106
- </Wrapper>
98
+ </Wrapper>,
107
99
  );
108
100
 
109
101
  Mousetrap.trigger("j");
@@ -114,14 +106,14 @@ describe("shortcutIterator", () => {
114
106
  });
115
107
 
116
108
  it("should call last callback once upon pressing backward in initial state", async () => {
117
- const callback = jest.fn();
118
- const callback2 = jest.fn();
119
- const callback3 = jest.fn();
109
+ const callback = vi.fn();
110
+ const callback2 = vi.fn();
111
+ const callback3 = vi.fn();
120
112
 
121
113
  render(
122
114
  <Wrapper>
123
115
  <List callbacks={[callback, callback2, callback3]} />
124
- </Wrapper>
116
+ </Wrapper>,
125
117
  );
126
118
 
127
119
  Mousetrap.trigger("k");
@@ -132,14 +124,14 @@ describe("shortcutIterator", () => {
132
124
  });
133
125
 
134
126
  it("should not allow moving past the end of the callback array", async () => {
135
- const callback = jest.fn();
136
- const callback2 = jest.fn();
137
- const callback3 = jest.fn();
127
+ const callback = vi.fn();
128
+ const callback2 = vi.fn();
129
+ const callback3 = vi.fn();
138
130
 
139
131
  render(
140
132
  <Wrapper initialIndex={1}>
141
133
  <List callbacks={[callback, callback2, callback3]} />
142
- </Wrapper>
134
+ </Wrapper>,
143
135
  );
144
136
 
145
137
  Mousetrap.trigger("j");
@@ -151,9 +143,9 @@ describe("shortcutIterator", () => {
151
143
  });
152
144
 
153
145
  it("should move to existing index when active index is at the end and last callback is deregistered", async () => {
154
- const callback = jest.fn();
155
- const callback2 = jest.fn();
156
- const callback3 = jest.fn();
146
+ const callback = vi.fn();
147
+ const callback2 = vi.fn();
148
+ const callback3 = vi.fn();
157
149
 
158
150
  const { rerender } = render(<List callbacks={[callback, callback2, callback3]} />, {
159
151
  wrapper: createWrapper(2),
@@ -171,9 +163,9 @@ describe("shortcutIterator", () => {
171
163
  });
172
164
 
173
165
  it("should move to existing index when active index is at the beginning and first callback is deregistered", async () => {
174
- const callback = jest.fn();
175
- const callback2 = jest.fn();
176
- const callback3 = jest.fn();
166
+ const callback = vi.fn();
167
+ const callback2 = vi.fn();
168
+ const callback3 = vi.fn();
177
169
 
178
170
  const { rerender } = render(<List callbacks={[callback, callback2, callback3]} />, {
179
171
  wrapper: createWrapper(0),
@@ -191,9 +183,9 @@ describe("shortcutIterator", () => {
191
183
  });
192
184
 
193
185
  it("should move to existing index when active index is at the end and first callback is deregistered", async () => {
194
- const callback = jest.fn();
195
- const callback2 = jest.fn();
196
- const callback3 = jest.fn();
186
+ const callback = vi.fn();
187
+ const callback2 = vi.fn();
188
+ const callback3 = vi.fn();
197
189
 
198
190
  const { rerender } = render(<List callbacks={[callback, callback2, callback3]} />, {
199
191
  wrapper: createWrapper(2),
@@ -211,9 +203,9 @@ describe("shortcutIterator", () => {
211
203
  });
212
204
 
213
205
  it("should move to existing index when active index in the middle is deregistered", async () => {
214
- const callback = jest.fn();
215
- const callback2 = jest.fn();
216
- const callback3 = jest.fn();
206
+ const callback = vi.fn();
207
+ const callback2 = vi.fn();
208
+ const callback3 = vi.fn();
217
209
 
218
210
  const { rerender } = render(<List callbacks={[callback, callback2, callback3]} />, {
219
211
  wrapper: createWrapper(1),
@@ -231,9 +223,9 @@ describe("shortcutIterator", () => {
231
223
  });
232
224
 
233
225
  it("should not move on deregistration if iterator is not active", async () => {
234
- const callback = jest.fn();
235
- const callback2 = jest.fn();
236
- const callback3 = jest.fn();
226
+ const callback = vi.fn();
227
+ const callback2 = vi.fn();
228
+ const callback3 = vi.fn();
237
229
 
238
230
  const { rerender } = render(<List callbacks={[callback, callback2, callback3]} />, {
239
231
  wrapper: createWrapper(),
@@ -251,7 +243,7 @@ describe("shortcutIterator", () => {
251
243
  });
252
244
 
253
245
  it("should not explode if the last item in the list is removed", async () => {
254
- const callback = jest.fn();
246
+ const callback = vi.fn();
255
247
 
256
248
  const { rerender } = render(<List callbacks={[callback]} />, {
257
249
  wrapper: createWrapper(),
@@ -266,9 +258,9 @@ describe("shortcutIterator", () => {
266
258
 
267
259
  describe("With Subiterator", () => {
268
260
  it("should call in correct order", () => {
269
- const callback = jest.fn();
270
- const callback2 = jest.fn();
271
- const callback3 = jest.fn();
261
+ const callback = vi.fn();
262
+ const callback2 = vi.fn();
263
+ const callback3 = vi.fn();
272
264
 
273
265
  render(
274
266
  <Wrapper>
@@ -276,7 +268,7 @@ describe("shortcutIterator", () => {
276
268
  <List callbacks={[callback, callback2]} />
277
269
  </KeyboardSubIterator>
278
270
  <List callbacks={[callback3]} />
279
- </Wrapper>
271
+ </Wrapper>,
280
272
  );
281
273
 
282
274
  Mousetrap.trigger("j");
@@ -289,9 +281,9 @@ describe("shortcutIterator", () => {
289
281
  });
290
282
 
291
283
  it("should call first target that is not an empty subiterator", () => {
292
- const callback = jest.fn();
293
- const callback2 = jest.fn();
294
- const callback3 = jest.fn();
284
+ const callback = vi.fn();
285
+ const callback2 = vi.fn();
286
+ const callback3 = vi.fn();
295
287
 
296
288
  render(
297
289
  <Wrapper>
@@ -302,7 +294,7 @@ describe("shortcutIterator", () => {
302
294
  <List callbacks={[]} />
303
295
  </KeyboardSubIterator>
304
296
  <List callbacks={[callback, callback2, callback3]} />
305
- </Wrapper>
297
+ </Wrapper>,
306
298
  );
307
299
 
308
300
  Mousetrap.trigger("j");
@@ -313,9 +305,9 @@ describe("shortcutIterator", () => {
313
305
  });
314
306
 
315
307
  it("should skip empty sub-iterators during navigation", () => {
316
- const callback = jest.fn();
317
- const callback2 = jest.fn();
318
- const callback3 = jest.fn();
308
+ const callback = vi.fn();
309
+ const callback2 = vi.fn();
310
+ const callback3 = vi.fn();
319
311
 
320
312
  render(
321
313
  <Wrapper>
@@ -327,7 +319,7 @@ describe("shortcutIterator", () => {
327
319
  <List callbacks={[]} />
328
320
  </KeyboardSubIterator>
329
321
  <List callbacks={[callback2, callback3]} />
330
- </Wrapper>
322
+ </Wrapper>,
331
323
  );
332
324
 
333
325
  Mousetrap.trigger("j");
@@ -340,9 +332,9 @@ describe("shortcutIterator", () => {
340
332
  });
341
333
 
342
334
  it("should not enter subiterator if its empty", () => {
343
- const callback = jest.fn();
344
- const callback2 = jest.fn();
345
- const callback3 = jest.fn();
335
+ const callback = vi.fn();
336
+ const callback2 = vi.fn();
337
+ const callback3 = vi.fn();
346
338
 
347
339
  render(
348
340
  <Wrapper initialIndex={1}>
@@ -350,7 +342,7 @@ describe("shortcutIterator", () => {
350
342
  <List callbacks={[]} />
351
343
  </KeyboardSubIterator>
352
344
  <List callbacks={[callback, callback2, callback3]} />
353
- </Wrapper>
345
+ </Wrapper>,
354
346
  );
355
347
 
356
348
  Mousetrap.trigger("k");
@@ -361,9 +353,9 @@ describe("shortcutIterator", () => {
361
353
  });
362
354
 
363
355
  it("should not loop", () => {
364
- const callback = jest.fn();
365
- const callback2 = jest.fn();
366
- const callback3 = jest.fn();
356
+ const callback = vi.fn();
357
+ const callback2 = vi.fn();
358
+ const callback3 = vi.fn();
367
359
 
368
360
  render(
369
361
  <Wrapper initialIndex={1}>
@@ -371,7 +363,7 @@ describe("shortcutIterator", () => {
371
363
  <List callbacks={[callback, callback2]} />
372
364
  </KeyboardSubIterator>
373
365
  <List callbacks={[callback3]} />
374
- </Wrapper>
366
+ </Wrapper>,
375
367
  );
376
368
 
377
369
  Mousetrap.trigger("k");
@@ -387,10 +379,10 @@ describe("shortcutIterator", () => {
387
379
  });
388
380
 
389
381
  it("should move subiterator if its active callback is de-registered", () => {
390
- const callback = jest.fn();
391
- const callback2 = jest.fn();
392
- const callback3 = jest.fn();
393
- const callback4 = jest.fn();
382
+ const callback = vi.fn();
383
+ const callback2 = vi.fn();
384
+ const callback3 = vi.fn();
385
+ const callback4 = vi.fn();
394
386
 
395
387
  const { rerender } = render(
396
388
  <>
@@ -401,7 +393,7 @@ describe("shortcutIterator", () => {
401
393
  </>,
402
394
  {
403
395
  wrapper: createWrapper(0),
404
- }
396
+ },
405
397
  );
406
398
 
407
399
  expect(callback).not.toHaveBeenCalled();
@@ -415,7 +407,7 @@ describe("shortcutIterator", () => {
415
407
  <List callbacks={[callback, callback3]} />
416
408
  </KeyboardSubIteratorContextProvider>
417
409
  <List callbacks={[callback4]} />
418
- </>
410
+ </>,
419
411
  );
420
412
 
421
413
  expect(callback).toHaveBeenCalledTimes(1);
@@ -424,4 +416,4 @@ describe("shortcutIterator", () => {
424
416
  expect(callback4).not.toHaveBeenCalled();
425
417
  });
426
418
  });
427
- });*/
419
+ });
@@ -35,7 +35,7 @@ describe("text split and replace", () => {
35
35
  const result = textSplitAndReplace<Wrapped>(
36
36
  "Don't Panic.",
37
37
  [{ textToReplace: "'", replacement: { text: "`" } }],
38
- testWrapper
38
+ testWrapper,
39
39
  );
40
40
  expect(result).toHaveLength(3);
41
41
  expect(result[0]).toStrictEqual({ text: "Don" });
@@ -47,7 +47,7 @@ describe("text split and replace", () => {
47
47
  const result = textSplitAndReplace<Wrapped>(
48
48
  "'So this is it,' said Arthur, 'We are going to die.'",
49
49
  [{ textToReplace: "'", replacement: { text: "“" } }],
50
- testWrapper
50
+ testWrapper,
51
51
  );
52
52
  expect(result).toHaveLength(2);
53
53
  expect(result[0]).toStrictEqual({ text: "“" });
@@ -58,7 +58,7 @@ describe("text split and replace", () => {
58
58
  const result = textSplitAndReplace<Wrapped>(
59
59
  "'So this is it,' said Arthur, 'We are going to die.'",
60
60
  [{ textToReplace: "'", replacement: { text: "“" }, replaceAll: true }],
61
- testWrapper
61
+ testWrapper,
62
62
  );
63
63
  expect(result).toHaveLength(7);
64
64
  expect(result[0]).toStrictEqual({ text: "“" });
@@ -77,7 +77,7 @@ describe("text split and replace", () => {
77
77
  { textToReplace: "'", replacement: { text: "“" }, replaceAll: true },
78
78
  { textToReplace: "Arthur", replacement: { text: "Dent" }, replaceAll: true },
79
79
  ],
80
- testWrapper
80
+ testWrapper,
81
81
  );
82
82
  expect(result).toHaveLength(9);
83
83
  expect(result[0]).toStrictEqual({ text: "“" });
@@ -100,7 +100,7 @@ describe("text split and replace", () => {
100
100
  { textToReplace: "d A", replacement: { text: "to be ignored 2" }, replaceAll: true },
101
101
  { textToReplace: "Arthur,", replacement: { text: "to be ignored 3" }, replaceAll: true },
102
102
  ],
103
- testWrapper
103
+ testWrapper,
104
104
  );
105
105
  expect(result).toHaveLength(3);
106
106
  expect(result[0]).toStrictEqual({ text: "'So this is it,' " });
@@ -116,7 +116,7 @@ describe("text split and replace", () => {
116
116
  { textToReplace: " said Arthur, ", replacement: { text: "two" } },
117
117
  { textToReplace: "'We are going to die.'", replacement: { text: "three" } },
118
118
  ],
119
- testWrapper
119
+ testWrapper,
120
120
  );
121
121
  expect(result).toHaveLength(3);
122
122
  expect(result[0]).toStrictEqual({ text: "one" });
package/tsconfig.json CHANGED
@@ -1,6 +1,9 @@
1
1
  {
2
2
  "extends": "@scm-manager/tsconfig",
3
+ "compilerOptions": {
4
+ "types": ["vitest/globals"]
5
+ },
3
6
  "include": [
4
- "./src",
7
+ "src/**/*"
5
8
  ]
6
9
  }
@@ -0,0 +1,36 @@
1
+ /*
2
+ * Copyright (c) 2020 - present Cloudogu GmbH
3
+ *
4
+ * This program is free software: you can redistribute it and/or modify it under
5
+ * the terms of the GNU Affero General Public License as published by the Free
6
+ * Software Foundation, version 3.
7
+ *
8
+ * This program is distributed in the hope that it will be useful, but WITHOUT
9
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10
+ * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
11
+ * details.
12
+ *
13
+ * You should have received a copy of the GNU Affero General Public License
14
+ * along with this program. If not, see https://www.gnu.org/licenses/.
15
+ */
16
+
17
+ import { defineConfig } from "vitest/config";
18
+ import { isCI } from "ci-info";
19
+
20
+ export default defineConfig({
21
+ test: {
22
+ globals: true,
23
+ environment: "jsdom",
24
+ reporters: ["default", "junit"],
25
+ outputFile: {
26
+ junit: "../build/jest-reports/TEST-vitest-report.xml",
27
+ },
28
+ coverage: {
29
+ enabled: isCI,
30
+ reporter: ["text", "lcov", "html"],
31
+ provider: "v8",
32
+ reportsDirectory: "../build/coverage-ui-core",
33
+ include: ["src/*.ts", "src/*.tsx"],
34
+ },
35
+ },
36
+ });