563 lines
26 KiB
TypeScript
563 lines
26 KiB
TypeScript
import {describe, expect, test} from 'bun:test'
|
|
import {
|
|
CreateDeploymentCommand,
|
|
CreateResourceCommand,
|
|
CreateRestApiCommand,
|
|
DeleteMethodCommand,
|
|
DeleteRestApiCommand,
|
|
GetRestApiCommand,
|
|
GetRestApisCommand,
|
|
GetMethodCommand,
|
|
GetResourcesCommand,
|
|
GetStagesCommand,
|
|
PutIntegrationCommand,
|
|
PutIntegrationResponseCommand,
|
|
PutMethodCommand,
|
|
PutMethodResponseCommand,
|
|
TestInvokeMethodCommand,
|
|
type APIGatewayClient,
|
|
} from '@aws-sdk/client-api-gateway'
|
|
import {AddPermissionCommand, GetFunctionCommand, RemovePermissionCommand, type LambdaClient} from '@aws-sdk/client-lambda'
|
|
import {AwsApiGatewayAdapter} from './AwsApiGatewayAdapter'
|
|
|
|
function fakeClient(handler: (command: unknown) => unknown): APIGatewayClient {
|
|
return {
|
|
send: async (command: unknown) => handler(command),
|
|
} as unknown as APIGatewayClient
|
|
}
|
|
|
|
function fakeLambda(handler: (command: unknown) => unknown): LambdaClient {
|
|
return {
|
|
send: async (command: unknown) => handler(command),
|
|
} as unknown as LambdaClient
|
|
}
|
|
|
|
const orders = {
|
|
id: 'a1b2c3',
|
|
name: 'orders-api',
|
|
description: 'Orders REST API',
|
|
createdDate: new Date('2026-01-02T03:04:05.000Z'),
|
|
version: '1.0',
|
|
endpointConfiguration: {types: ['REGIONAL']},
|
|
rootResourceId: 'root123',
|
|
}
|
|
|
|
describe('AwsApiGatewayAdapter', () => {
|
|
test('lists every page and maps REST APIs to normalized resources', async () => {
|
|
const adapter = new AwsApiGatewayAdapter(fakeClient((command) => {
|
|
if (!(command instanceof GetRestApisCommand)) throw new Error('Unexpected command')
|
|
if (!command.input.position) return {items: [orders], position: 'next'}
|
|
return {items: [{...orders, id: 'd4e5f6', name: 'accounts-api'}]}
|
|
}))
|
|
|
|
const result = await adapter.list()
|
|
|
|
expect(result).toHaveLength(2)
|
|
expect(result[0]).toMatchObject({
|
|
id: 'a1b2c3',
|
|
name: 'orders-api',
|
|
cloud: 'aws',
|
|
service: 'apigateway',
|
|
type: 'rest-api',
|
|
region: null,
|
|
createdAt: '2026-01-02T03:04:05.000Z',
|
|
})
|
|
expect(result[0].metadata).toMatchObject({
|
|
apigatewayService: 'rest',
|
|
description: 'Orders REST API',
|
|
rootResourceId: 'root123',
|
|
})
|
|
})
|
|
|
|
test('filters APIs by search term', async () => {
|
|
const adapter = new AwsApiGatewayAdapter(fakeClient(() => ({
|
|
items: [orders, {...orders, id: 'd4e5f6', name: 'accounts-api'}],
|
|
})))
|
|
|
|
const result = await adapter.list({search: 'ORDERS'})
|
|
|
|
expect(result.map((resource) => resource.name)).toEqual(['orders-api'])
|
|
})
|
|
|
|
test('gets and maps one REST API', async () => {
|
|
const adapter = new AwsApiGatewayAdapter(fakeClient((command) => {
|
|
expect(command).toBeInstanceOf(GetRestApiCommand)
|
|
return orders
|
|
}))
|
|
|
|
const result = await adapter.get('a1b2c3')
|
|
|
|
expect(result?.id).toBe('a1b2c3')
|
|
expect(result?.metadata.rootResourceId).toBe('root123')
|
|
})
|
|
|
|
test('returns null when API Gateway reports a missing REST API', async () => {
|
|
const adapter = new AwsApiGatewayAdapter(fakeClient(() => {
|
|
throw Object.assign(new Error('NotFoundException'), {$metadata: {httpStatusCode: 404}})
|
|
}))
|
|
|
|
await expect(adapter.get('missing')).resolves.toBeNull()
|
|
})
|
|
|
|
test('creates a REST API with an optional description', async () => {
|
|
const adapter = new AwsApiGatewayAdapter(fakeClient((command) => {
|
|
expect(command).toBeInstanceOf(CreateRestApiCommand)
|
|
expect((command as CreateRestApiCommand).input).toEqual({name: 'orders-api', description: 'Orders REST API'})
|
|
return orders
|
|
}))
|
|
|
|
const result = await adapter.create({values: {name: 'orders-api', description: 'Orders REST API'}})
|
|
|
|
expect(result.id).toBe('a1b2c3')
|
|
})
|
|
|
|
test('rejects a missing name before calling API Gateway', async () => {
|
|
let called = false
|
|
const adapter = new AwsApiGatewayAdapter(fakeClient(() => {
|
|
called = true
|
|
return {}
|
|
}))
|
|
|
|
await expect(adapter.create({values: {}})).rejects.toThrow('name is required')
|
|
expect(called).toBeFalse()
|
|
})
|
|
|
|
test('deletes the requested REST API', async () => {
|
|
const adapter = new AwsApiGatewayAdapter(fakeClient((command) => {
|
|
expect(command).toBeInstanceOf(DeleteRestApiCommand)
|
|
expect((command as DeleteRestApiCommand).input.restApiId).toBe('a1b2c3')
|
|
return {}
|
|
}))
|
|
|
|
await adapter.delete('a1b2c3')
|
|
})
|
|
|
|
test('creates and deploys a Lambda proxy route', async () => {
|
|
const apiCommands: unknown[] = []
|
|
const lambdaCommands: unknown[] = []
|
|
const adapter = new AwsApiGatewayAdapter(
|
|
fakeClient((command) => {
|
|
apiCommands.push(command)
|
|
if (command instanceof GetResourcesCommand) return {items: [{id: 'root123', path: '/'}]}
|
|
if (command instanceof CreateResourceCommand) return {id: 'resource456'}
|
|
if (command instanceof CreateDeploymentCommand) return {id: 'deployment789'}
|
|
return {}
|
|
}),
|
|
fakeLambda((command) => {
|
|
lambdaCommands.push(command)
|
|
if (command instanceof GetFunctionCommand) {
|
|
return {Configuration: {FunctionArn: 'arn:aws:lambda:us-east-1:000000000000:function:hello'}}
|
|
}
|
|
return {}
|
|
}),
|
|
'000000000000',
|
|
'us-east-1',
|
|
)
|
|
|
|
const result = await adapter.createApiGatewayLambdaRoute('a1b2c3', {
|
|
path: '/hello', method: 'GET', stage: 'dev', functionName: 'hello',
|
|
})
|
|
|
|
expect(apiCommands.map((command) => (command as {constructor: {name: string}}).constructor.name)).toEqual([
|
|
'GetResourcesCommand', 'CreateResourceCommand', 'PutMethodCommand',
|
|
'PutIntegrationCommand', 'CreateDeploymentCommand',
|
|
])
|
|
expect((apiCommands[1] as CreateResourceCommand).input).toMatchObject({
|
|
restApiId: 'a1b2c3', parentId: 'root123', pathPart: 'hello',
|
|
})
|
|
expect((apiCommands[2] as PutMethodCommand).input).toMatchObject({
|
|
httpMethod: 'GET', authorizationType: 'NONE',
|
|
})
|
|
expect((apiCommands[3] as PutIntegrationCommand).input).toMatchObject({
|
|
type: 'AWS_PROXY', integrationHttpMethod: 'POST',
|
|
uri: 'arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:000000000000:function:hello/invocations',
|
|
})
|
|
expect((lambdaCommands[1] as AddPermissionCommand).input).toMatchObject({
|
|
FunctionName: 'hello', Principal: 'apigateway.amazonaws.com',
|
|
SourceArn: 'arn:aws:execute-api:us-east-1:000000000000:a1b2c3/dev/GET/hello',
|
|
})
|
|
expect(result).toEqual({
|
|
resourceId: 'resource456', deploymentId: 'deployment789',
|
|
invokeUrl: 'http://localhost:4566/execute-api/a1b2c3/dev/hello',
|
|
})
|
|
})
|
|
|
|
test('creates missing nested resources and reuses existing path segments', async () => {
|
|
const apiCommands: unknown[] = []
|
|
const adapter = new AwsApiGatewayAdapter(
|
|
fakeClient((command) => {
|
|
apiCommands.push(command)
|
|
if (command instanceof GetResourcesCommand) return {items: [
|
|
{id: 'root123', path: '/'},
|
|
{id: 'orders123', parentId: 'root123', pathPart: 'orders', path: '/orders'},
|
|
]}
|
|
if (command instanceof CreateResourceCommand) return {id: 'orderId123'}
|
|
if (command instanceof CreateDeploymentCommand) return {id: 'deployment789'}
|
|
return {}
|
|
}),
|
|
fakeLambda((command) => command instanceof GetFunctionCommand
|
|
? {Configuration: {FunctionArn: 'arn:aws:lambda:us-east-1:000000000000:function:hello'}}
|
|
: {}),
|
|
)
|
|
|
|
const result = await adapter.createApiGatewayLambdaRoute('a1b2c3', {
|
|
path: '/orders/{id}', method: 'PATCH', stage: 'dev', functionName: 'hello',
|
|
})
|
|
|
|
const creates = apiCommands.filter((command) => command instanceof CreateResourceCommand) as CreateResourceCommand[]
|
|
expect(creates).toHaveLength(1)
|
|
expect(creates[0]?.input).toMatchObject({parentId: 'orders123', pathPart: '{id}'})
|
|
expect((apiCommands.find((command) => command instanceof PutMethodCommand) as PutMethodCommand).input.httpMethod).toBe('PATCH')
|
|
expect(result).toMatchObject({resourceId: 'orderId123', invokeUrl: 'http://localhost:4566/execute-api/a1b2c3/dev/orders/{id}'})
|
|
})
|
|
|
|
test('creates a greedy child under the explicitly selected parent', async () => {
|
|
const commands: unknown[] = []
|
|
const lambdaCommands: unknown[] = []
|
|
const adapter = new AwsApiGatewayAdapter(fakeClient((command) => {
|
|
commands.push(command)
|
|
if (command instanceof GetResourcesCommand) return {items: [
|
|
{id: 'root123', path: '/'},
|
|
{id: 'files123', parentId: 'root123', pathPart: 'files', path: '/files'},
|
|
]}
|
|
if (command instanceof CreateResourceCommand) return {id: 'proxy123'}
|
|
if (command instanceof CreateDeploymentCommand) return {id: 'deployment789'}
|
|
return {}
|
|
}), fakeLambda((command) => {
|
|
lambdaCommands.push(command)
|
|
return command instanceof GetFunctionCommand
|
|
? {Configuration: {FunctionArn: 'arn:aws:lambda:us-east-1:000000000000:function:files'}}
|
|
: {}
|
|
}))
|
|
|
|
await adapter.createApiGatewayLambdaRoute('a1b2c3', {
|
|
path: '/files/{proxy+}', parentResourceId: 'files123', pathPart: '{proxy+}',
|
|
method: 'ANY', stage: 'dev', functionName: 'files',
|
|
})
|
|
|
|
expect((commands.find((command) => command instanceof CreateResourceCommand) as CreateResourceCommand).input).toMatchObject({
|
|
parentId: 'files123', pathPart: '{proxy+}',
|
|
})
|
|
expect((lambdaCommands.find((command) => command instanceof AddPermissionCommand) as AddPermissionCommand).input).toMatchObject({
|
|
SourceArn: 'arn:aws:execute-api:us-east-1:000000000000:a1b2c3/dev/*/files/*',
|
|
})
|
|
})
|
|
|
|
test('adds a method to an existing resource without creating a duplicate path', async () => {
|
|
const apiCommands: unknown[] = []
|
|
const adapter = new AwsApiGatewayAdapter(
|
|
fakeClient((command) => {
|
|
apiCommands.push(command)
|
|
if (command instanceof GetResourcesCommand) {
|
|
return {items: [
|
|
{id: 'resource456', parentId: 'root123', pathPart: 'hello', path: '/hello'},
|
|
{id: 'root123', path: '/'},
|
|
]}
|
|
}
|
|
if (command instanceof CreateDeploymentCommand) return {id: 'deployment789'}
|
|
return {}
|
|
}),
|
|
fakeLambda((command) => command instanceof GetFunctionCommand
|
|
? {Configuration: {FunctionArn: 'arn:aws:lambda:us-east-1:000000000000:function:hello'}}
|
|
: {}),
|
|
'000000000000',
|
|
'us-east-1',
|
|
)
|
|
|
|
await adapter.createApiGatewayLambdaRoute('a1b2c3', {
|
|
path: '/hello', method: 'POST', stage: 'dev', functionName: 'hello',
|
|
})
|
|
|
|
expect(apiCommands.some((command) => command instanceof CreateResourceCommand)).toBeFalse()
|
|
expect((apiCommands.find((command) => command instanceof PutMethodCommand) as PutMethodCommand).input).toMatchObject({
|
|
resourceId: 'resource456', httpMethod: 'POST',
|
|
})
|
|
})
|
|
|
|
test('tests a deployed route and preserves its HTTP response', async () => {
|
|
const originalFetch = globalThis.fetch
|
|
const requests: Request[] = []
|
|
globalThis.fetch = (async (input: RequestInfo | URL, init?: RequestInit) => {
|
|
requests.push(new Request(input, init))
|
|
return new Response(JSON.stringify({error: 'invalid request'}), {
|
|
status: 400,
|
|
headers: {'content-type': 'application/json', 'x-request-id': 'request-123'},
|
|
})
|
|
}) as typeof fetch
|
|
try {
|
|
const adapter = new AwsApiGatewayAdapter(fakeClient(() => ({})))
|
|
|
|
const result = await adapter.testApiGatewayRoute('a1b2c3', {
|
|
path: '/hello', method: 'POST', stage: 'dev', body: '{"name":"Ada"}',
|
|
headers: {'x-client': 'console'}, query: 'verbose=true',
|
|
})
|
|
|
|
expect(requests).toHaveLength(1)
|
|
expect(requests[0]?.url).toBe('http://localhost:4566/execute-api/a1b2c3/dev/hello?verbose=true')
|
|
expect(requests[0]?.method).toBe('POST')
|
|
expect(requests[0]?.headers.get('content-type')).toBe('application/json')
|
|
expect(requests[0]?.headers.get('x-client')).toBe('console')
|
|
expect(await requests[0]?.text()).toBe('{"name":"Ada"}')
|
|
expect(result).toMatchObject({
|
|
statusCode: 400,
|
|
headers: {'content-type': 'application/json', 'x-request-id': 'request-123'},
|
|
body: '{"error":"invalid request"}',
|
|
})
|
|
} finally {
|
|
globalThis.fetch = originalFetch
|
|
}
|
|
})
|
|
|
|
test('omits a body when testing a GET route', async () => {
|
|
const originalFetch = globalThis.fetch
|
|
const requests: Request[] = []
|
|
globalThis.fetch = (async (input: RequestInfo | URL, init?: RequestInit) => {
|
|
requests.push(new Request(input, init))
|
|
return new Response('{}')
|
|
}) as typeof fetch
|
|
try {
|
|
const adapter = new AwsApiGatewayAdapter(fakeClient(() => ({})))
|
|
|
|
await adapter.testApiGatewayRoute('a1b2c3', {
|
|
path: '/hello', method: 'GET', stage: 'dev', body: '{}', headers: {}, query: '',
|
|
})
|
|
|
|
expect(await requests[0]?.text()).toBe('')
|
|
} finally {
|
|
globalThis.fetch = originalFetch
|
|
}
|
|
})
|
|
|
|
test('uses PATCH and HEAD for deployed requests and rejects ANY', async () => {
|
|
const originalFetch = globalThis.fetch
|
|
const requests: Request[] = []
|
|
globalThis.fetch = (async (input: RequestInfo | URL, init?: RequestInit) => {
|
|
requests.push(new Request(input, init))
|
|
return new Response(null)
|
|
}) as typeof fetch
|
|
try {
|
|
const adapter = new AwsApiGatewayAdapter(fakeClient(() => ({})))
|
|
await adapter.testApiGatewayRoute('a1b2c3', {path: '/orders/1', method: 'PATCH', stage: 'dev', body: '{}', headers: {}, query: ''})
|
|
await adapter.testApiGatewayRoute('a1b2c3', {path: '/orders/1', method: 'HEAD', stage: 'dev', body: '{}', headers: {}, query: ''})
|
|
await expect(adapter.testApiGatewayRoute('a1b2c3', {path: '/orders/1', method: 'ANY', stage: 'dev', body: '', headers: {}, query: ''})).rejects.toThrow('method must be')
|
|
expect(requests.map((request) => request.method)).toEqual(['PATCH', 'HEAD'])
|
|
expect(await requests[1]?.text()).toBe('')
|
|
} finally {
|
|
globalThis.fetch = originalFetch
|
|
}
|
|
})
|
|
|
|
test('tests a configured method through the AWS SDK without a deployed stage', async () => {
|
|
const commands: unknown[] = []
|
|
const adapter = new AwsApiGatewayAdapter(fakeClient((command) => {
|
|
commands.push(command)
|
|
if (command instanceof TestInvokeMethodCommand) {
|
|
return {
|
|
status: 201,
|
|
body: '{"id":"order-123"}',
|
|
headers: {'x-request-id': 'request-123'},
|
|
multiValueHeaders: {'set-cookie': ['first', 'second']},
|
|
log: 'Execution completed',
|
|
latency: 17,
|
|
}
|
|
}
|
|
throw new Error('Unexpected command')
|
|
}))
|
|
|
|
await expect(adapter.testApiGatewayMethod('a1b2c3', {
|
|
resourceId: 'resource456',
|
|
httpMethod: 'ANY',
|
|
pathWithQueryString: '/orders?dryRun=true',
|
|
body: '{"name":"Ada"}',
|
|
headers: {'content-type': 'application/json'},
|
|
multiValueHeaders: {'x-tag': ['one', 'two']},
|
|
stageVariables: {environment: 'test'},
|
|
})).resolves.toEqual({
|
|
statusCode: 201,
|
|
body: '{"id":"order-123"}',
|
|
headers: {'x-request-id': 'request-123'},
|
|
multiValueHeaders: {'set-cookie': ['first', 'second']},
|
|
log: 'Execution completed',
|
|
latency: 17,
|
|
})
|
|
expect((commands[0] as TestInvokeMethodCommand).input).toEqual({
|
|
restApiId: 'a1b2c3', resourceId: 'resource456', httpMethod: 'ANY',
|
|
pathWithQueryString: '/orders?dryRun=true', body: '{"name":"Ada"}',
|
|
headers: {'content-type': 'application/json'}, multiValueHeaders: {'x-tag': ['one', 'two']},
|
|
stageVariables: {environment: 'test'},
|
|
})
|
|
})
|
|
|
|
test('lists deployed methods, Lambda integrations, and stages', async () => {
|
|
const adapter = new AwsApiGatewayAdapter(fakeClient((command) => {
|
|
if (command instanceof GetResourcesCommand) {
|
|
return {items: [
|
|
{id: 'root123', path: '/', resourceMethods: {}},
|
|
{id: 'resource456', parentId: 'root123', pathPart: 'hello', path: '/hello', resourceMethods: {GET: true, POST: true}},
|
|
]}
|
|
}
|
|
if (command instanceof GetMethodCommand) {
|
|
return {methodIntegration: {
|
|
uri: 'arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:000000000000:function:hello/invocations',
|
|
}}
|
|
}
|
|
if (command instanceof GetStagesCommand) return {item: [{stageName: 'prod'}, {stageName: 'dev'}]}
|
|
throw new Error('Unexpected command')
|
|
}))
|
|
|
|
await expect(adapter.listApiGatewayRoutes('a1b2c3')).resolves.toEqual({
|
|
resources: [
|
|
{resourceId: 'root123', parentId: null, path: '/', pathPart: null, methods: []},
|
|
{resourceId: 'resource456', parentId: 'root123', path: '/hello', pathPart: 'hello', methods: [
|
|
{resourceId: 'resource456', path: '/hello', method: 'GET', functionName: 'hello', integrationType: null},
|
|
{resourceId: 'resource456', path: '/hello', method: 'POST', functionName: 'hello', integrationType: null},
|
|
]},
|
|
],
|
|
routes: [
|
|
{resourceId: 'resource456', path: '/hello', method: 'GET', functionName: 'hello', integrationType: null},
|
|
{resourceId: 'resource456', path: '/hello', method: 'POST', functionName: 'hello', integrationType: null},
|
|
],
|
|
stages: ['dev', 'prod'],
|
|
})
|
|
})
|
|
|
|
test('paginates and returns resources that have no configured methods', async () => {
|
|
const adapter = new AwsApiGatewayAdapter(fakeClient((command) => {
|
|
if (command instanceof GetResourcesCommand && !command.input.position) {
|
|
return {items: [{id: 'root123', path: '/', resourceMethods: {}}], position: 'next'}
|
|
}
|
|
if (command instanceof GetResourcesCommand) {
|
|
return {items: [{id: 'orders123', parentId: 'root123', pathPart: 'orders', path: '/orders'}]}
|
|
}
|
|
if (command instanceof GetStagesCommand) return {item: []}
|
|
throw new Error('Unexpected command')
|
|
}))
|
|
|
|
await expect(adapter.listApiGatewayRoutes('a1b2c3')).resolves.toEqual({
|
|
resources: [
|
|
{resourceId: 'root123', parentId: null, path: '/', pathPart: null, methods: []},
|
|
{resourceId: 'orders123', parentId: 'root123', path: '/orders', pathPart: 'orders', methods: []},
|
|
],
|
|
routes: [],
|
|
stages: [],
|
|
})
|
|
})
|
|
|
|
test('deletes one method and redeploys its stage', async () => {
|
|
const commands: unknown[] = []
|
|
const lambdaCommands: unknown[] = []
|
|
const adapter = new AwsApiGatewayAdapter(fakeClient((command) => {
|
|
commands.push(command)
|
|
if (command instanceof GetMethodCommand) {
|
|
return {methodIntegration: {uri: 'arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:000000000000:function:hello/invocations'}}
|
|
}
|
|
return {}
|
|
}), fakeLambda((command) => {
|
|
lambdaCommands.push(command)
|
|
return {}
|
|
}))
|
|
|
|
await adapter.deleteApiGatewayRoute('a1b2c3', {resourceId: 'resource456', path: '/hello', method: 'POST', stage: 'dev'})
|
|
|
|
expect((commands[1] as DeleteMethodCommand).input).toMatchObject({restApiId: 'a1b2c3', resourceId: 'resource456', httpMethod: 'POST'})
|
|
expect((commands[2] as CreateDeploymentCommand).input).toMatchObject({restApiId: 'a1b2c3', stageName: 'dev'})
|
|
expect((lambdaCommands[0] as RemovePermissionCommand).input).toMatchObject({FunctionName: 'hello', StatementId: 'apigateway-a1b2c3-dev-POST-hello'})
|
|
})
|
|
|
|
test('deletes a CORS OPTIONS method and redeploys its stage', async () => {
|
|
const commands: unknown[] = []
|
|
const adapter = new AwsApiGatewayAdapter(fakeClient((command) => {
|
|
commands.push(command)
|
|
if (command instanceof GetMethodCommand) {
|
|
return {methodIntegration: {type: 'MOCK'}}
|
|
}
|
|
return {}
|
|
}), fakeLambda(() => ({})))
|
|
|
|
await adapter.deleteApiGatewayRoute('a1b2c3', {resourceId: 'resource456', path: '/hello', method: 'OPTIONS', stage: 'dev'})
|
|
|
|
expect(commands.map((command) => (command as {constructor: {name: string}}).constructor.name)).toEqual([
|
|
'GetMethodCommand', 'DeleteMethodCommand', 'CreateDeploymentCommand',
|
|
])
|
|
expect((commands[1] as DeleteMethodCommand).input).toMatchObject({httpMethod: 'OPTIONS'})
|
|
})
|
|
|
|
test('enables CORS for non-proxy methods, creates OPTIONS, and reports proxy methods', async () => {
|
|
const commands: unknown[] = []
|
|
const adapter = new AwsApiGatewayAdapter(fakeClient((command) => {
|
|
commands.push(command)
|
|
if (command instanceof GetMethodCommand && command.input.httpMethod === 'GET') {
|
|
return {
|
|
methodResponses: {200: {
|
|
responseParameters: {'method.response.header.X-Existing': true},
|
|
responseModels: {'application/json': 'ExistingModel'},
|
|
}},
|
|
methodIntegration: {type: 'HTTP', integrationResponses: {200: {
|
|
responseParameters: {'method.response.header.X-Existing': "'existing'"},
|
|
responseTemplates: {'application/json': '$input.body'},
|
|
}}},
|
|
}
|
|
}
|
|
if (command instanceof GetMethodCommand && command.input.httpMethod === 'POST') {
|
|
return {methodIntegration: {type: 'AWS_PROXY'}}
|
|
}
|
|
if (command instanceof GetMethodCommand && command.input.httpMethod === 'OPTIONS') {
|
|
return {
|
|
methodResponses: {200: {
|
|
responseParameters: {'method.response.header.Access-Control-Allow-Origin': true},
|
|
responseModels: {'application/json': 'OptionsModel'},
|
|
}},
|
|
methodIntegration: {timeoutInMillis: 29000, integrationResponses: {200: {
|
|
responseTemplates: {'text/plain': 'existing template'},
|
|
}}},
|
|
}
|
|
}
|
|
return {}
|
|
}))
|
|
|
|
await expect(adapter.enableApiGatewayCors('a1b2c3', {
|
|
resourceId: 'resource456', stage: 'dev', origin: '*', headers: 'Content-Type', methods: ['GET', 'POST'],
|
|
})).resolves.toEqual({configuredMethods: ['GET'], proxyMethods: ['POST']})
|
|
|
|
expect(commands.map((command) => (command as {constructor: {name: string}}).constructor.name)).toEqual([
|
|
'GetMethodCommand', 'PutMethodResponseCommand', 'PutIntegrationResponseCommand', 'GetMethodCommand', 'GetMethodCommand',
|
|
'PutMethodCommand', 'PutMethodResponseCommand', 'PutIntegrationCommand', 'PutIntegrationResponseCommand', 'CreateDeploymentCommand',
|
|
])
|
|
expect((commands[1] as PutMethodResponseCommand).input.responseParameters).toEqual({
|
|
'method.response.header.X-Existing': true,
|
|
'method.response.header.Access-Control-Allow-Origin': false,
|
|
'method.response.header.Access-Control-Allow-Headers': false,
|
|
'method.response.header.Access-Control-Allow-Methods': false,
|
|
})
|
|
expect((commands[1] as PutMethodResponseCommand).input.responseModels).toEqual({'application/json': 'ExistingModel'})
|
|
expect((commands[2] as PutIntegrationResponseCommand).input.responseParameters).toMatchObject({
|
|
'method.response.header.X-Existing': "'existing'",
|
|
'method.response.header.Access-Control-Allow-Origin': "'*'",
|
|
'method.response.header.Access-Control-Allow-Headers': "'Content-Type'",
|
|
'method.response.header.Access-Control-Allow-Methods': "'GET,POST,OPTIONS'",
|
|
})
|
|
expect((commands[2] as PutIntegrationResponseCommand).input.responseTemplates).toEqual({'application/json': '$input.body'})
|
|
expect((commands[5] as PutMethodCommand).input).toMatchObject({httpMethod: 'OPTIONS', authorizationType: 'NONE'})
|
|
expect((commands[6] as PutMethodResponseCommand).input).toMatchObject({
|
|
responseParameters: {'method.response.header.Access-Control-Allow-Origin': true},
|
|
responseModels: {'application/json': 'OptionsModel'},
|
|
})
|
|
expect((commands[7] as PutIntegrationCommand).input).toMatchObject({
|
|
type: 'MOCK', requestTemplates: {'application/json': '{"statusCode": 200}'}, timeoutInMillis: 29000,
|
|
})
|
|
expect((commands[8] as PutIntegrationResponseCommand).input.responseTemplates).toEqual({'text/plain': 'existing template'})
|
|
expect((commands[9] as CreateDeploymentCommand).input).toMatchObject({stageName: 'dev'})
|
|
})
|
|
|
|
test('returns the AWS API Gateway schema', () => {
|
|
const adapter = new AwsApiGatewayAdapter(fakeClient(() => ({})))
|
|
|
|
expect(adapter.schema()).toMatchObject({
|
|
cloud: 'aws',
|
|
service: 'apigateway',
|
|
displayName: 'AWS API Gateway',
|
|
actions: ['list', 'create', 'delete', 'inspect'],
|
|
})
|
|
})
|
|
})
|