Skip to content

Commit df93db6

Browse files
committed
test: add ep2 tests to integ suite
1 parent 680efe6 commit df93db6

File tree

2 files changed

+92
-8
lines changed

2 files changed

+92
-8
lines changed

Makefile

+6-2
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,12 @@ test-integration: build-s3-browser-bundle
2929
rm -rf ./clients/client-sso/node_modules/\@smithy # todo(yarn) incompatible redundant nesting.
3030
yarn g:vitest run -c vitest.config.integ.ts
3131
npx jest -c jest.config.integ.js
32-
make test-protocols;
33-
make test-types;
32+
make test-protocols
33+
make test-types
34+
make test-endpoints
35+
36+
test-endpoints:
37+
npx jest -c ./tests/endpoints-2.0/jest.config.js --bail
3438

3539
test-e2e: build-s3-browser-bundle
3640
yarn g:vitest run -c vitest.config.e2e.ts --retry=4

tests/endpoints-2.0/endpoints-integration.spec.ts

+86-6
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import { resolveParams } from "@smithy/middleware-endpoint";
2-
import { EndpointV2 } from "@smithy/types";
3-
import { resolveEndpoint, EndpointParams } from "@smithy/util-endpoints";
2+
import { EndpointV2, RelativeMiddlewareOptions } from "@smithy/types";
3+
import { EndpointParams, resolveEndpoint } from "@smithy/util-endpoints";
44
import { existsSync, readdirSync } from "fs";
55
import { join } from "path";
66

77
import { EndpointExpectation, ServiceModel, ServiceNamespace } from "./integration-test-types";
8+
import { HttpRequest } from "@smithy/protocol-http";
89

910
describe("client list", () => {
1011
const root = join(__dirname, "..", "..");
11-
const clientPackageNameList = readdirSync(join(root, "clients"));
12+
const clientPackageNameList = readdirSync(join(root, "clients")).filter((f) => f.startsWith("client-"));
1213

1314
it("should be at least 300 clients", () => {
1415
expect(clientPackageNameList.length).toBeGreaterThan(300);
@@ -37,6 +38,7 @@ describe("client list", () => {
3738
function runTestCases(service: ServiceModel, namespace: ServiceNamespace) {
3839
const serviceId = service.traits["aws.api#service"].serviceId;
3940
const testCases = service.traits["smithy.rules#endpointTests"]?.testCases;
41+
const Client: any = Object.entries(namespace).find(([k, v]) => k.endsWith("Client"))![1];
4042

4143
const ruleSet = service.traits["smithy.rules#endpointRuleSet"];
4244
const defaultEndpointResolver = (endpointParams: EndpointParams) => resolveEndpoint(ruleSet, { endpointParams });
@@ -46,14 +48,23 @@ function runTestCases(service: ServiceModel, namespace: ServiceNamespace) {
4648
const { documentation, params = {}, expect: expectation, operationInputs } = testCase;
4749
params.serviceId = serviceId;
4850

49-
it(documentation || "undocumented testcase", async () => {
51+
const test = Client.name === "DynamoDBClient" && "AccountId" in params ? it.skip : it;
52+
53+
test(documentation || "undocumented testcase", async () => {
5054
if ("endpoint" in expectation) {
5155
const { endpoint } = expectation;
5256
if (operationInputs) {
5357
for (const operationInput of operationInputs) {
5458
const { operationName, operationParams = {} } = operationInput;
55-
const command = namespace[`${operationName}Command`];
56-
const endpointParams = await resolveParams(operationParams, command, params);
59+
const Command = namespace[`${operationName}Command`];
60+
const endpointParams = await resolveParams(operationParams, Command, mapClientConfig(params));
61+
62+
// todo: Use an actual client for a more integrated test.
63+
// todo: This call returns an intercepted EndpointV2 object that can replace the one
64+
// todo: used below.
65+
void useClient;
66+
void [Client, params, Command, operationParams];
67+
5768
const observed = defaultEndpointResolver(endpointParams as EndpointParams);
5869
assertEndpointResolvedCorrectly(endpoint, observed);
5970
}
@@ -106,3 +117,72 @@ function assertEndpointResolvedCorrectly(expected: EndpointExpectation["endpoint
106117
expect(observed.properties?.authSchemes).toEqual(authSchemes);
107118
}
108119
}
120+
121+
/**
122+
* Makes a client operation return its EndpointV2 instead of making a request.
123+
*/
124+
const requestInterceptorMiddleware = (next: any, context: any) => async (args: any) => {
125+
const { request } = args;
126+
if (HttpRequest.isInstance(request)) {
127+
const endpoint = context.endpointV2;
128+
return {
129+
response: {
130+
statusCode: 200,
131+
},
132+
output: {
133+
...endpoint,
134+
url: {
135+
protocol: request.protocol,
136+
hostname: request.hostname,
137+
pathname: request.path,
138+
href: `${request.protocol}//${request.hostname}${request.path}`,
139+
} as URL,
140+
},
141+
} as {
142+
output: EndpointV2;
143+
};
144+
}
145+
throw new Error("Request must not continue beyond serialization step.");
146+
};
147+
const requestInterceptorMiddlewareOptions: RelativeMiddlewareOptions = {
148+
name: "requestInterceptorMiddleware",
149+
override: true,
150+
toMiddleware: "serializerMiddleware",
151+
relation: "after",
152+
};
153+
154+
const paramMap = {
155+
Region: "region",
156+
UseFIPS: "useFipsEndpoint",
157+
UseDualStack: "useDualstackEndpoint",
158+
ForcePathStyle: "forcePathStyle",
159+
Accelerate: "useAccelerateEndpoint",
160+
DisableMRAP: "disableMultiregionAccessPoints",
161+
DisableMultiRegionAccessPoints: "disableMultiregionAccessPoints",
162+
UseArnRegion: "useArnRegion",
163+
Endpoint: "endpoint",
164+
UseGlobalEndpoint: "useGlobalEndpoint",
165+
};
166+
167+
async function useClient(Client: any, Command: any, clientConfig: any, input: any): Promise<EndpointV2> {
168+
const client = new Client({
169+
...mapClientConfig(clientConfig),
170+
credentials: {
171+
accessKeyId: "ENDPOINTS_TEST",
172+
secretAccessKey: "ENDPOINTS_TEST",
173+
},
174+
});
175+
client.middlewareStack.addRelativeTo(requestInterceptorMiddleware, requestInterceptorMiddlewareOptions);
176+
const command = new Command(input);
177+
const observed: EndpointV2 = await client.send(command);
178+
return observed;
179+
}
180+
181+
function mapClientConfig(params: any) {
182+
return Object.entries(params).reduce((acc: any, cur: [string, any]) => {
183+
const [k, v] = cur;
184+
const key = paramMap[k as keyof typeof paramMap] ?? k;
185+
acc[key] = v;
186+
return acc;
187+
}, {} as any);
188+
}

0 commit comments

Comments
 (0)