Skip to content

Commit

Permalink
Refactor getDereferencedOpenAPIDocument and improve test QUALITY
Browse files Browse the repository at this point in the history
  • Loading branch information
p10ns11y committed Nov 12, 2024
1 parent eb4946a commit 04b1c3a
Show file tree
Hide file tree
Showing 10 changed files with 95 additions and 77 deletions.
2 changes: 1 addition & 1 deletion coverage-badge.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions coverage/coverage-summary.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{"total": {"lines":{"total":197,"covered":187,"skipped":0,"pct":94.92},"statements":{"total":197,"covered":187,"skipped":0,"pct":94.92},"functions":{"total":8,"covered":7,"skipped":0,"pct":87.5},"branches":{"total":81,"covered":72,"skipped":0,"pct":88.88},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}}
{"total": {"lines":{"total":197,"covered":197,"skipped":0,"pct":100},"statements":{"total":197,"covered":197,"skipped":0,"pct":100},"functions":{"total":8,"covered":8,"skipped":0,"pct":100},"branches":{"total":82,"covered":75,"skipped":0,"pct":91.46},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}}
,"/Users/peram/code/adaptate/packages/core/src/index.ts": {"lines":{"total":82,"covered":82,"skipped":0,"pct":100},"functions":{"total":3,"covered":3,"skipped":0,"pct":100},"statements":{"total":82,"covered":82,"skipped":0,"pct":100},"branches":{"total":36,"covered":36,"skipped":0,"pct":100}}
,"/Users/peram/code/adaptate/packages/utils/src/load-yaml.ts": {"lines":{"total":14,"covered":14,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":14,"covered":14,"skipped":0,"pct":100},"branches":{"total":1,"covered":1,"skipped":0,"pct":100}}
,"/Users/peram/code/adaptate/packages/utils/src/openapi.ts": {"lines":{"total":101,"covered":91,"skipped":0,"pct":90.09},"functions":{"total":4,"covered":3,"skipped":0,"pct":75},"statements":{"total":101,"covered":91,"skipped":0,"pct":90.09},"branches":{"total":44,"covered":35,"skipped":0,"pct":79.54}}
,"/Users/peram/code/adaptate/packages/utils/src/openapi.ts": {"lines":{"total":101,"covered":101,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":101,"covered":101,"skipped":0,"pct":100},"branches":{"total":45,"covered":38,"skipped":0,"pct":84.44}}
}
Binary file added images/coverage-report-11-12-2024.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"scripts": {
"test": "vitest --coverage",
"build": "turbo run build",
"coveragebadge": "npx make-coverage-badge --output-path ./coverage-badge.svg"
"coveragebadge": "pnpm run test && npx make-coverage-badge --output-path ./coverage-badge.svg"
},
"devDependencies": {
"@types/jest": "^29.5.14",
Expand Down
Binary file added packages/core/images/get-openapi-spec.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
49 changes: 23 additions & 26 deletions packages/core/src/__tests__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import { describe, it, expect } from 'vitest';

import { z } from 'zod';

// NOTE to Self: In test it better import directly from source
// It is easy to forget building the dependencies
// Introduce special import map `#adaptate/utils/openapi`
import {
getDereferencedOpenAPIDocument,
openAPISchemaToZod,
Expand Down Expand Up @@ -56,7 +59,6 @@ describe('makeSchemaRequired', () => {
],
},
type: 'electronics',
warrantyPeriod: '2 years',
};

let invalidDataMissingName = {
Expand Down Expand Up @@ -113,13 +115,24 @@ describe('makeSchemaRequired', () => {

// Re transforming the schema with different config
// Here making warrantyPeriod required
expect(() =>
makeSchemaRequired(transformedSchema, {
category: {
warrantyPeriod: true,
},
}).parse(invalidDataMissingName)
).toThrow();
let reTransformedSchema = makeSchemaRequired(transformedSchema, {
warrantyPeriod: true,
});

expect(() => reTransformedSchema.parse(validData))
.toThrowErrorMatchingInlineSnapshot(`
[ZodError: [
{
"code": "invalid_type",
"expected": "string",
"received": "undefined",
"path": [
"warrantyPeriod"
],
"message": "Required"
}
]]
`);

expect(() => baseSchema.parse({})).not.toThrow();
expect(() =>
Expand Down Expand Up @@ -158,7 +171,6 @@ describe('makeSchemaRequired', () => {
]]
`);

// TODO: Update code after evaluating the case of list of objects at top level
let anotherValidData = [
{
category: {
Expand Down Expand Up @@ -210,31 +222,16 @@ describe('makeSchemaRequired', () => {
expect(() => anotherTransformedSchema.parse(anotherInValidData)).toThrow();

let dereferencedOpenAPIDocument = await getDereferencedOpenAPIDocument({
environment: 'server',
location: 'filesystem',
callSiteURL: import.meta.url,
relativePathToSpecFile: '../fixtures/base-schema.yml',
});

let dataZodSchema = openAPISchemaToZod(
// @ts-ignore
dereferencedOpenAPIDocument['components']['schemas']['Category']
);

try {
// Intentionally not mocking the fetch call
let dereferencedOpenAPIDocumentFromWeb =
await getDereferencedOpenAPIDocument({
environment: 'browser',
webURL:
'https://raw.githubusercontent.com/p10ns11y/adaptate/refs/heads/main/packages/core/src/fixtures/base-schema.yml',
});

expect(dereferencedOpenAPIDocumentFromWeb).toEqual(
dereferencedOpenAPIDocument
);
} catch (e) {
console.log('Network failure or', (e as any)?.message);
}

let yetAnotherTransformedSchema = makeSchemaRequired(dataZodSchema, config);

expect(() =>
Expand Down
4 changes: 2 additions & 2 deletions packages/utils/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ import { getDereferencedOpenAPIDocument } from '@adaptate/utils';

// from local disk
let dereferencedOpenAPIDocument = await getDereferencedOpenAPIDocument({
environment: 'server',
location: 'filesystem',
callSiteURL: import.meta.url,
relativePathToSpecFile: '../fixtures/base-schema.yml',
});

// or from web

let dereferencedOpenAPIDocument = await getDereferencedOpenAPIDocument({
environment: 'browser',
location: 'web',
webURL: 'https://api.apis.guru/v2/specs/googleapis.com/books/v1/openapi.yaml',
});

Expand Down
64 changes: 57 additions & 7 deletions packages/utils/src/__tests__/openapi.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ describe('openAPISchemaToZod', () => {

it('should convert OpenAPI schema with $ref to another component using openapi-spec-parser', async () => {
let dereferencedOpenAPIDocument = await getDereferencedOpenAPIDocument({
environment: 'server',
location: 'filesystem',
callSiteURL: import.meta.url,
relativePathToSpecFile: '../fixtures/base-schema.yml',
});
Expand Down Expand Up @@ -194,9 +194,9 @@ describe('zodToOpenAPISchema', () => {
});

describe('getDereferencedOpenAPIDocument', () => {
it('should return dereferencedOpenAPIDocument from OpenAPI yml spec file', async () => {
it('should return dereferencedOpenAPIDocument from OpenAPI yml spec file from filesystem', async () => {
let dereferencedOpenAPIDocument = await getDereferencedOpenAPIDocument({
environment: 'server',
location: 'filesystem',
callSiteURL: import.meta.url,
relativePathToSpecFile: '../fixtures/base-schema.yml',
});
Expand Down Expand Up @@ -323,12 +323,62 @@ describe('getDereferencedOpenAPIDocument', () => {

await expect(() =>
getDereferencedOpenAPIDocument({
environment: 'server',
location: 'filesystem',
callSiteURL: import.meta.url,
relativePathToSpecFile: '../fixtures/unknown.yml',
})
).rejects.toThrowErrorMatchingInlineSnapshot(
`[Error: Error reading OpenAPI document: ENOENT: no such file or directory, open '/Users/peram/code/adaptate/packages/utils/src/fixtures/unknown.yml']`
);
).rejects.toThrow(/no such file or directory/i);
});

it('should fetch and parse spec file form web', async () => {
try {
// Intentionally not mocking the fetch call
let dereferencedOpenAPIDocumentFromWeb =
await getDereferencedOpenAPIDocument({
location: 'web',
webURL:
'https://api.apis.guru/v2/specs/googleapis.com/books/v1/openapi.yaml',
});

// @ts-ignore
expect(dereferencedOpenAPIDocumentFromWeb.info).toMatchInlineSnapshot(`
{
"contact": {
"name": "Google",
"url": "https://google.com",
"x-twitter": "youtube",
},
"description": "The Google Books API allows clients to access the Google Books repository.",
"license": {
"name": "Creative Commons Attribution 3.0",
"url": "http://creativecommons.org/licenses/by/3.0/",
},
"termsOfService": "https://developers.google.com/terms/",
"title": "Books API",
"version": "v1",
"x-apiClientRegistration": {
"url": "https://console.developers.google.com",
},
"x-apisguru-categories": [
"analytics",
"media",
],
"x-logo": {
"url": "https://api.apis.guru/v2/cache/logo/https_www.google.com_images_branding_googlelogo_2x_googlelogo_color_272x92dp.png",
},
"x-origin": [
{
"format": "google",
"url": "https://books.googleapis.com/$discovery/rest?version=v1",
"version": "v1",
},
],
"x-providerName": "googleapis.com",
"x-serviceName": "books",
}
`);
} catch (e) {
console.log('Network failure or', (e as any)?.message);
}
});
});
16 changes: 9 additions & 7 deletions packages/utils/src/openapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,20 +85,25 @@ export async function fetchYamlContent(webURL: string) {
headers: {
'Content-Type': 'text/yaml',
},
// Mostly works in server runtime without CORS
// When calling from another domain in client
// Make sure to configure for CORS and the resource
// Also need to allow access
mode: 'cors',
});
let openapiDocument = yaml.load(await response.text());

return openapiDocument;
}

export type ServerOpenAPISpecParams = {
environment: 'server';
location: 'filesystem';
callSiteURL: string;
relativePathToSpecFile: string;
};

export type BrowserOpenAPISpecParams = {
environment: 'browser';
location: 'web';
webURL: string;
};

Expand All @@ -112,13 +117,10 @@ export async function getDereferencedOpenAPIDocument(

let isNodeEnvDetected = globalThis.process?.versions?.node;

// let isBrowserIntended = params.environment === 'browser';
let isBrowserDetected = globalThis?.window?.document;

try {
if (params.environment === 'browser' && isBrowserDetected) {
if (params.location === 'web') {
openapiDocument = (await fetchYamlContent(params.webURL)) as string;
} else if (params.environment === 'server' && isNodeEnvDetected) {
} else if (params.location === 'filesystem' || isNodeEnvDetected) {
let { getYamlContent } = await import('./load-yaml.ts');

openapiDocument = await getYamlContent(
Expand Down
31 changes: 0 additions & 31 deletions tsconfig.jest.json

This file was deleted.

0 comments on commit 04b1c3a

Please sign in to comment.