@shohojdhara/atomix 0.3.12 → 0.3.14

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 (155) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +2 -0
  3. package/dist/atomix.css +101 -88
  4. package/dist/atomix.css.map +1 -1
  5. package/dist/atomix.min.css +5 -15258
  6. package/dist/atomix.min.css.map +1 -1
  7. package/dist/charts.d.ts +1 -1
  8. package/dist/charts.js +17 -19
  9. package/dist/charts.js.map +1 -1
  10. package/dist/core.d.ts +41 -11
  11. package/dist/core.js +55 -41
  12. package/dist/core.js.map +1 -1
  13. package/dist/forms.d.ts +28 -11
  14. package/dist/forms.js +25 -24
  15. package/dist/forms.js.map +1 -1
  16. package/dist/heavy.d.ts +1 -1
  17. package/dist/heavy.js +32 -25
  18. package/dist/heavy.js.map +1 -1
  19. package/dist/index.d.ts +122 -46
  20. package/dist/index.esm.js +865 -200
  21. package/dist/index.esm.js.map +1 -1
  22. package/dist/index.js +870 -204
  23. package/dist/index.js.map +1 -1
  24. package/dist/index.min.js +1 -1
  25. package/dist/index.min.js.map +1 -1
  26. package/dist/theme.d.ts +27 -2
  27. package/dist/theme.js +721 -108
  28. package/dist/theme.js.map +1 -1
  29. package/package.json +1 -1
  30. package/scripts/atomix-cli.js +610 -1111
  31. package/scripts/cli/component-generator.js +610 -0
  32. package/scripts/cli/documentation-sync.js +542 -0
  33. package/scripts/cli/interactive-init.js +84 -288
  34. package/scripts/cli/mappings.js +211 -0
  35. package/scripts/cli/migration-tools.js +95 -288
  36. package/scripts/cli/template-manager.js +107 -0
  37. package/scripts/cli/templates/README.md +123 -0
  38. package/scripts/cli/templates/composable-templates.js +149 -0
  39. package/scripts/cli/templates/config-templates.js +126 -0
  40. package/scripts/cli/templates/index.js +95 -0
  41. package/scripts/cli/templates/project-templates.js +214 -0
  42. package/scripts/cli/templates/react-templates.js +261 -0
  43. package/scripts/cli/templates/scss-templates.js +156 -0
  44. package/scripts/cli/templates/storybook-templates.js +236 -0
  45. package/scripts/cli/templates/testing-templates.js +45 -0
  46. package/scripts/cli/templates/token-templates.js +447 -0
  47. package/scripts/cli/templates/types-templates.js +133 -0
  48. package/scripts/cli/templates-original-backup.js +1655 -0
  49. package/scripts/cli/templates.js +35 -0
  50. package/scripts/cli/templates_backup.js +684 -0
  51. package/scripts/cli/theme-bridge.js +20 -14
  52. package/scripts/cli/token-manager.js +150 -77
  53. package/scripts/cli/utils.js +37 -25
  54. package/src/components/Accordion/Accordion.stories.tsx +5 -5
  55. package/src/components/Accordion/Accordion.test.tsx +57 -0
  56. package/src/components/Accordion/Accordion.tsx +4 -0
  57. package/src/components/AtomixGlass/AtomixGlassContainer.tsx +41 -44
  58. package/src/components/AtomixGlass/stories/AtomixGlass.stories.tsx +1 -1
  59. package/src/components/AtomixGlass/stories/Examples.stories.tsx +37 -37
  60. package/src/components/AtomixGlass/stories/Modes.stories.tsx +1 -2
  61. package/src/components/AtomixGlass/stories/Playground.stories.tsx +50 -51
  62. package/src/components/Avatar/Avatar.stories.tsx +26 -26
  63. package/src/components/Badge/Badge.stories.tsx +31 -31
  64. package/src/components/Badge/Badge.test.tsx +51 -0
  65. package/src/components/Badge/Badge.tsx +20 -1
  66. package/src/components/Block/Block.stories.tsx +5 -5
  67. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +1 -1
  68. package/src/components/Breadcrumb/Breadcrumb.tsx +2 -2
  69. package/src/components/Button/Button.stories.tsx +13 -13
  70. package/src/components/Button/Button.tsx +4 -4
  71. package/src/components/Button/ButtonGroup.stories.tsx +2 -2
  72. package/src/components/Button/README.md +5 -0
  73. package/src/components/Callout/Callout.stories.tsx +11 -11
  74. package/src/components/Callout/Callout.test.tsx +10 -10
  75. package/src/components/Callout/Callout.tsx +7 -7
  76. package/src/components/Callout/README.md +9 -8
  77. package/src/components/Card/Card.tsx +2 -2
  78. package/src/components/Chart/Chart.stories.tsx +6 -6
  79. package/src/components/Chart/Chart.tsx +1 -1
  80. package/src/components/ColorModeToggle/ColorModeToggle.stories.tsx +1 -1
  81. package/src/components/DataTable/DataTable.tsx +14 -12
  82. package/src/components/DatePicker/DatePicker.stories.tsx +6 -6
  83. package/src/components/Dropdown/Dropdown.stories.tsx +4 -4
  84. package/src/components/Form/Checkbox.stories.tsx +3 -3
  85. package/src/components/Form/Checkbox.tsx +4 -2
  86. package/src/components/Form/Form.stories.tsx +3 -3
  87. package/src/components/Form/FormGroup.stories.tsx +1 -1
  88. package/src/components/Form/Input.stories.tsx +28 -16
  89. package/src/components/Form/Input.test.tsx +59 -0
  90. package/src/components/Form/Input.tsx +97 -95
  91. package/src/components/Form/Radio.stories.tsx +94 -94
  92. package/src/components/Form/Radio.tsx +2 -2
  93. package/src/components/Form/Select.stories.tsx +4 -4
  94. package/src/components/Form/Select.tsx +2 -2
  95. package/src/components/Form/Textarea.stories.tsx +22 -7
  96. package/src/components/Form/Textarea.test.tsx +45 -0
  97. package/src/components/Form/Textarea.tsx +88 -86
  98. package/src/components/List/List.stories.tsx +2 -2
  99. package/src/components/Modal/Modal.stories.tsx +4 -4
  100. package/src/components/Navigation/Navbar/Navbar.stories.tsx +5 -5
  101. package/src/components/Navigation/Navbar/Navbar.tsx +1 -1
  102. package/src/components/Navigation/README.md +1 -1
  103. package/src/components/Pagination/Pagination.stories.tsx +5 -2
  104. package/src/components/Pagination/Pagination.tsx +1 -1
  105. package/src/components/PhotoViewer/PhotoViewer.stories.tsx +10 -10
  106. package/src/components/Popover/Popover.stories.tsx +1 -1
  107. package/src/components/ProductReview/ProductReview.tsx +1 -1
  108. package/src/components/Progress/Progress.tsx +46 -46
  109. package/src/components/Rating/Rating.stories.tsx +4 -4
  110. package/src/components/Rating/Rating.tsx +8 -8
  111. package/src/components/Slider/Slider.stories.tsx +63 -63
  112. package/src/components/Spinner/Spinner.stories.tsx +2 -2
  113. package/src/components/Spinner/Spinner.test.tsx +35 -0
  114. package/src/components/Spinner/Spinner.tsx +9 -2
  115. package/src/components/Testimonial/Testimonial.stories.tsx +1 -1
  116. package/src/components/Toggle/Toggle.stories.tsx +32 -9
  117. package/src/components/Toggle/Toggle.test.tsx +91 -0
  118. package/src/components/Toggle/Toggle.tsx +44 -27
  119. package/src/components/Tooltip/Tooltip.tsx +1 -1
  120. package/src/layouts/Grid/Grid.stories.tsx +49 -49
  121. package/src/layouts/MasonryGrid/MasonryGrid.stories.tsx +2 -2
  122. package/src/lib/composables/useAccordion.ts +12 -3
  123. package/src/lib/composables/useBreadcrumb.ts +2 -2
  124. package/src/lib/composables/useCallout.ts +7 -7
  125. package/src/lib/composables/useNavbar.ts +1 -1
  126. package/src/lib/constants/components.ts +1 -1
  127. package/src/lib/storybook/InteractiveDemo.tsx +113 -0
  128. package/src/lib/storybook/PreviewContainer.tsx +36 -0
  129. package/src/lib/storybook/VariantsGrid.tsx +21 -0
  130. package/src/lib/storybook/index.ts +3 -0
  131. package/src/lib/theme/core/createThemeObject.ts +9 -5
  132. package/src/lib/theme/devtools/CLI.ts +155 -0
  133. package/src/lib/theme/devtools/DesignTokensCustomizer.stories.tsx +213 -0
  134. package/src/lib/theme/devtools/DesignTokensCustomizer.tsx +566 -0
  135. package/src/lib/theme/devtools/LiveEditor.tsx +2 -1
  136. package/src/lib/theme/devtools/index.ts +3 -0
  137. package/src/lib/theme/errors/errors.ts +8 -0
  138. package/src/lib/theme/runtime/ThemeProvider.tsx +117 -57
  139. package/src/lib/theme/runtime/__tests__/ThemeProvider.integration.test.tsx +305 -0
  140. package/src/lib/theme/runtime/__tests__/ThemeProvider.test.tsx +588 -0
  141. package/src/lib/theme/utils/__tests__/themeValidation.test.ts +264 -0
  142. package/src/lib/theme/utils/index.ts +1 -0
  143. package/src/lib/theme/utils/themeValidation.ts +501 -0
  144. package/src/lib/theme-tools.ts +32 -3
  145. package/src/lib/types/components.ts +81 -26
  146. package/src/lib/utils/themeNaming.ts +1 -1
  147. package/src/styles/06-components/_components.atomix-glass.scss +14 -15
  148. package/src/styles/06-components/_components.callout.scss +29 -33
  149. package/src/styles/06-components/_index.scss +1 -1
  150. package/src/styles/99-utilities/_utilities.display.scss +14 -3
  151. package/src/styles/99-utilities/_utilities.flex.scss +10 -10
  152. package/src/styles/99-utilities/_utilities.text.scss +28 -8
  153. package/scripts/cli/__tests__/cli-commands.test.js +0 -204
  154. package/scripts/cli/__tests__/utils.test.js +0 -201
  155. package/scripts/cli/__tests__/vitest.config.js +0 -26
@@ -8,9 +8,19 @@
8
8
  $utilities-text: (
9
9
  'font-size': (rfs: true,
10
10
  property: font-size,
11
- class: u-fs,
11
+ class: u-text,
12
12
  values: map.merge(color-maps.$font-sizes-extended,
13
- (1: map.get(color-maps.$font-sizes-extended, 'h1'),
13
+ (xs: map.get(color-maps.$font-sizes-extended, 'xs'),
14
+ sm: map.get(color-maps.$font-sizes-extended, 'sm'),
15
+ base: map.get(color-maps.$font-sizes-extended, 'base'),
16
+ lg: map.get(color-maps.$font-sizes-extended, 'lg'),
17
+ xl: map.get(color-maps.$font-sizes-extended, 'xl'),
18
+ '2xl': map.get(color-maps.$font-sizes-extended, '2xl'),
19
+ '3xl': map.get(color-maps.$font-sizes-extended, '3xl'),
20
+ '4xl': map.get(color-maps.$font-sizes-extended, '4xl'),
21
+ '5xl': map.get(color-maps.$font-sizes-extended, '5xl'),
22
+ '6xl': map.get(color-maps.$font-sizes-extended, '6xl'),
23
+ 1: map.get(color-maps.$font-sizes-extended, 'h1'),
14
24
  2: map.get(color-maps.$font-sizes-extended, 'h2'),
15
25
  3: map.get(color-maps.$font-sizes-extended, 'h3'),
16
26
  4: map.get(color-maps.$font-sizes-extended, 'h4'),
@@ -25,13 +35,19 @@ $utilities-text: (
25
35
  ),
26
36
  ),
27
37
  'font-weight': (property: font-weight,
28
- class: u-fw,
38
+ class: u-font,
29
39
  values: color-maps.$theme-font-weight,
30
40
  ),
31
41
  'line-height': (property: line-height,
32
- class: u-lh,
42
+ class: u-leading,
33
43
  values: map.merge(color-maps.$line-heights,
34
- (1: 1,
44
+ (none: 1,
45
+ tight: 1.25,
46
+ snug: 1.375,
47
+ normal: 1.5,
48
+ relaxed: 1.625,
49
+ loose: 2,
50
+ 1: 1,
35
51
  )),
36
52
  ),
37
53
  'text-align': (responsive: true,
@@ -42,9 +58,13 @@ $utilities-text: (
42
58
  center: center,
43
59
  ),
44
60
  ),
45
- 'text-decoration': (class: u-td,
46
- property: text-decoration,
47
- values: none underline line-through,
61
+ 'text-decoration': (property: text-decoration,
62
+ class: u,
63
+ values: (
64
+ 'underline': underline,
65
+ 'line-through': line-through,
66
+ 'no-underline': none,
67
+ ),
48
68
  ),
49
69
  'text-transform': (property: text-transform,
50
70
  class: u-text,
@@ -1,204 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
- import { execSync } from 'child_process';
3
- import { existsSync, mkdirSync, rmSync, readFileSync } from 'fs';
4
- import { join } from 'path';
5
- import { fileURLToPath } from 'url';
6
- import { dirname } from 'path';
7
-
8
- const __filename = fileURLToPath(import.meta.url);
9
- const __dirname = dirname(__filename);
10
- const CLI_PATH = join(__dirname, '../../atomix-cli.js');
11
- const TEST_DIR = join(__dirname, 'test-output');
12
-
13
- describe('Atomix CLI Commands', () => {
14
- beforeEach(() => {
15
- // Create test directory
16
- if (!existsSync(TEST_DIR)) {
17
- mkdirSync(TEST_DIR, { recursive: true });
18
- }
19
- });
20
-
21
- afterEach(() => {
22
- // Clean up test directory
23
- if (existsSync(TEST_DIR)) {
24
- rmSync(TEST_DIR, { recursive: true, force: true });
25
- }
26
- });
27
-
28
- describe('atomix --help', () => {
29
- it('should display help information', () => {
30
- const output = execSync(`node ${CLI_PATH} --help`).toString();
31
- expect(output).toContain('Atomix Design System CLI');
32
- expect(output).toContain('Commands:');
33
- expect(output).toContain('build-theme');
34
- expect(output).toContain('generate');
35
- expect(output).toContain('validate');
36
- });
37
- });
38
-
39
- describe('atomix --version', () => {
40
- it('should display version number', () => {
41
- const output = execSync(`node ${CLI_PATH} --version`).toString();
42
- expect(output).toMatch(/\d+\.\d+\.\d+/);
43
- });
44
- });
45
-
46
- describe('atomix generate component', () => {
47
- const componentPath = join(TEST_DIR, 'TestComponent');
48
-
49
- it('should create component files with valid name', () => {
50
- execSync(`node ${CLI_PATH} generate component TestButton --path ${TEST_DIR}`, {
51
- cwd: process.cwd()
52
- });
53
-
54
- const buttonPath = join(TEST_DIR, 'TestButton');
55
-
56
- // Check if files are created
57
- expect(existsSync(join(buttonPath, 'TestButton.tsx'))).toBe(true);
58
- expect(existsSync(join(buttonPath, 'index.ts'))).toBe(true);
59
- expect(existsSync(join(buttonPath, '_testbutton.scss'))).toBe(true);
60
- expect(existsSync(join(buttonPath, 'TestButton.stories.tsx'))).toBe(true);
61
-
62
- // Check component content
63
- const componentContent = readFileSync(join(buttonPath, 'TestButton.tsx'), 'utf8');
64
- expect(componentContent).toContain('export const TestButton');
65
- expect(componentContent).toContain('TestButtonProps');
66
- expect(componentContent).toContain('forwardRef');
67
- });
68
-
69
- it('should reject invalid component names', () => {
70
- expect(() => {
71
- execSync(`node ${CLI_PATH} generate component test-button --path ${TEST_DIR}`, {
72
- cwd: process.cwd()
73
- });
74
- }).toThrow();
75
- });
76
-
77
- it('should create test file when --test flag is used', () => {
78
- execSync(`node ${CLI_PATH} generate component TestCard --test --path ${TEST_DIR}`, {
79
- cwd: process.cwd()
80
- });
81
-
82
- const cardPath = join(TEST_DIR, 'TestCard');
83
- expect(existsSync(join(cardPath, 'TestCard.test.tsx'))).toBe(true);
84
-
85
- const testContent = readFileSync(join(cardPath, 'TestCard.test.tsx'), 'utf8');
86
- expect(testContent).toContain('describe(\'TestCard\'');
87
- expect(testContent).toContain('vitest');
88
- });
89
- });
90
-
91
- describe('atomix generate token', () => {
92
- it('should generate color tokens', () => {
93
- const settingsPath = join(TEST_DIR, 'src/styles/01-settings');
94
- mkdirSync(settingsPath, { recursive: true });
95
-
96
- execSync(`node ${CLI_PATH} generate token colors`, {
97
- cwd: TEST_DIR
98
- });
99
-
100
- const tokenFile = join(settingsPath, '_settings.colors.custom.scss');
101
- expect(existsSync(tokenFile)).toBe(true);
102
-
103
- const content = readFileSync(tokenFile, 'utf8');
104
- expect(content).toContain('Custom Color Tokens');
105
- expect(content).toContain('$custom-primary-6');
106
- expect(content).toContain('$custom-success');
107
- });
108
-
109
- it('should reject invalid token categories', () => {
110
- expect(() => {
111
- execSync(`node ${CLI_PATH} generate token invalid-category`, {
112
- cwd: TEST_DIR
113
- });
114
- }).toThrow();
115
- });
116
- });
117
-
118
- describe('atomix validate', () => {
119
- it('should validate tokens when --tokens flag is used', () => {
120
- // This is a mock test - in real implementation, you'd set up token files
121
- const output = execSync(`node ${CLI_PATH} validate --tokens`, {
122
- cwd: process.cwd()
123
- }).toString();
124
-
125
- // Should complete without throwing
126
- expect(output).toBeDefined();
127
- });
128
- });
129
-
130
- describe('atomix doctor', () => {
131
- it('should run diagnostics successfully', () => {
132
- const output = execSync(`node ${CLI_PATH} doctor`).toString();
133
- expect(output).toContain('Atomix Doctor Report');
134
- expect(output).toContain('Node.js Version');
135
- expect(output).toContain('Atomix Installation');
136
- });
137
- });
138
-
139
- describe('atomix theme create', () => {
140
- it('should create CSS theme with valid name', () => {
141
- const themesPath = join(TEST_DIR, 'themes');
142
- mkdirSync(themesPath, { recursive: true });
143
-
144
- execSync(`node ${CLI_PATH} theme create test-theme --output ${themesPath}`, {
145
- cwd: process.cwd()
146
- });
147
-
148
- const themePath = join(themesPath, 'test-theme');
149
- expect(existsSync(join(themePath, 'index.scss'))).toBe(true);
150
- expect(existsSync(join(themePath, 'README.md'))).toBe(true);
151
-
152
- const themeContent = readFileSync(join(themePath, 'index.scss'), 'utf8');
153
- expect(themeContent).toContain('data-theme="test-theme"');
154
- expect(themeContent).toContain('--atomix-color-primary');
155
- });
156
-
157
- it('should create JavaScript theme when --type js is used', () => {
158
- const themesPath = join(TEST_DIR, 'themes');
159
- mkdirSync(themesPath, { recursive: true });
160
-
161
- execSync(`node ${CLI_PATH} theme create js-theme --type js --output ${themesPath}`, {
162
- cwd: process.cwd()
163
- });
164
-
165
- const themePath = join(themesPath, 'js-theme');
166
- expect(existsSync(join(themePath, 'index.ts'))).toBe(true);
167
-
168
- const themeContent = readFileSync(join(themePath, 'index.ts'), 'utf8');
169
- expect(themeContent).toContain('jsTheme');
170
- expect(themeContent).toContain('createTheme');
171
- });
172
-
173
- it('should reject invalid theme names', () => {
174
- expect(() => {
175
- execSync(`node ${CLI_PATH} theme create InvalidTheme --output ${TEST_DIR}`, {
176
- cwd: process.cwd()
177
- });
178
- }).toThrow();
179
- });
180
- });
181
- });
182
-
183
- describe('CLI Error Handling', () => {
184
- it('should show suggestions for invalid commands', () => {
185
- try {
186
- execSync(`node ${CLI_PATH} invalidcommand`);
187
- } catch (error) {
188
- const output = error.stdout?.toString() || error.stderr?.toString();
189
- expect(output).toContain('unknown command');
190
- }
191
- });
192
-
193
- it('should handle missing required arguments', () => {
194
- expect(() => {
195
- execSync(`node ${CLI_PATH} generate`);
196
- }).toThrow();
197
- });
198
-
199
- it('should respect --debug flag', () => {
200
- const output = execSync(`node ${CLI_PATH} --debug --help`).toString();
201
- // Debug mode should be enabled
202
- expect(process.env.ATOMIX_DEBUG).toBe('true');
203
- });
204
- });
@@ -1,201 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
- import {
3
- validatePath,
4
- validateComponentName,
5
- validateThemeName,
6
- sanitizeInput,
7
- isValidColor,
8
- checkNodeVersion,
9
- formatFileSize
10
- } from '../utils.js';
11
- import { join, resolve } from 'path';
12
-
13
- describe('CLI Utils', () => {
14
- describe('validatePath', () => {
15
- const basePath = '/home/user/project';
16
-
17
- it('should validate safe paths within project', () => {
18
- const result = validatePath('src/components', basePath);
19
- expect(result.isValid).toBe(true);
20
- expect(result.safePath).toBe(resolve(basePath, 'src/components'));
21
- });
22
-
23
- it('should reject paths outside project directory', () => {
24
- const result = validatePath('../../etc/passwd', basePath);
25
- expect(result.isValid).toBe(false);
26
- expect(result.error).toContain('outside the project directory');
27
- });
28
-
29
- it('should reject paths to sensitive files', () => {
30
- const sensitiveFiles = ['.env', '.git/config', 'private/key.pem', 'secret.key'];
31
-
32
- sensitiveFiles.forEach(file => {
33
- const result = validatePath(file, basePath);
34
- expect(result.isValid).toBe(false);
35
- expect(result.error).toContain('sensitive path');
36
- });
37
- });
38
-
39
- it('should handle absolute paths correctly', () => {
40
- const absolutePath = join(basePath, 'src/components');
41
- const result = validatePath(absolutePath, basePath);
42
- expect(result.isValid).toBe(true);
43
- expect(result.safePath).toBe(absolutePath);
44
- });
45
- });
46
-
47
- describe('validateComponentName', () => {
48
- it('should accept valid PascalCase names', () => {
49
- const validNames = ['Button', 'CardHeader', 'MyComponent123'];
50
-
51
- validNames.forEach(name => {
52
- const result = validateComponentName(name);
53
- expect(result.isValid).toBe(true);
54
- });
55
- });
56
-
57
- it('should reject invalid component names', () => {
58
- const invalidNames = [
59
- 'button', // lowercase
60
- 'Button-Test', // contains hyphen
61
- 'Button_Test', // contains underscore
62
- '123Button', // starts with number
63
- 'A', // too short
64
- '', // empty
65
- ];
66
-
67
- invalidNames.forEach(name => {
68
- const result = validateComponentName(name);
69
- expect(result.isValid).toBe(false);
70
- });
71
- });
72
-
73
- it('should reject reserved words', () => {
74
- const reserved = ['Component', 'React', 'Fragment'];
75
-
76
- reserved.forEach(name => {
77
- const result = validateComponentName(name);
78
- expect(result.isValid).toBe(false);
79
- expect(result.error).toContain('reserved word');
80
- });
81
- });
82
- });
83
-
84
- describe('validateThemeName', () => {
85
- it('should accept valid kebab-case names', () => {
86
- const validNames = ['dark-theme', 'light-mode', 'custom-theme-2'];
87
-
88
- validNames.forEach(name => {
89
- const result = validateThemeName(name);
90
- expect(result.isValid).toBe(true);
91
- });
92
- });
93
-
94
- it('should reject invalid theme names', () => {
95
- const invalidNames = [
96
- 'DarkTheme', // PascalCase
97
- 'dark_theme', // underscore
98
- '123-theme', // starts with number
99
- 'theme-', // ends with hyphen
100
- 'theme--dark', // consecutive hyphens
101
- '', // empty
102
- ];
103
-
104
- invalidNames.forEach(name => {
105
- const result = validateThemeName(name);
106
- expect(result.isValid).toBe(false);
107
- });
108
- });
109
- });
110
-
111
- describe('sanitizeInput', () => {
112
- it('should remove dangerous shell characters', () => {
113
- const dangerous = 'test; rm -rf /';
114
- const sanitized = sanitizeInput(dangerous);
115
- expect(sanitized).toBe('test rm -rf /');
116
- expect(sanitized).not.toContain(';');
117
- });
118
-
119
- it('should remove multiple dangerous characters', () => {
120
- const input = 'cmd1 && cmd2 | cmd3 `evil` $var > file < input \\ ';
121
- const sanitized = sanitizeInput(input);
122
- expect(sanitized).toBe('cmd1 cmd2 cmd3 evil var file input');
123
- });
124
-
125
- it('should handle non-string inputs', () => {
126
- expect(sanitizeInput(123)).toBe('123');
127
- expect(sanitizeInput(null)).toBe('null');
128
- expect(sanitizeInput(undefined)).toBe('undefined');
129
- });
130
- });
131
-
132
- describe('isValidColor', () => {
133
- it('should validate hex colors', () => {
134
- const validHex = ['#FFF', '#FFFF', '#FFFFFF', '#FFFFFFFF', '#abc123'];
135
-
136
- validHex.forEach(color => {
137
- expect(isValidColor(color)).toBe(true);
138
- });
139
- });
140
-
141
- it('should validate CSS color functions', () => {
142
- const validFunctions = [
143
- 'rgb(255, 255, 255)',
144
- 'rgba(0, 0, 0, 0.5)',
145
- 'hsl(120, 100%, 50%)',
146
- 'hsla(240, 100%, 50%, 0.3)',
147
- 'var(--atomix-color-primary)',
148
- ];
149
-
150
- validFunctions.forEach(color => {
151
- expect(isValidColor(color)).toBe(true);
152
- });
153
- });
154
-
155
- it('should reject invalid colors', () => {
156
- const invalid = ['#GGG', '#12', 'red', '255,255,255', 'notacolor'];
157
-
158
- invalid.forEach(color => {
159
- expect(isValidColor(color)).toBe(false);
160
- });
161
- });
162
- });
163
-
164
- describe('checkNodeVersion', () => {
165
- it('should check Node version compatibility', () => {
166
- const currentVersion = process.version.substring(1);
167
- const [major, minor, patch] = currentVersion.split('.').map(Number);
168
-
169
- // Should pass for current version
170
- const result1 = checkNodeVersion(currentVersion);
171
- expect(result1.compatible).toBe(true);
172
-
173
- // Should fail for higher version
174
- const higherVersion = `${major + 1}.0.0`;
175
- const result2 = checkNodeVersion(higherVersion);
176
- expect(result2.compatible).toBe(false);
177
-
178
- // Should pass for lower version
179
- if (major > 0) {
180
- const lowerVersion = `${major - 1}.0.0`;
181
- const result3 = checkNodeVersion(lowerVersion);
182
- expect(result3.compatible).toBe(true);
183
- }
184
- });
185
- });
186
-
187
- describe('formatFileSize', () => {
188
- it('should format file sizes correctly', () => {
189
- expect(formatFileSize(0)).toBe('0 B');
190
- expect(formatFileSize(512)).toBe('512.00 B');
191
- expect(formatFileSize(1024)).toBe('1.00 KB');
192
- expect(formatFileSize(1048576)).toBe('1.00 MB');
193
- expect(formatFileSize(1073741824)).toBe('1.00 GB');
194
- });
195
-
196
- it('should handle decimal values', () => {
197
- expect(formatFileSize(1536)).toBe('1.50 KB'); // 1.5 KB
198
- expect(formatFileSize(2621440)).toBe('2.50 MB'); // 2.5 MB
199
- });
200
- });
201
- });
@@ -1,26 +0,0 @@
1
- import { defineConfig } from 'vitest/config';
2
-
3
- export default defineConfig({
4
- test: {
5
- globals: true,
6
- environment: 'node',
7
- coverage: {
8
- provider: 'v8',
9
- reporter: ['text', 'json', 'html'],
10
- exclude: [
11
- 'node_modules/**',
12
- '**/__tests__/**',
13
- '**/test-output/**',
14
- ],
15
- include: [
16
- '../*.js',
17
- ],
18
- thresholds: {
19
- lines: 80,
20
- functions: 80,
21
- branches: 80,
22
- statements: 80,
23
- },
24
- },
25
- },
26
- });