Handle Postman URL query and variable fields

This commit is contained in:
Gregory Schier
2024-09-17 05:58:21 -07:00
parent 29d2d0ec62
commit 92ac91733e
7 changed files with 356 additions and 73 deletions

View File

@@ -1,4 +1,13 @@
import { Environment, Folder, HttpRequest, HttpRequestHeader, Model, Workspace, Context } from '@yaakapp/api';
import {
Environment,
Folder,
HttpRequest,
HttpRequestHeader,
Model,
Workspace,
Context,
HttpUrlParameter,
} from '@yaakapp/api';
const POSTMAN_2_1_0_SCHEMA = 'https://schema.getpostman.com/json/collection/v2.1.0/collection.json';
const POSTMAN_2_0_0_SCHEMA = 'https://schema.getpostman.com/json/collection/v2.0.0/collection.json';
@@ -84,6 +93,8 @@ export function pluginHookImport(
headers.push(bodyPatchHeader);
}
const { url, urlParameters } = convertUrl(r.url);
const request: ExportResources['httpRequests'][0] = {
model: 'http_request',
id: generateId('http_request'),
@@ -91,7 +102,8 @@ export function pluginHookImport(
folderId,
name: v.name,
method: r.method || 'GET',
url: typeof r.url === 'string' ? r.url : convertUrl(toRecord(r.url)),
url,
urlParameters,
body: bodyPatch.body,
bodyType: bodyPatch.bodyType,
authentication: authPatch.authentication,
@@ -111,11 +123,13 @@ export function pluginHookImport(
return { resources: convertTemplateSyntax(exportResources) };
}
function convertUrl(url: Record<string, any>) {
if ('raw' in url) {
return url.raw;
function convertUrl(url: string | any): Pick<HttpRequest, 'url' | 'urlParameters'> {
if (typeof url === 'string') {
return { url, urlParameters: [] };
}
url = toRecord(url);
let v = '';
if ('protocol' in url && typeof url.protocol === 'string') {
@@ -134,9 +148,25 @@ function convertUrl(url: Record<string, any>) {
v += `/${Array.isArray(url.path) ? url.path.join('/') : url.path}`;
}
const params: HttpUrlParameter[] = [];
if ('query' in url && Array.isArray(url.query) && url.query.length > 0) {
const qs = url.query.map(q => `${q.key ?? ''}=${q.value ?? ''}`).join('&');
v += `?${qs}`;
for (const query of url.query) {
params.push({
name: query.key ?? '',
value: query.value ?? '',
enabled: !query.disabled,
});
}
}
if ('variable' in url && Array.isArray(url.variable) && url.variable.length > 0) {
for (const v of url.variable) {
params.push({
name: ':' + (v.key ?? ''),
value: v.value ?? '',
enabled: !v.disabled,
});
}
}
if ('hash' in url && typeof url.hash === 'string') {
@@ -145,7 +175,7 @@ function convertUrl(url: Record<string, any>) {
// TODO: Implement url.variables (path variables)
return v;
return { url: v, urlParameters: params };
}
function importAuth(

View File

@@ -0,0 +1,77 @@
{
"resources": {
"workspaces": [
{
"model": "workspace",
"id": "GENERATE_ID::WORKSPACE_0",
"name": "New Collection",
"description": "",
"variables": []
}
],
"environments": [],
"httpRequests": [
{
"model": "http_request",
"id": "GENERATE_ID::HTTP_REQUEST_0",
"workspaceId": "GENERATE_ID::WORKSPACE_0",
"folderId": "GENERATE_ID::FOLDER_1",
"name": "Request 1",
"method": "GET",
"url": "",
"urlParameters": [],
"body": {},
"bodyType": null,
"authentication": {},
"authenticationType": null,
"headers": []
},
{
"model": "http_request",
"id": "GENERATE_ID::HTTP_REQUEST_1",
"workspaceId": "GENERATE_ID::WORKSPACE_0",
"folderId": "GENERATE_ID::FOLDER_0",
"name": "Request 2",
"method": "GET",
"url": "",
"urlParameters": [],
"body": {},
"bodyType": null,
"authentication": {},
"authenticationType": null,
"headers": []
},
{
"model": "http_request",
"id": "GENERATE_ID::HTTP_REQUEST_2",
"workspaceId": "GENERATE_ID::WORKSPACE_0",
"folderId": null,
"name": "Request 3",
"method": "GET",
"url": "",
"urlParameters": [],
"body": {},
"bodyType": null,
"authentication": {},
"authenticationType": null,
"headers": []
}
],
"folders": [
{
"model": "folder",
"workspaceId": "GENERATE_ID::WORKSPACE_0",
"id": "GENERATE_ID::FOLDER_0",
"name": "Top Folder",
"folderId": null
},
{
"model": "folder",
"workspaceId": "GENERATE_ID::WORKSPACE_0",
"id": "GENERATE_ID::FOLDER_1",
"name": "Nested Folder",
"folderId": "GENERATE_ID::FOLDER_0"
}
]
}
}

View File

@@ -0,0 +1,136 @@
{
"info": {
"_postman_id": "9e6dfada-256c-49ea-a38f-7d1b05b7ca2d",
"name": "New Collection",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
"_exporter_id": "18798"
},
"item": [
{
"name": "Form URL",
"request": {
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "baeare",
"type": "string"
}
]
},
"method": "POST",
"header": [
{
"key": "X-foo",
"value": "bar",
"description": "description"
},
{
"key": "Disabled",
"value": "tnroant",
"description": "ntisorantosra",
"disabled": true
}
],
"body": {
"mode": "formdata",
"formdata": [
{
"key": "Key",
"contentType": "Custom/COntent",
"description": "DEscription",
"type": "file",
"src": "/Users/gschier/Desktop/Screenshot 2024-05-31 at 12.05.11PM.png"
}
]
},
"url": {
"raw": "example.com/:foo/:bar?q=qqq&",
"host": [
"example",
"com"
],
"path": [
":foo",
":bar"
],
"query": [
{
"key": "disabled",
"value": "secondvalue",
"description": "this is disabled",
"disabled": true
},
{
"key": "q",
"value": "qqq",
"description": "hello"
},
{
"key": "",
"value": null
}
],
"variable": [
{
"key": "foo",
"value": "fff",
"description": "Description"
},
{
"key": "bar",
"value": "bbb",
"description": "bbb description"
}
]
}
},
"response": []
}
],
"auth": {
"type": "basic",
"basic": [
{
"key": "password",
"value": "globalpass",
"type": "string"
},
{
"key": "username",
"value": "globaluser",
"type": "string"
}
]
},
"event": [
{
"listen": "prerequest",
"script": {
"type": "text/javascript",
"packages": {},
"exec": [
""
]
}
},
{
"listen": "test",
"script": {
"type": "text/javascript",
"packages": {},
"exec": [
""
]
}
}
],
"variable": [
{
"key": "COLLECTION VARIABLE",
"value": "collection variable",
"type": "string"
}
]
}

View File

@@ -0,0 +1,90 @@
{
"resources": {
"workspaces": [
{
"model": "workspace",
"id": "GENERATE_ID::WORKSPACE_1",
"name": "New Collection",
"description": "",
"variables": [
{
"name": "COLLECTION VARIABLE",
"value": "collection variable"
}
]
}
],
"environments": [],
"httpRequests": [
{
"model": "http_request",
"id": "GENERATE_ID::HTTP_REQUEST_3",
"workspaceId": "GENERATE_ID::WORKSPACE_1",
"folderId": null,
"name": "Form URL",
"method": "POST",
"url": "example.com/:foo/:bar",
"urlParameters": [
{
"name": "disabled",
"value": "secondvalue",
"enabled": false
},
{
"name": "q",
"value": "qqq",
"enabled": true
},
{
"name": "",
"value": "",
"enabled": true
},
{
"name": ":foo",
"value": "fff",
"enabled": true
},
{
"name": ":bar",
"value": "bbb",
"enabled": true
}
],
"body": {
"form": [
{
"enabled": true,
"contentType": "Custom/COntent",
"name": "Key",
"file": "/Users/gschier/Desktop/Screenshot 2024-05-31 at 12.05.11PM.png"
}
]
},
"bodyType": "multipart/form-data",
"authentication": {
"token": ""
},
"authenticationType": "bearer",
"headers": [
{
"name": "X-foo",
"value": "bar",
"enabled": true
},
{
"name": "Disabled",
"value": "tnroant",
"enabled": false
},
{
"name": "Content-Type",
"value": "multipart/form-data",
"enabled": true
}
]
}
],
"folders": []
}
}

View File

@@ -1,4 +1,4 @@
import { Context, Model } from '@yaakapp/api';
import { Context } from '@yaakapp/api';
import * as fs from 'node:fs';
import * as path from 'node:path';
import { describe, expect, test } from 'vitest';
@@ -11,71 +11,16 @@ describe('importer-postman', () => {
const fixtures = fs.readdirSync(p);
for (const fixture of fixtures) {
if (fixture.includes('.output')) {
continue;
}
test('Imports ' + fixture, () => {
const contents = fs.readFileSync(path.join(p, fixture), 'utf-8');
const imported = pluginHookImport(ctx, contents);
const folder0 = newId('folder');
const folder1 = newId('folder');
expect(imported).toEqual({
resources: expect.objectContaining({
workspaces: [
expect.objectContaining({
id: newId('workspace'),
model: 'workspace',
name: 'New Collection',
}),
],
folders: expect.arrayContaining([
expect.objectContaining({
id: folder0,
model: 'folder',
workspaceId: existingId('workspace'),
name: 'Top Folder',
}),
expect.objectContaining({
folderId: folder0,
id: folder1,
model: 'folder',
workspaceId: existingId('workspace'),
name: 'Nested Folder',
}),
]),
httpRequests: expect.arrayContaining([
expect.objectContaining({
id: newId('http_request'),
model: 'http_request',
name: 'Request 1',
workspaceId: existingId('workspace'),
folderId: folder1,
}),
expect.objectContaining({
id: newId('http_request'),
model: 'http_request',
name: 'Request 2',
workspaceId: existingId('workspace'),
folderId: folder0,
}),
expect.objectContaining({
id: newId('http_request'),
model: 'http_request',
name: 'Request 3',
workspaceId: existingId('workspace'),
folderId: null,
}),
]),
}),
});
const expected = fs.readFileSync(path.join(p, fixture.replace('.input', '.output')), 'utf-8');
const result = pluginHookImport(ctx, contents);
// console.log(JSON.stringify(result, null, 2))
expect(result).toEqual(JSON.parse(expected));
});
}
});
const idCount: Partial<Record<Model['model'], number>> = {};
function newId(model: Model['model']): string {
idCount[model] = (idCount[model] ?? -1) + 1;
return `GENERATE_ID::${model.toUpperCase()}_${idCount[model]}`;
}
function existingId(model: Model['model']): string {
return `GENERATE_ID::${model.toUpperCase()}_${idCount[model] ?? 0}`;
}

View File

@@ -10,13 +10,13 @@
"dependencies": {
"@xmldom/xmldom": "^0.8.10",
"@yaakapp/api": "^0.1.14",
"@yaakapp/cli": "^0.0.42",
"jsonpath-plus": "^9.0.0",
"xpath": "^0.0.34"
},
"devDependencies": {
"@types/jsonpath": "^0.2.4",
"@types/node": "^20.14.9",
"@yaakapp/cli": "^0.0.42",
"typescript": "^5.5.2",
"vitest": "^1.4.0"
}
@@ -766,6 +766,7 @@
"version": "0.0.42",
"resolved": "https://registry.npmjs.org/@yaakapp/cli/-/cli-0.0.42.tgz",
"integrity": "sha512-HFkg49sksZNQQpnOgZGfyh8pmHbxtkgSNCeEMlaSFezq42YZPHxOPlqTEGxk3JqX6Asz0YO2xJDfUADQCyKNYA==",
"dev": true,
"hasInstallScript": true,
"bin": {
"yaakcli": "bin/cli.js"
@@ -781,6 +782,7 @@
"version": "0.0.42",
"resolved": "https://registry.npmjs.org/@yaakapp/cli-darwin-arm64/-/cli-darwin-arm64-0.0.42.tgz",
"integrity": "sha512-l8+N/9jwvAYlMQBPfGzNkVoQsYeBtwM3/7ix5b6mT+3zcwrNIDW9HQTEZ2ZTNdo1H548U1F6ppvhAyOdOtIyLg==",
"dev": true,
"optional": true,
"os": [
"darwin"
@@ -790,6 +792,7 @@
"version": "0.0.42",
"resolved": "https://registry.npmjs.org/@yaakapp/cli-darwin-x64/-/cli-darwin-x64-0.0.42.tgz",
"integrity": "sha512-grm9UOVCNIpHO3XsEzvvoic43cYCxmuvrUFP/8MZLQgZeQ5L6EBTAlCTtXD2hUGW60+kNNwcgPrDVVrP7Wn2YQ==",
"dev": true,
"optional": true,
"os": [
"darwin"
@@ -799,6 +802,7 @@
"version": "0.0.42",
"resolved": "https://registry.npmjs.org/@yaakapp/cli-linux-x64/-/cli-linux-x64-0.0.42.tgz",
"integrity": "sha512-O4ly25zR0BVIN0KxUcc7hmmcdNiRq4tQACuYNMIQ2ppFJYCguSMmGFdeJuyCfvcC/SwJIK6/Kzkr8EAmaTjDOA==",
"dev": true,
"optional": true,
"os": [
"linux"
@@ -808,6 +812,7 @@
"version": "0.0.42",
"resolved": "https://registry.npmjs.org/@yaakapp/cli-win32-x64/-/cli-win32-x64-0.0.42.tgz",
"integrity": "sha512-40BTVcOBIP8VYwD1wfrr6tXG6NQuGz+XDA/ean4AWQWHi1P7BWHC9/uqHlMTLhFvbjcHjtwAl7bzVrXr37E0YQ==",
"dev": true,
"optional": true,
"os": [
"win32"