Import a spec and execute a request (#2887)

* feat: add swagger2 for prism

* feat: add test stub

* feat: can import from clipboard

* feat: click folder, request and send

* chore: add comments

* fix: now it actually breaks

* fix: typo

* fix: update webdriver implicit timeout

* feat: replace prism with tinyhttp (similar to express)
This commit is contained in:
Opender Singh authored and GitHub committed 2020-12-05 10:47:04 +13:00
1 parent a2cf11b23b
commit aeafe4a7c9
12 files changed
+345 -1782

No files matched your search

@@ -1,6 +1,9 @@
import * as debug from '../modules/debug';
import * as client from '../modules/client';
import { launchCore, stop } from '../modules/application';
import * as dropdown from '../modules/dropdown';
import * as settings from '../modules/settings';
import fs from 'fs';
describe('Application launch', function() {
jest.setTimeout(50000);
@@ -30,6 +33,35 @@ describe('Application launch', function() {
await debug.expect200(app);
});
it.each([true, false])(
'imports swagger 2 and sends request: new workspace=%s ',
async newWorkspace => {
await debug.workspaceDropdownExists(app);
// Copy text to clipboard
const buffer = await fs.promises.readFile(`${__dirname}/../fixtures/swagger2.yaml`);
const swagger2Text = buffer.toString();
await app.electron.clipboard.writeText(swagger2Text);
// Click dropdown and open import modal
const workspaceDropdown = await debug.clickWorkspaceDropdown(app);
await dropdown.clickDropdownItemByText(workspaceDropdown, 'Import/Export');
// Import from clipboard into new/current workspace
await settings.importFromClipboard(app, newWorkspace);
// Click imported folder and request
await debug.clickFolderByName(app, 'custom-tag');
await debug.clickRequestByName(app, 'get pet by id');
// Click send
await debug.clickSendRequest(app);
// Ensure 200
await debug.expect200(app);
},
);
it('sends CSV request and shows rich response', async () => {
const url = 'http://127.0.0.1:4010/csv';
@@ -1,7 +1,7 @@
openapi: "3.0.0"
info:
version: 1.0.0
title: E2E testing specification
title: E2E testing specification - openapi 3
description: This is a specification used for E2E testing of Insomnia, and is served via prism
servers:
- url: http://127.0.0.1:4010
@@ -0,0 +1,17 @@
swagger: "2.0"
info:
version: 1.0.0
title: E2E testing specification - swagger 2
description: This is a specification representing the oas3.yaml spec
schemes:
- http
host: 127.0.0.1:4010
tags:
- name: custom-tag
paths:
/pets/1:
get:
summary: get pet by id
operationId: findPetById
tags:
- custom-tag
@@ -70,6 +70,12 @@ const launch = async config => {
// https://github.com/electron-userland/spectron/issues/60
await app.browserWindow.focus();
await app.browserWindow.setAlwaysOnTop(true);
// Set the implicit wait timeout to 0 (webdriver default)
// https://webdriver.io/docs/timeouts.html#session-implicit-wait-timeout
// Spectron overrides it to an unreasonable value, as per the issue
// https://github.com/electron-userland/spectron/issues/763
await app.client.setTimeout({ implicit: 0 });
});
return app;
+35 -7
View File
@@ -4,6 +4,12 @@ export const workspaceDropdownExists = async (app, workspaceName = 'Insomnia') =
await app.client.waitUntilTextExists('.workspace-dropdown', workspaceName);
};
export const clickWorkspaceDropdown = async app => {
const dropdown = await app.client.react$('WorkspaceDropdown');
await dropdown.click();
return dropdown;
};
export const createNewRequest = async (app, name) => {
await app.client.$('.sidebar .dropdown .fa-plus-circle').then(e => e.click());
@@ -31,14 +37,29 @@ export const createNewRequest = async (app, name) => {
};
const waitUntilRequestIsActive = async (app, name) => {
const requestIsActive = async () => {
const requests = await app.client.react$$('SidebarRequestRow', { props: { isActive: true } });
const firstRequest = requests[0];
const activeRequestName = await firstRequest.react$('Editable').then(e => e.getText());
return activeRequestName === name;
};
const request = await app.client.react$('SidebarRequestRow', {
props: { isActive: true, request: { name } },
});
await app.client.waitUntil(requestIsActive);
await request.waitForDisplayed();
};
export const clickFolderByName = async (app, name) => {
const folder = await app.client.react$('SidebarRequestGroupRow', {
props: { requestGroup: { name } },
});
await folder.waitForClickable();
await folder.click();
};
export const clickRequestByName = async (app, name) => {
const folder = await app.client.react$('SidebarRequestRow', {
props: { request: { name } },
});
await folder.waitForClickable();
await folder.click();
};
export const typeInUrlBar = async (app, url) => {
@@ -53,6 +74,13 @@ export const clickSendRequest = async app => {
.react$('RequestUrlBar')
.then(e => e.$('.urlbar__send-btn'))
.then(e => e.click());
// Wait for spinner to show
const spinner = await app.client.react$('ResponseTimer');
await spinner.waitForDisplayed();
// Wait for spinner to hide
await spinner.waitForDisplayed({ reverse: true });
};
export const expect200 = async app => {
@@ -10,3 +10,11 @@ export const clickDropdownItemByText = async (dropdown, text) => {
await item.waitForDisplayed();
await item.click();
};
export const clickOpenDropdownItemByText = async (app, text) => {
const item = await app.client
.$('.dropdown__menu[aria-hidden=false]')
.then(e => e.$(`button*=${text}`));
await item.waitForDisplayed();
await item.click();
};
@@ -20,3 +20,11 @@ export const close = async (app, modalName) => {
await modal.$('button.modal__close-btn').then(e => e.click());
};
export const clickModalFooterByText = async (app, modalName, text) => {
const modal = await app.client.react$(modalName);
await modal.waitForDisplayed();
const btn = await modal.$(`.modal__footer`).then(e => e.$(`button*=${text}`));
await btn.waitForClickable();
await btn.click();
};
@@ -1,6 +1,7 @@
import { clickTabByText } from './tabs';
import { mapAccelerator } from 'spectron-keys';
import * as modal from './modal';
import * as dropdown from './dropdown';
export const openWithKeyboardShortcut = async app => {
await app.client.keys(mapAccelerator('CommandOrControl+,'));
@@ -20,6 +21,17 @@ export const goToPlugins = async app => {
await app.client.react$('Plugins').then(e => e.waitForDisplayed());
};
export const importFromClipboard = async (app, newWorkspace = false) => {
const importExport = await app.client.react$('ImportExport');
await importExport.waitForDisplayed();
await importExport.$('button*=Import Data').then(e => e.click());
await dropdown.clickOpenDropdownItemByText(app, 'From Clipboard');
await modal.clickModalFooterByText(app, 'AskModal', newWorkspace ? 'New Workspace' : 'Current');
};
export const installPlugin = async (app, pluginName) => {
const plugins = await app.client.react$('SettingsModal').then(e => e.react$('Plugins'));
File diff suppressed because it is too large. Load diff
+5 -3
View File
@@ -2,20 +2,22 @@
"private": true,
"name": "insomnia-smoke-test",
"version": "2.2.26",
"type": "module",
"scripts": {
"spectron:core:build": "cross-env BUNDLE=build xvfb-maybe jest --detectOpenHandles --testPathPattern core",
"spectron:designer:build": "cross-env BUNDLE=build xvfb-maybe jest --detectOpenHandles --testPathPattern designer",
"spectron:core:package": "cross-env BUNDLE=package xvfb-maybe jest --detectOpenHandles --testPathPattern core",
"spectron:designer:package": "cross-env BUNDLE=package xvfb-maybe jest --detectOpenHandles --testPathPattern designer",
"start:prism": "prism mock prism/oas3.yaml",
"with-mock": "concurrently --names prism,spectron --success first --kill-others \"npm run start:prism\"",
"serve": "node tinyhttp/index.js",
"with-mock": "concurrently --names server,spectron --success first --kill-others \"npm run serve\"",
"test:core:build": "npm run with-mock \"npm run spectron:core:build\"",
"test:designer:build": "npm run with-mock \"npm run spectron:designer:build\"",
"test:core:package": "npm run with-mock \"npm run spectron:core:package\"",
"test:designer:package": "npm run with-mock \"npm run spectron:designer:package\""
},
"devDependencies": {
"@stoplight/prism-cli": "^3.3.6",
"@tinyhttp/app": "^1.0.2",
"@tinyhttp/logger": "^1.0.2",
"concurrently": "^5.3.0",
"cross-env": "^7.0.2",
"faker": "^5.1.0",
@@ -1,77 +0,0 @@
openapi: "3.0.0"
info:
version: 1.0.0
title: E2E testing specification
description: This is a specification used for E2E testing of Insomnia, and is served via prism
servers:
- url: http://127.0.0.1:4010
paths:
/pets/{id}:
get:
description: Returns a user based on a single ID, if the user does not have access to the pet
operationId: find pet by id
parameters:
- name: id
in: path
description: ID of pet to fetch
required: true
schema:
type: integer
format: int64
responses:
'200':
description: pet response
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
default:
description: unexpected error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/csv:
get:
description: Returns CSV content
responses:
200:
description: Get Todo Items
content:
text/csv:
schema: {}
example: |
a,b,c
1,2,3
components:
schemas:
Pet:
allOf:
- $ref: '#/components/schemas/NewPet'
- type: object
required:
- id
properties:
id:
type: integer
format: int64
NewPet:
type: object
required:
- name
properties:
name:
type: string
tag:
type: string
Error:
type: object
required:
- code
- message
properties:
code:
type: integer
format: int32
message:
type: string
@@ -0,0 +1,19 @@
import { App } from '@tinyhttp/app';
import { logger } from '@tinyhttp/logger';
const app = new App();
app
.use(logger())
.get('/pets/:id', (req, res) => {
setTimeout(() => {
res.status(200).send({ id: req.params.id });
}, 500);
})
.get('/csv', (_, res) => {
res
.status(200)
.header('content-type', 'text/csv')
.send(`a,b,c\n1,2,3`);
})
.listen(4010);