@shohojdhara/atomix 0.5.0 → 0.5.2
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.
- package/atomix.config.ts +12 -0
- package/build-tools/webpack-loader.js +5 -4
- package/dist/atomix.css +230 -83
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +1 -1
- package/dist/atomix.min.css.map +1 -1
- package/dist/build-tools/webpack-loader.js +5 -4
- package/dist/charts.d.ts +24 -23
- package/dist/charts.js +271 -369
- package/dist/charts.js.map +1 -1
- package/dist/config.d.ts +624 -0
- package/dist/config.js +59 -0
- package/dist/config.js.map +1 -0
- package/dist/core.d.ts +3 -2
- package/dist/core.js +342 -382
- package/dist/core.js.map +1 -1
- package/dist/forms.d.ts +4 -6
- package/dist/forms.js +233 -334
- package/dist/forms.js.map +1 -1
- package/dist/heavy.d.ts +11 -2
- package/dist/heavy.js +406 -445
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +109 -65
- package/dist/index.esm.js +654 -748
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +621 -717
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/layout.js +59 -60
- package/dist/layout.js.map +1 -1
- package/dist/theme.js +4 -4
- package/dist/theme.js.map +1 -1
- package/package.json +24 -9
- package/scripts/atomix-cli.js +15 -1
- package/scripts/cli/__tests__/complexity-utils.test.js +24 -0
- package/scripts/cli/__tests__/detector.test.js +50 -0
- package/scripts/cli/__tests__/template-engine.test.js +23 -0
- package/scripts/cli/__tests__/test-setup.js +1 -133
- package/scripts/cli/commands/doctor.js +15 -3
- package/scripts/cli/commands/generate.js +113 -51
- package/scripts/cli/internal/ai-engine.js +30 -10
- package/scripts/cli/internal/complexity-utils.js +60 -0
- package/scripts/cli/internal/component-validator.js +49 -16
- package/scripts/cli/internal/generator.js +89 -36
- package/scripts/cli/internal/hook-generator.js +5 -2
- package/scripts/cli/internal/itcss-generator.js +16 -12
- package/scripts/cli/templates/next-templates.js +81 -30
- package/scripts/cli/templates/storybook-templates.js +12 -2
- package/scripts/cli/utils/detector.js +45 -7
- package/scripts/cli/utils/diagnostics.js +78 -0
- package/scripts/cli/utils/telemetry.js +13 -0
- package/src/components/Accordion/Accordion.stories.tsx +4 -0
- package/src/components/AtomixGlass/AtomixGlass.tsx +188 -128
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +63 -91
- package/src/components/AtomixGlass/PerformanceDashboard.tsx +153 -201
- package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +9 -6
- package/src/components/AtomixGlass/glass-utils.ts +51 -1
- package/src/components/AtomixGlass/stories/AnimationFeatures.stories.tsx +52 -46
- package/src/components/AtomixGlass/stories/Examples.stories.tsx +573 -236
- package/src/components/AtomixGlass/stories/Playground.stories.tsx +88 -41
- package/src/components/AtomixGlass/stories/argTypes.ts +19 -19
- package/src/components/AtomixGlass/stories/shared-components.tsx +7 -12
- package/src/components/AtomixGlass/stories/types.ts +3 -3
- package/src/components/Button/Button.tsx +114 -57
- package/src/components/Callout/Callout.tsx +4 -4
- package/src/components/Chart/ChartRenderer.tsx +1 -1
- package/src/components/Chart/DonutChart.tsx +11 -8
- package/src/components/EdgePanel/EdgePanel.tsx +119 -115
- package/src/components/Form/Select.tsx +4 -4
- package/src/components/List/List.tsx +4 -4
- package/src/components/Navigation/SideMenu/SideMenu.tsx +6 -6
- package/src/components/PhotoViewer/PhotoViewerImage.tsx +1 -1
- package/src/components/ProductReview/ProductReview.tsx +4 -2
- package/src/components/Rating/Rating.tsx +4 -2
- package/src/components/SectionIntro/SectionIntro.tsx +4 -2
- package/src/components/Steps/Steps.tsx +1 -1
- package/src/components/Tabs/Tabs.tsx +5 -5
- package/src/components/Testimonial/Testimonial.tsx +4 -2
- package/src/components/VideoPlayer/VideoPlayer.tsx +4 -2
- package/src/layouts/CssGrid/CssGrid.stories.tsx +464 -0
- package/src/layouts/CssGrid/CssGrid.tsx +215 -0
- package/src/layouts/CssGrid/index.ts +8 -0
- package/src/layouts/CssGrid/scripts/CssGrid.js +284 -0
- package/src/layouts/CssGrid/scripts/index.js +43 -0
- package/src/layouts/Grid/scripts/Container.js +139 -0
- package/src/layouts/Grid/scripts/Grid.js +184 -0
- package/src/layouts/Grid/scripts/GridCol.js +273 -0
- package/src/layouts/Grid/scripts/Row.js +154 -0
- package/src/layouts/Grid/scripts/index.js +48 -0
- package/src/layouts/MasonryGrid/MasonryGrid.tsx +71 -59
- package/src/lib/composables/atomix-glass/useGlassSize.ts +1 -1
- package/src/lib/composables/useAccordion.ts +5 -5
- package/src/lib/composables/useAtomixGlass.ts +111 -74
- package/src/lib/composables/useAtomixGlassStyles.ts +0 -2
- package/src/lib/composables/useBarChart.ts +2 -2
- package/src/lib/composables/useChart.ts +3 -2
- package/src/lib/composables/useChartToolbar.ts +48 -66
- package/src/lib/composables/useDataTable.ts +1 -1
- package/src/lib/composables/useDatePicker.ts +2 -2
- package/src/lib/composables/useEdgePanel.ts +45 -54
- package/src/lib/composables/useHeroBackgroundSlider.ts +5 -5
- package/src/lib/composables/usePhotoViewer.ts +2 -3
- package/src/lib/composables/usePieChart.ts +1 -1
- package/src/lib/composables/usePopover.ts +151 -139
- package/src/lib/composables/useSideMenu.ts +28 -41
- package/src/lib/composables/useSlider.ts +2 -6
- package/src/lib/composables/useTooltip.ts +2 -2
- package/src/lib/config/index.ts +39 -0
- package/src/lib/constants/components.ts +1 -0
- package/src/lib/theme/devtools/Comparator.tsx +1 -1
- package/src/lib/theme/devtools/Inspector.tsx +1 -1
- package/src/lib/theme/devtools/LiveEditor.tsx +1 -1
- package/src/lib/theme/runtime/ThemeProvider.tsx +1 -1
- package/src/lib/types/components.ts +1 -0
- package/src/styles/01-settings/_index.scss +1 -0
- package/src/styles/01-settings/_settings.atomix-glass.scss +174 -0
- package/src/styles/01-settings/_settings.masonry-grid.scss +42 -6
- package/src/styles/02-tools/_tools.glass.scss +6 -0
- package/src/styles/05-objects/_objects.masonry-grid.scss +162 -24
- package/src/styles/06-components/_components.atomix-glass.scss +160 -99
- package/scripts/cli/__tests__/README.md +0 -81
- package/scripts/cli/__tests__/basic.test.js +0 -116
- package/scripts/cli/__tests__/clean.test.js +0 -278
- package/scripts/cli/__tests__/component-generator.test.js +0 -332
- package/scripts/cli/__tests__/component-validator.test.js +0 -433
- package/scripts/cli/__tests__/generator.test.js +0 -613
- package/scripts/cli/__tests__/glass-motion.test.js +0 -256
- package/scripts/cli/__tests__/integration.test.js +0 -938
- package/scripts/cli/__tests__/migrate.test.js +0 -74
- package/scripts/cli/__tests__/security.test.js +0 -206
- package/scripts/cli/__tests__/theme-bridge.test.js +0 -507
- package/scripts/cli/__tests__/token-manager.test.js +0 -251
- package/scripts/cli/__tests__/token-provider.test.js +0 -361
- package/scripts/cli/__tests__/utils.test.js +0 -165
- package/src/components/AtomixGlass/stories/AnimationTests.stories.tsx +0 -95
- package/src/components/AtomixGlass/stories/CardExamples.stories.tsx +0 -212
- package/src/components/AtomixGlass/stories/Customization.stories.tsx +0 -131
- package/src/components/AtomixGlass/stories/DashboardExamples.stories.tsx +0 -348
- package/src/components/AtomixGlass/stories/EcommerceExamples.stories.tsx +0 -410
- package/src/components/AtomixGlass/stories/FormExamples.stories.tsx +0 -436
- package/src/components/AtomixGlass/stories/HeroExamples.stories.tsx +0 -264
- package/src/components/AtomixGlass/stories/InteractivePlayground.stories.tsx +0 -247
- package/src/components/AtomixGlass/stories/MobileUIExamples.stories.tsx +0 -418
- package/src/components/AtomixGlass/stories/ModalExamples.stories.tsx +0 -402
- package/src/components/AtomixGlass/stories/Modes.stories.tsx +0 -1082
- package/src/components/AtomixGlass/stories/Overview.stories.tsx +0 -497
- package/src/components/AtomixGlass/stories/Performance.stories.tsx +0 -103
- package/src/components/AtomixGlass/stories/PresetGallery.stories.tsx +0 -335
- package/src/components/AtomixGlass/stories/Shaders.stories.tsx +0 -395
- package/src/components/AtomixGlass/stories/WidgetExamples.stories.tsx +0 -441
- package/src/components/TypedButton/TypedButton.stories.tsx +0 -59
- package/src/components/TypedButton/TypedButton.tsx +0 -39
- package/src/components/TypedButton/index.ts +0 -2
- package/src/lib/composables/useBreadcrumb.ts +0 -81
- package/src/lib/composables/useChartInteractions.ts +0 -123
- package/src/lib/composables/useChartPerformance.ts +0 -347
- package/src/lib/composables/useDropdown.ts +0 -338
- package/src/lib/composables/useModal.ts +0 -110
- package/src/lib/composables/useTypedButton.ts +0 -66
- package/src/lib/hooks/usePerformanceMonitor.ts +0 -148
- package/src/lib/utils/displacement-generator.ts +0 -92
- package/src/lib/utils/memoryMonitor.ts +0 -191
- package/src/styles/01-settings/_settings.testtypecheck.scss +0 -53
- package/src/styles/01-settings/_settings.typedbutton.scss +0 -53
- package/src/styles/06-components/_components.testbutton.scss +0 -212
- package/src/styles/06-components/_components.testtypecheck.scss +0 -212
- package/src/styles/06-components/_components.typedbutton.scss +0 -212
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Migrate Command Unit Tests
|
|
3
|
-
* Tests ensureSourceIsDirectory behavior and migrate error paths
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
7
|
-
import { mkdtemp, rm, writeFile } from 'fs/promises';
|
|
8
|
-
import { join } from 'path';
|
|
9
|
-
import { tmpdir } from 'os';
|
|
10
|
-
import { migrateAction } from '../commands/migrate.js';
|
|
11
|
-
import { AtomixCLIError, ErrorCategory } from '../utils/error.js';
|
|
12
|
-
|
|
13
|
-
describe('Migrate Command', () => {
|
|
14
|
-
let tempDir;
|
|
15
|
-
let originalCwd;
|
|
16
|
-
|
|
17
|
-
beforeEach(async () => {
|
|
18
|
-
tempDir = await mkdtemp(join(tmpdir(), 'atomix-migrate-test-'));
|
|
19
|
-
originalCwd = process.cwd();
|
|
20
|
-
process.chdir(tempDir);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
afterEach(async () => {
|
|
24
|
-
process.chdir(originalCwd);
|
|
25
|
-
await rm(tempDir, { recursive: true, force: true });
|
|
26
|
-
vi.restoreAllMocks();
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
describe('ensureSourceIsDirectory (via migrateAction)', () => {
|
|
30
|
-
it('should throw INVALID_PATH when source does not exist', async () => {
|
|
31
|
-
await expect(
|
|
32
|
-
migrateAction('tailwind', './nonexistent-dir-xyz-123')
|
|
33
|
-
).rejects.toThrow(AtomixCLIError);
|
|
34
|
-
|
|
35
|
-
try {
|
|
36
|
-
await migrateAction('tailwind', './nonexistent-dir-xyz-123');
|
|
37
|
-
} catch (err) {
|
|
38
|
-
expect(err.code).toBe(ErrorCategory.INVALID_PATH);
|
|
39
|
-
expect(err.message).toContain('Source not found');
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it('should throw INVALID_PATH when source is a file not a directory', async () => {
|
|
44
|
-
const filePath = join(tempDir, 'package.json');
|
|
45
|
-
await writeFile(filePath, '{}');
|
|
46
|
-
const relativeFile = 'package.json';
|
|
47
|
-
|
|
48
|
-
await expect(
|
|
49
|
-
migrateAction('tailwind', relativeFile)
|
|
50
|
-
).rejects.toThrow(AtomixCLIError);
|
|
51
|
-
|
|
52
|
-
try {
|
|
53
|
-
await migrateAction('tailwind', relativeFile);
|
|
54
|
-
} catch (err) {
|
|
55
|
-
expect(err.code).toBe(ErrorCategory.INVALID_PATH);
|
|
56
|
-
expect(err.message).toContain('not a directory');
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it('should throw when migration type is unsupported', async () => {
|
|
61
|
-
let threw = false;
|
|
62
|
-
try {
|
|
63
|
-
await migrateAction('unknown-framework', '.');
|
|
64
|
-
} catch (err) {
|
|
65
|
-
threw = true;
|
|
66
|
-
if (err instanceof AtomixCLIError) {
|
|
67
|
-
expect(err.code).toBe(ErrorCategory.VALIDATION);
|
|
68
|
-
expect(err.message).toContain('Unsupported migration type');
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
expect(threw).toBe(true);
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
});
|
|
@@ -1,206 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Security-focused tests for Atomix CLI
|
|
3
|
-
* Tests path traversal prevention, input sanitization, and security features
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
7
|
-
import {
|
|
8
|
-
sanitizeInput,
|
|
9
|
-
validateSecurePath,
|
|
10
|
-
validateComponentNameSecure,
|
|
11
|
-
SecurityError,
|
|
12
|
-
RateLimiter
|
|
13
|
-
} from '../utils/security.js';
|
|
14
|
-
import { filesystem } from '../internal/filesystem.js';
|
|
15
|
-
|
|
16
|
-
// Mock filesystem operations to avoid actual file I/O
|
|
17
|
-
vi.mock('../internal/filesystem.js', () => ({
|
|
18
|
-
filesystem: {
|
|
19
|
-
writeFile: vi.fn(),
|
|
20
|
-
exists: vi.fn()
|
|
21
|
-
}
|
|
22
|
-
}));
|
|
23
|
-
|
|
24
|
-
describe('Security Utilities', () => {
|
|
25
|
-
describe('sanitizeInput', () => {
|
|
26
|
-
it('should sanitize filename inputs', () => {
|
|
27
|
-
const malicious = '../../etc/passwd';
|
|
28
|
-
const sanitized = sanitizeInput(malicious, 'filename');
|
|
29
|
-
expect(sanitized).not.toContain('..');
|
|
30
|
-
expect(sanitized).not.toContain('/');
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it('should sanitize component names', () => {
|
|
34
|
-
const malicious = 'Button<script>alert(1)</script>';
|
|
35
|
-
const sanitized = sanitizeInput(malicious, 'componentName');
|
|
36
|
-
expect(sanitized).toMatch(/^[A-Z][a-zA-Z0-9]*$/);
|
|
37
|
-
expect(sanitized).not.toContain('<');
|
|
38
|
-
expect(sanitized).not.toContain('>');
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it('should sanitize AI prompts', () => {
|
|
42
|
-
const malicious = 'Create a component that executes <script>malicious()</script>';
|
|
43
|
-
const sanitized = sanitizeInput(malicious, 'prompt');
|
|
44
|
-
expect(sanitized).not.toContain('<script>');
|
|
45
|
-
expect(sanitized).not.toContain('</script>');
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
it('should handle empty inputs', () => {
|
|
49
|
-
expect(() => sanitizeInput('', 'filename')).toThrow();
|
|
50
|
-
});
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
describe('validateSecurePath', () => {
|
|
54
|
-
it('should prevent path traversal attacks', () => {
|
|
55
|
-
const result = validateSecurePath('../../etc/passwd', '/safe/dir');
|
|
56
|
-
expect(result.isValid).toBe(false);
|
|
57
|
-
expect(result.error).toContain('Path traversal');
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it('should prevent access to system directories', () => {
|
|
61
|
-
const result = validateSecurePath('/etc/passwd', '/safe/dir');
|
|
62
|
-
expect(result.isValid).toBe(false);
|
|
63
|
-
expect(result.error).toMatch(/Path traversal|system directories/);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it('should allow valid relative paths', () => {
|
|
67
|
-
const result = validateSecurePath('./src/components', process.cwd());
|
|
68
|
-
expect(result.isValid).toBe(true);
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it('should allow valid absolute paths within project', () => {
|
|
72
|
-
const result = validateSecurePath(process.cwd() + '/src/components', process.cwd());
|
|
73
|
-
expect(result.isValid).toBe(true);
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
describe('validateComponentNameSecure', () => {
|
|
78
|
-
it('should reject malicious or reserved component names', () => {
|
|
79
|
-
const maliciousNames = [
|
|
80
|
-
'eval',
|
|
81
|
-
'script',
|
|
82
|
-
'javascript',
|
|
83
|
-
'onload',
|
|
84
|
-
'onerror',
|
|
85
|
-
'Button<script>'
|
|
86
|
-
];
|
|
87
|
-
|
|
88
|
-
maliciousNames.forEach(name => {
|
|
89
|
-
const result = validateComponentNameSecure(name);
|
|
90
|
-
expect(result.isValid).toBe(false);
|
|
91
|
-
expect(result.error).toBeTruthy();
|
|
92
|
-
});
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
it('should accept valid component names', () => {
|
|
96
|
-
const validNames = [
|
|
97
|
-
'Button',
|
|
98
|
-
'CardHeader',
|
|
99
|
-
'ModalDialog',
|
|
100
|
-
'AccordionItem'
|
|
101
|
-
];
|
|
102
|
-
|
|
103
|
-
validNames.forEach(name => {
|
|
104
|
-
const result = validateComponentNameSecure(name);
|
|
105
|
-
expect(result.isValid).toBe(true);
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
it('should reject reserved words', () => {
|
|
110
|
-
const reservedNames = ['Component', 'React', 'Fragment', 'Window'];
|
|
111
|
-
reservedNames.forEach(name => {
|
|
112
|
-
const result = validateComponentNameSecure(name);
|
|
113
|
-
expect(result.isValid).toBe(false);
|
|
114
|
-
});
|
|
115
|
-
});
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
describe('RateLimiter', () => {
|
|
119
|
-
let rateLimiter;
|
|
120
|
-
|
|
121
|
-
beforeEach(() => {
|
|
122
|
-
rateLimiter = new RateLimiter(2, 1000); // 2 requests per second
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
it('should enforce rate limits', () => {
|
|
126
|
-
expect(rateLimiter.checkLimit('user1')).toBe(true);
|
|
127
|
-
expect(rateLimiter.checkLimit('user1')).toBe(true);
|
|
128
|
-
expect(rateLimiter.checkLimit('user1')).toBe(false); // Third request should be blocked
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
it('should track different users separately', () => {
|
|
132
|
-
expect(rateLimiter.checkLimit('user1')).toBe(true);
|
|
133
|
-
expect(rateLimiter.checkLimit('user2')).toBe(true);
|
|
134
|
-
expect(rateLimiter.checkLimit('user1')).toBe(true);
|
|
135
|
-
expect(rateLimiter.checkLimit('user2')).toBe(true);
|
|
136
|
-
expect(rateLimiter.checkLimit('user1')).toBe(false);
|
|
137
|
-
expect(rateLimiter.checkLimit('user2')).toBe(false);
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
it('should reset after time window', async () => {
|
|
141
|
-
expect(rateLimiter.checkLimit('user1')).toBe(true);
|
|
142
|
-
expect(rateLimiter.checkLimit('user1')).toBe(true);
|
|
143
|
-
expect(rateLimiter.checkLimit('user1')).toBe(false);
|
|
144
|
-
|
|
145
|
-
await new Promise(resolve => setTimeout(resolve, 1100)); // Wait longer than time window
|
|
146
|
-
|
|
147
|
-
expect(rateLimiter.checkLimit('user1')).toBe(true); // Should work again
|
|
148
|
-
});
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
describe('Filesystem Security', () => {
|
|
152
|
-
it('should reject path traversal via validateSecurePath', () => {
|
|
153
|
-
const result = validateSecurePath('../../etc/passwd', process.cwd());
|
|
154
|
-
expect(result.isValid).toBe(false);
|
|
155
|
-
expect(result.error).toBeTruthy();
|
|
156
|
-
});
|
|
157
|
-
});
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
describe('Path Traversal Prevention', () => {
|
|
161
|
-
const testCases = [
|
|
162
|
-
{ input: '../../etc/passwd', expected: false },
|
|
163
|
-
{ input: '/etc/passwd', expected: false },
|
|
164
|
-
{ input: '..\\Windows\\System32', expected: false },
|
|
165
|
-
{ input: 'normal/path', expected: true },
|
|
166
|
-
{ input: './src/components', expected: true },
|
|
167
|
-
{ input: 'src/components/Button', expected: true },
|
|
168
|
-
{ input: '../' + process.cwd() + '/src', expected: false }, // Relative traversal
|
|
169
|
-
{ input: process.cwd() + '/../../etc', expected: false }, // Absolute traversal
|
|
170
|
-
];
|
|
171
|
-
|
|
172
|
-
testCases.forEach(({ input, expected }) => {
|
|
173
|
-
it(`should ${expected ? 'allow' : 'block'} path: ${input}`, () => {
|
|
174
|
-
const result = validateSecurePath(input, process.cwd());
|
|
175
|
-
expect(result.isValid).toBe(expected);
|
|
176
|
-
|
|
177
|
-
if (!expected) {
|
|
178
|
-
expect(result.error).toBeDefined();
|
|
179
|
-
}
|
|
180
|
-
});
|
|
181
|
-
});
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
describe('Input Sanitization Edge Cases', () => {
|
|
185
|
-
const edgeCases = [
|
|
186
|
-
{ input: null, type: 'filename', shouldThrow: true },
|
|
187
|
-
{ input: undefined, type: 'filename', shouldThrow: true },
|
|
188
|
-
{ input: '', type: 'filename', shouldThrow: true },
|
|
189
|
-
{ input: ' ', type: 'filename', shouldThrow: true },
|
|
190
|
-
{ input: 'normal', type: 'filename', expected: 'normal' },
|
|
191
|
-
{ input: 'file\x00name', type: 'filename', expected: 'filename' },
|
|
192
|
-
{ input: 'file\nname', type: 'filename', expected: 'filename' },
|
|
193
|
-
{ input: 'file<script>', type: 'filename', expected: 'filescript' },
|
|
194
|
-
];
|
|
195
|
-
|
|
196
|
-
edgeCases.forEach(({ input, type, expected, shouldThrow }) => {
|
|
197
|
-
it(`should handle ${JSON.stringify(input)} for ${type}`, () => {
|
|
198
|
-
if (shouldThrow) {
|
|
199
|
-
expect(() => sanitizeInput(input, type)).toThrow();
|
|
200
|
-
} else {
|
|
201
|
-
const result = sanitizeInput(input, type);
|
|
202
|
-
expect(result).toBe(expected);
|
|
203
|
-
}
|
|
204
|
-
});
|
|
205
|
-
});
|
|
206
|
-
});
|