Skip to content

Commit

Permalink
feat(experimentalIdentityAndAuth): add @httpApiKeyAuth integration …
Browse files Browse the repository at this point in the history
…tests
  • Loading branch information
Steven Yuan authored and syall committed Oct 11, 2023
1 parent 3d5da26 commit 940aad5
Show file tree
Hide file tree
Showing 5 changed files with 279 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changeset/little-doors-live.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@smithy/experimental-identity-and-auth": patch
---

Add `@httpApiKeyAuth` integration tests.
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
import {
HttpApiKeyAuthServiceClient,
OnlyHttpApiKeyAuthCommand,
OnlyHttpApiKeyAuthOptionalCommand,
SameAsServiceCommand,
} from "@smithy/identity-and-auth-http-api-key-auth-service";
import { requireRequestsFrom } from "@smithy/util-test";

describe("@httpApiKeyAuth integration tests", () => {
// TODO(experimentalIdentityAndAuth): should match `HttpApiKeyAuthService` `@httpApiKeyAuth` trait
const MOCK_API_KEY_NAME = "Authorization";
const MOCK_API_KEY_SCHEME = "ApiKey";
const MOCK_API_KEY = "APIKEY_123";

// Arbitrary mock endpoint (`requireRequestsFrom()` intercepts network requests)
const MOCK_ENDPOINT = "https://foo.bar";

describe("Operation requires `@httpApiKeyAuth`", () => {
it("Request is thrown when `apiKey` is not configured", async () => {
const client = new HttpApiKeyAuthServiceClient({
endpoint: MOCK_ENDPOINT,
});
requireRequestsFrom(client).toMatch({});
await expect(client.send(new OnlyHttpApiKeyAuthCommand({}))).rejects.toThrow(
"HttpAuthScheme `smithy.api#httpApiKeyAuth` did not have an IdentityProvider configured."
);
});

it("Request is thrown when `apiKey` is configured incorrectly", async () => {
const client = new HttpApiKeyAuthServiceClient({
endpoint: MOCK_ENDPOINT,
apiKey: {} as any,
});
requireRequestsFrom(client).toMatch({});
await expect(client.send(new OnlyHttpApiKeyAuthCommand({}))).rejects.toThrow(
"request could not be signed with `apiKey` since the `apiKey` is not defined"
);
});

it("Request is thrown given configured `apiKey` identity provider throws", async () => {
const client = new HttpApiKeyAuthServiceClient({
endpoint: MOCK_ENDPOINT,
apiKey: async () => {
throw new Error("IdentityProvider throws this error");
},
});
requireRequestsFrom(client).toMatch({});
await expect(client.send(new OnlyHttpApiKeyAuthCommand({}))).rejects.toThrow(
"IdentityProvider throws this error"
);
});

it("Request is signed given configured `apiKey` identity provider", async () => {
const client = new HttpApiKeyAuthServiceClient({
endpoint: MOCK_ENDPOINT,
apiKey: async () => ({
apiKey: MOCK_API_KEY,
}),
});
requireRequestsFrom(client).toMatch({
headers: {
[MOCK_API_KEY_NAME]: `${MOCK_API_KEY_SCHEME} ${MOCK_API_KEY}`,
},
});
await client.send(new OnlyHttpApiKeyAuthCommand({}));
});

it("Request is signed given configured `apiKey` identity", async () => {
const client = new HttpApiKeyAuthServiceClient({
endpoint: MOCK_ENDPOINT,
apiKey: {
apiKey: MOCK_API_KEY,
},
});
requireRequestsFrom(client).toMatch({
headers: {
[MOCK_API_KEY_NAME]: `${MOCK_API_KEY_SCHEME} ${MOCK_API_KEY}`,
},
});
await client.send(new OnlyHttpApiKeyAuthCommand({}));
});
});

describe("Operation has `@httpApiKeyAuth` and `@optionalAuth`", () => {
it("Request is NOT thrown and NOT signed when `apiKey` is not configured", async () => {
const client = new HttpApiKeyAuthServiceClient({
endpoint: MOCK_ENDPOINT,
});
requireRequestsFrom(client).toMatch({
headers: {
[MOCK_API_KEY_NAME]: (value) => expect(value).toBeUndefined(),
},
});
await client.send(new OnlyHttpApiKeyAuthOptionalCommand({}));
});

it("Request is thrown when `apiKey` is configured incorrectly", async () => {
const client = new HttpApiKeyAuthServiceClient({
endpoint: MOCK_ENDPOINT,
apiKey: {} as any,
});
requireRequestsFrom(client).toMatch({});
await expect(client.send(new OnlyHttpApiKeyAuthOptionalCommand({}))).rejects.toThrow(
"request could not be signed with `apiKey` since the `apiKey` is not defined"
);
});

it("Request is thrown given configured `apiKey` identity provider throws", async () => {
const client = new HttpApiKeyAuthServiceClient({
endpoint: MOCK_ENDPOINT,
apiKey: async () => {
throw new Error("IdentityProvider throws this error");
},
});
requireRequestsFrom(client).toMatch({});
await expect(client.send(new OnlyHttpApiKeyAuthOptionalCommand({}))).rejects.toThrow(
"IdentityProvider throws this error"
);
});

it("Request is signed given configured `apiKey` identity provider", async () => {
const client = new HttpApiKeyAuthServiceClient({
endpoint: MOCK_ENDPOINT,
apiKey: async () => ({
apiKey: MOCK_API_KEY,
}),
});
requireRequestsFrom(client).toMatch({
headers: {
[MOCK_API_KEY_NAME]: `${MOCK_API_KEY_SCHEME} ${MOCK_API_KEY}`,
},
});
await client.send(new OnlyHttpApiKeyAuthOptionalCommand({}));
});

it("Request is signed given configured `apiKey` identity", async () => {
const client = new HttpApiKeyAuthServiceClient({
endpoint: MOCK_ENDPOINT,
apiKey: {
apiKey: MOCK_API_KEY,
},
});
requireRequestsFrom(client).toMatch({
headers: {
[MOCK_API_KEY_NAME]: `${MOCK_API_KEY_SCHEME} ${MOCK_API_KEY}`,
},
});
await client.send(new OnlyHttpApiKeyAuthOptionalCommand({}));
});
});

describe("Service has `@httpApiKeyAuth`", () => {
it("Request is thrown when `apiKey` is not configured", async () => {
const client = new HttpApiKeyAuthServiceClient({
endpoint: MOCK_ENDPOINT,
});
requireRequestsFrom(client).toMatch({});
await expect(client.send(new SameAsServiceCommand({}))).rejects.toThrow(
"HttpAuthScheme `smithy.api#httpApiKeyAuth` did not have an IdentityProvider configured."
);
});

it("Request is thrown when `apiKey` is configured incorrectly", async () => {
const client = new HttpApiKeyAuthServiceClient({
endpoint: MOCK_ENDPOINT,
apiKey: {} as any,
});
requireRequestsFrom(client).toMatch({});
await expect(client.send(new SameAsServiceCommand({}))).rejects.toThrow(
"request could not be signed with `apiKey` since the `apiKey` is not defined"
);
});

it("Request is thrown given configured `apiKey` identity provider throws", async () => {
const client = new HttpApiKeyAuthServiceClient({
endpoint: MOCK_ENDPOINT,
apiKey: async () => {
throw new Error("IdentityProvider throws this error");
},
});
requireRequestsFrom(client).toMatch({});
await expect(client.send(new SameAsServiceCommand({}))).rejects.toThrow("IdentityProvider throws this error");
});

it("Request is signed given configured `apiKey` identity provider", async () => {
const client = new HttpApiKeyAuthServiceClient({
endpoint: MOCK_ENDPOINT,
apiKey: async () => ({
apiKey: MOCK_API_KEY,
}),
});
requireRequestsFrom(client).toMatch({
headers: {
[MOCK_API_KEY_NAME]: `${MOCK_API_KEY_SCHEME} ${MOCK_API_KEY}`,
},
});
await client.send(new SameAsServiceCommand({}));
});

it("Request is signed given configured `apiKey` identity", async () => {
const client = new HttpApiKeyAuthServiceClient({
endpoint: MOCK_ENDPOINT,
apiKey: {
apiKey: MOCK_API_KEY,
},
});
requireRequestsFrom(client).toMatch({
headers: {
[MOCK_API_KEY_NAME]: `${MOCK_API_KEY_SCHEME} ${MOCK_API_KEY}`,
},
});
await client.send(new SameAsServiceCommand({}));
});
});
});
9 changes: 9 additions & 0 deletions scripts/build-generated-test-packages.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ const weatherSsdkDir = path.join(
"typescript-ssdk-codegen"
)

// TODO(experimentalIdentityAndAuth): add `@httpApiKeyAuth` client for integration tests
const httpApiKeyAuthClientDir = path.join(
codegenTestDir,
"identity-and-auth-http-api-key-auth",
"typescript-codegen"
);

const nodeModulesDir = path.join(root, "node_modules");

const buildAndCopyToNodeModules = async (packageName, codegenDir, nodeModulesDir) => {
Expand All @@ -61,6 +68,8 @@ const buildAndCopyToNodeModules = async (packageName, codegenDir, nodeModulesDir
await buildAndCopyToNodeModules("weather-ssdk", weatherSsdkDir, nodeModulesDir);
// TODO(experimentalIdentityAndAuth): build generic client for integration tests
await buildAndCopyToNodeModules("@smithy/weather-experimental-identity-and-auth", weatherExperimentalIdentityAndAuthClientDir, nodeModulesDir);
// TODO(experimentalIdentityAndAuth): add `@httpApiKeyAuth` client for integration tests
await buildAndCopyToNodeModules("@smithy/identity-and-auth-http-api-key-auth-service", httpApiKeyAuthClientDir, nodeModulesDir);
} catch (e) {
console.log(e);
process.exit(1);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
$version: "2.0"

namespace identity.auth.httpApiKeyAuth

use common#fakeProtocol

@fakeProtocol
@httpApiKeyAuth(scheme: "ApiKey", name: "Authorization", in: "header")
service HttpApiKeyAuthService {
operations: [
OnlyHttpApiKeyAuth
OnlyHttpApiKeyAuthOptional
SameAsService
]
}

@http(method: "GET", uri: "/OnlyHttpApiKeyAuth")
@auth([httpApiKeyAuth])
operation OnlyHttpApiKeyAuth {}

@http(method: "GET", uri: "/OnlyHttpApiKeyAuthOptional")
@auth([httpApiKeyAuth])
@optionalAuth
operation OnlyHttpApiKeyAuthOptional {}

@http(method: "GET", uri: "/SameAsService")
operation SameAsService {}
23 changes: 23 additions & 0 deletions smithy-typescript-codegen-test/smithy-build.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,29 @@
}
}
}
},
"identity-and-auth-http-api-key-auth": {
"transforms": [
{
"name": "includeServices",
"args": {
"services": ["identity.auth.httpApiKeyAuth#HttpApiKeyAuthService"]
}
}
],
"plugins": {
"typescript-codegen": {
"service": "identity.auth.httpApiKeyAuth#HttpApiKeyAuthService",
"targetNamespace": "HttpApiKeyAuthService",
"package": "@smithy/identity-and-auth-http-api-key-auth-service",
"packageVersion": "0.0.1",
"packageJson": {
"license": "Apache-2.0",
"private": true
},
"experimentalIdentityAndAuth": true
}
}
}
},
"plugins": {
Expand Down

0 comments on commit 940aad5

Please sign in to comment.