com.wallstop-studios.dxmessaging 2.1.5 → 2.1.6

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 (161) hide show
  1. package/.artifacts/SourceGenerators.Tests/obj/Debug/net9.0/WallstopStudios.DxMessaging.SourceGenerators.Tests.AssemblyInfo.cs +1 -1
  2. package/.cspell.json +4 -1
  3. package/.github/workflows/actionlint.yml +11 -1
  4. package/.github/workflows/csharpier-autofix.yml +34 -3
  5. package/.github/workflows/dotnet-tests.yml +13 -0
  6. package/.github/workflows/format-on-demand.yml +38 -44
  7. package/.github/workflows/json-format-check.yml +24 -0
  8. package/.github/workflows/lint-doc-links.yml +13 -0
  9. package/.github/workflows/markdown-json.yml +21 -4
  10. package/.github/workflows/markdown-link-text-check.yml +10 -0
  11. package/.github/workflows/markdown-link-validity.yml +10 -0
  12. package/.github/workflows/markdownlint.yml +7 -5
  13. package/.github/workflows/prettier-autofix.yml +67 -11
  14. package/.github/workflows/release-drafter.yml +2 -2
  15. package/.github/workflows/sync-wiki.yml +3 -3
  16. package/.github/workflows/yaml-format-lint.yml +26 -0
  17. package/.llm/context.md +113 -3
  18. package/.llm/skills/documentation/changelog-management.md +38 -0
  19. package/.llm/skills/documentation/documentation-style-guide.md +18 -0
  20. package/.llm/skills/documentation/documentation-update-workflow.md +2 -0
  21. package/.llm/skills/documentation/documentation-updates.md +2 -0
  22. package/.llm/skills/documentation/markdown-compatibility.md +476 -0
  23. package/.llm/skills/documentation/mermaid-theming.md +326 -0
  24. package/.llm/skills/documentation/mkdocs-navigation.md +290 -0
  25. package/.llm/skills/github-actions/git-renormalize-patterns.md +231 -0
  26. package/.llm/skills/github-actions/workflow-consistency.md +346 -0
  27. package/.llm/skills/index.md +53 -27
  28. package/.llm/skills/scripting/javascript-code-quality.md +417 -0
  29. package/.llm/skills/scripting/regex-documentation.md +461 -0
  30. package/.llm/skills/scripting/shell-best-practices.md +55 -4
  31. package/.llm/skills/scripting/validation-patterns.md +418 -0
  32. package/.llm/skills/specification.md +4 -1
  33. package/.llm/skills/testing/test-code-quality.md +243 -0
  34. package/.llm/skills/testing/test-production-code.md +348 -0
  35. package/CHANGELOG.md +11 -0
  36. package/README.md +0 -11
  37. package/Tests/Runtime/Benchmarks/WallstopStudios.DxMessaging.Tests.Runtime.Benchmarks.asmdef +1 -6
  38. package/Tests/Runtime/Integrations/Reflex/WallstopStudios.DxMessaging.Tests.Runtime.Reflex.asmdef +1 -1
  39. package/Tests/Runtime/Integrations/VContainer/WallstopStudios.DxMessaging.Tests.Runtime.VContainer.asmdef +1 -1
  40. package/Tests/Runtime/Integrations/Zenject/WallstopStudios.DxMessaging.Tests.Runtime.Zenject.asmdef +1 -1
  41. package/coverage/clover.xml +216 -3
  42. package/coverage/clover.xml.meta +7 -7
  43. package/coverage/coverage-final.json +2 -1
  44. package/coverage/coverage-final.json.meta +7 -7
  45. package/coverage/lcov-report/base.css.meta +1 -1
  46. package/coverage/lcov-report/block-navigation.js.meta +1 -1
  47. package/coverage/lcov-report/favicon.png.meta +1 -1
  48. package/coverage/lcov-report/index.html +25 -10
  49. package/coverage/lcov-report/index.html.meta +7 -7
  50. package/coverage/lcov-report/prettify.css.meta +1 -1
  51. package/coverage/lcov-report/prettify.js.meta +1 -1
  52. package/coverage/lcov-report/sort-arrow-sprite.png.meta +1 -1
  53. package/coverage/lcov-report/sorter.js.meta +1 -1
  54. package/coverage/lcov-report/transform-docs-to-wiki.js.html +1 -1
  55. package/coverage/lcov-report/transform-docs-to-wiki.js.html.meta +7 -7
  56. package/coverage/lcov-report/vendor.meta +1 -1
  57. package/coverage/lcov-report.meta +8 -8
  58. package/coverage/lcov.info +365 -0
  59. package/coverage/lcov.info.meta +7 -7
  60. package/docs/architecture/design-and-architecture.md +0 -1
  61. package/docs/concepts/index.md +37 -0
  62. package/docs/concepts/index.md.meta +7 -0
  63. package/docs/concepts/interceptors-and-ordering.md +0 -2
  64. package/docs/concepts/mental-model.md +390 -0
  65. package/docs/concepts/mental-model.md.meta +7 -0
  66. package/docs/concepts/message-types.md +0 -1
  67. package/docs/getting-started/getting-started.md +1 -0
  68. package/docs/getting-started/index.md +6 -5
  69. package/docs/getting-started/overview.md +1 -0
  70. package/docs/getting-started/quick-start.md +2 -1
  71. package/docs/getting-started/visual-guide.md +4 -10
  72. package/docs/hooks.py +10 -1
  73. package/docs/images/DxMessaging-banner.svg +1 -1
  74. package/docs/index.md +7 -7
  75. package/docs/javascripts/mermaid-config.js +44 -4
  76. package/docs/reference/helpers.md +130 -154
  77. package/docs/reference/quick-reference.md +5 -1
  78. package/docs/reference/reference.md +124 -130
  79. package/mkdocs.yml +2 -0
  80. package/package.json +1 -1
  81. package/scripts/__tests__/generate-skills-index.test.js +397 -0
  82. package/scripts/__tests__/generate-skills-index.test.js.meta +7 -0
  83. package/scripts/__tests__/mermaid-config.test.js +467 -0
  84. package/scripts/__tests__/mermaid-config.test.js.meta +7 -0
  85. package/scripts/__tests__/validate-skills-optional-fields.test.js +1474 -0
  86. package/scripts/__tests__/validate-skills-optional-fields.test.js.meta +7 -0
  87. package/scripts/__tests__/validate-skills-required-fields.test.js +188 -0
  88. package/scripts/__tests__/validate-skills-required-fields.test.js.meta +7 -0
  89. package/scripts/__tests__/validate-skills-tags.test.js +353 -0
  90. package/scripts/__tests__/validate-skills-tags.test.js.meta +7 -0
  91. package/scripts/__tests__/validate-workflows.test.js +188 -0
  92. package/scripts/__tests__/validate-workflows.test.js.meta +7 -0
  93. package/scripts/generate-skills-index.js +88 -3
  94. package/scripts/validate-skills.js +230 -30
  95. package/scripts/validate-workflows.js +272 -0
  96. package/scripts/validate-workflows.js.meta +7 -0
  97. package/site/404.html +1 -1
  98. package/site/advanced/emit-shorthands/index.html +2 -2
  99. package/site/advanced/message-bus-providers/index.html +2 -2
  100. package/site/advanced/registration-builders/index.html +2 -2
  101. package/site/advanced/runtime-configuration/index.html +2 -2
  102. package/site/advanced/string-messages/index.html +2 -2
  103. package/site/advanced.meta +1 -1
  104. package/site/architecture/comparisons/index.html +2 -2
  105. package/site/architecture/design-and-architecture/index.html +2 -2
  106. package/site/architecture/performance/index.html +1 -1
  107. package/site/architecture.meta +1 -1
  108. package/site/concepts/index.html +1 -0
  109. package/site/concepts/index.html.meta +7 -0
  110. package/site/concepts/interceptors-and-ordering/index.html +4 -4
  111. package/site/concepts/listening-patterns/index.html +2 -2
  112. package/site/concepts/mental-model/index.html +146 -0
  113. package/site/concepts/mental-model/index.html.meta +7 -0
  114. package/site/concepts/mental-model.meta +8 -0
  115. package/site/concepts/message-types/index.html +2 -2
  116. package/site/concepts/targeting-and-context/index.html +2 -2
  117. package/site/concepts.meta +1 -1
  118. package/site/examples/end-to-end/index.html +2 -2
  119. package/site/examples/end-to-end-scene-transitions/index.html +2 -2
  120. package/site/examples.meta +1 -1
  121. package/site/getting-started/getting-started/index.html +3 -3
  122. package/site/getting-started/index.html +4 -4
  123. package/site/getting-started/install/index.html +3 -3
  124. package/site/getting-started/overview/index.html +2 -2
  125. package/site/getting-started/quick-start/index.html +2 -2
  126. package/site/getting-started/visual-guide/index.html +11 -11
  127. package/site/getting-started.meta +1 -1
  128. package/site/guides/advanced/index.html +2 -2
  129. package/site/guides/diagnostics/index.html +2 -2
  130. package/site/guides/migration-guide/index.html +2 -2
  131. package/site/guides/patterns/index.html +2 -2
  132. package/site/guides/testing/index.html +2 -2
  133. package/site/guides/unity-integration/index.html +2 -2
  134. package/site/guides.meta +1 -1
  135. package/site/hooks.py.meta +1 -1
  136. package/site/images/DxMessaging-banner.svg +119 -0
  137. package/site/images/DxMessaging-banner.svg.meta +7 -0
  138. package/site/images.meta +8 -0
  139. package/site/index.html +2 -2
  140. package/site/integrations/index.html +2 -2
  141. package/site/integrations/reflex/index.html +2 -2
  142. package/site/integrations/vcontainer/index.html +2 -2
  143. package/site/integrations/zenject/index.html +2 -2
  144. package/site/integrations.meta +1 -1
  145. package/site/javascripts/csharp-highlight.js.meta +7 -7
  146. package/site/javascripts/mermaid-config.js +4 -1
  147. package/site/javascripts/mermaid-config.js.meta +1 -1
  148. package/site/javascripts.meta +1 -1
  149. package/site/reference/compatibility/index.html +1 -1
  150. package/site/reference/faq/index.html +1 -1
  151. package/site/reference/glossary/index.html +2 -2
  152. package/site/reference/helpers/index.html +15 -15
  153. package/site/reference/quick-reference/index.html +3 -3
  154. package/site/reference/reference/index.html +37 -37
  155. package/site/reference/troubleshooting/index.html +1 -1
  156. package/site/reference.meta +1 -1
  157. package/site/search/search_index.json +1 -1
  158. package/site/sitemap.xml +46 -38
  159. package/site/sitemap.xml.gz +0 -0
  160. package/site/stylesheets/extra.css.meta +1 -1
  161. package/site/stylesheets.meta +1 -1
@@ -0,0 +1,397 @@
1
+ /**
2
+ * @fileoverview Tests for generate-skills-index.js logic.
3
+ *
4
+ * These tests validate the core logic of the skills index generator:
5
+ * - Brand name capitalization (BRAND_NAMES mapping)
6
+ * - Category title formatting (categoryToTitle function)
7
+ * - YAML frontmatter parsing
8
+ * - Edge cases for various inputs
9
+ */
10
+
11
+ "use strict";
12
+
13
+ const {
14
+ applyBrandCapitalization,
15
+ categoryToTitle,
16
+ BRAND_NAMES,
17
+ } = require('../generate-skills-index.js');
18
+
19
+ describe("generate-skills-index", () => {
20
+ describe("BRAND_NAMES mapping", () => {
21
+ test("should contain expected number of brand entries", () => {
22
+ const brandCount = Object.keys(BRAND_NAMES).length;
23
+ expect(brandCount).toBeGreaterThan(30);
24
+ });
25
+
26
+ test("should have all lowercase keys", () => {
27
+ for (const key of Object.keys(BRAND_NAMES)) {
28
+ expect(key).toBe(key.toLowerCase());
29
+ }
30
+ });
31
+
32
+ test("should have non-empty values for all keys", () => {
33
+ for (const value of Object.values(BRAND_NAMES)) {
34
+ expect(value).toBeTruthy();
35
+ expect(typeof value).toBe("string");
36
+ }
37
+ });
38
+ });
39
+
40
+ describe("applyBrandCapitalization", () => {
41
+ describe("known brand names", () => {
42
+ test("should return GitHub for github", () => {
43
+ expect(applyBrandCapitalization("github")).toBe("GitHub");
44
+ });
45
+
46
+ test("should return npm for npm (lowercase brand)", () => {
47
+ expect(applyBrandCapitalization("npm")).toBe("npm");
48
+ });
49
+
50
+ test("should return API for api", () => {
51
+ expect(applyBrandCapitalization("api")).toBe("API");
52
+ });
53
+
54
+ test("should return JavaScript for javascript", () => {
55
+ expect(applyBrandCapitalization("javascript")).toBe("JavaScript");
56
+ });
57
+
58
+ test("should return TypeScript for typescript", () => {
59
+ expect(applyBrandCapitalization("typescript")).toBe("TypeScript");
60
+ });
61
+
62
+ test("should return Node.js for nodejs", () => {
63
+ expect(applyBrandCapitalization("nodejs")).toBe("Node.js");
64
+ });
65
+
66
+ test("should return C# for csharp", () => {
67
+ expect(applyBrandCapitalization("csharp")).toBe("C#");
68
+ });
69
+
70
+ test("should return .NET for dotnet", () => {
71
+ expect(applyBrandCapitalization("dotnet")).toBe(".NET");
72
+ });
73
+
74
+ test("should return VS Code for vscode", () => {
75
+ expect(applyBrandCapitalization("vscode")).toBe("VS Code");
76
+ });
77
+
78
+ test("should return macOS for macos", () => {
79
+ expect(applyBrandCapitalization("macos")).toBe("macOS");
80
+ });
81
+
82
+ test("should return iOS for ios", () => {
83
+ expect(applyBrandCapitalization("ios")).toBe("iOS");
84
+ });
85
+
86
+ test("should return GraphQL for graphql", () => {
87
+ expect(applyBrandCapitalization("graphql")).toBe("GraphQL");
88
+ });
89
+
90
+ test("should return LLM for llm", () => {
91
+ expect(applyBrandCapitalization("llm")).toBe("LLM");
92
+ });
93
+
94
+ test("should return CI for ci", () => {
95
+ expect(applyBrandCapitalization("ci")).toBe("CI");
96
+ });
97
+
98
+ test("should return CD for cd", () => {
99
+ expect(applyBrandCapitalization("cd")).toBe("CD");
100
+ });
101
+ });
102
+
103
+ describe("case-insensitive input", () => {
104
+ test("should handle GITHUB (all uppercase)", () => {
105
+ expect(applyBrandCapitalization("GITHUB")).toBe("GitHub");
106
+ });
107
+
108
+ test("should handle GitHub (mixed case)", () => {
109
+ expect(applyBrandCapitalization("GitHub")).toBe("GitHub");
110
+ });
111
+
112
+ test("should handle NPM (all uppercase)", () => {
113
+ expect(applyBrandCapitalization("NPM")).toBe("npm");
114
+ });
115
+
116
+ test("should handle API (already uppercase)", () => {
117
+ expect(applyBrandCapitalization("API")).toBe("API");
118
+ });
119
+
120
+ test("should handle JavaScript (mixed case)", () => {
121
+ expect(applyBrandCapitalization("JavaScript")).toBe("JavaScript");
122
+ });
123
+
124
+ test("should handle VSCODE (all uppercase)", () => {
125
+ expect(applyBrandCapitalization("VSCODE")).toBe("VS Code");
126
+ });
127
+ });
128
+
129
+ describe("unknown words - standard title case", () => {
130
+ test("should title-case unknown word", () => {
131
+ expect(applyBrandCapitalization("unknown")).toBe("Unknown");
132
+ });
133
+
134
+ test("should title-case testing", () => {
135
+ expect(applyBrandCapitalization("testing")).toBe("Testing");
136
+ });
137
+
138
+ test("should title-case documentation", () => {
139
+ expect(applyBrandCapitalization("documentation")).toBe("Documentation");
140
+ });
141
+
142
+ test("should title-case scripting", () => {
143
+ expect(applyBrandCapitalization("scripting")).toBe("Scripting");
144
+ });
145
+
146
+ test("should title-case actions", () => {
147
+ expect(applyBrandCapitalization("actions")).toBe("Actions");
148
+ });
149
+
150
+ test("should convert UPPERCASE unknown to title case", () => {
151
+ expect(applyBrandCapitalization("TESTING")).toBe("Testing");
152
+ });
153
+
154
+ test("should convert MixedCase unknown to title case", () => {
155
+ expect(applyBrandCapitalization("TeStiNg")).toBe("Testing");
156
+ });
157
+ });
158
+
159
+ describe("edge cases", () => {
160
+ test("should handle empty string", () => {
161
+ const result = applyBrandCapitalization("");
162
+ expect(result).toBe("");
163
+ });
164
+
165
+ test("should handle single character lowercase", () => {
166
+ expect(applyBrandCapitalization("a")).toBe("A");
167
+ });
168
+
169
+ test("should handle single character uppercase", () => {
170
+ expect(applyBrandCapitalization("A")).toBe("A");
171
+ });
172
+
173
+ test("should handle two-letter word", () => {
174
+ expect(applyBrandCapitalization("ab")).toBe("Ab");
175
+ });
176
+
177
+ test("should handle word with numbers", () => {
178
+ expect(applyBrandCapitalization("test123")).toBe("Test123");
179
+ });
180
+
181
+ test("should handle number-only string", () => {
182
+ expect(applyBrandCapitalization("123")).toBe("123");
183
+ });
184
+
185
+ test("should handle word starting with number", () => {
186
+ expect(applyBrandCapitalization("3d")).toBe("3d");
187
+ });
188
+
189
+ test("should handle already-capitalized unknown word", () => {
190
+ expect(applyBrandCapitalization("Already")).toBe("Already");
191
+ });
192
+ });
193
+ });
194
+
195
+ describe("categoryToTitle", () => {
196
+ describe("single-word categories", () => {
197
+ test("should format testing category", () => {
198
+ expect(categoryToTitle("testing")).toBe("Testing");
199
+ });
200
+
201
+ test("should format documentation category", () => {
202
+ expect(categoryToTitle("documentation")).toBe("Documentation");
203
+ });
204
+
205
+ test("should format scripting category", () => {
206
+ expect(categoryToTitle("scripting")).toBe("Scripting");
207
+ });
208
+
209
+ test("should format github as brand name", () => {
210
+ expect(categoryToTitle("github")).toBe("GitHub");
211
+ });
212
+
213
+ test("should format api as brand name", () => {
214
+ expect(categoryToTitle("api")).toBe("API");
215
+ });
216
+
217
+ test("should format npm as brand name", () => {
218
+ expect(categoryToTitle("npm")).toBe("npm");
219
+ });
220
+
221
+ test("should format javascript as brand name", () => {
222
+ expect(categoryToTitle("javascript")).toBe("JavaScript");
223
+ });
224
+ });
225
+
226
+ describe("multi-word categories (hyphenated)", () => {
227
+ test("should format github-actions with brand capitalization", () => {
228
+ expect(categoryToTitle("github-actions")).toBe("GitHub Actions");
229
+ });
230
+
231
+ test("should format api-design with brand capitalization", () => {
232
+ expect(categoryToTitle("api-design")).toBe("API Design");
233
+ });
234
+
235
+ test("should format javascript-testing with brand capitalization", () => {
236
+ expect(categoryToTitle("javascript-testing")).toBe("JavaScript Testing");
237
+ });
238
+
239
+ test("should format test-coverage with standard title case", () => {
240
+ expect(categoryToTitle("test-coverage")).toBe("Test Coverage");
241
+ });
242
+
243
+ test("should format error-handling with standard title case", () => {
244
+ expect(categoryToTitle("error-handling")).toBe("Error Handling");
245
+ });
246
+
247
+ test("should format cross-platform with standard title case", () => {
248
+ expect(categoryToTitle("cross-platform")).toBe("Cross Platform");
249
+ });
250
+
251
+ test("should format ci-cd with brand names", () => {
252
+ expect(categoryToTitle("ci-cd")).toBe("CI CD");
253
+ });
254
+
255
+ test("should format typescript-nodejs with multiple brands", () => {
256
+ expect(categoryToTitle("typescript-nodejs")).toBe("TypeScript Node.js");
257
+ });
258
+ });
259
+
260
+ describe("complex multi-word categories", () => {
261
+ test("should format three-word category", () => {
262
+ expect(categoryToTitle("test-error-handling")).toBe("Test Error Handling");
263
+ });
264
+
265
+ test("should format category with multiple brands", () => {
266
+ expect(categoryToTitle("github-api-testing")).toBe("GitHub API Testing");
267
+ });
268
+
269
+ test("should format long category name", () => {
270
+ expect(categoryToTitle("comprehensive-test-coverage")).toBe(
271
+ "Comprehensive Test Coverage"
272
+ );
273
+ });
274
+ });
275
+
276
+ describe("edge cases", () => {
277
+ test("should handle empty string", () => {
278
+ expect(categoryToTitle("")).toBe("");
279
+ });
280
+
281
+ test("should handle single character", () => {
282
+ expect(categoryToTitle("a")).toBe("A");
283
+ });
284
+
285
+ test("should handle category with numbers", () => {
286
+ expect(categoryToTitle("test123")).toBe("Test123");
287
+ });
288
+
289
+ test("should handle category starting with number", () => {
290
+ expect(categoryToTitle("3d-graphics")).toBe("3d Graphics");
291
+ });
292
+
293
+ test("should handle multiple consecutive hyphens as empty words", () => {
294
+ // Edge case: multiple hyphens create empty strings
295
+ const result = categoryToTitle("test--case");
296
+ expect(result).toBe("Test Case");
297
+ });
298
+
299
+ test("should handle leading hyphen", () => {
300
+ const result = categoryToTitle("-testing");
301
+ expect(result).toBe(" Testing");
302
+ });
303
+
304
+ test("should handle trailing hyphen", () => {
305
+ const result = categoryToTitle("testing-");
306
+ expect(result).toBe("Testing ");
307
+ });
308
+
309
+ test("should handle already-capitalized input", () => {
310
+ expect(categoryToTitle("TESTING")).toBe("Testing");
311
+ });
312
+
313
+ test("should handle mixed-case input", () => {
314
+ expect(categoryToTitle("GitHub-Actions")).toBe("GitHub Actions");
315
+ });
316
+ });
317
+ });
318
+
319
+ describe("brand name coverage", () => {
320
+ test("should have all pure acronym brands in uppercase", () => {
321
+ // Only single-form acronyms (not plurals like APIs/URLs which keep lowercase 's')
322
+ const pureAcronymBrands = ["api", "cli", "json", "yaml", "xml", "html", "css", "sql", "url", "uri", "http", "https", "rest", "jwt", "sdk", "ide", "llm", "ai", "ml", "ci", "cd"];
323
+ for (const brand of pureAcronymBrands) {
324
+ const result = BRAND_NAMES[brand];
325
+ expect(result).toBeDefined();
326
+ expect(result).toBe(result.toUpperCase());
327
+ }
328
+ });
329
+
330
+ test("should have plural acronyms with lowercase s suffix", () => {
331
+ const pluralAcronyms = {
332
+ apis: "APIs",
333
+ urls: "URLs",
334
+ uris: "URIs",
335
+ };
336
+ for (const [input, expected] of Object.entries(pluralAcronyms)) {
337
+ expect(BRAND_NAMES[input]).toBe(expected);
338
+ }
339
+ });
340
+
341
+ test("should have proper camelCase brands", () => {
342
+ const camelCaseBrands = {
343
+ github: "GitHub",
344
+ javascript: "JavaScript",
345
+ typescript: "TypeScript",
346
+ graphql: "GraphQL",
347
+ webgl: "WebGL",
348
+ opengl: "OpenGL",
349
+ directx: "DirectX",
350
+ };
351
+ for (const [input, expected] of Object.entries(camelCaseBrands)) {
352
+ expect(BRAND_NAMES[input]).toBe(expected);
353
+ }
354
+ });
355
+
356
+ test("should have special case brands", () => {
357
+ const specialCases = {
358
+ npm: "npm", // all lowercase
359
+ macos: "macOS", // lowercase first letter
360
+ ios: "iOS", // lowercase first letter
361
+ nodejs: "Node.js", // with dot
362
+ csharp: "C#", // with symbol
363
+ dotnet: ".NET", // starts with dot
364
+ vscode: "VS Code", // with space
365
+ visualstudio: "Visual Studio", // with space
366
+ nuget: "NuGet", // mixed case
367
+ oauth: "OAuth", // mixed case
368
+ };
369
+ for (const [input, expected] of Object.entries(specialCases)) {
370
+ expect(BRAND_NAMES[input]).toBe(expected);
371
+ }
372
+ });
373
+ });
374
+
375
+ describe("integration scenarios", () => {
376
+ test("should format realistic category names correctly", () => {
377
+ const testCases = [
378
+ ["testing", "Testing"],
379
+ ["github-actions", "GitHub Actions"],
380
+ ["documentation", "Documentation"],
381
+ ["scripting", "Scripting"],
382
+ ["api", "API"],
383
+ ["javascript", "JavaScript"],
384
+ ["typescript", "TypeScript"],
385
+ ];
386
+ for (const [input, expected] of testCases) {
387
+ expect(categoryToTitle(input)).toBe(expected);
388
+ }
389
+ });
390
+
391
+ test("should handle all single-word brands as categories", () => {
392
+ for (const [slug, expected] of Object.entries(BRAND_NAMES)) {
393
+ expect(categoryToTitle(slug)).toBe(expected);
394
+ }
395
+ });
396
+ });
397
+ });
@@ -0,0 +1,7 @@
1
+ fileFormatVersion: 2
2
+ guid: 7fc490d5053dd9747a0f8aec3c839eb7
3
+ DefaultImporter:
4
+ externalObjects: {}
5
+ userData:
6
+ assetBundleName:
7
+ assetBundleVariant: