Finished implementing PictureService

This commit is contained in:
2026-04-03 09:18:34 +02:00
parent 7b1d023a94
commit 7b19bea790
7 changed files with 213 additions and 10 deletions

View File

@@ -95,4 +95,15 @@ export interface Image {
liked: boolean
likes: number
userData: PublicUserData | null
}
export interface Comment {
commentId: string
author: string
imageId: string
comment: string
commented_at: TimeStamp
username: string
pfp: string
displayName: string
}

View File

@@ -0,0 +1,35 @@
import {http, HttpResponse} from "msw";
import {CreateNetworkReq, Network, NetworkInvite} from "../../domain/networkService.schema";
import {Album, Comment, CreateAlbumReq, GetResp} from "../../domain/pictureService.schema";
export const pictureHandlers = [
http.get('*/picture/pictures', () => {
return HttpResponse.json(<GetResp>{
pictures: [{
name: "Album name"
}],
userData: {
username: "bob"
}
})
}),
http.post('*/picture/createAlbum', async ({request}) => {
const body = await request.json() as CreateAlbumReq;
return HttpResponse.json(<Album>{
name: body.name,
})
}),
http.get('*/picture/getAlbums', () => {
return HttpResponse.json(<Album[]>[{
name: "Album name"
}])
}),
http.get('*/picture/comment', () => {
return HttpResponse.json(<Comment[]>[{
comment: "This is a comment",
}])
}),
]

View File

@@ -1,7 +1,9 @@
import {networkHandlers} from "./handlers/auth.http";
import {authHandlers} from "./handlers/network.http";
import {pictureHandlers} from "./handlers/picture.http";
export const allHandlers = [
...authHandlers,
...networkHandlers
...networkHandlers,
...pictureHandlers
]

View File

@@ -0,0 +1,30 @@
import {describe, expect, it} from "vitest";
import {PictureService} from "./pictureService";
import {DatabaseMock} from "../mocks/storage/database";
import {faker} from "@faker-js/faker/locale/en";
describe("PictureService", () => {
const service = new PictureService("", "", "", new DatabaseMock(), null, null)
it('should get pictures', async () => {
const uploads = await service.get()
expect(uploads.pictures[0].name).toBe("Album name")
expect(uploads.userData.username).toBe("bob")
})
it('should create an album', async () => {
const albumName = faker.internet.displayName()
const album = await service.createAlbum(albumName)
expect(album.name).toBe(albumName)
});
it('should fetch the albums', async () => {
const albums = await service.getAlbums()
expect(albums[0].name).toBe("Album name")
});
it('should fetch comments', async () => {
const comments = await service.getComments("")
expect(comments[0]).toBe("This is a comment")
})
})

View File

@@ -4,7 +4,7 @@ import {getClient} from "../core/http";
import {NetworkInvite} from "../domain/networkService.schema";
import {GenericErrorBody} from "../domain/http.schema";
import {
Album, ChangePictureVisibilityReq,
Album, ChangePictureVisibilityReq, Comment,
CreateAlbumReq,
DeleteImageReq,
DiscoveryResp, EditPictureTitleReq,
@@ -36,6 +36,9 @@ export class PictureService {
})
}
/**
* Fetches all images uploaded by the specified uploader categorized in albums
*/
async get(): Promise<GetResp> {
try {
const resp = await this.client.get<GetResp>(`picture/pictures?userid=${this.userid}&target=${this.uploaderId}`);
@@ -49,6 +52,9 @@ export class PictureService {
}
}
/**
* Fetches the top 10 most liked and newest pictures
*/
async discovery(): Promise<DiscoveryResp> {
try {
const resp = await this.client.get<DiscoveryResp>("picture/discovery");
@@ -62,6 +68,10 @@ export class PictureService {
}
}
/**
* Creates a new album
* @param name Provided by the user
*/
async createAlbum(name: string): Promise<Album> {
try {
const resp = await this.client.post<Album>("picture/createAlbum", <CreateAlbumReq>{
@@ -78,6 +88,10 @@ export class PictureService {
}
}
/**
* Registers all uploaded pictures in the database
* @param uploadId Must the be the one that was used when uploading the images
*/
async finalizeUpload(uploadId: string): Promise<void> {
try {
await this.client.post("picture/finalizeUpload", <FinalizeUploadReq>{
@@ -94,9 +108,13 @@ export class PictureService {
}
}
/**
* Deletes the specified picture
* @param imageId
*/
async deletePicture(imageId: string): Promise<void> {
try {
await this.client.post("picture/delete", <DeleteImageReq>{
await this.client.patch("picture/delete", <DeleteImageReq>{
userid: this.userid,
imageId: imageId
});
@@ -110,11 +128,18 @@ export class PictureService {
}
}
/**
* Changes the visibility of the specified picture
* @param imageId
* @param newVisibility
*/
async changeVisibility(imageId: string, newVisibility: string): Promise<void> {
try {
await this.client.post("picture/changeVisibility", <ChangePictureVisibilityReq>{
await this.client.patch("picture/changeVisibility", <ChangePictureVisibilityReq>{
userid: this.userid,
visibility: newVisibility
visibility: newVisibility,
imageId: imageId
});
return
} catch (e) {
@@ -126,11 +151,17 @@ export class PictureService {
}
}
/**
* Edits the title of the specified picture
* @param imageId
* @param newTitle
*/
async editTitle(imageId: string, newTitle: string): Promise<void> {
try {
await this.client.post("picture/editTitle", <EditPictureTitleReq>{
await this.client.patch("picture/editTitle", <EditPictureTitleReq>{
userid: this.userid,
title: newTitle
title: newTitle,
imageId: imageId
});
return
} catch (e) {
@@ -142,6 +173,10 @@ export class PictureService {
}
}
/**
* (un)likes the specified picture
* @param imageId
*/
async toggleLike(imageId: string): Promise<void> {
try {
await this.client.post("picture/toggleLike", <TogglePictureLikeReq>{
@@ -158,6 +193,11 @@ export class PictureService {
}
}
/**
* Posts a comment under the specified picture
* @param imageId
* @param comment
*/
async postComment(imageId: string, comment: string): Promise<void> {
try {
await this.client.post("picture/comment", <PostCommentReq>{
@@ -175,6 +215,9 @@ export class PictureService {
}
}
/**
* (un)follows the uploader
*/
async toggleFollow(): Promise<void> {
try {
await this.client.post("picture/toggleFollow", <ToggleFollowReq>{
@@ -191,6 +234,9 @@ export class PictureService {
}
}
/**
* Fetches all albums
*/
async getAlbums(): Promise<Album[]> {
try {
const resp = await this.client.get(`picture/getAlbums?userid=${this.userid}`);
@@ -204,9 +250,13 @@ export class PictureService {
}
}
async getComments(imageId: string): Promise<Album[]> {
/**
* Gets all comments under the specified picture
* @param imageId
*/
async getComments(imageId: string): Promise<Comment[]> {
try {
const resp = await this.client.get(`picture/comment?userid=${this.userid}&imageId=${imageId}`);
const resp = await this.client.get<Comment[]>(`picture/comment?userid=${this.userid}&imageId=${imageId}`);
return resp.data
} catch (e) {
console.log(e)
@@ -217,6 +267,15 @@ export class PictureService {
}
}
/**
* Uploads a new picture to the CDN
* @param picture
* @param title
* @param visibility
* @param album
* @param uploadId
* @param name
*/
async uploadPicture(picture: string, title: string, visibility: string, album: string, uploadId: string, name: string): Promise<void> {
try {
await this.cdnClient.post("picture/upload", <UploadImageReq>{

View File

@@ -24,7 +24,7 @@ describe("NetworkService Integration Testing", () => {
NETWORK_SERVICE_TESTING_TOKEN,
NETWORK_SERVICE_TESTING_NETWORK_ID,
new DatabaseMock(),
getClient()
getClient(false),
)
it("should get invites", async () => {

View File

@@ -0,0 +1,66 @@
import {describe, expect, it} from "vitest";
import {environment, SDKConfig} from "../src/core/environment";
import {NetworkService} from "../src/services/networkService";
import {DatabaseMock} from "../src/mocks/storage/database";
import {getClient} from "../src/core/http";
import {PictureService} from "../src/services/pictureService";
import {faker} from "@faker-js/faker/locale/en";
const PICTURE_SERVICE_TESTING_TOKEN = "testingToken"
const PICTURE_SERVICE_TESTING_USER_ID = "000000000000000000000000"
const PICTURE_SERVICE_TESTING_IMAGE_ID = "111111111111111111111111"
describe("PictureService Integration Test", () => {
environment.overwrite(<SDKConfig>{apiUrl: "http://localhost:3000", cdnUrl: "http://localhost:4000"})
const service = new PictureService(
PICTURE_SERVICE_TESTING_TOKEN,
PICTURE_SERVICE_TESTING_USER_ID,
PICTURE_SERVICE_TESTING_USER_ID,
new DatabaseMock(),
getClient(false),
getClient(true),
)
it('should get uploads', async () => {
const uploads = await service.get()
expect(uploads.pictures[0].name).toBe("Album name")
});
it('should create an album', async () => {
const albumName = faker.internet.displayName()
await service.createAlbum(albumName)
const uploads = await service.get()
expect(uploads.pictures[1].name).toBe(albumName)
});
it('should delete image', async () => {
await service.deletePicture(PICTURE_SERVICE_TESTING_IMAGE_ID)
const uploads = await service.get()
expect(uploads.pictures[0].images.length).toBe(0)
});
it('should change image visibility', async () => {
await service.changeVisibility(PICTURE_SERVICE_TESTING_IMAGE_ID, "private")
const uploads = await service.get()
expect(uploads.pictures[0].images[0].visibility).toBe("private")
});
it('should edit image title', async () => {
const newTitle = faker.internet.displayName()
await service.editTitle(PICTURE_SERVICE_TESTING_IMAGE_ID, newTitle)
const uploads = await service.get()
expect(uploads.pictures[0].images[0].title).toBe(newTitle)
});
it('should post and get comment', async () => {
const comment = faker.lorem.sentence()
await service.postComment(PICTURE_SERVICE_TESTING_IMAGE_ID, comment)
const comments = await service.getComments(PICTURE_SERVICE_TESTING_IMAGE_ID)
expect(comments.length).not.toBe(0)
});
it('should fetch albums', async () => {
const albums = await service.getAlbums()
expect(albums[0].name).toBe("Album name")
});
})