| | import { beforeAll, describe, expect, test } from 'vitest' |
| |
|
| | import { get } from '@/tests/helpers/e2etest' |
| |
|
| | const makeURL = (pathname: string, apiVersion?: string): string => { |
| | const params = new URLSearchParams({ pathname }) |
| | if (apiVersion) { |
| | params.set('apiVersion', apiVersion) |
| | } |
| | return `/api/article/body?${params}` |
| | } |
| |
|
| | describe('REST transformer', () => { |
| | beforeAll(() => { |
| | if (!process.env.ROOT) { |
| | console.warn( |
| | 'WARNING: The REST transformer tests require the ROOT environment variable to be set to the fixture root', |
| | ) |
| | } |
| | }) |
| |
|
| | test('REST page renders with markdown structure', async () => { |
| | const res = await get(makeURL('/en/rest/actions/artifacts')) |
| | expect(res.statusCode).toBe(200) |
| | expect(res.headers['content-type']).toContain('text/markdown') |
| |
|
| | |
| | expect(res.body).toContain('# GitHub Actions Artifacts') |
| |
|
| | |
| | expect(res.body).toContain('Use the REST API to interact with artifacts in HubGit Actions.') |
| |
|
| | |
| | expect(res.body).toContain('## About artifacts in HubGit Actions') |
| | }) |
| |
|
| | test('REST operations are formatted correctly', async () => { |
| | const res = await get(makeURL('/en/rest/actions/artifacts')) |
| | expect(res.statusCode).toBe(200) |
| |
|
| | |
| | expect(res.body).toContain('## List artifacts for a repository') |
| |
|
| | |
| | expect(res.body).toContain('GET /repos/{owner}/{repo}/actions/artifacts') |
| |
|
| | |
| | expect(res.body).toContain('Lists all artifacts for a repository.') |
| | }) |
| |
|
| | test('Parameters section includes headers', async () => { |
| | const res = await get(makeURL('/en/rest/actions/artifacts')) |
| | expect(res.statusCode).toBe(200) |
| |
|
| | |
| | expect(res.body).toContain('### Parameters') |
| |
|
| | |
| | expect(res.body).toContain('#### Headers') |
| |
|
| | |
| | expect(res.body).toContain('**`accept`** (string)') |
| | expect(res.body).toContain('Setting to `application/vnd.github+json` is recommended.') |
| | }) |
| |
|
| | test('Path and query parameters are listed', async () => { |
| | const res = await get(makeURL('/en/rest/actions/artifacts')) |
| | expect(res.statusCode).toBe(200) |
| |
|
| | |
| | expect(res.body).toContain('#### Path and query parameters') |
| |
|
| | |
| | expect(res.body).toContain('**`owner`** (string) (required)') |
| | expect(res.body).toContain('The account owner of the repository.') |
| |
|
| | expect(res.body).toContain('**`repo`** (string) (required)') |
| |
|
| | expect(res.body).toContain('**`per_page`** (integer)') |
| | expect(res.body).toContain('Default: `30`') |
| | }) |
| |
|
| | test('Status codes are formatted correctly', async () => { |
| | const res = await get(makeURL('/en/rest/actions/artifacts')) |
| | expect(res.statusCode).toBe(200) |
| |
|
| | |
| | expect(res.body).toContain('### HTTP response status codes') |
| |
|
| | |
| | expect(res.body).toContain('**200**') |
| | expect(res.body).toContain('OK') |
| | }) |
| |
|
| | test('Code examples include curl with proper formatting', async () => { |
| | const res = await get(makeURL('/en/rest/actions/artifacts')) |
| | expect(res.statusCode).toBe(200) |
| |
|
| | |
| | expect(res.body).toContain('### Code examples') |
| |
|
| | |
| | expect(res.body).toContain('**Request:**') |
| | expect(res.body).toContain('**Response schema:**') |
| |
|
| | |
| | expect(res.body).toContain('```curl') |
| | expect(res.body).toContain('curl -L \\') |
| | expect(res.body).toContain('-X GET \\') |
| | expect(res.body).toContain('https://api.github.com/repos/OWNER/REPO/actions/artifacts \\') |
| | expect(res.body).toContain('-H "Accept: application/vnd.github.v3+json" \\') |
| | expect(res.body).toContain('-H "Authorization: Bearer <YOUR-TOKEN>"') |
| | }) |
| |
|
| | test('Code examples include X-GitHub-Api-Version header by default', async () => { |
| | const res = await get(makeURL('/en/rest/actions/artifacts')) |
| | expect(res.statusCode).toBe(200) |
| |
|
| | |
| | expect(res.body).toContain('-H "X-GitHub-Api-Version: 2022-11-28"') |
| | }) |
| |
|
| | test('Code examples include specified API version', async () => { |
| | const res = await get(makeURL('/en/rest/actions/artifacts', '2022-11-28')) |
| | expect(res.statusCode).toBe(200) |
| |
|
| | |
| | expect(res.body).toContain('-H "X-GitHub-Api-Version: 2022-11-28"') |
| | }) |
| |
|
| | test('Liquid tags are rendered in intro', async () => { |
| | const res = await get(makeURL('/en/rest/actions/artifacts')) |
| | expect(res.statusCode).toBe(200) |
| |
|
| | |
| | expect(res.body).toContain('HubGit Actions') |
| | expect(res.body).not.toContain('{% data variables.product.prodname_actions %}') |
| |
|
| | |
| | expect(res.body).toMatch(/Use the REST API to interact with artifacts in HubGit Actions/) |
| | expect(res.body).toMatch(/About artifacts in HubGit Actions/) |
| | }) |
| |
|
| | test('AUTOTITLE links are resolved', async () => { |
| | const res = await get(makeURL('/en/rest/actions/artifacts')) |
| | expect(res.statusCode).toBe(200) |
| |
|
| | |
| | |
| | expect(res.body).toContain('[Storing workflow data as artifacts]') |
| | expect(res.body).toContain('(/en/actions/using-workflows/storing-workflow-data-as-artifacts)') |
| |
|
| | |
| | expect(res.body).not.toContain('[AUTOTITLE]') |
| |
|
| | |
| | expect(res.body).toMatch( |
| | /About artifacts in HubGit Actions[\s\S]*Storing workflow data as artifacts/, |
| | ) |
| | }) |
| |
|
| | test('Markdown links are preserved in descriptions', async () => { |
| | const res = await get(makeURL('/en/rest/actions/artifacts')) |
| | expect(res.statusCode).toBe(200) |
| |
|
| | |
| | expect(res.body).toMatch(/\[.*?\]\(\/en\/.*?\)/) |
| | }) |
| |
|
| | test('Response schema is formatted correctly', async () => { |
| | const res = await get(makeURL('/en/rest/actions/artifacts')) |
| | expect(res.statusCode).toBe(200) |
| |
|
| | |
| | expect(res.body).toContain('**Response schema:**') |
| | expect(res.body).toContain('```json') |
| | expect(res.body).toContain('Status: 200') |
| |
|
| | |
| | expect(res.body).toContain('"type":') |
| | expect(res.body).toContain('"properties":') |
| |
|
| | |
| | const schemaMatch = res.body.match(/```json\s+Status: 200\s+([\s\S]*?)```/) |
| | expect(schemaMatch).toBeTruthy() |
| |
|
| | if (schemaMatch) { |
| | const schemaContent = schemaMatch[1] |
| | const schema = JSON.parse(schemaContent) |
| |
|
| | |
| | expect(schema).toHaveProperty('type') |
| | expect(schema.type).toBe('object') |
| | expect(schema).toHaveProperty('properties') |
| |
|
| | |
| | expect(schema.properties).toHaveProperty('total_count') |
| | expect(schema.properties).toHaveProperty('artifacts') |
| | } |
| | }) |
| |
|
| | test('Non-REST pages return appropriate error', async () => { |
| | const res = await get(makeURL('/en/get-started/start-your-journey/hello-world')) |
| | expect(res.statusCode).toBe(200) |
| |
|
| | |
| | expect(res.body).toContain('## Introduction') |
| | }) |
| |
|
| | test('Invalid apiVersion returns 400 error', async () => { |
| | |
| | const res = await get(makeURL('/en/rest/actions/artifacts', 'invalid-version')) |
| |
|
| | |
| | expect(res.statusCode).toBe(400) |
| | const parsed = JSON.parse(res.body) |
| | expect(parsed.error).toContain("Invalid apiVersion 'invalid-version'") |
| | expect(parsed.error).toContain('Valid API versions are:') |
| | expect(parsed.error).toContain('2022-11-28') |
| | }) |
| |
|
| | test('Multiple apiVersion query parameters returns 400 error', async () => { |
| | |
| | const res = await get( |
| | '/api/article/body?pathname=/en/rest/actions/artifacts&apiVersion=2022-11-28&apiVersion=2023-01-01', |
| | ) |
| |
|
| | expect(res.statusCode).toBe(400) |
| | const parsed = JSON.parse(res.body) |
| | expect(parsed.error).toBe("Multiple 'apiVersion' keys") |
| | }) |
| |
|
| | test('Valid apiVersion passes validation', async () => { |
| | |
| | const res = await get(makeURL('/en/rest/actions/artifacts', '2022-11-28')) |
| |
|
| | expect(res.statusCode).toBe(200) |
| | expect(res.body).toContain('-H "X-GitHub-Api-Version: 2022-11-28"') |
| | }) |
| |
|
| | test('Missing apiVersion defaults to latest', async () => { |
| | |
| | const res = await get(makeURL('/en/rest/actions/artifacts')) |
| |
|
| | expect(res.statusCode).toBe(200) |
| | |
| | expect(res.body).toContain('-H "X-GitHub-Api-Version: 2022-11-28"') |
| | }) |
| |
|
| | test('Multiple operations on a page are all rendered', async () => { |
| | const res = await get(makeURL('/en/rest/actions/artifacts')) |
| | expect(res.statusCode).toBe(200) |
| |
|
| | |
| | expect(res.body).toContain('## List artifacts for a repository') |
| | expect(res.body).toContain('## Get an artifact') |
| | expect(res.body).toContain('## Delete an artifact') |
| | }) |
| |
|
| | test('Body parameters are formatted correctly for POST/PUT operations', async () => { |
| | const res = await get(makeURL('/en/rest/actions/artifacts')) |
| | expect(res.statusCode).toBe(200) |
| |
|
| | |
| | |
| | |
| | }) |
| |
|
| | test('Content-type header is included for operations that need it', async () => { |
| | const res = await get(makeURL('/en/rest/actions/artifacts')) |
| | expect(res.statusCode).toBe(200) |
| |
|
| | |
| | |
| | }) |
| |
|
| | test('Non-English language paths work correctly', async () => { |
| | |
| | |
| | const res = await get(makeURL('/ja/rest/actions/artifacts')) |
| | expect(res.statusCode).toBe(200) |
| |
|
| | |
| | |
| | |
| |
|
| | |
| | expect(res.body).toContain('## List artifacts for a repository') |
| | expect(res.body).toContain('GET /repos/{owner}/{repo}/actions/artifacts') |
| |
|
| | |
| | |
| | |
| | const hasJapaneseTitle = res.body.includes('# GitHub Actions アーティファクト') |
| | const hasEnglishTitle = res.body.includes('# GitHub Actions Artifacts') |
| |
|
| | |
| | expect(hasJapaneseTitle || hasEnglishTitle).toBe(true) |
| |
|
| | |
| | if (hasJapaneseTitle) { |
| | |
| | expect(res.body).toContain('アーティファクト') |
| | } else { |
| | |
| | expect(res.body).toContain('Use the REST API to interact with artifacts in HubGit Actions') |
| | } |
| | }) |
| | }) |
| |
|