/**
 * Copyright 2018 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */ import ava , { TestInterface } from 'ava' ; import * as sinon from 'sinon' ; import * as common from '../../common' ; import { JsonObject } from '../../common' ; import { Lambda } from '../lambda' ; import { StandardResponse , Headers } from '../framework' ; interface AvaContext { lambda : Lambda ; } const test = ava as TestInterface < AvaContext > ; test . beforeEach ( t => { t . context . lambda = new Lambda ( ) ; } ) ; test ( 'checks against valid mock request' , t => { t . true ( t . context . lambda . check ( { } , { succeed ( ) { } , } as any , ( e , body ) => { } ) ) ; } ) ; test ( 'checks against invalid context' , t => { t . false ( t . context . lambda . check ( { } , { } as any , ( e , body ) => { } ) ) ; } ) ; test ( 'handles valid body fine' , async ( t ) => { const expectedBody = { prop : true , } ; const expectedStatus = 123 ; const sentBody = { a : '1' , } ; const sentHeaders = { key : 'value' , } ; let receivedBody = null ; let receivedStatus = - 1 ; let promise = null ; t . context . lambda . handle ( ( body , headers ) => { t . deepEqual ( body , sentBody ) ; t . deepEqual ( headers , sentHeaders ) ; promise = Promise . resolve ( { body : expectedBody , status : expectedStatus , } ) ; return promise ; } ) ( { body : JSON . stringify ( sentBody ) , headers : sentHeaders , } , { succeed ( ) { } , } as any , ( e , body ) => { receivedStatus = body . statusCode ; receivedBody = body . body ; } ) ; await promise ; await new Promise ( resolve => setTimeout ( resolve , 1 ) ) ; t . deepEqual ( JSON . parse ( receivedBody as any ) , expectedBody ) ; t . is ( receivedStatus , expectedStatus ) ; } ) ; test ( 'converts headers to lower' , async ( t ) => { const expectedBody = { prop : true , } ; const expectedStatus = 123 ; const sentBody = { a : '1' , } ; const sentHeaders = { Key : 'value' , } ; let receivedBody = null ; let receivedStatus = - 1 ; let promise = null ; t . context . lambda . handle ( ( body , headers ) => { t . deepEqual ( body , sentBody ) ; t . deepEqual ( headers , { key : 'value' , } ) ; promise = Promise . resolve ( { body : expectedBody , status : expectedStatus , } ) ; return promise ; } ) ( { body : JSON . stringify ( sentBody ) , headers : sentHeaders , } , { succeed ( ) { } , } as any , ( e , body ) => { receivedStatus = body . statusCode ; receivedBody = body . body ; } ) ; await promise ; await new Promise ( resolve => setTimeout ( resolve , 1 ) ) ; t . deepEqual ( JSON . parse ( receivedBody as any ) , expectedBody ) ; t . is ( receivedStatus , expectedStatus ) ; } ) ; test . serial ( 'handles error' , async ( t ) => { const expectedError = new Error ( 'test' ) ; const sentBody = { a : '1' , } ; const sentHeaders = { key : 'value' , } ; let receivedError = null ; let promise = null ; const stub = sinon . stub ( common , 'error' ) ; t . context . lambda . handle ( ( body , headers ) => { t . deepEqual ( body , sentBody ) ; t . deepEqual ( headers , sentHeaders ) ; promise = Promise . reject ( expectedError ) ; return promise ; } ) ( { body : JSON . stringify ( sentBody ) , headers : sentHeaders , } , { succeed ( ) { } , } as any , ( e ) => { receivedError = e ; } ) ; await ( promise as any ) . catch ( ( ) => { } ) ; await new Promise ( resolve => setTimeout ( resolve , 1 ) ) ; t . true ( stub . called ) ; stub . restore ( ) ; t . is ( receivedError , expectedError ) ; } ) ; test . serial ( 'handles string error' , async ( t ) => { const expectedError = 'test' ; const sentBody = { a : '1' , } ; const sentHeaders = { key : 'value' , } ; let receivedError = null ; let promise = null ; const stub = sinon . stub ( common , 'error' ) ; t . context . lambda . handle ( ( body , headers ) => { t . deepEqual ( body , sentBody ) ; t . deepEqual ( headers , sentHeaders ) ; promise = Promise . reject ( expectedError ) ; return promise ; } ) ( { body : JSON . stringify ( sentBody ) , headers : sentHeaders , } , { succeed ( ) { } , } as any , ( e ) => { receivedError = e ; } ) ; await ( promise as any ) . catch ( ( ) => { } ) ; await new Promise ( resolve => setTimeout ( resolve , 1 ) ) ; t . true ( stub . called ) ; stub . restore ( ) ; t . is ( receivedError , expectedError ) ; } ) ; test ( 'handles valid headers fine' , async ( t ) => { const expectedHeaders = { header1 : 'header2' , } ; const expectedStatus = 123 ; let receivedHeaders = null ; let receivedStatus = - 1 ; let promise = null ; t . context . lambda . handle ( ( body , headers ) => { promise = Promise . resolve ( { body : { } , status : expectedStatus , headers : expectedHeaders , } ) ; return promise ; } ) ( { body : JSON . stringify ( { } ) , headers : { } , } , { succeed ( ) { } , } as any , ( e , body ) => { receivedStatus = body . statusCode ; receivedHeaders = body . headers ; } ) ; await promise ; await new Promise ( resolve => setTimeout ( resolve , 1 ) ) ; t . is ( receivedStatus , expectedStatus ) ; t . is ( receivedHeaders , expectedHeaders ) ; } ) ; test ( 'sends back metadata' , async ( t ) => { const expectedBody = { prop : true , } ; const expectedStatus = 123 ; const sentBody = { a : '1' , } ; const sentHeaders = { key : 'value' , } ; let receivedBody = null ; let receivedStatus = - 1 ; let promise = null ; const event = { body : JSON . stringify ( sentBody ) , headers : sentHeaders , } ; const context = { succeed ( ) { } , } ; t . context . lambda . handle ( ( body , headers , metadata ) => { t . deepEqual ( body , sentBody ) ; t . deepEqual ( headers , sentHeaders ) ; t . is ( metadata ! . lambda ! . event , event ) ; t . is ( metadata ! . lambda ! . context , context ) ; promise = Promise . resolve ( { body : expectedBody , status : expectedStatus , } ) ; return promise ; } ) ( event , context , ( e , body ) => { receivedStatus = body . statusCode ; receivedBody = body . body ; } ) ; await promise ; await new Promise ( resolve => setTimeout ( resolve , 1 ) ) ; t . deepEqual ( JSON . parse ( receivedBody as any ) , expectedBody ) ; t . is ( receivedStatus , expectedStatus ) ; } ) ; test ( 'returns back correctly when only the body is received' , async ( t ) => { const expectedBody = { prop : true , } ; const expectedStatus = 123 ; const sentBody = { a : '1' , } ; let receivedBody = null ; let receivedStatus = - 1 ; let promise = null ; t . context . lambda . handle ( ( body , headers ) => { t . deepEqual ( body , sentBody ) ; t . deepEqual ( headers , { } ) ; promise = Promise . resolve ( { body : expectedBody , status : expectedStatus , } ) ; return promise ; } ) ( sentBody , { succeed ( ) { } , } as any , ( e , body ) => { receivedStatus = body . statusCode ; receivedBody = body . body ; } ) ; await promise ; await new Promise ( resolve => setTimeout ( resolve , 1 ) ) ; t . deepEqual ( JSON . parse ( receivedBody as any ) , expectedBody ) ; t . is ( receivedStatus , expectedStatus ) ; } ) ; test ( 'parses body if it is an object' , async ( t ) => { const expectedBody = { prop : true , } ; const expectedStatus = 123 ; const sentBody = { a : '1' , } ; const sentHeaders = { key : 'value' , } ; let receivedBody = null ; let receivedStatus = - 1 ; let promise = null ; t . context . lambda . handle ( ( body , headers ) => { t . deepEqual ( body , sentBody ) ; t . deepEqual ( headers , sentHeaders ) ; promise = Promise . resolve ( { body : expectedBody , status : expectedStatus , } ) ; return promise ; } ) ( { body : sentBody , headers : sentHeaders , } , { succeed ( ) { } , } as any , ( e , body ) => { receivedStatus = body . statusCode ; receivedBody = body . body ; } ) ; await promise ; await new Promise ( resolve => setTimeout ( resolve , 1 ) ) ; t . deepEqual ( JSON . parse ( receivedBody as any ) , expectedBody ) ; t . is ( receivedStatus , expectedStatus ) ; } ) ;