g360-cli 1.10.0 → 1.11.0

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.
@@ -0,0 +1,173 @@
1
+ /**
2
+ * @file manifest.test.js
3
+ * @description Tests para el módulo manifest
4
+ */
5
+
6
+ import { describe, it, expect, beforeEach, vi } from 'vitest';
7
+ import fs from 'fs-extra';
8
+ import path from 'path';
9
+ import { manifest } from '../lib/manifest.js';
10
+
11
+ // Mock de fs-extra
12
+ vi.mock('fs-extra', () => ({
13
+ default: {
14
+ writeJson: vi.fn(),
15
+ readJson: vi.fn(),
16
+ existsSync: vi.fn(),
17
+ remove: vi.fn()
18
+ }
19
+ }));
20
+
21
+ describe('manifest module', () => {
22
+ beforeEach(() => {
23
+ vi.clearAllMocks();
24
+ });
25
+
26
+ describe('init', () => {
27
+ it('should create a new manifest file', async () => {
28
+ const projectData = {
29
+ name: 'test-project',
30
+ template: 'web-pwa',
31
+ version: '1.0.0'
32
+ };
33
+
34
+ fs.writeJson.mockResolvedValue();
35
+
36
+ const result = await manifest.init('/test/project', projectData);
37
+
38
+ expect(fs.writeJson).toHaveBeenCalledWith(
39
+ path.join('/test/project', 'g360-manifest.json'),
40
+ expect.objectContaining({
41
+ name: 'test-project',
42
+ template: 'web-pwa',
43
+ version: '1.0.0',
44
+ createdAt: expect.any(String),
45
+ assets: []
46
+ }),
47
+ { spaces: 2 }
48
+ );
49
+
50
+ expect(result).toMatchObject({
51
+ name: 'test-project',
52
+ template: 'web-pwa',
53
+ version: '1.0.0'
54
+ });
55
+ });
56
+
57
+ it('should include assets array in manifest', async () => {
58
+ const projectData = {
59
+ name: 'test-project',
60
+ template: 'web-pwa',
61
+ version: '1.0.0'
62
+ };
63
+
64
+ fs.writeJson.mockResolvedValue();
65
+
66
+ const result = await manifest.init('/test/project', projectData);
67
+
68
+ expect(result.assets).toEqual([]);
69
+ });
70
+ });
71
+
72
+ describe('load', () => {
73
+ it('should load existing manifest', async () => {
74
+ const mockManifest = {
75
+ name: 'test-project',
76
+ template: 'web-pwa',
77
+ version: '1.0.0',
78
+ createdAt: '2024-01-01T00:00:00.000Z',
79
+ assets: []
80
+ };
81
+
82
+ fs.existsSync.mockReturnValue(true);
83
+ fs.readJson.mockResolvedValue(mockManifest);
84
+
85
+ const result = await manifest.load('/test/project');
86
+
87
+ expect(result).toEqual(mockManifest);
88
+ });
89
+
90
+ it('should return null for non-existing manifest', async () => {
91
+ fs.existsSync.mockReturnValue(false);
92
+
93
+ const result = await manifest.load('/test/project');
94
+
95
+ expect(result).toBeNull();
96
+ });
97
+
98
+ it('should return null when manifest file does not exist', async () => {
99
+ fs.existsSync.mockReturnValue(true);
100
+ fs.readJson.mockRejectedValue(new Error('File not found'));
101
+
102
+ const result = await manifest.load('/test/project');
103
+
104
+ // El código actual no maneja errores de readJson, así que debería lanzar el error
105
+ // Para este test, vamos a verificar que el error se maneja correctamente
106
+ expect(result).toBeNull();
107
+ });
108
+ });
109
+
110
+ describe('addAsset', () => {
111
+ it('should add asset to existing manifest', async () => {
112
+ const existingManifest = {
113
+ name: 'test-project',
114
+ template: 'web-pwa',
115
+ version: '1.0.0',
116
+ assets: []
117
+ };
118
+
119
+ const newAsset = {
120
+ name: 'components',
121
+ type: 'directory'
122
+ };
123
+
124
+ fs.readJson.mockResolvedValue(existingManifest);
125
+ fs.writeJson.mockResolvedValue();
126
+
127
+ await manifest.addAsset('/test/project', newAsset);
128
+
129
+ expect(fs.writeJson).toHaveBeenCalledWith(
130
+ path.join('/test/project', 'g360-manifest.json'),
131
+ expect.objectContaining({
132
+ assets: expect.arrayContaining([
133
+ expect.objectContaining({
134
+ name: 'components',
135
+ type: 'directory',
136
+ addedAt: expect.any(String)
137
+ })
138
+ ])
139
+ }),
140
+ { spaces: 2 }
141
+ );
142
+ });
143
+
144
+ it('should not add asset when manifest does not exist', async () => {
145
+ fs.readJson.mockResolvedValue(null);
146
+
147
+ await manifest.addAsset('/test/project', { name: 'test' });
148
+
149
+ expect(fs.writeJson).not.toHaveBeenCalled();
150
+ });
151
+ });
152
+
153
+ describe('remove', () => {
154
+ it('should remove manifest file', async () => {
155
+ fs.existsSync.mockReturnValue(true);
156
+ fs.remove.mockResolvedValue();
157
+
158
+ await manifest.remove('/test/project');
159
+
160
+ expect(fs.remove).toHaveBeenCalledWith(
161
+ path.join('/test/project', 'g360-manifest.json')
162
+ );
163
+ });
164
+
165
+ it('should handle non-existing manifest gracefully', async () => {
166
+ fs.existsSync.mockReturnValue(false);
167
+
168
+ await manifest.remove('/test/project');
169
+
170
+ expect(fs.remove).not.toHaveBeenCalled();
171
+ });
172
+ });
173
+ });
@@ -0,0 +1,115 @@
1
+ /**
2
+ * @file validator.test.js
3
+ * @description Tests para el módulo validator
4
+ */
5
+
6
+ import { describe, it, expect, beforeEach, vi } from 'vitest';
7
+ import fs from 'fs-extra';
8
+ import { validator } from '../lib/validator.js';
9
+
10
+ // Mock de fs-extra
11
+ vi.mock('fs-extra', () => ({
12
+ default: {
13
+ existsSync: vi.fn()
14
+ }
15
+ }));
16
+
17
+ describe('validator module', () => {
18
+ beforeEach(() => {
19
+ vi.clearAllMocks();
20
+ });
21
+
22
+ describe('isValidProjectName', () => {
23
+ it('should accept valid project names', () => {
24
+ expect(validator.isValidProjectName('my-project')).toBe(true);
25
+ expect(validator.isValidProjectName('project123')).toBe(true);
26
+ expect(validator.isValidProjectName('my-project-123')).toBe(true);
27
+ expect(validator.isValidProjectName('123project')).toBe(true); // Empieza con número es válido según la regex actual
28
+ });
29
+
30
+ it('should reject invalid project names', () => {
31
+ expect(validator.isValidProjectName('My-Project')).toBe(false); // Mayúsculas
32
+ expect(validator.isValidProjectName('my_project')).toBe(false); // Guiones bajos
33
+ expect(validator.isValidProjectName('my project')).toBe(false); // Espacios
34
+ expect(validator.isValidProjectName('-project')).toBe(false); // Empieza con guion
35
+ expect(validator.isValidProjectName('')).toBe(false); // Vacío
36
+ });
37
+ });
38
+
39
+ describe('isValidPath', () => {
40
+ it('should return true for existing paths', () => {
41
+ fs.existsSync.mockReturnValue(true);
42
+ expect(validator.isValidPath('/existing/path')).toBe(true);
43
+ });
44
+
45
+ it('should return false for non-existing paths', () => {
46
+ fs.existsSync.mockReturnValue(false);
47
+ expect(validator.isValidPath('/non/existing/path')).toBe(false);
48
+ });
49
+
50
+ it('should handle errors gracefully', () => {
51
+ fs.existsSync.mockImplementation(() => {
52
+ throw new Error('Permission denied');
53
+ });
54
+ expect(validator.isValidPath('/error/path')).toBe(false);
55
+ });
56
+ });
57
+
58
+ describe('validateProject', () => {
59
+ it('should validate a valid G360 project', () => {
60
+ fs.existsSync.mockImplementation((path) => {
61
+ // El directorio del proyecto existe
62
+ if (path === '/valid/project') return true;
63
+ // El manifest y el directorio g360 existen
64
+ if (path.includes('g360-manifest.json') || path.includes('g360')) return true;
65
+ return false;
66
+ });
67
+
68
+ const result = validator.validateProject('/valid/project');
69
+
70
+ expect(result.valid).toBe(true);
71
+ expect(result.errors).toHaveLength(0);
72
+ expect(result.warnings).toHaveLength(0);
73
+ });
74
+
75
+ it('should return errors for non-existing project', () => {
76
+ fs.existsSync.mockReturnValue(false);
77
+
78
+ const result = validator.validateProject('/non/existing');
79
+
80
+ expect(result.valid).toBe(false);
81
+ expect(result.errors).toContain('Project directory does not exist');
82
+ });
83
+
84
+ it('should return warnings for missing G360 files', () => {
85
+ fs.existsSync.mockImplementation((path) => {
86
+ // El directorio del proyecto existe
87
+ if (path === '/project/without/g360') return true;
88
+ // El manifest y el directorio g360 no existen
89
+ return false;
90
+ });
91
+
92
+ const result = validator.validateProject('/project/without/g360');
93
+
94
+ expect(result.valid).toBe(true);
95
+ expect(result.warnings).toContain('No g360-manifest.json found');
96
+ expect(result.warnings).toContain('No g360 directory found');
97
+ });
98
+
99
+ it('should handle partial G360 setup', () => {
100
+ fs.existsSync.mockImplementation((path) => {
101
+ // El directorio del proyecto existe
102
+ if (path === '/project/partial') return true;
103
+ // Solo el manifest existe
104
+ if (path.includes('g360-manifest.json')) return true;
105
+ // El directorio g360 no existe
106
+ return false;
107
+ });
108
+
109
+ const result = validator.validateProject('/project/partial');
110
+
111
+ expect(result.valid).toBe(true);
112
+ expect(result.warnings).toContain('No g360 directory found');
113
+ });
114
+ });
115
+ });