diff --git a/AGENTS.md b/AGENTS.md index 740c330..d6b1091 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -15,6 +15,12 @@ HTTP API, протокол HTTP, Postman, js-playwright, курсы Selenium и Код обработчиков курсы делят свободно, свой у каждого курса только адрес. +### Навигация + +Курс с префиксом получает страницу по самому префиксу (`/http-protocol`, `/http-for-automation`) и строку на главной `/`. Страница ведёт на опыты, которые открываются из браузера, то есть на GET-маршруты курса. HTML лежит в `custom-server/assets/<префикс>/index.html`, маршрут регистрируется в `custom-server/src/index.ts` рядом с остальными страницами. + +`test/app.test.ts` проверяет, что ссылки главной и страниц курсов не отдают 404. Страница нового курса добавляется в этот список. `/http-protocol` в нём нет, потому что `/http-protocol/stream` отдаёт пять чанков с паузой в секунду и не укладывается в пятисекундный таймаут vitest. + ## Как собран сервер Четыре спецификации на TypeSpec (`typespec//`) компилируются в OpenAPI diff --git a/custom-server/assets/http-for-automation/index.html b/custom-server/assets/http-for-automation/index.html new file mode 100644 index 0000000..da89f28 --- /dev/null +++ b/custom-server/assets/http-for-automation/index.html @@ -0,0 +1,18 @@ + + + + + + Example + + +

It works!

+ + + diff --git a/custom-server/assets/main/index.html b/custom-server/assets/main/index.html index ccebe28..0185952 100644 --- a/custom-server/assets/main/index.html +++ b/custom-server/assets/main/index.html @@ -11,6 +11,7 @@

It works!

  • HTTP API
  • HTTP Protocol
  • HTTP Form
  • +
  • HTTP for Automation
  • JS Playwright
  • Postman
  • diff --git a/custom-server/src/index.ts b/custom-server/src/index.ts index 9f42add..76f2881 100644 --- a/custom-server/src/index.ts +++ b/custom-server/src/index.ts @@ -173,6 +173,8 @@ export default async (app: FastifyInstance, _options: unknown) => { app.get('/http-protocol', (req, res) => res.sendFile('http-protocol/index.html')); + app.get('/http-for-automation', (req, res) => res.sendFile('http-for-automation/index.html')); + app.get('/http-protocol/removed', (req, res) => res.code(301).redirect('/http-protocol/example')); app.get('/js-playwright/users-list', (req, res) => res.sendFile('users-list/index.html')); diff --git a/test/app.test.ts b/test/app.test.ts index a064f59..3255c04 100644 --- a/test/app.test.ts +++ b/test/app.test.ts @@ -34,6 +34,15 @@ describe('документация и статика', () => { expect((await client.send('/')).status).toBe(200); }); + it.each(['/', '/http-for-automation'])('ссылки со страницы %s живые', async (page) => { + const html = String((await client.send(page)).body); + const links = [...html.matchAll(/href="([^"]+)"/g)].map((match) => match[1]); + expect(links.length).toBeGreaterThan(0); + for (const link of links) { + expect({ link, status: (await client.send(link)).status }).not.toEqual({ link, status: 404 }); + } + }); + it('несуществующий адрес → 404 с кодом в теле', async () => { const reply = await client.send('/nosuch'); expect(reply.status).toBe(404);