Skip to content

Commit

Permalink
refactor: on upload success waiting
Browse files Browse the repository at this point in the history
  • Loading branch information
jrasm91 committed Feb 27, 2024
1 parent 9b976bc commit 0fc5d83
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 63 deletions.
114 changes: 67 additions & 47 deletions e2e/src/api/specs/asset.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,8 @@ describe('/asset', () => {
let user1: LoginResponseDto;
let user2: LoginResponseDto;
let userStats: LoginResponseDto;
let asset1: AssetFileUploadResponseDto;
let asset2: AssetFileUploadResponseDto;
let asset3: AssetFileUploadResponseDto;
let asset4: AssetFileUploadResponseDto; // user2 asset
let asset5: AssetFileUploadResponseDto;
let asset6: AssetFileUploadResponseDto;
let user1Assets: AssetFileUploadResponseDto[];
let user2Assets: AssetFileUploadResponseDto[];
let assetLocation: AssetFileUploadResponseDto;
let ws: Socket;

Expand All @@ -70,15 +66,20 @@ describe('/asset', () => {

// asset location
assetLocation = await apiUtils.createAsset(
user1.accessToken,
admin.accessToken,
{},
{
filename: 'thompson-springs.jpg',
bytes: await readFile(locationAssetFilepath),
},
);

[asset1, asset2, asset3, asset4, asset5, asset6] = await Promise.all([
await wsUtils.waitForEvent({
event: 'upload',
assetId: assetLocation.id,
});

user1Assets = await Promise.all([
apiUtils.createAsset(user1.accessToken),
apiUtils.createAsset(user1.accessToken),
apiUtils.createAsset(
Expand All @@ -92,10 +93,13 @@ describe('/asset', () => {
},
{ filename: 'example.mp4' },
),
apiUtils.createAsset(user2.accessToken),
apiUtils.createAsset(user1.accessToken),
apiUtils.createAsset(user1.accessToken),
]);

user2Assets = await Promise.all([apiUtils.createAsset(user2.accessToken)]);

await Promise.all([
// stats
apiUtils.createAsset(userStats.accessToken),
apiUtils.createAsset(userStats.accessToken, { isFavorite: true }),
Expand All @@ -113,8 +117,11 @@ describe('/asset', () => {
const person1 = await apiUtils.createPerson(user1.accessToken, {
name: 'Test Person',
});
await dbUtils.createFace({ assetId: asset1.id, personId: person1.id });
});
await dbUtils.createFace({
assetId: user1Assets[0].id,
personId: person1.id,
});
}, 30_000);

afterAll(() => {
wsUtils.disconnect(ws);
Expand All @@ -139,41 +146,41 @@ describe('/asset', () => {

it('should require access', async () => {
const { status, body } = await request(app)
.get(`/asset/${asset4.id}`)
.get(`/asset/${user2Assets[0].id}`)
.set('Authorization', `Bearer ${user1.accessToken}`);
expect(status).toBe(400);
expect(body).toEqual(errorDto.noPermission);
});

it('should get the asset info', async () => {
const { status, body } = await request(app)
.get(`/asset/${asset1.id}`)
.get(`/asset/${user1Assets[0].id}`)
.set('Authorization', `Bearer ${user1.accessToken}`);
expect(status).toBe(200);
expect(body).toMatchObject({ id: asset1.id });
expect(body).toMatchObject({ id: user1Assets[0].id });
});

it('should work with a shared link', async () => {
const sharedLink = await apiUtils.createSharedLink(user1.accessToken, {
type: SharedLinkType.Individual,
assetIds: [asset1.id],
assetIds: [user1Assets[0].id],
});

const { status, body } = await request(app).get(
`/asset/${asset1.id}?key=${sharedLink.key}`,
`/asset/${user1Assets[0].id}?key=${sharedLink.key}`,
);
expect(status).toBe(200);
expect(body).toMatchObject({ id: asset1.id });
expect(body).toMatchObject({ id: user1Assets[0].id });
});

it('should not send people data for shared links for un-authenticated users', async () => {
const { status, body } = await request(app)
.get(`/asset/${asset1.id}`)
.get(`/asset/${user1Assets[0].id}`)
.set('Authorization', `Bearer ${user1.accessToken}`);

expect(status).toEqual(200);
expect(body).toMatchObject({
id: asset1.id,
id: user1Assets[0].id,
isFavorite: false,
people: [
{
Expand All @@ -188,11 +195,11 @@ describe('/asset', () => {

const sharedLink = await apiUtils.createSharedLink(user1.accessToken, {
type: SharedLinkType.Individual,
assetIds: [asset1.id],
assetIds: [user1Assets[0].id],
});

const data = await request(app).get(
`/asset/${asset1.id}?key=${sharedLink.key}`,
`/asset/${user1Assets[0].id}?key=${sharedLink.key}`,
);
expect(data.status).toBe(200);
expect(data.body).toMatchObject({ people: [] });
Expand Down Expand Up @@ -286,11 +293,11 @@ describe('/asset', () => {
const assets: AssetResponseDto[] = body;
expect(assets.length).toBe(1);
expect(assets[0].ownerId).toBe(user1.userId);
//
// assets owned by user2
expect(assets[0].id).not.toBe(asset4.id);

// assets owned by user1
expect([asset1.id, asset2.id, asset3.id]).toContain(assets[0].id);
expect([user1Assets.map(({ id }) => id)]).toContain(assets[0].id);
// assets owned by user2
expect([user1Assets.map(({ id }) => id)]).not.toContain(assets[0].id);
});

it.each(Array(10))('should return 2 random assets', async () => {
Expand All @@ -306,9 +313,9 @@ describe('/asset', () => {
for (const asset of assets) {
expect(asset.ownerId).toBe(user1.userId);
// assets owned by user1
expect([asset1.id, asset2.id, asset3.id]).toContain(asset.id);
expect([user1Assets.map(({ id }) => id)]).toContain(asset.id);
// assets owned by user2
expect(asset.id).not.toBe(asset4.id);
expect([user2Assets.map(({ id }) => id)]).not.toContain(asset.id);
}
});

Expand All @@ -320,7 +327,9 @@ describe('/asset', () => {
.set('Authorization', `Bearer ${user2.accessToken}`);

expect(status).toBe(200);
expect(body).toEqual([expect.objectContaining({ id: asset4.id })]);
expect(body).toEqual([
expect.objectContaining({ id: user2Assets[0].id }),
]);
},
);

Expand Down Expand Up @@ -352,44 +361,50 @@ describe('/asset', () => {

it('should require access', async () => {
const { status, body } = await request(app)
.put(`/asset/${asset4.id}`)
.put(`/asset/${user2Assets[0].id}`)
.set('Authorization', `Bearer ${user1.accessToken}`);
expect(status).toBe(400);
expect(body).toEqual(errorDto.noPermission);
});

it('should favorite an asset', async () => {
const before = await apiUtils.getAssetInfo(user1.accessToken, asset1.id);
const before = await apiUtils.getAssetInfo(
user1.accessToken,
user1Assets[0].id,
);
expect(before.isFavorite).toBe(false);

const { status, body } = await request(app)
.put(`/asset/${asset1.id}`)
.put(`/asset/${user1Assets[0].id}`)
.set('Authorization', `Bearer ${user1.accessToken}`)
.send({ isFavorite: true });
expect(body).toMatchObject({ id: asset1.id, isFavorite: true });
expect(body).toMatchObject({ id: user1Assets[0].id, isFavorite: true });
expect(status).toEqual(200);
});

it('should archive an asset', async () => {
const before = await apiUtils.getAssetInfo(user1.accessToken, asset1.id);
const before = await apiUtils.getAssetInfo(
user1.accessToken,
user1Assets[0].id,
);
expect(before.isArchived).toBe(false);

const { status, body } = await request(app)
.put(`/asset/${asset1.id}`)
.put(`/asset/${user1Assets[0].id}`)
.set('Authorization', `Bearer ${user1.accessToken}`)
.send({ isArchived: true });
expect(body).toMatchObject({ id: asset1.id, isArchived: true });
expect(body).toMatchObject({ id: user1Assets[0].id, isArchived: true });
expect(status).toEqual(200);
});

it('should update date time original', async () => {
const { status, body } = await request(app)
.put(`/asset/${asset1.id}`)
.put(`/asset/${user1Assets[0].id}`)
.set('Authorization', `Bearer ${user1.accessToken}`)
.send({ dateTimeOriginal: '2023-11-19T18:11:00.000-07:00' });

expect(body).toMatchObject({
id: asset1.id,
id: user1Assets[0].id,
exifInfo: expect.objectContaining({
dateTimeOriginal: '2023-11-20T01:11:00.000Z',
}),
Expand All @@ -411,7 +426,7 @@ describe('/asset', () => {
{ latitude: 12, longitude: 181 },
]) {
const { status, body } = await request(app)
.put(`/asset/${asset1.id}`)
.put(`/asset/${user1Assets[0].id}`)
.send(test)
.set('Authorization', `Bearer ${user1.accessToken}`);
expect(status).toBe(400);
Expand All @@ -421,24 +436,24 @@ describe('/asset', () => {

it('should update gps data', async () => {
const { status, body } = await request(app)
.put(`/asset/${asset1.id}`)
.put(`/asset/${user1Assets[0].id}`)
.set('Authorization', `Bearer ${user1.accessToken}`)
.send({ latitude: 12, longitude: 12 });

expect(body).toMatchObject({
id: asset1.id,
id: user1Assets[0].id,
exifInfo: expect.objectContaining({ latitude: 12, longitude: 12 }),
});
expect(status).toEqual(200);
});

it('should set the description', async () => {
const { status, body } = await request(app)
.put(`/asset/${asset1.id}`)
.put(`/asset/${user1Assets[0].id}`)
.set('Authorization', `Bearer ${user1.accessToken}`)
.send({ description: 'Test asset description' });
expect(body).toMatchObject({
id: asset1.id,
id: user1Assets[0].id,
exifInfo: expect.objectContaining({
description: 'Test asset description',
}),
Expand All @@ -448,12 +463,12 @@ describe('/asset', () => {

it('should return tagged people', async () => {
const { status, body } = await request(app)
.put(`/asset/${asset1.id}`)
.put(`/asset/${user1Assets[0].id}`)
.set('Authorization', `Bearer ${user1.accessToken}`)
.send({ isFavorite: true });
expect(status).toEqual(200);
expect(body).toMatchObject({
id: asset1.id,
id: user1Assets[0].id,
isFavorite: true,
people: [
{
Expand Down Expand Up @@ -643,7 +658,7 @@ describe('/asset', () => {

expect(duplicate).toBe(false);

await wsUtils.once(ws, 'on_upload_success');
await wsUtils.waitForEvent({ event: 'upload', assetId: id });

const asset = await apiUtils.getAssetInfo(admin.accessToken, id);

Expand Down Expand Up @@ -698,9 +713,9 @@ describe('/asset', () => {
},
);

expect(response.duplicate).toBe(false);
await wsUtils.waitForEvent({ event: 'upload', assetId: response.id });

await wsUtils.once(ws, 'on_upload_success');
expect(response.duplicate).toBe(false);

const asset = await apiUtils.getAssetInfo(
admin.accessToken,
Expand Down Expand Up @@ -732,6 +747,11 @@ describe('/asset', () => {
.get(`/asset/thumbnail/${assetLocation.id}?format=WEBP`)
.set('Authorization', `Bearer ${user1.accessToken}`);

await wsUtils.waitForEvent({
event: 'upload',
assetId: assetLocation.id,
});

expect(status).toBe(200);
expect(body).toBeDefined();
expect(type).toBe('image/webp');
Expand Down
4 changes: 2 additions & 2 deletions e2e/src/api/specs/audit.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@ describe('/audit', () => {
await Promise.all([
deleteAssets(
{ assetBulkDeleteDto: { ids: [trashedAsset.id] } },
{ headers: asBearerAuth(admin.accessToken) }
{ headers: asBearerAuth(admin.accessToken) },
),
updateAsset(
{
id: archivedAsset.id,
updateAssetDto: { isArchived: true },
},
{ headers: asBearerAuth(admin.accessToken) }
{ headers: asBearerAuth(admin.accessToken) },
),
]);

Expand Down
2 changes: 1 addition & 1 deletion e2e/src/api/specs/trash.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ describe('/trash', () => {
.set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toBe(204);

await wsUtils.once(ws, 'on_asset_delete');
await wsUtils.waitForEvent({ event: 'delete', assetId });

const after = await getAllAssets(
{},
Expand Down
8 changes: 4 additions & 4 deletions e2e/src/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,25 @@ import { spawn, exec } from 'child_process';

export default async () => {
let _resolve: () => unknown;
const promise = new Promise<void>((resolve) => (_resolve = resolve));
const ready = new Promise<void>((resolve) => (_resolve = resolve));

const child = spawn('docker', ['compose', 'up'], { stdio: 'pipe' });

child.stdout.on('data', (data) => {
const input = data.toString();
console.log(input);
if (input.includes('Immich Server is listening')) {
if (input.includes('Immich Microservices is listening')) {
_resolve();
}
});

child.stderr.on('data', (data) => console.log(data.toString()));

await promise;
await ready;

return async () => {
await new Promise<void>((resolve) =>
exec('docker compose down', () => resolve())
exec('docker compose down', () => resolve()),
);
};
};

0 comments on commit 0fc5d83

Please sign in to comment.