@amirdaraee/namewise 0.5.3 → 0.5.4

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 (68) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/index.js +0 -0
  3. package/package.json +2 -2
  4. package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -82
  5. package/.github/ISSUE_TEMPLATE/feature_request.yml +0 -61
  6. package/.github/workflows/auto-release.yml +0 -81
  7. package/.github/workflows/build.yml +0 -55
  8. package/.github/workflows/publish.yml +0 -134
  9. package/.github/workflows/test.yml +0 -45
  10. package/eng.traineddata +0 -0
  11. package/src/cli/commands.ts +0 -64
  12. package/src/cli/rename.ts +0 -171
  13. package/src/index.ts +0 -54
  14. package/src/parsers/excel-parser.ts +0 -66
  15. package/src/parsers/factory.ts +0 -38
  16. package/src/parsers/pdf-parser.ts +0 -99
  17. package/src/parsers/text-parser.ts +0 -43
  18. package/src/parsers/word-parser.ts +0 -50
  19. package/src/services/ai-factory.ts +0 -39
  20. package/src/services/claude-service.ts +0 -119
  21. package/src/services/file-renamer.ts +0 -141
  22. package/src/services/lmstudio-service.ts +0 -161
  23. package/src/services/ollama-service.ts +0 -191
  24. package/src/services/openai-service.ts +0 -117
  25. package/src/types/index.ts +0 -76
  26. package/src/types/pdf-extraction.d.ts +0 -7
  27. package/src/utils/ai-prompts.ts +0 -76
  28. package/src/utils/file-templates.ts +0 -275
  29. package/src/utils/naming-conventions.ts +0 -67
  30. package/src/utils/pdf-to-image.ts +0 -137
  31. package/tests/data/console-test-1.txt +0 -1
  32. package/tests/data/console-test-2.txt +0 -1
  33. package/tests/data/console-test-long-filename-for-display-testing.txt +0 -1
  34. package/tests/data/empty-file.txt +0 -0
  35. package/tests/data/failure.txt +0 -1
  36. package/tests/data/file1.txt +0 -1
  37. package/tests/data/file2.txt +0 -1
  38. package/tests/data/much-longer-filename-to-test-clearing.txt +0 -1
  39. package/tests/data/sample-markdown.md +0 -9
  40. package/tests/data/sample-pdf.pdf +0 -0
  41. package/tests/data/sample-text.txt +0 -25
  42. package/tests/data/short.txt +0 -1
  43. package/tests/data/single-file.txt +0 -1
  44. package/tests/data/success.txt +0 -1
  45. package/tests/data/this-is-a-very-long-filename-that-should-be-truncated-for-better-display-purposes.txt +0 -1
  46. package/tests/data/very-long-filename-that-should-be-cleared-properly.txt +0 -1
  47. package/tests/data/x.txt +0 -1
  48. package/tests/integration/ai-prompting.test.ts +0 -386
  49. package/tests/integration/end-to-end.test.ts +0 -209
  50. package/tests/integration/person-name-extraction.test.ts +0 -440
  51. package/tests/integration/workflow.test.ts +0 -336
  52. package/tests/mocks/mock-ai-service.ts +0 -58
  53. package/tests/unit/cli/commands.test.ts +0 -169
  54. package/tests/unit/parsers/factory.test.ts +0 -100
  55. package/tests/unit/parsers/pdf-parser.test.ts +0 -63
  56. package/tests/unit/parsers/text-parser.test.ts +0 -85
  57. package/tests/unit/services/ai-factory.test.ts +0 -85
  58. package/tests/unit/services/claude-service.test.ts +0 -188
  59. package/tests/unit/services/file-renamer.test.ts +0 -514
  60. package/tests/unit/services/lmstudio-service.test.ts +0 -326
  61. package/tests/unit/services/ollama-service.test.ts +0 -264
  62. package/tests/unit/services/openai-service.test.ts +0 -196
  63. package/tests/unit/utils/ai-prompts.test.ts +0 -213
  64. package/tests/unit/utils/file-templates.test.ts +0 -199
  65. package/tests/unit/utils/naming-conventions.test.ts +0 -88
  66. package/tests/unit/utils/pdf-to-image.test.ts +0 -127
  67. package/tsconfig.json +0 -20
  68. package/vitest.config.ts +0 -30
@@ -1,196 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from 'vitest';
2
- import { OpenAIService } from '../../../src/services/openai-service.js';
3
-
4
- // Mock the OpenAI SDK
5
- vi.mock('openai', () => {
6
- const MockOpenAI = vi.fn().mockImplementation(() => ({
7
- chat: {
8
- completions: {
9
- create: vi.fn()
10
- }
11
- }
12
- }));
13
- return {
14
- default: MockOpenAI
15
- };
16
- });
17
-
18
- describe('OpenAIService', () => {
19
- let service: OpenAIService;
20
- let mockClient: any;
21
-
22
- beforeEach(() => {
23
- service = new OpenAIService('test-api-key');
24
- mockClient = (service as any).client;
25
- });
26
-
27
- describe('Basic Properties', () => {
28
- it('should have correct name', () => {
29
- expect(service.name).toBe('OpenAI');
30
- });
31
-
32
- it('should initialize with API key', () => {
33
- expect(service).toBeDefined();
34
- });
35
- });
36
-
37
- describe('generateFileName() with different naming conventions', () => {
38
- const sampleContent = 'This is a user manual for software installation and configuration.';
39
- const originalName = 'manual.docx';
40
-
41
- beforeEach(() => {
42
- mockClient.chat.completions.create.mockResolvedValue({
43
- choices: [
44
- {
45
- message: {
46
- content: 'user manual software installation configuration'
47
- }
48
- }
49
- ]
50
- });
51
- });
52
-
53
- it('should generate filename with kebab-case convention (default)', async () => {
54
- const result = await service.generateFileName(sampleContent, originalName);
55
-
56
- expect(mockClient.chat.completions.create).toHaveBeenCalledWith(
57
- expect.objectContaining({
58
- model: 'gpt-3.5-turbo',
59
- messages: [expect.objectContaining({
60
- role: 'user',
61
- content: expect.stringContaining('Use lowercase with hyphens between words')
62
- })],
63
- temperature: 0.3
64
- })
65
- );
66
-
67
- expect(result).toBe('user-manual-software-installation-configuration');
68
- });
69
-
70
- it('should generate filename with snake_case convention', async () => {
71
- const result = await service.generateFileName(sampleContent, originalName, 'snake_case');
72
-
73
- expect(mockClient.chat.completions.create).toHaveBeenCalledWith(
74
- expect.objectContaining({
75
- messages: [expect.objectContaining({
76
- content: expect.stringContaining('Use lowercase with underscores between words')
77
- })]
78
- })
79
- );
80
-
81
- expect(result).toBe('user_manual_software_installation_configuration');
82
- });
83
-
84
- it('should generate filename with camelCase convention', async () => {
85
- const result = await service.generateFileName(sampleContent, originalName, 'camelCase');
86
-
87
- expect(mockClient.chat.completions.create).toHaveBeenCalledWith(
88
- expect.objectContaining({
89
- messages: [expect.objectContaining({
90
- content: expect.stringContaining('Use camelCase format starting with lowercase')
91
- })]
92
- })
93
- );
94
-
95
- expect(result).toBe('userManualSoftwareInstallationConfiguration');
96
- });
97
-
98
- it('should generate filename with UPPERCASE convention', async () => {
99
- const result = await service.generateFileName(sampleContent, originalName, 'UPPERCASE');
100
-
101
- expect(result).toBe('USERMANUALSOFTWAREINSTALLATIONCONFIGURATION');
102
- });
103
-
104
- it('should include original filename and content in prompt', async () => {
105
- await service.generateFileName(sampleContent, originalName, 'kebab-case');
106
-
107
- const call = mockClient.chat.completions.create.mock.calls[0][0];
108
- expect(call.messages[0].content).toContain(sampleContent.substring(0, 2000));
109
- expect(call.messages[0].content).toContain('Document content (first 2000 characters)');
110
- });
111
-
112
- it('should use correct OpenAI parameters', async () => {
113
- await service.generateFileName(sampleContent, originalName);
114
-
115
- expect(mockClient.chat.completions.create).toHaveBeenCalledWith(
116
- expect.objectContaining({
117
- model: 'gpt-3.5-turbo',
118
- max_tokens: 100,
119
- temperature: 0.3
120
- })
121
- );
122
- });
123
- });
124
-
125
- describe('Error Handling', () => {
126
- it('should handle API errors gracefully', async () => {
127
- mockClient.chat.completions.create.mockRejectedValue(new Error('OpenAI API Error'));
128
-
129
- await expect(service.generateFileName('content', 'file.txt')).rejects.toThrow(
130
- 'Failed to generate filename with OpenAI: OpenAI API Error'
131
- );
132
- });
133
-
134
- it('should handle empty choices response', async () => {
135
- mockClient.chat.completions.create.mockResolvedValue({
136
- choices: []
137
- });
138
-
139
- const result = await service.generateFileName('content', 'file.txt');
140
- expect(result).toBe('untitled-document');
141
- });
142
-
143
- it('should handle missing message content', async () => {
144
- mockClient.chat.completions.create.mockResolvedValue({
145
- choices: [
146
- {
147
- message: {
148
- content: null
149
- }
150
- }
151
- ]
152
- });
153
-
154
- const result = await service.generateFileName('content', 'file.txt');
155
- expect(result).toBe('untitled-document');
156
- });
157
-
158
- it('should handle undefined choices', async () => {
159
- mockClient.chat.completions.create.mockResolvedValue({
160
- choices: [undefined]
161
- });
162
-
163
- const result = await service.generateFileName('content', 'file.txt');
164
- expect(result).toBe('untitled-document');
165
- });
166
- });
167
-
168
- describe('Filename Sanitization', () => {
169
- beforeEach(() => {
170
- mockClient.chat.completions.create.mockResolvedValue({
171
- choices: [
172
- {
173
- message: {
174
- content: 'Test@Document#With$Special%Characters.xlsx'
175
- }
176
- }
177
- ]
178
- });
179
- });
180
-
181
- it('should sanitize special characters and apply naming convention', async () => {
182
- const result = await service.generateFileName('content', 'original.txt', 'kebab-case');
183
- expect(result).toBe('testdocumentwithspecialcharacters');
184
- });
185
-
186
- it('should handle different conventions for sanitized input', async () => {
187
- const kebabResult = await service.generateFileName('content', 'file.txt', 'kebab-case');
188
- const snakeResult = await service.generateFileName('content', 'file.txt', 'snake_case');
189
- const camelResult = await service.generateFileName('content', 'file.txt', 'camelCase');
190
-
191
- expect(kebabResult).toBe('testdocumentwithspecialcharacters');
192
- expect(snakeResult).toBe('testdocumentwithspecialcharacters');
193
- expect(camelResult).toBe('testdocumentwithspecialcharacters');
194
- });
195
- });
196
- });
@@ -1,213 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { buildFileNamePrompt, AI_SYSTEM_PROMPT } from '../../../src/utils/ai-prompts.js';
3
- import { FileInfo } from '../../../src/types/index.js';
4
-
5
- describe('AI Prompts', () => {
6
- describe('buildFileNamePrompt', () => {
7
- it('should build basic prompt with minimal context', () => {
8
- const prompt = buildFileNamePrompt({
9
- content: 'This is a sample document about contract negotiations.',
10
- originalName: 'document.pdf',
11
- namingConvention: 'kebab-case',
12
- category: 'general'
13
- });
14
-
15
- expect(prompt).toContain('Based on the following document information');
16
- expect(prompt).toContain('Descriptive and meaningful');
17
- expect(prompt).toContain('Between 3-10 words');
18
- expect(prompt).toContain('hyphens between words');
19
- expect(prompt).toContain('This is a sample document about contract negotiations');
20
- expect(prompt).toContain('Respond with only the filename');
21
- });
22
-
23
- it('should include file metadata when provided', () => {
24
- const mockFileInfo: FileInfo = {
25
- name: 'contract.pdf',
26
- path: '/documents/contract.pdf',
27
- extension: '.pdf',
28
- size: 1024 * 50, // 50KB
29
- createdAt: new Date('2024-01-15'),
30
- modifiedAt: new Date('2024-02-01'),
31
- parentFolder: 'contracts',
32
- folderPath: ['home', 'documents', 'contracts']
33
- };
34
-
35
- const prompt = buildFileNamePrompt({
36
- content: 'Employment contract for John Doe.',
37
- originalName: 'contract.pdf',
38
- namingConvention: 'kebab-case',
39
- category: 'document',
40
- fileInfo: mockFileInfo
41
- });
42
-
43
- expect(prompt).toContain('File Information:');
44
- expect(prompt).toContain('- Original filename: contract.pdf');
45
- expect(prompt).toContain('- File size: 50KB');
46
- expect(prompt).toContain('- Parent folder: contracts');
47
- expect(prompt).toContain('- Folder path: home > documents > contracts');
48
- });
49
-
50
- it('should include document metadata when available', () => {
51
- const mockFileInfo: FileInfo = {
52
- name: 'report.pdf',
53
- path: '/reports/report.pdf',
54
- extension: '.pdf',
55
- size: 1024 * 100,
56
- createdAt: new Date('2024-01-15'),
57
- modifiedAt: new Date('2024-02-01'),
58
- parentFolder: 'reports',
59
- folderPath: ['home', 'reports'],
60
- documentMetadata: {
61
- title: 'Annual Financial Report',
62
- author: 'Jane Smith',
63
- creator: 'Microsoft Word',
64
- subject: 'Company Finances',
65
- keywords: ['finance', 'annual', 'report'],
66
- creationDate: new Date('2024-01-10'),
67
- modificationDate: new Date('2024-01-20'),
68
- pages: 25,
69
- wordCount: 5000
70
- }
71
- };
72
-
73
- const prompt = buildFileNamePrompt({
74
- content: 'This report covers the annual financial performance...',
75
- originalName: 'report.pdf',
76
- namingConvention: 'snake_case',
77
- category: 'document',
78
- fileInfo: mockFileInfo
79
- });
80
-
81
- expect(prompt).toContain('Document Properties:');
82
- expect(prompt).toContain('- Title: Annual Financial Report');
83
- expect(prompt).toContain('- Author: Jane Smith');
84
- expect(prompt).toContain('- Creator: Microsoft Word');
85
- expect(prompt).toContain('- Subject: Company Finances');
86
- expect(prompt).toContain('- Keywords: finance, annual, report');
87
- expect(prompt).toContain('- Pages: 25');
88
- expect(prompt).toContain('- Word count: 5000');
89
- });
90
-
91
- it('should include person name detection instructions', () => {
92
- const prompt = buildFileNamePrompt({
93
- content: 'Visa application for Setareh Ahmadi to visit Canada.',
94
- originalName: 'visa-app.pdf',
95
- namingConvention: 'kebab-case',
96
- category: 'document'
97
- });
98
-
99
- expect(prompt).toContain('If the document is specifically for/about a person (based on content), include their name at the beginning');
100
- expect(prompt).toContain('Important: If this document is specifically for or about a particular person mentioned in the content, start the filename with their name');
101
- });
102
-
103
- it('should include folder name filtering instructions', () => {
104
- const prompt = buildFileNamePrompt({
105
- content: 'Meeting notes from Q4 planning session.',
106
- originalName: 'notes.txt',
107
- namingConvention: 'camelCase',
108
- category: 'general'
109
- });
110
-
111
- expect(prompt).toContain('Ignore irrelevant folder names that don\'t describe the document content');
112
- expect(prompt).toContain('Focus on the document\'s actual content and purpose, not just metadata');
113
- });
114
-
115
- it('should handle different naming conventions', () => {
116
- const kebabPrompt = buildFileNamePrompt({
117
- content: 'Test content',
118
- originalName: 'test.txt',
119
- namingConvention: 'kebab-case',
120
- category: 'general'
121
- });
122
-
123
- const snakePrompt = buildFileNamePrompt({
124
- content: 'Test content',
125
- originalName: 'test.txt',
126
- namingConvention: 'snake_case',
127
- category: 'general'
128
- });
129
-
130
- expect(kebabPrompt).toContain('hyphens between words');
131
- expect(snakePrompt).toContain('underscores between words');
132
- });
133
-
134
- it('should handle different file categories', () => {
135
- const documentPrompt = buildFileNamePrompt({
136
- content: 'Contract content',
137
- originalName: 'contract.pdf',
138
- namingConvention: 'kebab-case',
139
- category: 'document'
140
- });
141
-
142
- const moviePrompt = buildFileNamePrompt({
143
- content: 'Movie file content',
144
- originalName: 'movie.mp4',
145
- namingConvention: 'kebab-case',
146
- category: 'movie'
147
- });
148
-
149
- expect(documentPrompt).toContain('document');
150
- expect(moviePrompt).toContain('movie');
151
- });
152
-
153
- it('should truncate content to 2000 characters', () => {
154
- const longContent = 'a'.repeat(3000);
155
-
156
- const prompt = buildFileNamePrompt({
157
- content: longContent,
158
- originalName: 'long.txt',
159
- namingConvention: 'kebab-case',
160
- category: 'general'
161
- });
162
-
163
- const contentSection = prompt.substring(prompt.indexOf('Document content'));
164
- expect(contentSection).toContain('a'.repeat(2000));
165
- expect(contentSection).not.toContain('a'.repeat(2001));
166
- });
167
-
168
- it('should handle missing optional metadata gracefully', () => {
169
- const mockFileInfo: FileInfo = {
170
- name: 'simple.txt',
171
- path: '/simple.txt',
172
- extension: '.txt',
173
- size: 1024,
174
- createdAt: new Date('2024-01-15'),
175
- modifiedAt: new Date('2024-02-01'),
176
- parentFolder: 'root',
177
- folderPath: ['root'],
178
- documentMetadata: {
179
- // Only some fields provided
180
- title: 'Simple Document'
181
- // author, creator, etc. are undefined
182
- }
183
- };
184
-
185
- const prompt = buildFileNamePrompt({
186
- content: 'Simple document content.',
187
- originalName: 'simple.txt',
188
- namingConvention: 'kebab-case',
189
- category: 'general',
190
- fileInfo: mockFileInfo
191
- });
192
-
193
- expect(prompt).toContain('- Title: Simple Document');
194
- expect(prompt).not.toContain('- Author:');
195
- expect(prompt).not.toContain('- Creator:');
196
- });
197
- });
198
-
199
- describe('AI_SYSTEM_PROMPT', () => {
200
- it('should provide clear system instructions', () => {
201
- expect(AI_SYSTEM_PROMPT).toContain('helpful assistant');
202
- expect(AI_SYSTEM_PROMPT).toContain('generates descriptive filenames');
203
- expect(AI_SYSTEM_PROMPT).toContain('just the filename');
204
- expect(AI_SYSTEM_PROMPT).toContain('no explanation');
205
- });
206
-
207
- it('should be a non-empty string', () => {
208
- expect(AI_SYSTEM_PROMPT).toBeTruthy();
209
- expect(typeof AI_SYSTEM_PROMPT).toBe('string');
210
- expect(AI_SYSTEM_PROMPT.length).toBeGreaterThan(20);
211
- });
212
- });
213
- });
@@ -1,199 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import {
3
- categorizeFile,
4
- applyTemplate,
5
- getTemplateInstructions,
6
- FILE_TEMPLATES,
7
- FileCategory
8
- } from '../../../src/utils/file-templates.js';
9
-
10
- describe('File Templates', () => {
11
- describe('categorizeFile()', () => {
12
- it('should categorize document files', () => {
13
- expect(categorizeFile('/path/contract.pdf')).toBe('document');
14
- expect(categorizeFile('/path/license.docx')).toBe('document');
15
- expect(categorizeFile('/path/certificate.txt')).toBe('document');
16
- });
17
-
18
- it('should categorize document files by content', () => {
19
- expect(categorizeFile('/path/file.pdf', 'This is a work contract agreement')).toBe('document');
20
- expect(categorizeFile('/path/file.pdf', 'License application form')).toBe('document');
21
- expect(categorizeFile('/path/file.pdf', 'Invoice for services rendered')).toBe('document');
22
- });
23
-
24
- it('should categorize movie files', () => {
25
- expect(categorizeFile('/path/movie.mp4')).toBe('movie');
26
- expect(categorizeFile('/path/film.mkv')).toBe('movie');
27
- expect(categorizeFile('/path/video.avi')).toBe('movie');
28
- });
29
-
30
- it('should categorize series files', () => {
31
- expect(categorizeFile('/path/show.s01e01.mkv')).toBe('series');
32
- expect(categorizeFile('/path/series.season.1.mp4')).toBe('series');
33
- expect(categorizeFile('/path/tv.episode.avi')).toBe('series');
34
- });
35
-
36
- it('should categorize music files', () => {
37
- expect(categorizeFile('/path/song.mp3')).toBe('music');
38
- expect(categorizeFile('/path/audio.flac')).toBe('music');
39
- expect(categorizeFile('/path/track.wav')).toBe('music');
40
- });
41
-
42
- it('should categorize photo files', () => {
43
- expect(categorizeFile('/path/image.jpg')).toBe('photo');
44
- expect(categorizeFile('/path/picture.png')).toBe('photo');
45
- expect(categorizeFile('/path/photo.heic')).toBe('photo');
46
- });
47
-
48
- it('should categorize book files', () => {
49
- expect(categorizeFile('/path/novel.epub')).toBe('book');
50
- expect(categorizeFile('/path/book.mobi')).toBe('book');
51
- expect(categorizeFile('/path/ebook.azw')).toBe('book');
52
- });
53
-
54
- it('should default to general for unknown types', () => {
55
- expect(categorizeFile('/path/unknown.xyz')).toBe('general');
56
- expect(categorizeFile('/path/file')).toBe('general');
57
- });
58
-
59
- it('should prioritize series over movie for video files with series keywords', () => {
60
- expect(categorizeFile('/path/breaking-bad.s01e01.mp4')).toBe('series');
61
- expect(categorizeFile('/path/movie.mkv', 'This is season 1 episode 1')).toBe('series');
62
- });
63
- });
64
-
65
- describe('applyTemplate()', () => {
66
- it('should apply document template with personal name and date', () => {
67
- const result = applyTemplate(
68
- 'driving-license',
69
- 'document',
70
- { category: 'document', personalName: 'amirhossein', dateFormat: 'YYYYMMDD' },
71
- 'kebab-case'
72
- );
73
-
74
- // Should match pattern: {content}-{personalName}-{date}
75
- expect(result).toMatch(/^driving-license-amirhossein-\d{8}$/);
76
- });
77
-
78
- it('should apply movie template with year', () => {
79
- const result = applyTemplate(
80
- 'the-dark-knight',
81
- 'movie',
82
- { category: 'movie', dateFormat: 'YYYY' },
83
- 'kebab-case'
84
- );
85
-
86
- // Movies don't use personal names in their template pattern
87
- expect(result).toBe('the-dark-knight');
88
- });
89
-
90
- it('should apply different date formats', () => {
91
- const baseOptions = { category: 'document' as FileCategory, personalName: 'john' };
92
-
93
- const yyyymmdd = applyTemplate('contract', 'document', { ...baseOptions, dateFormat: 'YYYYMMDD' }, 'kebab-case');
94
- const yyyymmdd2 = applyTemplate('contract', 'document', { ...baseOptions, dateFormat: 'YYYY-MM-DD' }, 'kebab-case');
95
- const yyyy = applyTemplate('contract', 'document', { ...baseOptions, dateFormat: 'YYYY' }, 'kebab-case');
96
-
97
- expect(yyyymmdd).toMatch(/^contract-john-\d{8}$/);
98
- expect(yyyymmdd2).toMatch(/^contract-john-\d{4}-\d{2}-\d{2}$/);
99
- expect(yyyy).toMatch(/^contract-john-\d{4}$/);
100
- });
101
-
102
- it('should handle no date format', () => {
103
- const result = applyTemplate(
104
- 'document',
105
- 'document',
106
- { category: 'document', personalName: 'jane', dateFormat: 'none' },
107
- 'kebab-case'
108
- );
109
-
110
- expect(result).toBe('document-jane');
111
- });
112
-
113
- it('should handle missing personal name', () => {
114
- const result = applyTemplate(
115
- 'report',
116
- 'document',
117
- { category: 'document', dateFormat: 'YYYY' },
118
- 'kebab-case'
119
- );
120
-
121
- expect(result).toMatch(/^report-\d{4}$/);
122
- });
123
-
124
- it('should apply naming conventions correctly', () => {
125
- const baseOptions = { category: 'document' as FileCategory, personalName: 'test-user', dateFormat: 'none' as const };
126
-
127
- const kebab = applyTemplate('My Document', 'document', baseOptions, 'kebab-case');
128
- const snake = applyTemplate('My Document', 'document', baseOptions, 'snake_case');
129
- const camel = applyTemplate('My Document', 'document', baseOptions, 'camelCase');
130
-
131
- expect(kebab).toBe('my-document-test-user');
132
- expect(snake).toBe('my_document_test_user');
133
- expect(camel).toBe('myDocumentTestUser');
134
- });
135
-
136
- it('should clean up multiple separators', () => {
137
- const result = applyTemplate(
138
- 'test--document',
139
- 'document',
140
- { category: 'document', personalName: 'user', dateFormat: 'none' },
141
- 'kebab-case'
142
- );
143
-
144
- expect(result).toBe('test-document-user');
145
- });
146
-
147
- it('should handle general category', () => {
148
- const result = applyTemplate(
149
- 'meeting-notes',
150
- 'general',
151
- { category: 'general', personalName: 'admin', dateFormat: 'YYYY' },
152
- 'kebab-case'
153
- );
154
-
155
- expect(result).toBe('meeting-notes');
156
- });
157
- });
158
-
159
- describe('getTemplateInstructions()', () => {
160
- it('should return instructions for each category', () => {
161
- const categories: FileCategory[] = ['document', 'movie', 'music', 'series', 'photo', 'book', 'general'];
162
-
163
- categories.forEach(category => {
164
- const instructions = getTemplateInstructions(category);
165
- expect(instructions).toContain(category);
166
- expect(instructions.length).toBeGreaterThan(10);
167
- });
168
- });
169
-
170
- it('should include examples in instructions', () => {
171
- const documentInstructions = getTemplateInstructions('document');
172
- expect(documentInstructions).toContain('driving-license-amirhossein');
173
-
174
- const movieInstructions = getTemplateInstructions('movie');
175
- expect(movieInstructions).toContain('the-dark-knight-2008');
176
- });
177
- });
178
-
179
- describe('FILE_TEMPLATES', () => {
180
- it('should have all required template categories', () => {
181
- const expectedCategories: FileCategory[] = ['document', 'movie', 'music', 'series', 'photo', 'book', 'general'];
182
-
183
- expectedCategories.forEach(category => {
184
- expect(FILE_TEMPLATES[category]).toBeDefined();
185
- expect(FILE_TEMPLATES[category].category).toBe(category);
186
- expect(FILE_TEMPLATES[category].pattern).toBeDefined();
187
- expect(FILE_TEMPLATES[category].description).toBeDefined();
188
- expect(FILE_TEMPLATES[category].examples.length).toBeGreaterThan(0);
189
- });
190
- });
191
-
192
- it('should have valid patterns', () => {
193
- Object.values(FILE_TEMPLATES).forEach(template => {
194
- expect(template.pattern).toContain('{content}');
195
- expect(template.examples.length).toBeGreaterThan(2);
196
- });
197
- });
198
- });
199
- });