@shohojdhara/atomix 0.4.9 → 0.5.1

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 (67) hide show
  1. package/dist/atomix.css +95 -69
  2. package/dist/atomix.css.map +1 -1
  3. package/dist/atomix.min.css +1 -1
  4. package/dist/atomix.min.css.map +1 -1
  5. package/dist/charts.d.ts +1 -0
  6. package/dist/charts.js +231 -332
  7. package/dist/charts.js.map +1 -1
  8. package/dist/core.d.ts +1 -0
  9. package/dist/core.js +232 -333
  10. package/dist/core.js.map +1 -1
  11. package/dist/forms.d.ts +1 -0
  12. package/dist/forms.js +231 -332
  13. package/dist/forms.js.map +1 -1
  14. package/dist/heavy.d.ts +11 -2
  15. package/dist/heavy.js +233 -334
  16. package/dist/heavy.js.map +1 -1
  17. package/dist/index.d.ts +13 -2
  18. package/dist/index.esm.js +228 -327
  19. package/dist/index.esm.js.map +1 -1
  20. package/dist/index.js +227 -326
  21. package/dist/index.js.map +1 -1
  22. package/dist/index.min.js +1 -1
  23. package/dist/index.min.js.map +1 -1
  24. package/package.json +11 -1
  25. package/src/components/AtomixGlass/AtomixGlass.tsx +188 -128
  26. package/src/components/AtomixGlass/AtomixGlassContainer.tsx +62 -90
  27. package/src/components/AtomixGlass/PerformanceDashboard.tsx +153 -201
  28. package/src/components/AtomixGlass/glass-utils.ts +50 -0
  29. package/src/components/AtomixGlass/shader-utils.ts +1 -1
  30. package/src/components/AtomixGlass/stories/{Phase1-Animation.stories.tsx → AnimationFeatures.stories.tsx} +53 -47
  31. package/src/components/AtomixGlass/stories/Examples.stories.tsx +573 -236
  32. package/src/components/AtomixGlass/stories/Playground.stories.tsx +656 -44
  33. package/src/components/AtomixGlass/stories/argTypes.ts +384 -0
  34. package/src/components/AtomixGlass/stories/shared-components.tsx +82 -3
  35. package/src/components/AtomixGlass/stories/types.ts +127 -0
  36. package/src/lib/composables/useAtomixGlass.ts +108 -71
  37. package/src/lib/composables/useAtomixGlassStyles.ts +0 -2
  38. package/src/lib/constants/components.ts +1 -0
  39. package/src/lib/types/components.ts +1 -0
  40. package/src/lib/utils/displacement-generator.ts +1 -1
  41. package/src/styles/06-components/_components.atomix-glass.scss +158 -97
  42. package/scripts/cli/__tests__/README.md +0 -81
  43. package/scripts/cli/__tests__/basic.test.js +0 -116
  44. package/scripts/cli/__tests__/clean.test.js +0 -278
  45. package/scripts/cli/__tests__/component-generator.test.js +0 -332
  46. package/scripts/cli/__tests__/component-validator.test.js +0 -433
  47. package/scripts/cli/__tests__/generator.test.js +0 -613
  48. package/scripts/cli/__tests__/glass-motion.test.js +0 -256
  49. package/scripts/cli/__tests__/integration.test.js +0 -938
  50. package/scripts/cli/__tests__/migrate.test.js +0 -74
  51. package/scripts/cli/__tests__/security.test.js +0 -206
  52. package/scripts/cli/__tests__/test-setup.js +0 -135
  53. package/scripts/cli/__tests__/theme-bridge.test.js +0 -507
  54. package/scripts/cli/__tests__/token-manager.test.js +0 -251
  55. package/scripts/cli/__tests__/token-provider.test.js +0 -361
  56. package/scripts/cli/__tests__/utils.test.js +0 -165
  57. package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +0 -216
  58. package/src/components/AtomixGlass/stories/Customization.stories.tsx +0 -131
  59. package/src/components/AtomixGlass/stories/Modes.stories.tsx +0 -1082
  60. package/src/components/AtomixGlass/stories/Overview.stories.tsx +0 -497
  61. package/src/components/AtomixGlass/stories/Performance.stories.tsx +0 -103
  62. package/src/components/AtomixGlass/stories/Phase1-Test.stories.tsx +0 -95
  63. package/src/components/AtomixGlass/stories/Shaders.stories.tsx +0 -395
  64. package/src/components/TypedButton/TypedButton.stories.tsx +0 -59
  65. package/src/components/TypedButton/TypedButton.tsx +0 -39
  66. package/src/components/TypedButton/index.ts +0 -2
  67. package/src/lib/composables/useTypedButton.ts +0 -66
@@ -1,251 +0,0 @@
1
- /**
2
- * Token Manager Tests
3
- */
4
-
5
- import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
6
- import {
7
- listTokens,
8
- validateTokens,
9
- exportTokens,
10
- importTokens,
11
- fixTokens,
12
- setProjectRoot
13
- } from '../token-manager.js';
14
- import { mkdtemp, rm, writeFile, readFile, mkdir } from 'fs/promises';
15
- import { join } from 'path';
16
- import { tmpdir } from 'os';
17
-
18
- // Mock dependencies
19
- vi.mock('ora', () => ({
20
- default: vi.fn(() => ({
21
- start: vi.fn(() => ({
22
- succeed: vi.fn(),
23
- fail: vi.fn(),
24
- text: ''
25
- }))
26
- }))
27
- }));
28
-
29
- vi.mock('chalk', () => ({
30
- default: {
31
- green: vi.fn((text) => text),
32
- red: vi.fn((text) => text),
33
- yellow: vi.fn((text) => text),
34
- cyan: vi.fn((text) => text),
35
- gray: vi.fn((text) => text),
36
- bold: vi.fn((obj) => obj)
37
- }
38
- }));
39
-
40
- describe('Token Manager', () => {
41
- let tempDir;
42
- let tokenDir;
43
-
44
- beforeEach(async () => {
45
- const tmp = await mkdtemp(join(tmpdir(), 'atomix-test-'));
46
- // Ensure absolute path
47
- // On some systems/configs tmpdir might return symlinked path or weirdness
48
- const { resolve } = await import('path');
49
- tempDir = resolve(tmp);
50
-
51
- tokenDir = join(tempDir, 'src', 'styles', '01-settings');
52
- await mkdir(tokenDir, { recursive: true });
53
- setProjectRoot(tempDir);
54
- });
55
-
56
- afterEach(async () => {
57
- setProjectRoot('');
58
- await rm(tempDir, { recursive: true, force: true });
59
- vi.clearAllMocks();
60
- });
61
-
62
- describe('listTokens', () => {
63
- it('should list tokens from valid files', async () => {
64
- // Create test token files
65
- await writeFile(join(tokenDir, '_settings.colors.scss'), `
66
- $primary-500: #7AFFD7 !default;
67
- $secondary-500: #FF5733 !default;
68
- --atomix-color-primary: #7AFFD7;
69
- --atomix-color-secondary: #FF5733;
70
- `);
71
-
72
- const result = await listTokens();
73
-
74
- expect(result.tokens).toHaveProperty('colors');
75
- // Check keys inside the category object
76
- const colorTokens = result.tokens.colors.tokens;
77
- expect(colorTokens).toHaveProperty('$primary-500');
78
- expect(colorTokens).toHaveProperty('--atomix-color-primary');
79
- });
80
-
81
- it('should handle missing files gracefully', async () => {
82
- const result = await listTokens();
83
- expect(result.tokens).toEqual({});
84
- expect(result.categoryCount).toBe(0);
85
- });
86
- });
87
-
88
- describe('validateTokens', () => {
89
- it('should detect hardcoded colors', async () => {
90
- await writeFile(join(tokenDir, '_settings.colors.scss'), `
91
- $primary: #ffffff !default;
92
- $secondary: #000000 !default;
93
- background: #ff0000; // Hardcoded color
94
- `);
95
-
96
- const result = await validateTokens();
97
-
98
- expect(result.warnings).toContainEqual(
99
- expect.objectContaining({
100
- category: 'hardcoded-value',
101
- file: expect.stringContaining('_settings.colors.scss')
102
- })
103
- );
104
- });
105
-
106
- it('should detect missing !default flags', async () => {
107
- await writeFile(join(tokenDir, '_settings.colors.scss'), `
108
- $primary: #7AFFD7; // Missing !default
109
- $secondary: #FF5733 !default;
110
- `);
111
-
112
- const result = await validateTokens();
113
-
114
- expect(result.issues).toContainEqual(
115
- expect.objectContaining({
116
- category: 'missing-default',
117
- file: expect.stringContaining('_settings.colors.scss')
118
- })
119
- );
120
- });
121
-
122
- it('should validate naming conventions', async () => {
123
- await writeFile(join(tokenDir, '_settings.colors.scss'), `
124
- $Invalid-Name: #7AFFD7 !default;
125
- $valid_name: #FF5733 !default;
126
- `);
127
-
128
- const result = await validateTokens();
129
-
130
- expect(result.issues).toContainEqual(
131
- expect.objectContaining({
132
- category: 'naming-convention',
133
- file: expect.stringContaining('_settings.colors.scss')
134
- })
135
- );
136
- });
137
- });
138
-
139
- describe('exportTokens', () => {
140
- it('should export tokens as JSON', async () => {
141
- await writeFile(join(tokenDir, '_settings.colors.scss'), `
142
- $primary-500: #7AFFD7 !default;
143
- --atomix-color-primary: #7AFFD7;
144
- `);
145
-
146
- const outputPath = join(tempDir, 'tokens.json');
147
- await exportTokens('json', outputPath);
148
-
149
- const exported = JSON.parse(await readFile(outputPath, 'utf8'));
150
- expect(exported).toHaveProperty('colors');
151
- expect(exported.colors).toHaveProperty('$primary-500');
152
- });
153
-
154
- it('should export tokens as CSS custom properties', async () => {
155
- await writeFile(join(tokenDir, '_settings.colors.scss'), `
156
- $primary-500: #7AFFD7 !default;
157
- --atomix-color-primary: #7AFFD7;
158
- `);
159
-
160
- const outputPath = join(tempDir, 'tokens.css');
161
- await exportTokens('css', outputPath);
162
-
163
- const css = await readFile(outputPath, 'utf8');
164
- expect(css).toContain('--atomix-color-primary: #7AFFD7');
165
- });
166
-
167
- it('should export tokens as TypeScript', async () => {
168
- await writeFile(join(tokenDir, '_settings.colors.scss'), `
169
- $primary-500: #7AFFD7 !default;
170
- --atomix-color-primary: #7AFFD7;
171
- `);
172
-
173
- const outputPath = join(tempDir, 'tokens.ts');
174
- await exportTokens('ts', outputPath);
175
-
176
- const ts = await readFile(outputPath, 'utf8');
177
- expect(ts).toContain('export interface');
178
- expect(ts).toContain('AtomixTokens');
179
- });
180
- });
181
-
182
- describe('importTokens', () => {
183
- it('should import tokens from JSON', async () => {
184
- const jsonPath = join(tempDir, 'tokens.json');
185
- await writeFile(jsonPath, JSON.stringify({
186
- colors: {
187
- '$primary-500': '#7AFFD7',
188
- '--atomix-color-primary': '#7AFFD7'
189
- }
190
- }));
191
-
192
- await importTokens(jsonPath);
193
-
194
- // Verify the tokens were written to SCSS files
195
- const colorsFile = await readFile(join(tokenDir, '_settings.colors.scss'), 'utf8');
196
- expect(colorsFile).toContain('$primary-500: #7AFFD7 !default');
197
- expect(colorsFile).toContain('--atomix-color-primary: #7AFFD7');
198
- });
199
-
200
- it('should import tokens from JavaScript', async () => {
201
- const jsPath = join(tempDir, 'tokens.js');
202
- await writeFile(jsPath, `
203
- export const tokens = {
204
- colors: {
205
- '$primary-500': '#7AFFD7',
206
- '--atomix-color-primary': '#7AFFD7'
207
- }
208
- };
209
- `);
210
-
211
- await importTokens(jsPath);
212
-
213
- const colorsFile = await readFile(join(tokenDir, '_settings.colors.scss'), 'utf8');
214
- expect(colorsFile).toContain('$primary-500: #7AFFD7 !default');
215
- });
216
-
217
- it('should handle malformed JSON gracefully', async () => {
218
- const jsonPath = join(tempDir, 'invalid.json');
219
- await writeFile(jsonPath, '{ invalid json }');
220
-
221
- await expect(importTokens(jsonPath)).rejects.toThrow();
222
- });
223
- });
224
-
225
- describe('fixTokens', () => {
226
- it('should add missing !default flags', async () => {
227
- await writeFile(join(tokenDir, '_settings.colors.scss'), `
228
- $primary: #7AFFD7;
229
- $secondary: #FF5733 !default;
230
- `);
231
-
232
- await fixTokens();
233
-
234
- const content = await readFile(join(tokenDir, '_settings.colors.scss'), 'utf8');
235
- expect(content).toContain('$primary: var(--atomix-color-primary) !default');
236
- });
237
-
238
- it('should convert hardcoded colors to variables', async () => {
239
- await writeFile(join(tokenDir, '_settings.colors.scss'), `
240
- $primary: #7AFFD7 !default;
241
- background: #ffffff;
242
- `);
243
-
244
- await fixTokens();
245
-
246
- const content = await readFile(join(tokenDir, '_settings.colors.scss'), 'utf8');
247
- // Should replace hardcoded colors with variables
248
- expect(content).toContain('var(--atomix-color-text)');
249
- });
250
- });
251
- });
@@ -1,361 +0,0 @@
1
- /**
2
- * Token Provider & Validator Tests
3
- * Tests for Phase 1: Enhanced Design Token Integration
4
- */
5
-
6
- import { describe, it, expect, beforeEach } from 'vitest';
7
- import {
8
- TokenProvider,
9
- TOKEN_FORMATS,
10
- TOKEN_CATEGORIES,
11
- tokenProvider
12
- } from '../internal/tokens/token-provider.js';
13
- import {
14
- TokenValidator,
15
- VALIDATION_RULES,
16
- SEVERITY,
17
- tokenValidator
18
- } from '../internal/tokens/token-validator.js';
19
-
20
- describe('TokenProvider', () => {
21
- let provider;
22
-
23
- beforeEach(() => {
24
- provider = new TokenProvider();
25
- });
26
-
27
- describe('Initialization', () => {
28
- it('should create a new TokenProvider instance', () => {
29
- expect(provider).toBeInstanceOf(TokenProvider);
30
- });
31
-
32
- it('should have default options', () => {
33
- expect(provider.tokenPath).toBe('./design-tokens');
34
- expect(provider.format).toBe(TOKEN_FORMATS.JSON);
35
- expect(provider.tokens).toEqual({});
36
- });
37
-
38
- it('should accept custom options', () => {
39
- const customProvider = new TokenProvider({
40
- tokenPath: './custom-tokens',
41
- format: TOKEN_FORMATS.CSS
42
- });
43
-
44
- expect(customProvider.tokenPath).toBe('./custom-tokens');
45
- expect(customProvider.format).toBe(TOKEN_FORMATS.CSS);
46
- });
47
- });
48
-
49
- describe('Token Loading', () => {
50
- it('should throw error when file not found', async () => {
51
- await expect(provider.loadTokens('./non-existent.json'))
52
- .rejects
53
- .toThrow('Token file not found');
54
- });
55
-
56
- it('should categorize tokens correctly', () => {
57
- const categorizeToken = provider.categorizeToken.bind(provider);
58
-
59
- expect(categorizeToken('color-primary')).toBe(TOKEN_CATEGORIES.COLOR);
60
- expect(categorizeToken('space-sm')).toBe(TOKEN_CATEGORIES.SPACING);
61
- expect(categorizeToken('font-size-lg')).toBe(TOKEN_CATEGORIES.TYPOGRAPHY);
62
- expect(categorizeToken('shadow-md')).toBe(TOKEN_CATEGORIES.SHADOW);
63
- expect(categorizeToken('radius-lg')).toBe(TOKEN_CATEGORIES.RADIUS);
64
- expect(categorizeToken('duration-fast')).toBe(TOKEN_CATEGORIES.ANIMATION);
65
- });
66
-
67
- it('should infer token types from values', () => {
68
- const inferTokenType = provider.inferTokenType.bind(provider);
69
-
70
- expect(inferTokenType('#ff0000')).toBe('color');
71
- expect(inferTokenType('rgb(255, 0, 0)')).toBe('color');
72
- expect(inferTokenType('hsl(0, 100%, 50%)')).toBe('color');
73
- expect(inferTokenType('16px')).toBe('dimension');
74
- expect(inferTokenType('1rem')).toBe('dimension');
75
- expect(inferTokenType('300ms')).toBe('duration');
76
- expect(inferTokenType('0.5s')).toBe('duration');
77
- expect(inferTokenType(42)).toBe('number');
78
- });
79
- });
80
-
81
- describe('Token Merging', () => {
82
- it('should merge multiple token sets', () => {
83
- const existing = {
84
- color: { primary: { value: '#000' } },
85
- spacing: { sm: { value: '8px' } }
86
- };
87
-
88
- const newTokens = {
89
- color: { secondary: { value: '#fff' } },
90
- typography: { base: { value: '16px' } }
91
- };
92
-
93
- const merged = provider.mergeTokens(existing, newTokens);
94
-
95
- expect(merged.color.primary).toBeDefined();
96
- expect(merged.color.secondary).toBeDefined();
97
- expect(merged.spacing.sm).toBeDefined();
98
- expect(merged.typography.base).toBeDefined();
99
- });
100
- });
101
-
102
- describe('Token Export', () => {
103
- beforeEach(() => {
104
- provider.tokens = {
105
- color: {
106
- primary: { value: '#007bff', type: 'color' },
107
- secondary: { value: '#6c757d', type: 'color' }
108
- },
109
- spacing: {
110
- sm: { value: '8px', type: 'dimension' },
111
- lg: { value: '16px', type: 'dimension' }
112
- }
113
- };
114
- });
115
-
116
- it('should export to JSON format', () => {
117
- const json = provider.exportTokens(TOKEN_FORMATS.JSON, { pretty: false });
118
- const parsed = JSON.parse(json);
119
-
120
- expect(parsed.color.primary.value).toBe('#007bff');
121
- expect(parsed.spacing.lg.value).toBe('16px');
122
- });
123
-
124
- it('should export to CSS custom properties', () => {
125
- const css = provider.exportTokens(TOKEN_FORMATS.CSS, {
126
- selector: ':root',
127
- prefix: 'atomix'
128
- });
129
-
130
- expect(css).toContain(':root {');
131
- expect(css).toContain('--atomix-color-primary: #007bff;');
132
- expect(css).toContain('--atomix-spacing-lg: 16px;');
133
- });
134
-
135
- it('should export to W3C DTCG format', () => {
136
- const dtcg = provider.exportTokens(TOKEN_FORMATS.W3C_DTCG);
137
-
138
- expect(dtcg.$schema).toBe('https://design-tokens.org/schema.json');
139
- expect(dtcg.tokens.color.primary.value).toBe('#007bff');
140
- });
141
- });
142
- });
143
-
144
- describe('TokenValidator', () => {
145
- let validator;
146
-
147
- beforeEach(() => {
148
- validator = new TokenValidator();
149
- });
150
-
151
- describe('Initialization', () => {
152
- it('should create a new TokenValidator instance', () => {
153
- expect(validator).toBeInstanceOf(TokenValidator);
154
- });
155
-
156
- it('should register all built-in rules', () => {
157
- expect(validator.rules.size).toBeGreaterThan(0);
158
- expect(validator.rules.has('COLOR_CONTRAST')).toBe(true);
159
- expect(validator.rules.has('SEMANTIC_NAMING')).toBe(true);
160
- expect(validator.rules.has('NO_HARDCODED_COLORS')).toBe(true);
161
- });
162
-
163
- it('should have all rules enabled by default', () => {
164
- expect(validator.enabledRules.length).toBeGreaterThan(0);
165
- });
166
- });
167
-
168
- describe('Validation Rules', () => {
169
- it('should validate color contrast', () => {
170
- const tokens = {
171
- color: {
172
- text: { value: '#999999' },
173
- background: { value: '#ffffff' }
174
- }
175
- };
176
-
177
- const result = validator.validate(tokens);
178
-
179
- // Low contrast should be flagged
180
- const contrastIssue = result.issues.find(i => i.rule === 'color-contrast');
181
- expect(contrastIssue).toBeDefined();
182
- expect(contrastIssue.severity).toBe(SEVERITY.ERROR);
183
- });
184
-
185
- it('should detect semantic naming issues', () => {
186
- const tokens = {
187
- color: {
188
- blue: { value: '#0000ff' },
189
- red: { value: '#ff0000' }
190
- }
191
- };
192
-
193
- const result = validator.validate(tokens);
194
-
195
- const namingIssue = result.issues.find(i => i.rule === 'semantic-naming');
196
- expect(namingIssue).toBeDefined();
197
- expect(namingIssue.severity).toBe(SEVERITY.WARNING);
198
- });
199
-
200
- it('should pass semantic naming for brand colors', () => {
201
- const tokens = {
202
- color: {
203
- brandBlue: { value: '#0000ff' },
204
- primaryRed: { value: '#ff0000' }
205
- }
206
- };
207
-
208
- const result = validator.validate(tokens);
209
-
210
- // Filter out token-completeness warnings which are expected
211
- const namingIssue = result.issues.find(i => i.rule === 'semantic-naming');
212
- // Should not flag brand colors or primary/secondary prefixed colors
213
- expect(namingIssue).toBeUndefined();
214
- });
215
-
216
- it('should detect hardcoded colors in code', () => {
217
- const codeContent = `
218
- const styles = {
219
- color: '#ff0000',
220
- backgroundColor: 'rgb(0, 123, 255)',
221
- borderColor: 'hsl(120, 100%, 50%)'
222
- };
223
- `;
224
-
225
- const result = validator.validate({}, { codeContent });
226
-
227
- const hardcodedIssue = result.issues.find(i => i.rule === 'no-hardcoded-colors');
228
- expect(hardcodedIssue).toBeDefined();
229
- expect(hardcodedIssue.matches).toHaveLength(3);
230
- });
231
-
232
- it('should validate token completeness', () => {
233
- const tokens = {
234
- color: { primary: { value: '#000' } }
235
- // Missing spacing and typography
236
- };
237
-
238
- const result = validator.validate(tokens);
239
-
240
- const completenessIssues = result.issues.filter(i => i.rule === 'token-completeness');
241
- expect(completenessIssues.length).toBeGreaterThan(0);
242
- });
243
-
244
- it('should detect duplicate tokens', () => {
245
- const tokens = {
246
- color: {
247
- primary: { value: '#007bff' },
248
- main: { value: '#007bff' }
249
- },
250
- spacing: {
251
- sm: { value: '8px' },
252
- small: { value: '8px' }
253
- }
254
- };
255
-
256
- const result = validator.validate(tokens);
257
-
258
- const duplicateIssues = result.issues.filter(i => i.rule === 'duplicate-detection');
259
- expect(duplicateIssues.length).toBeGreaterThan(0);
260
- });
261
- });
262
-
263
- describe('Rule Management', () => {
264
- it('should toggle rules on/off', () => {
265
- const initialCount = validator.enabledRules.length;
266
-
267
- validator.toggleRule('COLOR_CONTRAST', false);
268
- expect(validator.enabledRules).not.toContain('COLOR_CONTRAST');
269
-
270
- validator.toggleRule('COLOR_CONTRAST', true);
271
- expect(validator.enabledRules).toContain('COLOR_CONTRAST');
272
- });
273
-
274
- it('should allow registering custom rules', () => {
275
- const customRule = {
276
- name: 'custom-rule',
277
- description: 'Custom validation rule',
278
- severity: SEVERITY.INFO,
279
- validate: (tokens) => []
280
- };
281
-
282
- validator.registerRule('CUSTOM_RULE', customRule);
283
-
284
- expect(validator.rules.has('CUSTOM_RULE')).toBe(true);
285
- });
286
-
287
- it('should reject invalid rules', () => {
288
- expect(() => {
289
- validator.registerRule('INVALID', { name: 'test' });
290
- }).toThrow('must have name, validate, and severity');
291
- });
292
- });
293
-
294
- describe('Validation Report', () => {
295
- it('should generate formatted report', () => {
296
- const tokens = {
297
- color: {
298
- lowContrast: { value: '#ccc' },
299
- background: { value: '#fff' }
300
- }
301
- };
302
-
303
- const result = validator.validate(tokens);
304
- const report = validator.getReport(result);
305
-
306
- expect(report).toContain('Token Validation Report');
307
- expect(report).toContain('Status:');
308
- expect(report).toContain('Summary:');
309
- expect(report).toContain('Errors:');
310
- });
311
- });
312
- });
313
-
314
- describe('Integration Tests', () => {
315
- it('should load and validate tokens together', async () => {
316
- const provider = new TokenProvider();
317
- const validator = new TokenValidator();
318
-
319
- // Simulate loading tokens
320
- provider.tokens = {
321
- color: {
322
- primary: { value: '#007bff', type: 'color' },
323
- success: { value: '#22c55e', type: 'color' }
324
- },
325
- spacing: {
326
- 4: { value: '1rem', type: 'dimension' },
327
- 8: { value: '2rem', type: 'dimension' }
328
- }
329
- };
330
-
331
- const tokens = provider.getAllTokens();
332
- const result = validator.validate(tokens);
333
-
334
- expect(result).toBeDefined();
335
- expect(typeof result.valid).toBe('boolean');
336
- expect(result.summary).toBeDefined();
337
- });
338
-
339
- it('should validate component with loaded tokens', () => {
340
- const provider = new TokenProvider();
341
- const validator = new TokenValidator();
342
-
343
- provider.tokens = {
344
- color: {
345
- primary: { value: '#007bff' }
346
- }
347
- };
348
-
349
- const cleanCode = `
350
- const Component = () => {
351
- return <div style={{ color: 'var(--color-primary)' }} />;
352
- };
353
- `;
354
-
355
- const result = validator.validateComponent(cleanCode, provider.getAllTokens());
356
-
357
- // Should not have hardcoded color errors
358
- const hardcodedIssue = result.issues.find(i => i.rule === 'no-hardcoded-colors');
359
- expect(hardcodedIssue).toBeUndefined();
360
- });
361
- });