Skip to content

Commit

Permalink
write tests for run (#2626)
Browse files Browse the repository at this point in the history
  • Loading branch information
niclim authored Dec 22, 2023
1 parent dd75633 commit 649eab4
Show file tree
Hide file tree
Showing 10 changed files with 467 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`run can include files in gitignore with -I and file paths 1`] = `
"Optic matched 1 OpenAPI specification file:
openapi-local.yml
--------------------------------------------------------------------------------------------------
┌─────────────────────────────────┐
│ [1] Optic Cloud [2] │
└───┬─────────────────────────▲───┘
│Compare Update│
┌───▼─────────────────────────┴───┐
│ Local specs │
└─────────────────────────────────┘
replaced line
replaced line
--------------------------------------------------------------------------------------------------
Pass a GITHUB_TOKEN or OPTIC_GITLAB_TOKEN environment variable with write permission to let Optic post comment with API change summaries to your pull requests.
Uploading diff...
| a spec [openapi-local.yml]
| Report: 👁️ http://localhost:3001/organizations/org-id/apis/generated-api/runs/run-id
| Changes: 2 operations added, 1 removed
| Rules: ✅ 5/5 passed
| Tests: Set up API contract testing for this spec: https://www.useoptic.com/docs/verify-openapi
💬 Configure commenting on PR/MR: https://www.useoptic.com/docs/setup-ci#configure-commenting-on-pull-requests-optional
"
`;

exports[`run ignores files in gitignore 1`] = `
"Optic matched 1 OpenAPI specification file:
openapi.yml
--------------------------------------------------------------------------------------------------
┌─────────────────────────────────┐
│ [1] Optic Cloud [2] │
└───┬─────────────────────────▲───┘
│Compare Update│
┌───▼─────────────────────────┴───┐
│ Local specs │
└─────────────────────────────────┘
replaced line
replaced line
--------------------------------------------------------------------------------------------------
Pass a GITHUB_TOKEN or OPTIC_GITLAB_TOKEN environment variable with write permission to let Optic post comment with API change summaries to your pull requests.
Uploading diff...
| a spec [openapi.yml]
| Report: 👁️ http://localhost:3001/organizations/org-id/apis/generated-api/runs/run-id
| Changes: 2 operations added, 1 removed
| Rules: ✅ 5/5 passed
| Tests: Set up API contract testing for this spec: https://www.useoptic.com/docs/verify-openapi
💬 Configure commenting on PR/MR: https://www.useoptic.com/docs/setup-ci#configure-commenting-on-pull-requests-optional
"
`;

exports[`run runs and diffs against APIs and runs capture 1`] = `
"Optic matched 1 OpenAPI specification file:
openapi.yml
--------------------------------------------------------------------------------------------------
┌─────────────────────────────────┐
│ [1] Optic Cloud [2] │
└───┬─────────────────────────▲───┘
│Compare Update│
┌───▼─────────────────────────┴───┐
│ Local specs │
└─────────────────────────────────┘
replaced line
replaced line
--------------------------------------------------------------------------------------------------
Pass a GITHUB_TOKEN or OPTIC_GITLAB_TOKEN environment variable with write permission to let Optic post comment with API change summaries to your pull requests.
Uploading diff...
| a spec [openapi.yml]
| Report: 👁️ http://localhost:3001/organizations/org-id/apis/generated-api/runs/run-id
| Changes: 2 operations added, 1 removed
| Rules: ⚠️  1/3 failed
| Tests: 🆕 5 undocumented paths ⚠️ 1 mismatch
Errors were found: exiting with code 1. Disable this behaviour with the \`--severity none\` option.
💬 Configure commenting on PR/MR: https://www.useoptic.com/docs/setup-ci#configure-commenting-on-pull-requests-optional
"
`;
7 changes: 6 additions & 1 deletion projects/optic/src/__tests__/integration/capture.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,12 @@ beforeEach(async () => {
oldEnv = { ...process.env };
process.env.LOG_LEVEL = 'info';
process.env.OPTIC_ENV = 'local';
port = String(await portfinder.getPortPromise());
port = String(
await portfinder.getPortPromise({
port: 8000,
stopPort: 9000,
})
);
process.env.PORT = port;
});

Expand Down
152 changes: 152 additions & 0 deletions projects/optic/src/__tests__/integration/run.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
import {
test,
expect,
describe,
jest,
beforeEach,
afterEach,
} from '@jest/globals';
import {
runOptic,
setupWorkspace,
normalizeWorkspace,
run,
setupTestServer,
} from './integration';
import portfinder from 'portfinder';

jest.setTimeout(30000);

let oldEnv: any;
beforeEach(async () => {
oldEnv = { ...process.env };
process.env.LOG_LEVEL = 'info';
process.env.OPTIC_ENV = 'local';
process.env.OPTIC_TOKEN = '123';
process.env.GITHUB_BASE_REF = 'main';
process.env.CI = 'true';
delete process.env.GITHUB_TOKEN;
});

afterEach(() => {
process.env = { ...oldEnv };
});

async function setPortInFile(workspace: string, file: string, port: string) {
// Set the port in the optic yml for an available port
await run(`sed -i.bak 's/%PORT/${port}/' ${file} ${file}`, false, workspace);
}

function sanitizeOutput(out: string) {
return out.replace(/\[[1|2]\]: `.+` tag\n/g, 'replaced line\n');
}

setupTestServer(({ url, method }) => {
if (method === 'POST' && /\/api\/specs\/prepare$/.test(url)) {
return JSON.stringify({
spec_id: 'already-uploaded',
});
} else if (method === 'POST' && /\/api\/runs\/prepare$/.test(url)) {
return JSON.stringify({
check_results_url: `${process.env.BWTS_HOST_OVERRIDE}/special-s3-route`,
upload_id: '123',
});
} else if (method === 'POST' && /\/api\/verifications\/prepare$/.test(url)) {
return JSON.stringify({
url: `${process.env.BWTS_HOST_OVERRIDE}/special-s3-route`,
upload_id: '123',
});
} else if (method === 'POST' && /\api\/verifications$/.test(url)) {
return JSON.stringify({
id: 'verification-id',
});
} else if (method === 'POST' && /\/api\/runs2$/.test(url)) {
return JSON.stringify({
id: 'run-id',
});
} else if (method === 'GET' && /spec$/.test(url)) {
return `{"openapi":"3.1.0","paths":{ "/api/users": { "get": { "responses":{} }}},"info":{"version":"0.0.0","title":"Empty"}}`;
} else if (method === 'GET' && /sourcemap$/.test(url)) {
return `{"rootFilePath":"empty.json","files":[{"path":"empty.json","sha256":"815b8e5491a1f491765084f236c741d5073e10fcece23436f2db84a8c788db09","contents":"{'openapi':'3.1.0','paths':{ '/api/users': { 'get': { 'responses':{} }}},'info':{'version':'0.0.0','title':'Empty'}}","index":0}],"refMappings":{}}`;
} else if (method === 'GET' && /api\/apis\/.*\/specs\/.*$/.test(url)) {
return JSON.stringify({
id: 'run-id',
specUrl: `${process.env.BWTS_HOST_OVERRIDE}/spec`,
sourcemapUrl: `${process.env.BWTS_HOST_OVERRIDE}/sourcemap`,
});
} else if (method === 'GET' && /\/api\/apis/.test(url)) {
return JSON.stringify({
apis: [null],
});
} else if (method === 'POST' && /\/api\/api$/.test(url)) {
return JSON.stringify({
id: 'generated-api',
});
} else if (method === 'GET' && /\/api\/token\/orgs/.test(url)) {
return JSON.stringify({
organizations: [{ id: 'org-id', name: 'org-blah' }],
});
}
return JSON.stringify({});
});

describe('run', () => {
test('runs and diffs against APIs and runs capture', async () => {
const workspace = await setupWorkspace('run/multi-spec', {
repo: true,
commit: true,
});
const port = String(
await portfinder.getPortPromise({
port: 9000,
stopPort: 10000,
})
);
process.env.PORT = port;
await setPortInFile(workspace, 'optic.yml', port);
const { combined, code } = await runOptic(workspace, 'run');
expect(
sanitizeOutput(normalizeWorkspace(workspace, combined))
).toMatchSnapshot();
expect(code).toBe(1);
});

test('ignores files in gitignore', async () => {
const workspace = await setupWorkspace('run/gitignore', {
repo: true,
commit: true,
});

await run(
`cp openapi.yml openapi-local.yml && echo openapi-local.yml > .gitignore`,
false,
workspace
);

const { combined, code } = await runOptic(workspace, 'run');
expect(
sanitizeOutput(normalizeWorkspace(workspace, combined))
).toMatchSnapshot();
expect(code).toBe(0);
});

test('can include files in gitignore with -I and file paths', async () => {
const workspace = await setupWorkspace('run/gitignore', {
repo: true,
commit: true,
});
await run(
`cp openapi.yml openapi-local.yml && echo openapi-local.yml > .gitignore`,
false,
workspace
);
const { combined, code } = await runOptic(
workspace,
'run openapi-local.yml -I'
);
expect(
sanitizeOutput(normalizeWorkspace(workspace, combined))
).toMatchSnapshot();
expect(code).toBe(0);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
openapi: 3.0.3
info:
title: a spec
description: The API
version: 0.1.0
paths:
/books:
post:
"responses": {}
get:
# a comment about something
responses:
"200":
description: 200 response
content:
application/json:
schema:
# use the refs here
$ref: "#/components/schemas/GetBooks200ResponseBody"
components:
schemas:
# this is a schema
GetBooks200ResponseBody:
type: object
properties:
books:
type: array
items:
type: object
properties:
id:
type: string
author_id:
type: number
status:
type: string
enum:
- ready
- not_ready
price:
type: number
maximum: 6
minimum: 2
required:
- id
- author_id
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ruleset:
- naming:
properties: snake_case
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
openapi: 3.0.3
info:
title: a spec
description: The API
version: 0.1.0
paths:
/books:
post:
"responses": {}
get:
# a comment about something
responses:
"200":
description: 200 response
content:
application/json:
schema:
# use the refs here
$ref: "#/components/schemas/GetBooks200ResponseBody"
components:
schemas:
# this is a schema
GetBooks200ResponseBody:
type: object
properties:
books:
type: array
items:
type: object
properties:
id:
type: string
author_id:
type: number
status:
type: string
enum:
- ready
- not_ready
price:
type: number
maximum: 6
minimum: 2
required:
- id
- author_id
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
ruleset:
- breaking-changes
- naming:
pathComponents: camelCase
capture:
openapi.yml:
server:
command: node server.js
url: http://localhost:%PORT
ready_endpoint: /healthcheck
requests:
send:
- path: /
- path: /books
method: GET
- path: /books/asd
method: GET
- path: /books/def
method: GET
- path: /books/asd
method: POST
data:
name: asd
price: 1
author_id: 6nTxAFM5ck4Hob77hGQoL
- path: /authors
method: GET
Loading

0 comments on commit 649eab4

Please sign in to comment.