Skip to content

Commit d9f03cb

Browse files
committed
implemented e2e tests
1 parent 7ed1c36 commit d9f03cb

2 files changed

Lines changed: 484 additions & 0 deletions

File tree

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
import { Test, TestingModule } from '@nestjs/testing';
2+
import {
3+
ClassSerializerInterceptor,
4+
INestApplication,
5+
ValidationPipe,
6+
} from '@nestjs/common';
7+
import { AppModule } from './../src/app.module';
8+
import { Reflector } from '@nestjs/core';
9+
import * as request from 'supertest';
10+
import {
11+
ResetProtoFile,
12+
FileProviderProtoFile,
13+
FileBucketProtoFile,
14+
FileProtoFile,
15+
FileProviderProto,
16+
} from 'juno-proto';
17+
import * as GRPC from '@grpc/grpc-js';
18+
import * as ProtoLoader from '@grpc/proto-loader';
19+
import { RpcExceptionFilter } from 'src/rpc_exception_filter';
20+
21+
let app: INestApplication;
22+
const ADMIN_EMAIL = 'test-superadmin@test.com';
23+
const ADMIN_PASSWORD = 'test-password';
24+
let apiKey: string | undefined = undefined;
25+
26+
async function APIKeyForProjectName(projectName: string): Promise<string> {
27+
const key = await request(app.getHttpServer())
28+
.post('/auth/key')
29+
.set('X-User-Email', ADMIN_EMAIL)
30+
.set('X-User-Password', ADMIN_PASSWORD)
31+
.send({
32+
environment: 'prod',
33+
project: {
34+
name: projectName,
35+
},
36+
});
37+
38+
return key.body['apiKey'];
39+
}
40+
41+
const bucketName = 'test-delete-gw-juno';
42+
const configId = 0;
43+
const providerName = 'backblazeb2-delete-gw';
44+
45+
const accessKeyId = process.env.accessKeyId;
46+
const secretAccessKey = process.env.secretAccessKey;
47+
const baseURL = process.env.baseURL;
48+
49+
beforeAll(async () => {
50+
const proto = ProtoLoader.loadSync([ResetProtoFile]) as any;
51+
const protoGRPC = GRPC.loadPackageDefinition(proto) as any;
52+
const resetClient = new protoGRPC.juno.reset_db.DatabaseReset(
53+
process.env.DB_SERVICE_ADDR,
54+
GRPC.credentials.createInsecure(),
55+
);
56+
await new Promise((resolve) => {
57+
resetClient.resetDb({}, () => resolve(0));
58+
});
59+
60+
const providerProto = ProtoLoader.loadSync([FileProviderProtoFile]) as any;
61+
const providerProtoGRPC = GRPC.loadPackageDefinition(providerProto) as any;
62+
const providerClient =
63+
new providerProtoGRPC.juno.file_service.provider.FileProviderDbService(
64+
process.env.DB_SERVICE_ADDR,
65+
GRPC.credentials.createInsecure(),
66+
);
67+
68+
await new Promise((resolve) => {
69+
providerClient.createProvider(
70+
{
71+
providerName,
72+
accessKey: JSON.stringify({ accessKeyId, secretAccessKey }),
73+
metadata: JSON.stringify({ endpoint: baseURL }),
74+
bucket: [],
75+
type: FileProviderProto.ProviderType.S3,
76+
},
77+
() => resolve(0),
78+
);
79+
});
80+
81+
const bucketProto = ProtoLoader.loadSync([FileBucketProtoFile]) as any;
82+
const bucketProtoGRPC = GRPC.loadPackageDefinition(bucketProto) as any;
83+
const bucketClient =
84+
new bucketProtoGRPC.juno.file_service.bucket.BucketDbService(
85+
process.env.DB_SERVICE_ADDR,
86+
GRPC.credentials.createInsecure(),
87+
);
88+
89+
await new Promise((resolve) => {
90+
bucketClient.createBucket(
91+
{
92+
name: bucketName,
93+
configId,
94+
fileProviderName: providerName,
95+
files: [],
96+
configEnv: 'prod',
97+
},
98+
() => resolve(0),
99+
);
100+
});
101+
});
102+
103+
afterAll((done) => {
104+
app.close();
105+
done();
106+
});
107+
108+
beforeEach(async () => {
109+
const moduleFixture: TestingModule = await Test.createTestingModule({
110+
imports: [AppModule],
111+
}).compile();
112+
113+
app = moduleFixture.createNestApplication();
114+
app.useGlobalPipes(
115+
new ValidationPipe({
116+
transform: true,
117+
}),
118+
);
119+
app.useGlobalInterceptors(new ClassSerializerInterceptor(app.get(Reflector)));
120+
app.useGlobalFilters(new RpcExceptionFilter());
121+
122+
await app.init();
123+
124+
if (!apiKey) {
125+
apiKey = await APIKeyForProjectName('test-seed-project');
126+
}
127+
});
128+
129+
describe('File Delete Routes', () => {
130+
it('Rejects delete without auth key', () => {
131+
return request(app.getHttpServer())
132+
.delete('/file/delete')
133+
.send({
134+
bucketName,
135+
configId,
136+
fileNames: ['SomeFile'],
137+
})
138+
.expect(401);
139+
});
140+
141+
it('Rejects delete with missing bucketName', () => {
142+
return request(app.getHttpServer())
143+
.delete('/file/delete')
144+
.set('Authorization', 'Bearer ' + apiKey)
145+
.send({
146+
bucketName: '',
147+
configId,
148+
fileNames: ['SomeFile'],
149+
})
150+
.expect(400);
151+
});
152+
153+
it('Rejects delete with negative configId', () => {
154+
return request(app.getHttpServer())
155+
.delete('/file/delete')
156+
.set('Authorization', 'Bearer ' + apiKey)
157+
.send({
158+
bucketName,
159+
configId: -1,
160+
fileNames: ['SomeFile'],
161+
})
162+
.expect(400);
163+
});
164+
165+
it('Rejects delete with empty fileNames', () => {
166+
return request(app.getHttpServer())
167+
.delete('/file/delete')
168+
.set('Authorization', 'Bearer ' + apiKey)
169+
.send({
170+
bucketName,
171+
configId,
172+
fileNames: [],
173+
})
174+
.expect(400);
175+
});
176+
177+
it('Successfully deletes a file', async () => {
178+
// Upload the file first via the file service proto directly
179+
const fileProto = ProtoLoader.loadSync([FileProtoFile]) as any;
180+
const fileProtoGRPC = GRPC.loadPackageDefinition(fileProto) as any;
181+
const fileClient = new fileProtoGRPC.juno.file_service.file.FileDbService(
182+
process.env.DB_SERVICE_ADDR,
183+
GRPC.credentials.createInsecure(),
184+
);
185+
186+
await new Promise((resolve) => {
187+
fileClient.createFile(
188+
{
189+
fileId: {
190+
bucketName,
191+
configId,
192+
configEnv: 'prod',
193+
path: 'FileToDeleteGW',
194+
},
195+
metadata: '',
196+
},
197+
() => resolve(0),
198+
);
199+
});
200+
201+
return request(app.getHttpServer())
202+
.delete('/file/delete')
203+
.set('Authorization', 'Bearer ' + apiKey)
204+
.send({
205+
bucketName,
206+
configId,
207+
fileNames: ['FileToDeleteGW'],
208+
})
209+
.expect(200);
210+
});
211+
});

0 commit comments

Comments
 (0)