Skip to content

Commit

Permalink
feat: Detect preferred and semantic method (#39)
Browse files Browse the repository at this point in the history
* feat: Detect preferred and semantic method

* ci: Format code

* implement semantic and preferred methods helper functions

* unit test for get and post methods

* add unit tests for complex methods combinations

* minor fixes

* test complex parameters preferred method detection and refactor

* format

* resolve merge conflict

* ci: Generate code

* resolve conflicts

* refactor tests

---------

Co-authored-by: Seam Bot <[email protected]>
  • Loading branch information
kainpets and seambot authored Aug 6, 2024
1 parent 90540b6 commit 3ab1aa3
Show file tree
Hide file tree
Showing 3 changed files with 347 additions and 32 deletions.
272 changes: 270 additions & 2 deletions src/lib/blueprint.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import test from 'ava'

import { createProperties } from 'lib/blueprint.js'
import type { OpenapiSchema } from 'lib/openapi.js'
import {
createProperties,
getPreferredMethod,
getSemanticMethod,
type Method,
} from 'lib/blueprint.js'
import type { OpenapiOperation, OpenapiSchema } from 'lib/openapi.js'

test('createProperties: assigns appropriate default values', (t) => {
const minimalProperties = {
Expand Down Expand Up @@ -71,3 +76,266 @@ test('createProperties: uses provided values', (t) => {
'isUndocumented should be true when x-undocumented is provided',
)
})

const postEndpoint: OpenapiOperation = {
summary: '/users/create',
responses: {
'200': {
description: 'OK',
content: {
'application/json': {
schema: {
properties: {
user: {
$ref: '#/components/schemas/user',
type: 'object',
},
ok: {
type: 'boolean',
},
},
required: ['user', 'ok'],
},
},
},
},
},
operationId: 'usersCreatePost',
}

test('getSemanticMethod: post only', (t) => {
const postOnlyMethods: Method[] = ['POST']
t.is(
getSemanticMethod(postOnlyMethods),
'POST',
'Semantic method should be POST when only POST is available',
)
})

test('getPreferredMethod: post only', (t) => {
const postOnlyMethods: Method[] = ['POST']
t.is(
getPreferredMethod(postOnlyMethods, 'POST', postEndpoint),
'POST',
'Preferred method should be POST when only POST is available',
)
})

const getPostEndpoint: OpenapiOperation = {
summary: '/workspaces/get',
responses: {
'200': {
description: 'OK',
content: {
'application/json': {
schema: {
type: 'object',
properties: {
workspace: {
type: 'object',
$ref: '#/components/schemas/workspace',
},
ok: {
type: 'boolean',
},
},
required: ['workspace', 'ok'],
},
},
},
},
},
operationId: 'workspacesGetPost',
}

test('getSemanticMethod: get and post', (t) => {
const bothMethods: Method[] = ['GET', 'POST']
t.is(
getSemanticMethod(bothMethods),
'GET',
'Semantic method should be GET when both GET and POST are available',
)
})

test('getPreferredMethod: get and post without complex parameters', (t) => {
const bothMethods: Method[] = ['GET', 'POST']
t.is(
getPreferredMethod(bothMethods, 'GET', getPostEndpoint),
'GET',
'Preferred method should be GET when both methods are available and no complex parameters',
)
})

const getPostComplexParamsEndpoint: OpenapiOperation = {
...getPostEndpoint,
requestBody: {
content: {
'application/json': {
schema: {
type: 'object',
properties: {
complexParam: { type: 'object' },
},
},
},
},
},
}

test('getPreferredMethod: get and post with complex parameters', (t) => {
const bothMethods: Method[] = ['GET', 'POST']
t.is(
getPreferredMethod(bothMethods, 'GET', getPostComplexParamsEndpoint),
'POST',
'Preferred method should be POST when both GET and POST are available and complex parameters are present',
)
})

const patchPostEndpoint: OpenapiOperation = {
summary: '/user_identities/update',
responses: {
'200': {
description: 'OK',
content: {
'application/json': {
schema: {
properties: {
ok: {
type: 'boolean',
},
},
required: ['ok'],
},
},
},
},
'400': {
description: 'Bad Request',
},
'401': {
description: 'Unauthorized',
},
},
security: [
{ pat_with_workspace: [] },
{ console_session: [] },
{ api_key: [] },
],
requestBody: {
content: {
'application/json': {
schema: {
type: 'object',
properties: {
user_identity_id: {
type: 'string',
format: 'uuid',
},
user_identity_key: {
type: 'string',
},
email_address: {
type: 'string',
format: 'email',
},
phone_number: {
type: 'string',
},
full_name: {
type: 'string',
},
},
required: ['user_identity_id'],
},
},
},
},
tags: ['/user_identities'],
operationId: 'userIdentitiesUpdatePost',
}

test('getSemanticMethod: patch and post', (t) => {
const patchPostMethods: Method[] = ['PATCH', 'POST']
t.is(
getSemanticMethod(patchPostMethods),
'PATCH',
'Semantic method should be PATCH when both PATCH and POST are available',
)
})

test('getPreferredMethod: patch and post', (t) => {
const patchPostMethods: Method[] = ['PATCH', 'POST']
t.is(
getPreferredMethod(patchPostMethods, 'PATCH', patchPostEndpoint),
'PATCH',
'Preferred method should be PATCH when both PATCH and POST are available',
)
})

const deletePostEndpoint: OpenapiOperation = {
summary: '/user_identities/delete',
responses: {
'200': {
description: 'OK',
content: {
'application/json': {
schema: {
properties: {
ok: {
type: 'boolean',
},
},
required: ['ok'],
},
},
},
},
'400': {
description: 'Bad Request',
},
'401': {
description: 'Unauthorized',
},
},
security: [
{ api_key: [] },
{ pat_with_workspace: [] },
{ console_session: [] },
],
requestBody: {
content: {
'application/json': {
schema: {
type: 'object',
properties: {
user_identity_id: {
type: 'string',
format: 'uuid',
},
},
required: ['user_identity_id'],
},
},
},
},
tags: ['/user_identities'],
operationId: 'userIdentitiesDeletePost',
}

test('getSemanticMethod: delete and post', (t) => {
const deletePostMethods: Method[] = ['DELETE', 'POST']
t.is(
getSemanticMethod(deletePostMethods),
'DELETE',
'Semantic method should be DELETE when both DELETE and POST are available',
)
})

test('getPreferredMethod: delete and post', (t) => {
const deletePostMethods: Method[] = ['DELETE', 'POST']
t.is(
getPreferredMethod(deletePostMethods, 'DELETE', deletePostEndpoint),
'POST',
'Preferred method should be POST when both DELETE and POST are available',
)
})
Loading

0 comments on commit 3ab1aa3

Please sign in to comment.