Skip to content

Commit 6ee250e

Browse files
authored
Merge pull request #6 from f-lab-edu/feature/FileUpload
chore: ํŒŒ์ผ ๊ฒ€์ฆ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ
2 parents 3cbf789 + d15ac4a commit 6ee250e

File tree

3 files changed

+206
-3
lines changed

3 files changed

+206
-3
lines changed

โ€Žbackend/.gitignoreโ€Ž

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,3 @@ pids
5757
# Diagnostic reports (https://nodejs.org/api/report.html)
5858
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
5959

60-
61-
file-upload.service.spec.ts
62-
file-upload.service.ts
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
import { Test, TestingModule } from '@nestjs/testing';
2+
import { FileUploadService } from './file-upload.service';
3+
import { Express } from 'express';
4+
import { Readable } from 'stream';
5+
6+
const createEmptyStream = (): Readable => {
7+
const stream = new Readable();
8+
stream.push(null);
9+
return stream;
10+
};
11+
12+
export const createMockFile = (
13+
originalname: string,
14+
content: string,
15+
): Express.Multer.File => ({
16+
originalname,
17+
buffer: Buffer.from(content),
18+
size: Buffer.from(content).length,
19+
fieldname: 'file',
20+
encoding: '7bit',
21+
mimetype: 'application/json',
22+
destination: '',
23+
filename: originalname,
24+
path: `/tmp/${originalname}`,
25+
stream: createEmptyStream(),
26+
});
27+
28+
describe('FileUploadService', () => {
29+
let service: FileUploadService;
30+
31+
beforeEach(async () => {
32+
const module: TestingModule = await Test.createTestingModule({
33+
providers: [FileUploadService],
34+
}).compile();
35+
36+
service = module.get<FileUploadService>(FileUploadService);
37+
});
38+
39+
describe('isJsonExtension_true', () => {
40+
it('should return true for .json', () => {
41+
const file = createMockFile('package.json', '{}');
42+
expect(service['isJsonExtension'](file)).toBe(true);
43+
});
44+
45+
it('should return false for non-json file', () => {
46+
const file = createMockFile('package.js', 'dependencies {}');
47+
expect(service['isJsonExtension'](file)).toBe(false);
48+
});
49+
});
50+
51+
// ๋‹ค๋ฅธ ์˜์กด์„ฑ ํŒŒ์ผ ์ถ”๊ฐ€ ์‹œ ๋ณ€๊ฒฝ
52+
describe('isPackageJsonFileName', () => {
53+
it('should return true for package.json', () => {
54+
const file = createMockFile('package.json', '{}');
55+
expect(service['isPackageJsonFileName'](file)).toBe(true);
56+
});
57+
58+
it('should return false for package-lock.json', () => {
59+
const file = createMockFile('package-lock.json', '{}');
60+
expect(service['isPackageJsonFileName'](file)).toBe(false);
61+
});
62+
});
63+
64+
describe('parseJson', () => {
65+
it('should return parsed object for valid JSON', () => {
66+
const file = createMockFile('package.json', '{"name": "test"}');
67+
const result = service['parseJson'](file);
68+
expect(result).toEqual({ name: 'test' });
69+
});
70+
71+
it('should return null for invalid JSON', () => {
72+
const file = createMockFile('package.json', '{"name": "test"');
73+
const result = service['parseJson'](file);
74+
expect(result).toBeNull();
75+
});
76+
});
77+
78+
describe('hasDependencies', () => {
79+
it('should return true if dependencies exists', () => {
80+
const json = { dependencies: { express: '4.18.2' } };
81+
expect(service['hasDependencies'](json)).toBe(true);
82+
});
83+
84+
it('should return true if devDependencies exists', () => {
85+
const json = { devDependencies: { '@types/express': '4.17.17' } };
86+
expect(service['hasDependencies'](json)).toBe(true);
87+
});
88+
89+
it('should return true if both dependencies and devDependencies exist', () => {
90+
const json = {
91+
dependencies: { express: '4.18.2' },
92+
devDependencies: { '@types/express': '4.17.17' },
93+
};
94+
expect(service['hasDependencies'](json)).toBe(true);
95+
});
96+
97+
it('should return false if both are missing', () => {
98+
const json = { name: 'test' };
99+
expect(service['hasDependencies'](json)).toBe(false);
100+
});
101+
102+
it('should return false if json is null', () => {
103+
expect(service['hasDependencies'](null)).toBe(false);
104+
});
105+
106+
it('should return false if json is undefined', () => {
107+
expect(service['hasDependencies'](undefined)).toBe(false);
108+
});
109+
});
110+
111+
describe('isPackageJson', () => {
112+
it('should return true for package.json with dependencies only', () => {
113+
const file = createMockFile(
114+
'package.json',
115+
'{"dependencies": {"express": "4.18.2"}}',
116+
);
117+
expect(service.isPackageJson(file)).toBe(true);
118+
});
119+
120+
it('should return true for package.json with devDependencies only', () => {
121+
const file = createMockFile(
122+
'package.json',
123+
'{"devDependencies": {"@types/express": "4.17.17"}}',
124+
);
125+
expect(service.isPackageJson(file)).toBe(true);
126+
});
127+
128+
it('should return true for package.json with both dependencies and devDependencies', () => {
129+
const file = createMockFile(
130+
'package.json',
131+
'{"dependencies": {}, "devDependencies": {}}',
132+
);
133+
expect(service.isPackageJson(file)).toBe(true);
134+
});
135+
136+
it('should return false if extension is not .json', () => {
137+
const file = createMockFile('package.txt', '{}');
138+
expect(service.isPackageJson(file)).toBe(false);
139+
});
140+
141+
it('should return false if filename is not package.json', () => {
142+
const file = createMockFile('package-lock.json', '{}');
143+
expect(service.isPackageJson(file)).toBe(false);
144+
});
145+
146+
it('should return false if JSON is invalid', () => {
147+
const file = createMockFile('package.json', '{"name": "test"');
148+
expect(service.isPackageJson(file)).toBe(false);
149+
});
150+
151+
it('should return false if both dependencies and devDependencies are missing', () => {
152+
const file = createMockFile('package.json', '{"name": "test"}');
153+
expect(service.isPackageJson(file)).toBe(false);
154+
});
155+
});
156+
});
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { Injectable } from '@nestjs/common';
2+
3+
@Injectable()
4+
export class FileUploadService {
5+
isPackageJson(file): boolean {
6+
if (!this.isJsonExtension(file)) {
7+
return false;
8+
}
9+
10+
if (!this.isPackageJsonFileName(file)) {
11+
return false;
12+
}
13+
14+
const json = this.parseJson(file);
15+
if (!json) {
16+
return false;
17+
}
18+
19+
return this.hasDependencies(json);
20+
}
21+
22+
private isJsonExtension(file): boolean {
23+
return file.originalname.endsWith('.json');
24+
}
25+
26+
// ๋‹ค๋ฅธ ์˜์กด์„ฑ ํŒŒ์ผ๋„ ์ถ”๊ฐ€ ์˜ˆ์ •
27+
private isPackageJsonFileName(file): boolean {
28+
return file.originalname === 'package.json';
29+
}
30+
31+
private parseJson(file): any | null {
32+
try {
33+
const content = file.buffer.toString('utf-8');
34+
return JSON.parse(content);
35+
} catch (error) {
36+
return null;
37+
}
38+
}
39+
40+
private hasDependencies(json): boolean {
41+
if (!json) {
42+
return false;
43+
}
44+
45+
return (
46+
json.hasOwnProperty('dependencies') ||
47+
json.hasOwnProperty('devDependencies')
48+
);
49+
}
50+
}

0 commit comments

Comments
ย (0)