Compare commits

..

No commits in common. "87f4719fd168dc247c4faa19a1b770240bdb7e45" and "cda0b2485160d749e1a1a4e9a67452fd047a95ae" have entirely different histories.

8 changed files with 29 additions and 84 deletions

View File

@ -1,4 +1,5 @@
name: Unit Tests with docker compose name: Unit Tests with docker compose
run-name: ${{ gitea.actor }} is testing out Gitea Actions 🚀
on: [pull_request] on: [pull_request]
jobs: jobs:

View File

@ -8,20 +8,33 @@ WORKDIR /usr/src/app
# install dependencies into temp folder # install dependencies into temp folder
# this will cache them and speed up future builds # this will cache them and speed up future builds
FROM base AS install FROM base AS install
RUN mkdir -p /temp/dev
COPY package.json bun.lockb /temp/dev/
RUN cd /temp/dev && bun install
# install with --production (exclude devDependencies) # install with --production (exclude devDependencies)
RUN mkdir -p /temp/prod RUN mkdir -p /temp/prod
COPY package.json bun.lockb /temp/prod/ COPY package.json bun.lockb /temp/prod/
RUN cd /temp/prod && bun install --production RUN cd /temp/prod && bun install --production
# Copy production dependencies and source code into final image # copy node_modules from temp folder
# then copy all (non-ignored) project files into the image
FROM install AS prerelease
COPY --from=install /temp/dev/node_modules node_modules
COPY . .
# [optional] tests & build
# ENV NODE_ENV=production
# RUN bun test
# RUN bun run build
# copy production dependencies and source code into final image
FROM base AS release FROM base AS release
COPY --from=install /temp/prod/node_modules node_modules COPY --from=install /temp/prod/node_modules node_modules
COPY --from=install /usr/src/app/src ./src COPY --from=prerelease /usr/src/app/index.ts .
COPY --from=install /usr/src/app/package.json . COPY --from=prerelease /usr/src/app/package.json .
# run the app # run the app
USER bun USER bun
ENV NODE_ENV=production
EXPOSE 8080/tcp EXPOSE 8080/tcp
CMD ["bun", "run", "start"] CMD ["bun", "run", "start"]

View File

@ -1,33 +1,5 @@
# bot-api # bot-api
## Introduction
The function of the API is basically to access the images' metadata stored in the database.
## Usage
The API exposes some endpoints to interact with the database.
### GET `/images`
Allows to get a list of image documents.
#### Query params
- `limit`: an optional parameter, which accepts a non-negative integer that dictates the number of documents that the list will have. If its value is equal to `0`, or if this parameter is missing, the endpoint will return all the image documents in the database.
- `status`: an optional parameter, which accepts the values `consumed`, `available` and `unavailable`. It filters the documents that have only the `status` attribute equal to that indicated in the parameter's value. If the parameter is missing, no filter will be applied to the document.
#### Example
- `GET /images?limit=5&status=available`: will return 5 documents that have the `available` value in their `status` attribute.
### PUT `/images/<id>`
Modifies an existing image document. The request must provide a JSON-formatted body, with one or more valid document attributes. The existing document attributes will be replaced with the provided new ones.
#### Params
- `id`: the id of the document to be modified.
#### Example
- `PUT /images/61f7e48f0c651345677b7775` with body `{ "status": "consumed" }`: will modify the document referenced by the `id` param, changing their `status` value to `consumed`.
### POST `/images`
### POST `/login`
## Installation
To install dependencies: To install dependencies:
```bash ```bash

View File

@ -14,7 +14,6 @@ app.get("/", (_, res) => {
}); });
app.get("/images", imageController.getAllImages); app.get("/images", imageController.getAllImages);
app.get("/images/:id", imageController.getImageById);
app.post("/images", authControler.authorize, imageController.addImage); app.post("/images", authControler.authorize, imageController.addImage);
app.post("/login", authControler.login); app.post("/login", authControler.login);

View File

@ -3,23 +3,6 @@ import imageService from "../services/ImageService";
import mongoose, { mongo } from "mongoose"; import mongoose, { mongo } from "mongoose";
class ImageController { class ImageController {
async getImageById(req: Request, res: Response) {
try {
const image = await imageService.findById(req.params.id);
if (image) {
res.json({ image });
} else {
res.status(404).json({ error: "Image not found" });
}
} catch (error: any) {
if (error instanceof mongoose.Error.CastError) {
res.status(400).json({ error: "Invalid Id" });
} else {
res.status(500).json({ error: "Internal Server Error" });
}
}
}
async getAllImages(_: Request, res: Response): Promise<void> { async getAllImages(_: Request, res: Response): Promise<void> {
try { try {
const images = await imageService.findAll(); const images = await imageService.findAll();

View File

@ -3,10 +3,6 @@ import { startApp } from "./app";
await startApp(); await startApp();
// This try carch is to prevent hot reload from making the process die due to coliding entries
try { try {
// Not insert test data into production await populateDatabase();
if (process.env.NODE_ENV != "production"){
await populateDatabase();
}
} catch {} } catch {}

View File

@ -1,10 +1,6 @@
import imageModel, { Image } from "../models/ImageModel"; import imageModel, { Image } from "../models/ImageModel";
class ImageService { class ImageService {
async findById(id: string) {
const image = await imageModel.findOne({ _id: id });
return image;
}
async findAll(): Promise<Image[]> { async findAll(): Promise<Image[]> {
const allImages = await imageModel.find(); const allImages = await imageModel.find();
return allImages; return allImages;

View File

@ -1,4 +1,11 @@
import { afterEach, beforeAll, describe, expect, it, mock } from "bun:test"; import {
afterEach,
beforeAll,
describe,
expect,
it,
mock,
} from "bun:test";
import request, { Response } from "supertest"; import request, { Response } from "supertest";
import app, { startApp } from "../src/app"; import app, { startApp } from "../src/app";
import imageService from "../src/services/ImageService"; import imageService from "../src/services/ImageService";
@ -79,7 +86,8 @@ describe("GET /images works properly", async () => {
}, },
})); }));
const res = await request(app).get("/images"); const res = await request(app)
.get("/images");
expect(res.status).toBe(500); expect(res.status).toBe(500);
}); });
@ -177,26 +185,3 @@ describe("POST /images works properly", () => {
expect(res.status).toBe(400); expect(res.status).toBe(400);
}); });
}); });
describe("/images/:id works properly", () => {
it("should return 200 for existing ids", async () => {
const list = await request(app).get("/images");
const id = list.body.images[0]._id;
const res = await request(app).get(`/images/${id}`);
expect(res.status).toBe(200);
});
it("should return 404 for non-existing ids", async () => {
const list = await request(app).get("/images");
const id = "000000000000000000000000"; // this was the least posible to exist ID
if (!(id in list.body.images)) {
const res = await request(app).get(`/images/${id}`);
expect(res.status).toBe(404);
}
});
it("should return 400 for malformed ids", async () => {
const res = await request(app).get("/images/98439384");
expect(res.status).toBe(400);
});
});