feat(api): implement GET /wikipedia/pages/[id]
Some checks failed
Chromatic / chromatic (push) Successful in 2m33s
CI / ci (push) Failing after 1m27s
CI / commitlint (push) Successful in 13s

This commit is contained in:
Théo LUDWIG 2024-08-13 11:58:38 +01:00
parent 376c0fd041
commit 63862b19c0
Signed by: theoludwig
GPG Key ID: ADFE5A563D718F3B
10 changed files with 84 additions and 4 deletions

View File

@ -32,7 +32,8 @@
- [x] Init AdonisJS project - [x] Init AdonisJS project
- [x] Create Lucid models and migrations for Wikipedia Database Dump: `pages` and `internal_links` tables - [x] Create Lucid models and migrations for Wikipedia Database Dump: `pages` and `internal_links` tables
- [x] Implement `GET /wikipedia/pages?title=Node.js` to search a page by title (not necessarily with the title sanitized, search with input by user to check if page exists) - [x] Implement `GET /wikipedia/pages?title=Node.js` to search a page by title (not necessarily with the title sanitized, search with input by user to check if page exists)
- [ ] Implement `GET /wikipedia/pages/internal-links/paths?from=Node.js&to=Linux` to get all the possible paths between 2 pages with titles sanitized - [x] Implement `GET /wikipedia/pages/[id]` to get a page and all its internal links with the pageId
- [ ] Implement `GET /wikipedia/internal-links/paths?fromPageId=id&toPageId=id` to get all the possible paths between 2 pages
- [x] Setup tests with database + add coverage - [x] Setup tests with database + add coverage
- [x] Setup Health checks - [x] Setup Health checks
- [x] Setup Rate limiting - [x] Setup Rate limiting

View File

@ -1,3 +1,4 @@
import "#app/routes/get.js" import "#app/routes/get.js"
import "#app/routes/health/get.js" import "#app/routes/health/get.js"
import "#app/routes/wikipedia/index.js" import "#app/routes/wikipedia/pages/[id]/get.js"
import "#app/routes/wikipedia/pages/get.js"

View File

@ -1 +0,0 @@
import "#app/routes/wikipedia/pages/get.js"

View File

@ -0,0 +1,52 @@
import { PageFactory } from "#database/factories/page_factory.js"
import testUtils from "@adonisjs/core/services/test_utils"
import db from "@adonisjs/lucid/services/db"
import { test } from "@japa/runner"
test.group("GET /wikipedia/pages/[id]", (group) => {
group.each.setup(async () => {
return await testUtils.db().truncate()
})
test("should succeeds and get the page with the given id, and get all its internal links", async ({
client,
}) => {
// Arrange - Given
const page = await PageFactory.create()
const pages = await PageFactory.createMany(10)
const internalLinksPages = pages.slice(0, 5)
await Promise.all(
internalLinksPages.map(async (internalLinkPage) => {
await db.table("internal_links").insert({
from_page_id: page.id,
to_page_id: internalLinkPage.id,
})
}),
)
// Act - When
const response = await client.get(`/wikipedia/pages/${page.id}`)
// Assert - Then
response.assertStatus(200)
response.assertBody({
...page.toJSON(),
internalLinks: internalLinksPages.map((page) => {
return page.toJSON()
}),
})
})
test("should fails with a 404 status code when the page with the given id does not exist", async ({
client,
}) => {
// Arrange - Given
const page = await PageFactory.create()
// Act - When
const response = await client.get(`/wikipedia/pages/${page.id + 1}`)
// Assert - Then
response.assertStatus(404)
})
})

View File

@ -0,0 +1,24 @@
import Page from "#app/models/page.js"
import { throttle } from "#start/limiter.js"
import type { HttpContext } from "@adonisjs/core/http"
import router from "@adonisjs/core/services/router"
import vine from "@vinejs/vine"
const requestValidator = vine.compile(
vine.object({
params: vine.object({
id: vine.number().withoutDecimals().positive(),
}),
}),
)
class Controller {
public async handle(context: HttpContext): Promise<Page> {
const payload = await context.request.validateUsing(requestValidator)
const page = await Page.findOrFail(payload.params.id)
await page.load("internalLinks")
return page
}
}
router.get("/wikipedia/pages/:id", [Controller]).use(throttle)

View File

@ -7,7 +7,7 @@ const databaseConfig = defineConfig({
connection: app.inTest ? "sqlite" : "postgres", connection: app.inTest ? "sqlite" : "postgres",
connections: { connections: {
postgres: { postgres: {
debug: !app.inProduction, debug: app.inDev,
client: "pg", client: "pg",
connection: { connection: {
host: env.get("DATABASE_HOST"), host: env.get("DATABASE_HOST"),

View File

@ -8,4 +8,7 @@ export const PageFactory = factory
title: sanitizePageTitle(faker.commerce.productName()), title: sanitizePageTitle(faker.commerce.productName()),
} }
}) })
.relation("internalLinks", () => {
return []
})
.build() .build()