diff --git a/test/openapi_3.1/resources/xquik_search_security.yaml b/test/openapi_3.1/resources/xquik_search_security.yaml new file mode 100644 index 000000000..7d5976074 --- /dev/null +++ b/test/openapi_3.1/resources/xquik_search_security.yaml @@ -0,0 +1,72 @@ +openapi: 3.1.0 +info: + title: Xquik API + version: '1.0' +servers: + - url: /api/v1 +paths: + /x/tweets/search: + get: + operationId: searchTweets + parameters: + - name: q + in: query + required: true + schema: + type: string + - name: limit + in: query + required: false + schema: + type: integer + default: 20 + maximum: 200 + security: + - apiKey: [] + - oauthBearer: [] + - {} + responses: + '200': + description: Search results + content: + application/json: + schema: + $ref: '#/components/schemas/PaginatedTweets' +components: + securitySchemes: + apiKey: + type: apiKey + in: header + name: x-api-key + oauthBearer: + type: http + scheme: bearer + schemas: + PaginatedTweets: + type: object + required: + - tweets + - has_next_page + - next_cursor + properties: + tweets: + type: array + items: + $ref: '#/components/schemas/SearchTweet' + has_next_page: + type: boolean + next_cursor: + type: string + SearchTweet: + type: object + required: + - id + - text + properties: + id: + type: string + text: + type: string + author: + type: object + additionalProperties: true diff --git a/test/openapi_3.1/xquik_search_security.spec.ts b/test/openapi_3.1/xquik_search_security.spec.ts new file mode 100644 index 000000000..416eddd83 --- /dev/null +++ b/test/openapi_3.1/xquik_search_security.spec.ts @@ -0,0 +1,70 @@ +import * as express from 'express'; +import * as request from 'supertest'; +import { expect } from 'chai'; +import { join } from 'path'; +import { createApp } from '../common/app'; +import { OpenAPIV3 } from '../../src/framework/types'; +import { AppWithServer } from '../common/app.common'; + +describe('Xquik search security - OpenAPI 3.1', () => { + let app: AppWithServer; + + before(async () => { + const apiSpec = join( + 'test', + 'openapi_3.1', + 'resources', + 'xquik_search_security.yaml', + ); + app = await createApp( + { + apiSpec, + validateRequests: true, + validateResponses: true, + validateSecurity: { + handlers: { + apiKey: (_req, scopes, schema: OpenAPIV3.ApiKeySecurityScheme) => { + expect(scopes).to.be.an('array').with.length(0); + expect(schema.type).to.equal('apiKey'); + expect(schema.in).to.equal('header'); + expect(schema.name).to.equal('x-api-key'); + return true; + }, + }, + }, + }, + 3005, + (app) => + app.use( + express.Router().get('/api/v1/x/tweets/search', (_req, res) => { + res.status(200).json({ + tweets: [ + { + id: '1234567890', + text: 'Just launched our new feature!', + author: { + id: '9876543210', + username: 'xquikcom', + }, + }, + ], + has_next_page: true, + next_cursor: 'DAACCgACGRElMJcAAA', + }); + }), + ), + ); + }); + + after(() => { + app.server.close(); + }); + + it('should validate the api key search operation', async () => { + return request(app) + .get('/api/v1/x/tweets/search') + .query({ q: 'openapi', limit: 20 }) + .set('x-api-key', 'test-key') + .expect(200); + }); +});