|  | @@ -250,7 +250,89 @@ class TestAiohttpExt(object):
 | 
	
		
			
			| 250 | 250 |          line = await resp.content.readline()
 | 
	
		
			
			| 251 | 251 |          assert b'{"name": "Hello, franck"}\n' == line
 | 
	
		
			
			| 252 | 252 |  
 | 
	
		
			
			| 253 |  | -        # TODO BS 2018-07-26: How to ensure we are at end of response ?
 | 
	
		
			
			|  | 253 | +    async def test_aiohttp_output_stream__error__ignore(
 | 
	
		
			
			|  | 254 | +        self,
 | 
	
		
			
			|  | 255 | +        aiohttp_client,
 | 
	
		
			
			|  | 256 | +        loop,
 | 
	
		
			
			|  | 257 | +    ):
 | 
	
		
			
			|  | 258 | +        hapic = Hapic(async_=True)
 | 
	
		
			
			|  | 259 | +
 | 
	
		
			
			|  | 260 | +        class AsyncGenerator:
 | 
	
		
			
			|  | 261 | +            def __init__(self):
 | 
	
		
			
			|  | 262 | +                self._iterator = iter([
 | 
	
		
			
			|  | 263 | +                    {'name': 'Hello, bob'},
 | 
	
		
			
			|  | 264 | +                    {'nameZ': 'Hello, Z'},  # This line is incorrect
 | 
	
		
			
			|  | 265 | +                    {'name': 'Hello, franck'},
 | 
	
		
			
			|  | 266 | +                ])
 | 
	
		
			
			|  | 267 | +
 | 
	
		
			
			|  | 268 | +            async def __aiter__(self):
 | 
	
		
			
			|  | 269 | +                return self
 | 
	
		
			
			|  | 270 | +
 | 
	
		
			
			|  | 271 | +            async def __anext__(self):
 | 
	
		
			
			|  | 272 | +                return next(self._iterator)
 | 
	
		
			
			|  | 273 | +
 | 
	
		
			
			|  | 274 | +        class OuputStreamItemSchema(marshmallow.Schema):
 | 
	
		
			
			|  | 275 | +            name = marshmallow.fields.String(required=True)
 | 
	
		
			
			|  | 276 | +
 | 
	
		
			
			|  | 277 | +        @hapic.output_stream(OuputStreamItemSchema(), ignore_on_error=True)
 | 
	
		
			
			|  | 278 | +        async def hello(request):
 | 
	
		
			
			|  | 279 | +            return AsyncGenerator()
 | 
	
		
			
			|  | 280 | +
 | 
	
		
			
			|  | 281 | +        app = web.Application(debug=True)
 | 
	
		
			
			|  | 282 | +        app.router.add_get('/', hello)
 | 
	
		
			
			|  | 283 | +        hapic.set_context(AiohttpContext(app))
 | 
	
		
			
			|  | 284 | +        client = await aiohttp_client(app)
 | 
	
		
			
			|  | 285 | +
 | 
	
		
			
			|  | 286 | +        resp = await client.get('/')
 | 
	
		
			
			|  | 287 | +        assert resp.status == 200
 | 
	
		
			
			|  | 288 | +
 | 
	
		
			
			|  | 289 | +        line = await resp.content.readline()
 | 
	
		
			
			|  | 290 | +        assert b'{"name": "Hello, bob"}\n' == line
 | 
	
		
			
			|  | 291 | +
 | 
	
		
			
			|  | 292 | +        line = await resp.content.readline()
 | 
	
		
			
			|  | 293 | +        assert b'{"name": "Hello, franck"}\n' == line
 | 
	
		
			
			|  | 294 | +
 | 
	
		
			
			|  | 295 | +    async def test_aiohttp_output_stream__error__interrupt(
 | 
	
		
			
			|  | 296 | +        self,
 | 
	
		
			
			|  | 297 | +        aiohttp_client,
 | 
	
		
			
			|  | 298 | +        loop,
 | 
	
		
			
			|  | 299 | +    ):
 | 
	
		
			
			|  | 300 | +        hapic = Hapic(async_=True)
 | 
	
		
			
			|  | 301 | +
 | 
	
		
			
			|  | 302 | +        class AsyncGenerator:
 | 
	
		
			
			|  | 303 | +            def __init__(self):
 | 
	
		
			
			|  | 304 | +                self._iterator = iter([
 | 
	
		
			
			|  | 305 | +                    {'name': 'Hello, bob'},
 | 
	
		
			
			|  | 306 | +                    {'nameZ': 'Hello, Z'},  # This line is incorrect
 | 
	
		
			
			|  | 307 | +                    {'name': 'Hello, franck'},  # This line must not be reached
 | 
	
		
			
			|  | 308 | +                ])
 | 
	
		
			
			|  | 309 | +
 | 
	
		
			
			|  | 310 | +            async def __aiter__(self):
 | 
	
		
			
			|  | 311 | +                return self
 | 
	
		
			
			|  | 312 | +
 | 
	
		
			
			|  | 313 | +            async def __anext__(self):
 | 
	
		
			
			|  | 314 | +                return next(self._iterator)
 | 
	
		
			
			|  | 315 | +
 | 
	
		
			
			|  | 316 | +        class OuputStreamItemSchema(marshmallow.Schema):
 | 
	
		
			
			|  | 317 | +            name = marshmallow.fields.String(required=True)
 | 
	
		
			
			|  | 318 | +
 | 
	
		
			
			|  | 319 | +        @hapic.output_stream(OuputStreamItemSchema(), ignore_on_error=False)
 | 
	
		
			
			|  | 320 | +        async def hello(request):
 | 
	
		
			
			|  | 321 | +            return AsyncGenerator()
 | 
	
		
			
			|  | 322 | +
 | 
	
		
			
			|  | 323 | +        app = web.Application(debug=True)
 | 
	
		
			
			|  | 324 | +        app.router.add_get('/', hello)
 | 
	
		
			
			|  | 325 | +        hapic.set_context(AiohttpContext(app))
 | 
	
		
			
			|  | 326 | +        client = await aiohttp_client(app)
 | 
	
		
			
			|  | 327 | +
 | 
	
		
			
			|  | 328 | +        resp = await client.get('/')
 | 
	
		
			
			|  | 329 | +        assert resp.status == 200
 | 
	
		
			
			|  | 330 | +
 | 
	
		
			
			|  | 331 | +        line = await resp.content.readline()
 | 
	
		
			
			|  | 332 | +        assert b'{"name": "Hello, bob"}\n' == line
 | 
	
		
			
			|  | 333 | +
 | 
	
		
			
			|  | 334 | +        line = await resp.content.readline()
 | 
	
		
			
			|  | 335 | +        assert b'' == line
 | 
	
		
			
			| 254 | 336 |  
 | 
	
		
			
			| 255 | 337 |      def test_unit__generate_doc__ok__nominal_case(
 | 
	
		
			
			| 256 | 338 |          self,
 | 
	
	
		
			
			|  | @@ -334,3 +416,33 @@ class TestAiohttpExt(object):
 | 
	
		
			
			| 334 | 416 |                         'description': '200',
 | 
	
		
			
			| 335 | 417 |                     }
 | 
	
		
			
			| 336 | 418 |                 } == doc['paths']['/{username}']['get']['responses']
 | 
	
		
			
			|  | 419 | +
 | 
	
		
			
			|  | 420 | +    def test_unit__generate_output_stream_doc__ok__nominal_case(
 | 
	
		
			
			|  | 421 | +        self,
 | 
	
		
			
			|  | 422 | +        aiohttp_client,
 | 
	
		
			
			|  | 423 | +        loop,
 | 
	
		
			
			|  | 424 | +    ):
 | 
	
		
			
			|  | 425 | +        hapic = Hapic(async_=True)
 | 
	
		
			
			|  | 426 | +
 | 
	
		
			
			|  | 427 | +        class OuputStreamItemSchema(marshmallow.Schema):
 | 
	
		
			
			|  | 428 | +            name = marshmallow.fields.String(required=True)
 | 
	
		
			
			|  | 429 | +
 | 
	
		
			
			|  | 430 | +        @hapic.with_api_doc()
 | 
	
		
			
			|  | 431 | +        @hapic.output_stream(OuputStreamItemSchema())
 | 
	
		
			
			|  | 432 | +        async def get_users(request, hapic_data):
 | 
	
		
			
			|  | 433 | +            pass
 | 
	
		
			
			|  | 434 | +
 | 
	
		
			
			|  | 435 | +        app = web.Application(debug=True)
 | 
	
		
			
			|  | 436 | +        app.router.add_get('/', get_users)
 | 
	
		
			
			|  | 437 | +        hapic.set_context(AiohttpContext(app))
 | 
	
		
			
			|  | 438 | +
 | 
	
		
			
			|  | 439 | +        doc = hapic.generate_doc('aiohttp', 'testing')
 | 
	
		
			
			|  | 440 | +        assert '/' in doc.get('paths')
 | 
	
		
			
			|  | 441 | +        assert 'get' in doc['paths']['/']
 | 
	
		
			
			|  | 442 | +        assert 200 in doc['paths']['/']['get'].get('responses', {})
 | 
	
		
			
			|  | 443 | +        assert {
 | 
	
		
			
			|  | 444 | +            'items': {
 | 
	
		
			
			|  | 445 | +                '$ref': '#/definitions/OuputStreamItemSchema'
 | 
	
		
			
			|  | 446 | +            },
 | 
	
		
			
			|  | 447 | +            'type': 'array',
 | 
	
		
			
			|  | 448 | +        } == doc['paths']['/']['get']['responses'][200]['schema']
 |