diff --git a/.chronus/changes/specs-xmlNextLinkPaging-2026-1-23-16-47-56.md b/.chronus/changes/specs-xmlNextLinkPaging-2026-1-23-16-47-56.md new file mode 100644 index 00000000000..00a0b7262f1 --- /dev/null +++ b/.chronus/changes/specs-xmlNextLinkPaging-2026-1-23-16-47-56.md @@ -0,0 +1,7 @@ +--- +changeKind: feature +packages: + - "@typespec/http-specs" +--- + +Add test for xml pagination with next link diff --git a/.chronus/changes/specs-xmlPaging-2026-0-23-15-43-39.md b/.chronus/changes/specs-xmlPaging-2026-0-23-15-43-39.md new file mode 100644 index 00000000000..d318db5c1ef --- /dev/null +++ b/.chronus/changes/specs-xmlPaging-2026-0-23-15-43-39.md @@ -0,0 +1,7 @@ +--- +changeKind: feature +packages: + - "@typespec/http-specs" +--- + +Add test for xml paging \ No newline at end of file diff --git a/packages/http-specs/spec-summary.md b/packages/http-specs/spec-summary.md index af295728cc2..0ddeea65523 100644 --- a/packages/http-specs/spec-summary.md +++ b/packages/http-specs/spec-summary.md @@ -2835,6 +2835,104 @@ Two requests need to be tested. } ``` +### Payload_Pageable_XmlPagination_listWithContinuation + +- Endpoint: `get /payload/pageable/xml/list-with-continuation` + +Test case for XML pagination with continuation token. Continuation token is passed in the request query and response body. + +Two requests need to be tested. + +1. Initial request: + Expected route: /payload/pageable/xml/list + +Expected response body: + +```xml + + + + 1 + dog + + + 2 + cat + + + page2 + +``` + +2. Next page request: + Expected route: /payload/pageable/xml/list?marker=page2 + +Expected response body: + +```xml + + + + 3 + bird + + + 4 + fish + + + +``` + +### Payload_Pageable_XmlPagination_listWithNextLink + +- Endpoint: `get /payload/pageable/xml/list-with-next-link` + +Test case for XML pagination with next link. + +Two requests need to be tested. + +1. Initial request: + Expected route: /payload/pageable/xml/list-with-next-link + +Expected response body: + +```xml + + + + 1 + dog + + + 2 + cat + + + http://[host]:[port]/payload/pageable/xml/list-with-next-link/nextPage + +``` + +2. Next page request: + Expected route: /payload/pageable/xml/list-with-next-link/nextPage + +Expected response body: + +```xml + + + + 3 + bird + + + 4 + fish + + + +``` + ### Payload_Xml_ModelWithArrayOfModelValue_get - Endpoint: `get /payload/xml/modelWithArrayOfModel` diff --git a/packages/http-specs/specs/payload/pageable/main.tsp b/packages/http-specs/specs/payload/pageable/main.tsp index 63f7d30e4ee..a717076947e 100644 --- a/packages/http-specs/specs/payload/pageable/main.tsp +++ b/packages/http-specs/specs/payload/pageable/main.tsp @@ -1,8 +1,10 @@ import "@typespec/http"; import "@typespec/spector"; +import "@typespec/xml"; using Http; using Spector; +using Xml; /** * Test for pageable payload. @@ -514,3 +516,141 @@ namespace PageSize { pets: Pet[]; }; } + +@doc("An XML pet item.") +@name("Pet") +model XmlPet { + @name("Id") id: string; + @name("Name") name: string; +} + +@route("/xml") +namespace XmlPagination { + @scenario + @scenarioDoc(""" + Test case for XML pagination with continuation token. Continuation token is passed in the request query and response body. + + Two requests need to be tested. + + 1. Initial request: + Expected route: /payload/pageable/xml/list + + Expected response body: + ```xml + + + + 1 + dog + + + 2 + cat + + + page2 + + ``` + + 2. Next page request: + Expected route: /payload/pageable/xml/list?marker=page2 + + Expected response body: + ```xml + + + + 3 + bird + + + 4 + fish + + + + ``` + """) + @route("/list-with-continuation") + @list + op listWithContinuation(@continuationToken @query marker?: string): { + @header("content-type") contentType: "application/xml"; + @body body: XmlPetListResult; + }; + + @scenario + @scenarioDoc(""" + Test case for XML pagination with next link. + + Two requests need to be tested. + + 1. Initial request: + Expected route: /payload/pageable/xml/list-with-next-link + + Expected response body: + ```xml + + + + 1 + dog + + + 2 + cat + + + http://[host]:[port]/payload/pageable/xml/list-with-next-link/nextPage + + ``` + + 2. Next page request: + Expected route: /payload/pageable/xml/list-with-next-link/nextPage + + Expected response body: + ```xml + + + + 3 + bird + + + 4 + fish + + + + ``` + """) + @route("/list-with-next-link") + @list + op listWithNextLink(): { + @header("content-type") contentType: "application/xml"; + @body body: XmlPetListResultWithNextLink; + }; +} + +@doc("The XML response for listing pets.") +@name("PetListResult") +model XmlPetListResult { + @pageItems + @name("Pets") + pets: XmlPet[]; + + @continuationToken + @name("NextMarker") + nextMarker?: string; +} + +@doc("The XML response for listing pets with next link.") +@name("PetListResult") +model XmlPetListResultWithNextLink { + @pageItems + @name("Pets") + pets: XmlPet[]; + + @nextLink + @name("NextLink") + nextLink?: url; +} diff --git a/packages/http-specs/specs/payload/pageable/mockapi.ts b/packages/http-specs/specs/payload/pageable/mockapi.ts index 565bfde9ace..3fdbf8c794e 100644 --- a/packages/http-specs/specs/payload/pageable/mockapi.ts +++ b/packages/http-specs/specs/payload/pageable/mockapi.ts @@ -6,6 +6,7 @@ import { passOnSuccess, ScenarioMockApi, ValidationError, + xml, } from "@typespec/spec-api"; export const Scenarios: Record = {}; @@ -511,3 +512,180 @@ Scenarios.Payload_Pageable_ServerDrivenPagination_ContinuationToken_requestHeade kind: "MockApiDefinition", }, ]); + +const XmlContTokenFirstPage = ` + + + + 1 + dog + + + 2 + cat + + + page2 + +`; + +const XmlContTokenSecondPage = ` + + + + 3 + bird + + + 4 + fish + + + +`; + +Scenarios.Payload_Pageable_XmlPagination_listWithContinuation = passOnSuccess([ + { + uri: "/payload/pageable/xml/list-with-continuation", + method: "get", + request: {}, + response: { + status: 200, + body: xml(XmlContTokenFirstPage), + headers: { + "content-type": "application/xml", + }, + }, + handler: (req: MockRequest) => { + const marker = req.query?.marker; + + switch (marker) { + case undefined: + return { + status: 200, + body: xml(XmlContTokenFirstPage), + headers: { + "content-type": "application/xml", + }, + }; + case "page2": + return { + status: 200, + body: xml(XmlContTokenSecondPage), + headers: { + "content-type": "application/xml", + }, + }; + default: + throw new ValidationError("Unsupported marker", `"undefined" | "page2"`, marker); + } + }, + kind: "MockApiDefinition", + }, + { + uri: "/payload/pageable/xml/list-with-continuation", + method: "get", + request: { query: { marker: "page2" } }, + response: { + status: 200, + body: xml(XmlContTokenSecondPage), + headers: { + "content-type": "application/xml", + }, + }, + handler: (req: MockRequest) => { + const marker = req.query?.marker; + + switch (marker) { + case undefined: + return { + status: 200, + body: xml(XmlContTokenFirstPage), + headers: { + "content-type": "application/xml", + }, + }; + case "page2": + return { + status: 200, + body: xml(XmlContTokenSecondPage), + headers: { + "content-type": "application/xml", + }, + }; + default: + throw new ValidationError("Unsupported marker", `"undefined" | "page2"`, marker); + } + }, + kind: "MockApiDefinition", + }, +]); + +const xmlNextLinkFirstPage = (baseUrl: string) => ` + + + + 1 + dog + + + 2 + cat + + + ${baseUrl}/payload/pageable/xml/list-with-next-link/nextPage + +`; + +const XmlNextLinkSecondPage = ` + + + + 3 + bird + + + 4 + fish + + + +`; + +Scenarios.Payload_Pageable_XmlPagination_listWithNextLink = passOnSuccess([ + { + uri: "/payload/pageable/xml/list-with-next-link", + method: "get", + request: {}, + response: { + status: 200, + body: xml(xmlNextLinkFirstPage("PLACEHOLDER_BASE_URL")), + headers: { + "content-type": "application/xml", + }, + }, + handler: (req: MockRequest) => { + return { + status: 200, + body: xml(xmlNextLinkFirstPage(req.baseUrl)), + headers: { + "content-type": "application/xml", + }, + }; + }, + kind: "MockApiDefinition", + }, + { + uri: "/payload/pageable/xml/list-with-next-link/nextPage", + method: "get", + request: {}, + response: { + status: 200, + body: xml(XmlNextLinkSecondPage), + headers: { + "content-type": "application/xml", + }, + }, + kind: "MockApiDefinition", + }, +]);