@simplysm/solid 13.0.70 → 13.0.71

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.
Files changed (98) hide show
  1. package/README.md +1 -1
  2. package/dist/components/disclosure/Dropdown.d.ts +6 -4
  3. package/dist/components/disclosure/Dropdown.d.ts.map +1 -1
  4. package/dist/components/disclosure/Dropdown.js +24 -8
  5. package/dist/components/disclosure/Dropdown.js.map +2 -2
  6. package/dist/components/disclosure/dialogZIndex.d.ts +2 -0
  7. package/dist/components/disclosure/dialogZIndex.d.ts.map +1 -1
  8. package/dist/components/disclosure/dialogZIndex.js +4 -0
  9. package/dist/components/disclosure/dialogZIndex.js.map +1 -1
  10. package/dist/components/features/crud-detail/CrudDetail.d.ts.map +1 -1
  11. package/dist/components/features/crud-detail/CrudDetail.js +16 -7
  12. package/dist/components/features/crud-detail/CrudDetail.js.map +2 -2
  13. package/dist/components/features/crud-sheet/CrudSheet.d.ts.map +1 -1
  14. package/dist/components/features/crud-sheet/CrudSheet.js +14 -5
  15. package/dist/components/features/crud-sheet/CrudSheet.js.map +2 -2
  16. package/dist/components/features/crudRegistry.d.ts +16 -0
  17. package/dist/components/features/crudRegistry.d.ts.map +1 -0
  18. package/dist/components/features/crudRegistry.js +37 -0
  19. package/dist/components/features/crudRegistry.js.map +6 -0
  20. package/dist/components/features/permission-table/PermissionTable.d.ts.map +1 -1
  21. package/dist/components/features/permission-table/PermissionTable.js +71 -86
  22. package/dist/components/features/permission-table/PermissionTable.js.map +2 -2
  23. package/dist/components/features/shared-data/SharedDataSelect.js +2 -4
  24. package/dist/components/features/shared-data/SharedDataSelect.js.map +2 -2
  25. package/dist/components/features/shared-data/SharedDataSelectList.d.ts +2 -4
  26. package/dist/components/features/shared-data/SharedDataSelectList.d.ts.map +1 -1
  27. package/dist/components/features/shared-data/SharedDataSelectList.js +11 -46
  28. package/dist/components/features/shared-data/SharedDataSelectList.js.map +2 -2
  29. package/dist/components/form-control/select/Select.d.ts.map +1 -1
  30. package/dist/components/form-control/select/Select.js +1 -1
  31. package/dist/components/form-control/select/Select.js.map +1 -1
  32. package/dist/helpers/createAppStructure.d.ts.map +1 -1
  33. package/dist/helpers/createAppStructure.js +3 -2
  34. package/dist/helpers/createAppStructure.js.map +1 -1
  35. package/dist/helpers/createHmrSafeContext.d.ts +3 -0
  36. package/dist/helpers/createHmrSafeContext.d.ts.map +1 -0
  37. package/dist/helpers/createHmrSafeContext.js +10 -0
  38. package/dist/helpers/createHmrSafeContext.js.map +6 -0
  39. package/dist/hooks/createSelectionGroup.d.ts.map +1 -1
  40. package/dist/hooks/createSelectionGroup.js +3 -2
  41. package/dist/hooks/createSelectionGroup.js.map +2 -2
  42. package/package.json +6 -5
  43. package/src/components/disclosure/Dropdown.tsx +31 -17
  44. package/src/components/disclosure/dialogZIndex.ts +5 -0
  45. package/src/components/features/crud-detail/CrudDetail.tsx +16 -5
  46. package/src/components/features/crud-sheet/CrudSheet.tsx +13 -3
  47. package/src/components/features/crudRegistry.ts +60 -0
  48. package/src/components/features/permission-table/PermissionTable.tsx +49 -46
  49. package/src/components/features/shared-data/SharedDataSelect.tsx +2 -2
  50. package/src/components/features/shared-data/SharedDataSelectList.tsx +11 -36
  51. package/src/components/form-control/select/Select.tsx +1 -5
  52. package/src/helpers/createAppStructure.ts +3 -2
  53. package/src/helpers/createHmrSafeContext.ts +8 -0
  54. package/src/hooks/createSelectionGroup.tsx +4 -2
  55. package/tests/components/data/List.spec.tsx +52 -52
  56. package/tests/components/data/Pagination.spec.tsx +43 -43
  57. package/tests/components/data/Table.spec.tsx +4 -4
  58. package/tests/components/data/kanban/Kanban.selection.spec.tsx +21 -21
  59. package/tests/components/data/sheet/DataSheet.spec.tsx +50 -50
  60. package/tests/components/disclosure/Collapse.spec.tsx +24 -24
  61. package/tests/components/disclosure/Dialog.spec.tsx +33 -33
  62. package/tests/components/disclosure/DialogProvider.spec.tsx +9 -9
  63. package/tests/components/disclosure/Dropdown.spec.tsx +134 -14
  64. package/tests/components/disclosure/Tabs.spec.tsx +21 -21
  65. package/tests/components/disclosure/dialogZIndex.spec.ts +45 -0
  66. package/tests/components/display/Alert.spec.tsx +4 -4
  67. package/tests/components/display/Barcode.spec.tsx +7 -7
  68. package/tests/components/display/Card.spec.tsx +3 -3
  69. package/tests/components/display/Link.spec.tsx +5 -5
  70. package/tests/components/display/Tag.spec.tsx +4 -4
  71. package/tests/components/features/address/AddressSearch.spec.tsx +3 -3
  72. package/tests/components/features/crudRegistry.spec.ts +119 -0
  73. package/tests/components/features/data-select-button/DataSelectButton.spec.tsx +8 -8
  74. package/tests/components/features/permission-table/PermissionTable.spec.tsx +43 -43
  75. package/tests/components/features/shared-data/SharedDataSelectList.spec.tsx +2 -17
  76. package/tests/components/feedback/busy/BusyContainer.spec.tsx +7 -7
  77. package/tests/components/feedback/notification/NotificationBell.spec.tsx +9 -9
  78. package/tests/components/feedback/print/Print.spec.tsx +4 -4
  79. package/tests/components/form-control/Button.spec.tsx +18 -18
  80. package/tests/components/form-control/checkbox/Checkbox.spec.tsx +20 -20
  81. package/tests/components/form-control/checkbox/CheckboxGroup.spec.tsx +12 -12
  82. package/tests/components/form-control/checkbox/Radio.spec.tsx +21 -21
  83. package/tests/components/form-control/checkbox/RadioGroup.spec.tsx +12 -12
  84. package/tests/components/form-control/color-picker/ColorPicker.spec.tsx +10 -10
  85. package/tests/components/form-control/combobox/Combobox.spec.tsx +16 -16
  86. package/tests/components/form-control/combobox/ComboboxItem.spec.tsx +7 -7
  87. package/tests/components/form-control/date-range-picker/DateRangePicker.spec.tsx +24 -24
  88. package/tests/components/form-control/field/DatePicker.spec.tsx +50 -50
  89. package/tests/components/form-control/field/DateTimePicker.spec.tsx +47 -47
  90. package/tests/components/form-control/field/NumberInput.spec.tsx +54 -54
  91. package/tests/components/form-control/field/TextInput.spec.tsx +49 -49
  92. package/tests/components/form-control/field/Textarea.spec.tsx +33 -33
  93. package/tests/components/form-control/field/TimePicker.spec.tsx +42 -42
  94. package/tests/components/form-control/numpad/Numpad.spec.tsx +40 -40
  95. package/tests/components/form-control/select/Select.spec.tsx +9 -9
  96. package/tests/components/form-control/select/SelectItem.spec.tsx +10 -10
  97. package/tests/helpers/createAppStructure.spec.tsx +57 -57
  98. package/tests/helpers/mergeStyles.spec.ts +31 -31
@@ -11,7 +11,7 @@ import type { AppPerm } from "../../../../src/helpers/createAppStructure";
11
11
  import { I18nProvider } from "../../../../src/providers/i18n/I18nContext";
12
12
  import { ConfigProvider } from "../../../../src/providers/ConfigContext";
13
13
 
14
- // --- 테스트 데이터 ---
14
+ // --- test data ---
15
15
 
16
16
  const sampleItems: AppPerm[] = [
17
17
  {
@@ -32,11 +32,11 @@ const sampleItems: AppPerm[] = [
32
32
  ];
33
33
 
34
34
  // =====================
35
- // Part 1: 유틸리티 함수 테스트
35
+ // Part 1: utility function tests
36
36
  // =====================
37
37
 
38
38
  describe("collectAllPerms", () => {
39
- it("트리에서 모든 고유 perm 타입을 수집한다", () => {
39
+ it("collects all unique perm types from the tree", () => {
40
40
  const result = collectAllPerms(sampleItems);
41
41
  expect(result).toContain("use");
42
42
  expect(result).toContain("edit");
@@ -44,12 +44,12 @@ describe("collectAllPerms", () => {
44
44
  expect(result).toHaveLength(3);
45
45
  });
46
46
 
47
- it(" 배열은 결과를 반환한다", () => {
47
+ it("returns empty result for empty array", () => {
48
48
  const result = collectAllPerms([]);
49
49
  expect(result).toEqual([]);
50
50
  });
51
51
 
52
- it("중첩된 아이템의 perms 수집한다", () => {
52
+ it("collects perms from nested items", () => {
53
53
  const items: AppPerm[] = [
54
54
  {
55
55
  title: "루트",
@@ -71,32 +71,32 @@ describe("collectAllPerms", () => {
71
71
  });
72
72
 
73
73
  describe("filterByModules", () => {
74
- it("modules가 undefined이면 모든 아이템을 반환한다", () => {
74
+ it("returns all items when modules is undefined", () => {
75
75
  const result = filterByModules(sampleItems, undefined);
76
76
  expect(result).toBe(sampleItems);
77
77
  });
78
78
 
79
- it("활성 모듈과 교차가 없는 아이템을 제외한다", () => {
79
+ it("excludes items with no intersection with active modules", () => {
80
80
  const result = filterByModules(sampleItems, ["other"]);
81
- // "시스템" modules: ["admin"]이므로 "other" 교차 없음 제외
81
+ // "시스템" has modules: ["admin"], no intersection with "other" → excluded
82
82
  const titles = result.map((i) => i.title);
83
83
  expect(titles).toContain("사용자 관리");
84
84
  expect(titles).not.toContain("시스템");
85
85
  });
86
86
 
87
- it("modules가 없는 아이템은 항상 포함된다", () => {
87
+ it("always includes items with no modules set", () => {
88
88
  const result = filterByModules(sampleItems, ["admin"]);
89
- // "사용자 관리" modules 미설정항상 포함
89
+ // "사용자 관리" has no modules setalways included
90
90
  const titles = result.map((i) => i.title);
91
91
  expect(titles).toContain("사용자 관리");
92
92
  expect(titles).toContain("시스템");
93
93
  });
94
94
 
95
- it("자식이 전부 필터링된 그룹 노드(perms 없음) 제거된다", () => {
95
+ it("removes group node (no perms) when all children are filtered out", () => {
96
96
  const items: AppPerm[] = [
97
97
  {
98
98
  title: "그룹",
99
- // perms 없음 그룹 노드
99
+ // no perms → group node
100
100
  children: [
101
101
  { title: "항목A", href: "/a", perms: ["use"], modules: ["admin"] },
102
102
  { title: "항목B", href: "/b", perms: ["use"], modules: ["admin"] },
@@ -109,19 +109,19 @@ describe("filterByModules", () => {
109
109
  });
110
110
 
111
111
  describe("changePermCheck", () => {
112
- it("리프 아이템에 perm 설정한다", () => {
112
+ it("sets perm on a leaf item", () => {
113
113
  const result = changePermCheck({}, sampleItems[1], "use", true);
114
114
  expect(result["/system/use"]).toBe(true);
115
115
  });
116
116
 
117
- it("부모 체크 모든 자식이 체크된다 (cascading down)", () => {
117
+ it("checking parent checks all children (cascading down)", () => {
118
118
  const result = changePermCheck({}, sampleItems[0], "use", true);
119
119
  expect(result["/user/use"]).toBe(true);
120
120
  expect(result["/user/permission/use"]).toBe(true);
121
121
  expect(result["/user/list/use"]).toBe(true);
122
122
  });
123
123
 
124
- it("부모 체크 해제 모든 자식이 해제된다 (cascading down)", () => {
124
+ it("unchecking parent unchecks all children (cascading down)", () => {
125
125
  const initial: Record<string, boolean> = {
126
126
  "/user/use": true,
127
127
  "/user/permission/use": true,
@@ -133,7 +133,7 @@ describe("changePermCheck", () => {
133
133
  expect(result["/user/list/use"]).toBe(false);
134
134
  });
135
135
 
136
- it("기본 perm(perms[0]) 해제 나머지 perms도 해제된다", () => {
136
+ it("unchecking the base perm (perms[0]) unchecks all other perms", () => {
137
137
  const initial: Record<string, boolean> = {
138
138
  "/user/use": true,
139
139
  "/user/edit": true,
@@ -144,69 +144,69 @@ describe("changePermCheck", () => {
144
144
  "/user/list/edit": true,
145
145
  };
146
146
  const result = changePermCheck(initial, sampleItems[0], "use", false);
147
- // 기본 perm "use" 해제 → "edit", "approve" 해제
147
+ // unchecking base perm "use" → "edit", "approve" are also unchecked
148
148
  expect(result["/user/edit"]).toBe(false);
149
149
  expect(result["/user/permission/edit"]).toBe(false);
150
150
  expect(result["/user/permission/approve"]).toBe(false);
151
151
  expect(result["/user/list/edit"]).toBe(false);
152
152
  });
153
153
 
154
- it("비기본 perm 체크 기본 perm이 꺼져있으면 해당 아이템은 건너뛰고 자식에 cascading된다", () => {
155
- // 부모(/user) 기본 perm "use" 꺼져있으나, 자식들의 "use" 켜져있음
154
+ it("checking non-base perm cascades to children, skipping items where base perm is off", () => {
155
+ // parent (/user) base perm "use" is off, but children's "use" is on
156
156
  const initial: Record<string, boolean> = {
157
157
  "/user/permission/use": true,
158
158
  "/user/list/use": true,
159
159
  };
160
160
  const result = changePermCheck(initial, sampleItems[0], "edit", true);
161
- // 부모(/user): use 꺼져있으므로 edit 설정 건너뜀
161
+ // parent (/user): use is off skip setting edit
162
162
  expect(result["/user/edit"]).toBeUndefined();
163
- // 자식: use 켜져있으므로 edit 설정됨
163
+ // children: use is on → edit is set
164
164
  expect(result["/user/permission/edit"]).toBe(true);
165
165
  expect(result["/user/list/edit"]).toBe(true);
166
166
  });
167
167
  });
168
168
 
169
169
  // =====================
170
- // Part 2: 컴포넌트 렌더링 테스트
170
+ // Part 2: component rendering tests
171
171
  // =====================
172
172
 
173
- describe("PermissionTable 컴포넌트", () => {
173
+ describe("PermissionTable component", () => {
174
174
  describe("basic rendering", () => {
175
- it("data-permission-table 속성이 있는 div 렌더링된다", () => {
175
+ it("renders as DataSheet (div with data-sheet attribute)", () => {
176
176
  const { container } = render(() => <PermissionTable items={sampleItems} />);
177
- const wrapper = container.querySelector("[data-permission-table]");
177
+ const wrapper = container.querySelector("[data-sheet]");
178
178
  expect(wrapper).toBeTruthy();
179
179
  expect(wrapper!.tagName).toBe("DIV");
180
180
  });
181
181
 
182
- it("내부에 DataSheet(table)가 렌더링된다", () => {
182
+ it("renders a table inside DataSheet", () => {
183
183
  const { container } = render(() => <PermissionTable items={sampleItems} />);
184
184
  const table = container.querySelector("[data-sheet] table");
185
185
  expect(table).toBeTruthy();
186
186
  });
187
187
 
188
- it("헤더에 perm 타입 컬럼이 표시된다", () => {
188
+ it("displays perm type columns in header", () => {
189
189
  const { getByText } = render(() => <PermissionTable items={sampleItems} />);
190
190
  expect(getByText("use")).toBeTruthy();
191
191
  expect(getByText("edit")).toBeTruthy();
192
192
  expect(getByText("approve")).toBeTruthy();
193
193
  });
194
194
 
195
- it("아이템 타이틀이 표시된다", () => {
195
+ it("displays item titles", () => {
196
196
  const { getByText } = render(() => <PermissionTable items={sampleItems} />);
197
197
  expect(getByText("사용자 관리")).toBeTruthy();
198
198
  expect(getByText("시스템")).toBeTruthy();
199
199
  });
200
200
 
201
- it("자식 아이템이 기본적으로 펼쳐져서 표시된다", () => {
201
+ it("child items are expanded by default", () => {
202
202
  const { getByText } = render(() => <PermissionTable items={sampleItems} />);
203
203
  expect(getByText("권한 설정")).toBeTruthy();
204
204
  expect(getByText("사용자 목록")).toBeTruthy();
205
205
  });
206
206
  });
207
207
 
208
- describe("체크박스 인터랙션", () => {
209
- it("체크박스 클릭 onValueChange가 호출된다", () => {
208
+ describe("checkbox interaction", () => {
209
+ it("clicking a checkbox calls onValueChange", () => {
210
210
  const handleChange = vi.fn();
211
211
  const { getAllByRole } = render(() => (
212
212
  <ConfigProvider clientName="test"><I18nProvider>
@@ -215,12 +215,12 @@ describe("PermissionTable 컴포넌트", () => {
215
215
  ));
216
216
 
217
217
  const checkboxes = getAllByRole("checkbox");
218
- // 번째 체크박스를 클릭
218
+ // click the first checkbox
219
219
  fireEvent.click(checkboxes[0]);
220
220
  expect(handleChange).toHaveBeenCalled();
221
221
  });
222
222
 
223
- it("controlled 패턴: value prop 체크박스에 반영된다", () => {
223
+ it("controlled pattern: value prop is reflected in checkboxes", () => {
224
224
  const [value, setValue] = createSignal<Record<string, boolean>>({
225
225
  "/system/use": true,
226
226
  });
@@ -232,43 +232,43 @@ describe("PermissionTable 컴포넌트", () => {
232
232
  ));
233
233
 
234
234
  const checkboxes = getAllByRole("checkbox");
235
- // "시스템" "use" 체크박스가 체크되어 있어야
235
+ // "시스템"'s "use" checkbox should be checked
236
236
  const checkedBox = checkboxes.find((cb) => cb.getAttribute("aria-checked") === "true");
237
237
  expect(checkedBox).toBeTruthy();
238
238
  });
239
239
  });
240
240
 
241
- describe("접기/펼치기", () => {
242
- it("자식이 있는 아이템의 행에 펼치기/접기 토글이 존재한다", () => {
241
+ describe("expand/collapse", () => {
242
+ it("rows with children have an expand/collapse toggle", () => {
243
243
  const { getByText } = render(() => <PermissionTable items={sampleItems} />);
244
- // "사용자 관리" 있는 행(tr)을 찾고, 그 행에 expand toggle button이 있는지 확인
244
+ // find the row containing "사용자 관리" and check for expand toggle button
245
245
  const titleEl = getByText("사용자 관리");
246
246
  const row = titleEl.closest("tr")!;
247
247
  const expandButton = row.querySelector("button");
248
248
  expect(expandButton).toBeTruthy();
249
249
  });
250
250
 
251
- it("접기 버튼 클릭 자식이 DOM에서 제거된다", () => {
251
+ it("clicking collapse button removes children from the DOM", () => {
252
252
  const { getByText, queryByText } = render(() => <PermissionTable items={sampleItems} />);
253
253
 
254
- // 초기: 자식 표시 (기본적으로 모두 펼침)
254
+ // initially: children are visible (all expanded by default)
255
255
  expect(getByText("권한 설정")).toBeTruthy();
256
256
  expect(getByText("사용자 목록")).toBeTruthy();
257
257
 
258
- // 접기 버튼 클릭 (사용자 관리 행의 expand toggle)
258
+ // click collapse button (expand toggle on "사용자 관리" row)
259
259
  const titleEl = getByText("사용자 관리");
260
260
  const row = titleEl.closest("tr")!;
261
261
  const expandButton = row.querySelector("button")!;
262
262
  fireEvent.click(expandButton);
263
263
 
264
- // 자식이 DOM에서 제거됨 (Sheet 접힌 항목을 렌더링하지 않음)
264
+ // children are removed from the DOM (Sheet does not render collapsed items)
265
265
  expect(queryByText("권한 설정")).toBeNull();
266
266
  expect(queryByText("사용자 목록")).toBeNull();
267
267
  });
268
268
  });
269
269
 
270
- describe("비활성화", () => {
271
- it("disabled prop true이면 체크박스 클릭이 무시된다", () => {
270
+ describe("disabled state", () => {
271
+ it("checkbox clicks are ignored when disabled prop is true", () => {
272
272
  const handleChange = vi.fn();
273
273
  const { getAllByRole } = render(() => (
274
274
  <ConfigProvider clientName="test"><I18nProvider>
@@ -430,9 +430,9 @@ describe("SharedDataSelectList", () => {
430
430
  });
431
431
  });
432
432
 
433
- // ─── header / modal ────────────────────────────────────
433
+ // ─── header ────────────────────────────────────────────
434
434
 
435
- describe("header / modal", () => {
435
+ describe("header", () => {
436
436
  it("header text is displayed when header is provided", () => {
437
437
  const accessor = createMockAccessor(["Apple"]);
438
438
 
@@ -444,20 +444,5 @@ describe("SharedDataSelectList", () => {
444
444
 
445
445
  expect(screen.getByText("과일 목록")).toBeTruthy();
446
446
  });
447
-
448
- it("management button is displayed when modal is provided", () => {
449
- const accessor = createMockAccessor(["Apple"]);
450
-
451
- renderWithDialog(() => (
452
- <SharedDataSelectList data={accessor} header="과일" modal={() => <div>Modal</div>} required>
453
- <SharedDataSelectList.ItemTemplate>{(item) => <>{item}</>}</SharedDataSelectList.ItemTemplate>
454
- </SharedDataSelectList>
455
- ));
456
-
457
- // Button is rendered (with IconExternalLink)
458
- const headerArea = screen.getByText("과일").parentElement!;
459
- const button = headerArea.querySelector("button");
460
- expect(button).toBeTruthy();
461
- });
462
447
  });
463
448
  });
@@ -5,7 +5,7 @@ import { BusyContainer } from "../../../../src/components/feedback/busy/BusyCont
5
5
 
6
6
  describe("BusyContainer", () => {
7
7
  describe("basic rendering", () => {
8
- it("children이 표시된다", () => {
8
+ it("renders children", () => {
9
9
  const { getByText } = render(() => (
10
10
  <BusyContainer>
11
11
  <span>Content</span>
@@ -14,7 +14,7 @@ describe("BusyContainer", () => {
14
14
  expect(getByText("Content")).toBeTruthy();
15
15
  });
16
16
 
17
- it("busy가 false이면 오버레이가 표시되지 않는다", () => {
17
+ it("does not show overlay when busy is false", () => {
18
18
  const { container } = render(() => (
19
19
  <BusyContainer busy={false}>
20
20
  <span>Content</span>
@@ -26,7 +26,7 @@ describe("BusyContainer", () => {
26
26
  });
27
27
 
28
28
  describe("ready prop", () => {
29
- it("ready가 false이면 children DOM에서 제거된다", () => {
29
+ it("removes children from DOM when ready is false", () => {
30
30
  const { queryByText } = render(() => (
31
31
  <BusyContainer ready={false}>
32
32
  <span>Content</span>
@@ -35,7 +35,7 @@ describe("BusyContainer", () => {
35
35
  expect(queryByText("Content")).toBeNull();
36
36
  });
37
37
 
38
- it("ready true이면 children이 표시된다", () => {
38
+ it("shows children when ready is true", () => {
39
39
  const { getByText } = render(() => (
40
40
  <BusyContainer ready={true}>
41
41
  <span>Content</span>
@@ -44,7 +44,7 @@ describe("BusyContainer", () => {
44
44
  expect(getByText("Content")).toBeTruthy();
45
45
  });
46
46
 
47
- it("ready undefined이면 children이 표시된다", () => {
47
+ it("shows children when ready is undefined", () => {
48
48
  const { getByText } = render(() => (
49
49
  <BusyContainer>
50
50
  <span>Content</span>
@@ -53,7 +53,7 @@ describe("BusyContainer", () => {
53
53
  expect(getByText("Content")).toBeTruthy();
54
54
  });
55
55
 
56
- it("ready false이면 오버레이가 마운트된다", async () => {
56
+ it("mounts overlay when ready is false", async () => {
57
57
  const { container } = render(() => (
58
58
  <BusyContainer ready={false}>
59
59
  <span>Content</span>
@@ -65,7 +65,7 @@ describe("BusyContainer", () => {
65
65
  expect(overlay).toBeTruthy();
66
66
  });
67
67
 
68
- it("ready false에서 true로 변경되면 children이 다시 표시된다", () => {
68
+ it("shows children again when ready changes from false to true", () => {
69
69
  const [ready, setReady] = createSignal(false);
70
70
  const { queryByText } = render(() => (
71
71
  <BusyContainer ready={ready()}>
@@ -15,7 +15,7 @@ describe("NotificationBell", () => {
15
15
  vi.unstubAllGlobals();
16
16
  });
17
17
 
18
- it("버튼이 렌더링된다", () => {
18
+ it("renders button", () => {
19
19
  const { container } = render(() => (
20
20
  <ConfigContext.Provider value={{ clientName: "testApp" }}>
21
21
  <NotificationProvider>
@@ -27,7 +27,7 @@ describe("NotificationBell", () => {
27
27
  expect(container.querySelector("[data-notification-bell]")).not.toBeNull();
28
28
  });
29
29
 
30
- it("알림이 없으면 뱃지가 표시되지 않는다", () => {
30
+ it("does not show badge when there are no notifications", () => {
31
31
  render(() => (
32
32
  <ConfigContext.Provider value={{ clientName: "testApp" }}>
33
33
  <NotificationProvider>
@@ -40,7 +40,7 @@ describe("NotificationBell", () => {
40
40
  expect(badge).toBeNull();
41
41
  });
42
42
 
43
- it("알림이 있으면 뱃지에 개수가 표시된다", async () => {
43
+ it("shows count on badge when notifications are present", async () => {
44
44
  let notification: ReturnType<typeof useNotification>;
45
45
 
46
46
  render(() => (
@@ -64,7 +64,7 @@ describe("NotificationBell", () => {
64
64
  });
65
65
  });
66
66
 
67
- it("버튼 클릭 Dropdown이 열린다", async () => {
67
+ it("opens Dropdown on button click", async () => {
68
68
  let notification: ReturnType<typeof useNotification>;
69
69
 
70
70
  render(() => (
@@ -90,7 +90,7 @@ describe("NotificationBell", () => {
90
90
  });
91
91
  });
92
92
 
93
- it("Dropdown에 알림 목록이 표시된다", async () => {
93
+ it("shows notification list in Dropdown", async () => {
94
94
  let notification: ReturnType<typeof useNotification>;
95
95
 
96
96
  render(() => (
@@ -118,7 +118,7 @@ describe("NotificationBell", () => {
118
118
  });
119
119
  });
120
120
 
121
- it("aria-label에 알림 개수가 포함된다", async () => {
121
+ it("includes notification count in aria-label", async () => {
122
122
  let notification: ReturnType<typeof useNotification>;
123
123
 
124
124
  render(() => (
@@ -141,7 +141,7 @@ describe("NotificationBell", () => {
141
141
  });
142
142
  });
143
143
 
144
- it("aria-haspopup aria-expanded 올바르게 설정된다", async () => {
144
+ it("sets aria-haspopup and aria-expanded correctly", async () => {
145
145
  render(() => (
146
146
  <ConfigContext.Provider value={{ clientName: "testApp" }}>
147
147
  <NotificationProvider>
@@ -161,7 +161,7 @@ describe("NotificationBell", () => {
161
161
  });
162
162
  });
163
163
 
164
- it("드롭다운 열면 모든 알림이 읽음 처리된다", async () => {
164
+ it("marks all notifications as read when dropdown opens", async () => {
165
165
  let notification: ReturnType<typeof useNotification>;
166
166
 
167
167
  render(() => (
@@ -191,7 +191,7 @@ describe("NotificationBell", () => {
191
191
  });
192
192
  });
193
193
 
194
- it("전체 삭제 버튼 클릭 clear가 호출된다", async () => {
194
+ it("calls clear when clear-all button is clicked", async () => {
195
195
  let notification: ReturnType<typeof useNotification>;
196
196
 
197
197
  render(() => (
@@ -2,7 +2,7 @@ import { render } from "@solidjs/testing-library";
2
2
  import { describe, it, expect } from "vitest";
3
3
  import { Print } from "../../../../src/components/feedback/print/Print";
4
4
 
5
- describe("Print 컴포넌트", () => {
5
+ describe("Print", () => {
6
6
  describe("basic rendering", () => {
7
7
  it("renders children", () => {
8
8
  const { getByText } = render(() => <Print>테스트 내용</Print>);
@@ -11,7 +11,7 @@ describe("Print 컴포넌트", () => {
11
11
  });
12
12
 
13
13
  describe("Print.Page", () => {
14
- it("data-print-page 속성이 렌더링된다", () => {
14
+ it("renders with data-print-page attribute", () => {
15
15
  const { container } = render(() => (
16
16
  <Print>
17
17
  <Print.Page>페이지 1</Print.Page>
@@ -21,7 +21,7 @@ describe("Print 컴포넌트", () => {
21
21
  expect(page).toBeTruthy();
22
22
  });
23
23
 
24
- it("여러 Print.Page 각각 data-print-page 가진다", () => {
24
+ it("each Print.Page has data-print-page attribute", () => {
25
25
  const { container } = render(() => (
26
26
  <Print>
27
27
  <Print.Page>페이지 1</Print.Page>
@@ -33,7 +33,7 @@ describe("Print 컴포넌트", () => {
33
33
  expect(pages.length).toBe(3);
34
34
  });
35
35
 
36
- it("Print.Page children이 렌더링된다", () => {
36
+ it("renders Print.Page children", () => {
37
37
  const { getByText } = render(() => (
38
38
  <Print>
39
39
  <Print.Page>페이지 내용</Print.Page>
@@ -2,23 +2,23 @@ import { render, fireEvent } from "@solidjs/testing-library";
2
2
  import { describe, it, expect, vi } from "vitest";
3
3
  import { Button } from "../../../src/components/form-control/Button";
4
4
 
5
- describe("Button 컴포넌트", () => {
5
+ describe("Button component", () => {
6
6
  describe("basic rendering", () => {
7
- it("children 버튼 내부에 표시된다", () => {
7
+ it("renders children inside the button", () => {
8
8
  const { getByRole } = render(() => <Button>Click Me</Button>);
9
9
  const button = getByRole("button");
10
10
 
11
11
  expect(button.textContent).toBe("Click Me");
12
12
  });
13
13
 
14
- it("type 속성 기본값은 button이다", () => {
14
+ it("defaults type to button", () => {
15
15
  const { getByRole } = render(() => <Button>Click</Button>);
16
16
  const button = getByRole("button");
17
17
 
18
18
  expect(button.getAttribute("type")).toBe("button");
19
19
  });
20
20
 
21
- it("type 속성을 submit으로 오버라이드할 수 있다", () => {
21
+ it("overrides type with submit", () => {
22
22
  const { getByRole } = render(() => <Button type="submit">Submit</Button>);
23
23
  const button = getByRole("button");
24
24
 
@@ -26,8 +26,8 @@ describe("Button 컴포넌트", () => {
26
26
  });
27
27
  });
28
28
 
29
- describe("theme 속성", () => {
30
- it("theme prop에 따라 스타일이 달라진다", () => {
29
+ describe("theme prop", () => {
30
+ it("applies different styles per theme", () => {
31
31
  const { getByRole: getDefault } = render(() => <Button>Click</Button>);
32
32
  const { getByRole: getThemed } = render(() => <Button theme="danger">Click</Button>);
33
33
 
@@ -35,8 +35,8 @@ describe("Button 컴포넌트", () => {
35
35
  });
36
36
  });
37
37
 
38
- describe("variant 속성", () => {
39
- it("variant prop에 따라 스타일이 달라진다", () => {
38
+ describe("variant prop", () => {
39
+ it("applies different styles per variant", () => {
40
40
  const { getByRole: getOutline } = render(() => <Button>Click</Button>);
41
41
  const { getByRole: getSolid } = render(() => <Button variant="solid">Click</Button>);
42
42
  const { getByRole: getGhost } = render(() => <Button variant="ghost">Click</Button>);
@@ -51,8 +51,8 @@ describe("Button 컴포넌트", () => {
51
51
  });
52
52
  });
53
53
 
54
- describe("size 속성", () => {
55
- it("size prop에 따라 스타일이 달라진다", () => {
54
+ describe("size prop", () => {
55
+ it("applies different styles per size", () => {
56
56
  const { getByRole: getDefault } = render(() => <Button>Click</Button>);
57
57
  const { getByRole: getSm } = render(() => <Button size="sm">Click</Button>);
58
58
  const { getByRole: getLg } = render(() => <Button size="lg">Click</Button>);
@@ -67,8 +67,8 @@ describe("Button 컴포넌트", () => {
67
67
  });
68
68
  });
69
69
 
70
- describe("inset 속성", () => {
71
- it("inset prop에 따라 스타일이 달라진다", () => {
70
+ describe("inset prop", () => {
71
+ it("applies different styles when inset", () => {
72
72
  const { getByRole: getDefault } = render(() => <Button>Click</Button>);
73
73
  const { getByRole: getInset } = render(() => <Button inset>Click</Button>);
74
74
 
@@ -76,23 +76,23 @@ describe("Button 컴포넌트", () => {
76
76
  });
77
77
  });
78
78
 
79
- describe("disabled 속성", () => {
80
- it("disabled prop에 따라 스타일이 달라진다", () => {
79
+ describe("disabled prop", () => {
80
+ it("applies different styles when disabled", () => {
81
81
  const { getByRole: getDefault } = render(() => <Button>Click</Button>);
82
82
  const { getByRole: getDisabled } = render(() => <Button disabled>Click</Button>);
83
83
 
84
84
  expect(getDefault("button").className).not.toBe(getDisabled("button").className);
85
85
  });
86
86
 
87
- it("disabled=true일 HTML disabled 속성이 설정된다", () => {
87
+ it("sets HTML disabled attribute when disabled=true", () => {
88
88
  const { getByRole } = render(() => <Button disabled>Click</Button>);
89
89
 
90
90
  expect(getByRole("button").hasAttribute("disabled")).toBe(true);
91
91
  });
92
92
  });
93
93
 
94
- describe("이벤트 핸들링", () => {
95
- it("onClick handler 버튼 클릭 시 호출된다", () => {
94
+ describe("event handling", () => {
95
+ it("calls onClick handler on click", () => {
96
96
  const handleClick = vi.fn();
97
97
  const { getByRole } = render(() => <Button onClick={handleClick}>Click</Button>);
98
98
 
@@ -101,7 +101,7 @@ describe("Button 컴포넌트", () => {
101
101
  expect(handleClick).toHaveBeenCalledTimes(1);
102
102
  });
103
103
 
104
- it("disabled 상태에서는 클릭이 차단된다", () => {
104
+ it("blocks click when disabled", () => {
105
105
  const { getByRole } = render(() => <Button disabled>Click</Button>);
106
106
 
107
107
  expect(getByRole("button").hasAttribute("disabled")).toBe(true);