mirror of
https://github.com/usebruno/bruno.git
synced 2026-06-11 09:51:30 +00:00
@@ -13,6 +13,9 @@ const STATIC_API_HINTS = {
|
||||
'req.timeout',
|
||||
'req.getUrl()',
|
||||
'req.setUrl(url)',
|
||||
'req.getHost()',
|
||||
'req.getPath()',
|
||||
'req.getQueryString()',
|
||||
'req.getMethod()',
|
||||
'req.getAuthMode()',
|
||||
'req.setMethod(method)',
|
||||
@@ -27,6 +30,7 @@ const STATIC_API_HINTS = {
|
||||
'req.setTimeout(timeout)',
|
||||
'req.getExecutionMode()',
|
||||
'req.getName()',
|
||||
'req.getPathParams()',
|
||||
'req.getTags()',
|
||||
'req.disableParsingResponseJson()',
|
||||
'req.onFail(function(err) {})'
|
||||
|
||||
@@ -38,10 +38,18 @@ const replacements = {
|
||||
|
||||
// Supported Postman request translations:
|
||||
// - pm.request.url / request.url -> req.getUrl()
|
||||
// - pm.request.url.getHost() -> req.getHost()
|
||||
// - pm.request.url.getPath() -> req.getPath()
|
||||
// - pm.request.url.getQueryString() -> req.getQueryString()
|
||||
// - pm.request.url.variables -> req.getPathParams()
|
||||
// - pm.request.method / request.method -> req.getMethod()
|
||||
// - pm.request.headers / request.headers -> req.getHeaders()
|
||||
// - pm.request.body / request.body -> req.getBody()
|
||||
// - pm.info.requestName / request.name -> req.getName()
|
||||
'pm\\.request\\.url\\.getHost\\(\\)': 'req.getHost()',
|
||||
'pm\\.request\\.url\\.getPath\\(\\)': 'req.getPath()',
|
||||
'pm\\.request\\.url\\.getQueryString\\(\\)': 'req.getQueryString()',
|
||||
'pm\\.request\\.url\\.variables': 'req.getPathParams()',
|
||||
'pm\\.request\\.url': 'req.getUrl()',
|
||||
'pm\\.request\\.method': 'req.getMethod()',
|
||||
'pm\\.request\\.headers': 'req.getHeaders()',
|
||||
|
||||
@@ -38,6 +38,10 @@ const simpleTranslations = {
|
||||
'pm.info.requestName': 'req.getName()',
|
||||
|
||||
// Request properties (pm.request.*)
|
||||
'pm.request.url.getHost': 'req.getHost',
|
||||
'pm.request.url.getPath': 'req.getPath',
|
||||
'pm.request.url.getQueryString': 'req.getQueryString',
|
||||
'pm.request.url.variables': 'req.getPathParams()',
|
||||
'pm.request.url': 'req.getUrl()',
|
||||
'pm.request.method': 'req.getMethod()',
|
||||
'pm.request.headers': 'req.getHeaders()',
|
||||
|
||||
@@ -42,4 +42,20 @@ describe('postmanTranslations - request commands', () => {
|
||||
`;
|
||||
expect(postmanTranslation(inputScript)).toBe(expectedOutput);
|
||||
});
|
||||
|
||||
test('should handle pm.request.url helper methods', () => {
|
||||
const inputScript = `
|
||||
const host = pm.request.url.getHost();
|
||||
const path = pm.request.url.getPath();
|
||||
const queryString = pm.request.url.getQueryString();
|
||||
const pathVariables = pm.request.url.variables;
|
||||
`;
|
||||
const expectedOutput = `
|
||||
const host = req.getHost();
|
||||
const path = req.getPath();
|
||||
const queryString = req.getQueryString();
|
||||
const pathVariables = req.getPathParams();
|
||||
`;
|
||||
expect(postmanTranslation(inputScript)).toBe(expectedOutput);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -332,9 +332,6 @@ const configureRequest = async (
|
||||
request.url = urlObj.toString();
|
||||
}
|
||||
|
||||
// Remove pathParams, already in URL (Issue #2439)
|
||||
delete request.pathParams;
|
||||
|
||||
// Remove apiKeyAuthValueForQueryParams, already interpolated and added to URL
|
||||
delete request.apiKeyAuthValueForQueryParams;
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ class BrunoRequest {
|
||||
this.headers = req.headers;
|
||||
this.timeout = req.timeout;
|
||||
this.name = req.name;
|
||||
this.pathParams = req.pathParams;
|
||||
this.tags = req.tags || [];
|
||||
/**
|
||||
* We automatically parse the JSON body if the content type is JSON
|
||||
@@ -41,6 +42,53 @@ class BrunoRequest {
|
||||
this.req.url = url;
|
||||
}
|
||||
|
||||
getHost() {
|
||||
try {
|
||||
const url = new URL(this.req.url);
|
||||
return url.host;
|
||||
} catch (e) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
getPath() {
|
||||
try {
|
||||
const url = new URL(this.req.url);
|
||||
let pathname = url.pathname;
|
||||
|
||||
// If path params exist, interpolate them into the pathname
|
||||
if (this.req.pathParams && Array.isArray(this.req.pathParams)) {
|
||||
pathname = pathname
|
||||
.split('/')
|
||||
.map((segment) => {
|
||||
if (segment.startsWith(':')) {
|
||||
const paramName = segment.slice(1);
|
||||
const pathParam = this.req.pathParams.find((param) => param.name === paramName);
|
||||
if (pathParam && pathParam.value) {
|
||||
return pathParam.value;
|
||||
}
|
||||
}
|
||||
return segment;
|
||||
})
|
||||
.join('/');
|
||||
}
|
||||
|
||||
return pathname;
|
||||
} catch (e) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
getQueryString() {
|
||||
try {
|
||||
const url = new URL(this.req.url);
|
||||
// Return query string without the leading '?'
|
||||
return url.search ? url.search.substring(1) : '';
|
||||
} catch (e) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
getMethod() {
|
||||
return this.req.method;
|
||||
}
|
||||
@@ -191,6 +239,16 @@ class BrunoRequest {
|
||||
return this.req.name;
|
||||
}
|
||||
|
||||
getPathParams() {
|
||||
const params = Array.isArray(this.req.pathParams) ? this.req.pathParams : [];
|
||||
|
||||
return params.map((param) => ({
|
||||
name: param.name,
|
||||
value: param.value,
|
||||
type: param.type
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tags associated with this request
|
||||
* @returns {Array<string>} Array of tag strings
|
||||
|
||||
@@ -9,6 +9,7 @@ const addBrunoRequestShimToContext = (vm, req) => {
|
||||
const body = marshallToVm(req.getBody(), vm);
|
||||
const timeout = marshallToVm(req.getTimeout(), vm);
|
||||
const name = marshallToVm(req.getName(), vm);
|
||||
const pathParams = marshallToVm(req.getPathParams(), vm);
|
||||
const tags = marshallToVm(req.getTags(), vm);
|
||||
|
||||
vm.setProp(reqObject, 'url', url);
|
||||
@@ -17,6 +18,7 @@ const addBrunoRequestShimToContext = (vm, req) => {
|
||||
vm.setProp(reqObject, 'body', body);
|
||||
vm.setProp(reqObject, 'timeout', timeout);
|
||||
vm.setProp(reqObject, 'name', name);
|
||||
vm.setProp(reqObject, 'pathParams', pathParams);
|
||||
vm.setProp(reqObject, 'tags', tags);
|
||||
|
||||
url.dispose();
|
||||
@@ -25,6 +27,7 @@ const addBrunoRequestShimToContext = (vm, req) => {
|
||||
body.dispose();
|
||||
timeout.dispose();
|
||||
name.dispose();
|
||||
pathParams.dispose();
|
||||
tags.dispose();
|
||||
|
||||
let getUrl = vm.newFunction('getUrl', function () {
|
||||
@@ -39,6 +42,24 @@ const addBrunoRequestShimToContext = (vm, req) => {
|
||||
vm.setProp(reqObject, 'setUrl', setUrl);
|
||||
setUrl.dispose();
|
||||
|
||||
let getHost = vm.newFunction('getHost', function () {
|
||||
return marshallToVm(req.getHost(), vm);
|
||||
});
|
||||
vm.setProp(reqObject, 'getHost', getHost);
|
||||
getHost.dispose();
|
||||
|
||||
let getPath = vm.newFunction('getPath', function () {
|
||||
return marshallToVm(req.getPath(), vm);
|
||||
});
|
||||
vm.setProp(reqObject, 'getPath', getPath);
|
||||
getPath.dispose();
|
||||
|
||||
let getQueryString = vm.newFunction('getQueryString', function () {
|
||||
return marshallToVm(req.getQueryString(), vm);
|
||||
});
|
||||
vm.setProp(reqObject, 'getQueryString', getQueryString);
|
||||
getQueryString.dispose();
|
||||
|
||||
let getMethod = vm.newFunction('getMethod', function () {
|
||||
return marshallToVm(req.getMethod(), vm);
|
||||
});
|
||||
@@ -57,6 +78,12 @@ const addBrunoRequestShimToContext = (vm, req) => {
|
||||
vm.setProp(reqObject, 'getName', getName);
|
||||
getName.dispose();
|
||||
|
||||
let getPathParams = vm.newFunction('getPathParams', function () {
|
||||
return marshallToVm(req.getPathParams(), vm);
|
||||
});
|
||||
vm.setProp(reqObject, 'getPathParams', getPathParams);
|
||||
getPathParams.dispose();
|
||||
|
||||
let setMethod = vm.newFunction('setMethod', function (method) {
|
||||
req.setMethod(vm.dump(method));
|
||||
});
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
meta {
|
||||
name: getHost
|
||||
type: http
|
||||
seq: 1
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{host}}/ping
|
||||
body: none
|
||||
auth: none
|
||||
}
|
||||
|
||||
assert {
|
||||
res.status: eq 200
|
||||
res.body: eq pong
|
||||
}
|
||||
|
||||
tests {
|
||||
test("req.getHost()", function() {
|
||||
const host = req.getHost();
|
||||
expect(host).to.equal("testbench-sanity.usebruno.com");
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
meta {
|
||||
name: getPath
|
||||
type: http
|
||||
seq: 1
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{host}}/api/users/123
|
||||
body: none
|
||||
auth: none
|
||||
}
|
||||
|
||||
tests {
|
||||
test("req.getPath()", function() {
|
||||
const path = req.getPath();
|
||||
expect(path).to.equal("/api/users/123");
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
meta {
|
||||
name: getPathParam
|
||||
type: http
|
||||
seq: 1
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{host}}/:pathParam
|
||||
body: none
|
||||
auth: none
|
||||
}
|
||||
|
||||
params:path {
|
||||
pathParam: ping
|
||||
}
|
||||
|
||||
tests {
|
||||
test("req.getPathParams()", function() {
|
||||
const pathParams = req.getPathParams();
|
||||
expect(pathParams[0].name).to.equal('pathParam');
|
||||
expect(pathParams[0].value).to.equal('ping');
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
meta {
|
||||
name: getQueryString
|
||||
type: http
|
||||
seq: 1
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{host}}/ping?page=1&limit=10&sort=desc
|
||||
body: none
|
||||
auth: none
|
||||
}
|
||||
|
||||
params:query {
|
||||
page: 1
|
||||
limit: 10
|
||||
sort: desc
|
||||
}
|
||||
|
||||
assert {
|
||||
res.status: eq 200
|
||||
res.body: eq pong
|
||||
}
|
||||
|
||||
tests {
|
||||
test("req.getQueryString()", function() {
|
||||
const queryString = req.getQueryString();
|
||||
expect(queryString).to.equal("page=1&limit=10&sort=desc");
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"version": "1",
|
||||
"name": "url_helpers_test",
|
||||
"type": "collection",
|
||||
"ignore": [
|
||||
"node_modules",
|
||||
".git"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
meta {
|
||||
name: url-helpers-test
|
||||
type: http
|
||||
seq: 1
|
||||
}
|
||||
|
||||
get {
|
||||
url: https://echo.usebruno.com/api/users/:userId?name=john&age=30
|
||||
body: none
|
||||
auth: none
|
||||
}
|
||||
|
||||
params:path {
|
||||
userId: 123
|
||||
}
|
||||
|
||||
script:pre-request {
|
||||
// Test URL helper methods in pre-request script
|
||||
const host = req.getHost();
|
||||
const path = req.getPath();
|
||||
const queryString = req.getQueryString();
|
||||
const pathParams = req.getPathParams();
|
||||
|
||||
// Store values for verification in tests
|
||||
bru.setVar('preReqHost', host);
|
||||
bru.setVar('preReqPath', path);
|
||||
bru.setVar('preReqQueryString', queryString);
|
||||
bru.setVar('preReqPathParams', JSON.stringify(pathParams));
|
||||
}
|
||||
|
||||
script:post-response {
|
||||
// Test URL helper methods in post-response script
|
||||
const host = req.getHost();
|
||||
const path = req.getPath();
|
||||
const queryString = req.getQueryString();
|
||||
const pathParams = req.getPathParams();
|
||||
|
||||
// Store values for verification in tests
|
||||
bru.setVar('postResHost', host);
|
||||
bru.setVar('postResPath', path);
|
||||
bru.setVar('postResQueryString', queryString);
|
||||
bru.setVar('postResPathParams', JSON.stringify(pathParams));
|
||||
}
|
||||
|
||||
tests {
|
||||
test("getHost() returns correct host", function() {
|
||||
const preReqHost = bru.getVar('preReqHost');
|
||||
const postResHost = bru.getVar('postResHost');
|
||||
|
||||
expect(preReqHost).to.equal('echo.usebruno.com');
|
||||
expect(postResHost).to.equal('echo.usebruno.com');
|
||||
});
|
||||
|
||||
test("getPath() returns correct path", function() {
|
||||
const preReqPath = bru.getVar('preReqPath');
|
||||
const postResPath = bru.getVar('postResPath');
|
||||
|
||||
expect(preReqPath).to.equal('/api/users/123');
|
||||
expect(postResPath).to.equal('/api/users/123');
|
||||
});
|
||||
|
||||
test("getQueryString() returns correct query string", function() {
|
||||
const preReqQueryString = bru.getVar('preReqQueryString');
|
||||
const postResQueryString = bru.getVar('postResQueryString');
|
||||
|
||||
expect(preReqQueryString).to.equal('name=john&age=30');
|
||||
expect(postResQueryString).to.equal('name=john&age=30');
|
||||
});
|
||||
|
||||
test("getPathParams() returns correct path parameters", function() {
|
||||
const preReqPathParams = JSON.parse(bru.getVar('preReqPathParams'));
|
||||
const postResPathParams = JSON.parse(bru.getVar('postResPathParams'));
|
||||
|
||||
expect(preReqPathParams).to.be.an('array');
|
||||
expect(preReqPathParams).to.have.lengthOf(1);
|
||||
expect(preReqPathParams[0].name).to.equal('userId');
|
||||
expect(preReqPathParams[0].value).to.equal('123');
|
||||
|
||||
expect(postResPathParams).to.be.an('array');
|
||||
expect(postResPathParams).to.have.lengthOf(1);
|
||||
expect(postResPathParams[0].name).to.equal('userId');
|
||||
expect(postResPathParams[0].value).to.equal('123');
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"maximized": false,
|
||||
"lastOpenedCollections": [
|
||||
"{{projectRoot}}/tests/scripting/url-helpers/fixtures/collections/url_helpers_test"
|
||||
]
|
||||
}
|
||||
38
tests/scripting/url-helpers/url-helpers.spec.ts
Normal file
38
tests/scripting/url-helpers/url-helpers.spec.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { test } from '../../../playwright';
|
||||
import { setSandboxMode, runCollection, validateRunnerResults } from '../../utils/page';
|
||||
|
||||
test.describe.serial('URL helper methods', () => {
|
||||
test.describe('req.getHost(), req.getPath(), req.getQueryString(), req.getPathParams()', () => {
|
||||
test('should work in developer mode', async ({ pageWithUserData: page }) => {
|
||||
// Set up developer mode
|
||||
await setSandboxMode(page, 'url_helpers_test', 'developer');
|
||||
|
||||
// Run the collection
|
||||
await runCollection(page, 'url_helpers_test');
|
||||
|
||||
// Validate test results - 1 request should pass (with 4 assertions inside)
|
||||
await validateRunnerResults(page, {
|
||||
totalRequests: 1,
|
||||
passed: 1,
|
||||
failed: 0,
|
||||
skipped: 0
|
||||
});
|
||||
});
|
||||
|
||||
test('should work in safe mode', async ({ pageWithUserData: page }) => {
|
||||
// Set up safe mode
|
||||
await setSandboxMode(page, 'url_helpers_test', 'safe');
|
||||
|
||||
// Run the collection
|
||||
await runCollection(page, 'url_helpers_test');
|
||||
|
||||
// Validate test results - 1 request should pass in safe mode too (with 4 assertions inside)
|
||||
await validateRunnerResults(page, {
|
||||
totalRequests: 1,
|
||||
passed: 1,
|
||||
failed: 0,
|
||||
skipped: 0
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user