move bruno collections in own folder

This commit is contained in:
2026-07-22 12:04:55 +02:00
parent ca9ba75c21
commit 044c54ab7b
313 changed files with 0 additions and 0 deletions
@@ -0,0 +1,2 @@
IrisApiPassword=
IrisApiUsername=
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,264 @@
info:
name: SCRIPT - Get Contracts with two or more contributors
type: http
seq: 5
http:
method: GET
url: "{{IrisApiUrl}}/contracts;full?year=2026"
params:
- name: year
value: "2026"
type: query
- name: wfState
value: signed
type: query
disabled: true
- name: page
value: "1"
type: query
disabled: true
auth: inherit
runtime:
scripts:
- type: after-response
code: |-
// Aggregates contracts with 2+ contributors across all pages and reports summary.
// // Fixes TypeError: pm.request.url.query.toObject(...).find is not a function by avoiding Array.prototype.find on toObject() result.
// Adds robust helpers for working with query params across Postman SDK versions and edge cases.
//
// Requirements addressed:
// 1) Read Page-Count header to know total pages
// 2) Iteratively call same endpoint for pages from current+1 to Page-Count, preserving other query params
// 3) Aggregate items where contributorSet exists and has length >= 2
// 4) Build a map pid -> contributorCount across all pages (including initial)
// 5) Print summary in Test Results and set env var `multiContributorContracts` with [{ pid, contributorCount }]
// 6) Robust error handling, rate limiting, early stop on non-2xx; handle JSON array or paginated object response shapes
// 7) Augment aggregation with department (ownerSet[0].organizationUnit.idAb + " - " + description). Keep first non-empty.
(function () {
const RATE_LIMIT_DELAY_MS = 200; // small delay between page fetches
const TARGET_ENV_VAR = 'multiContributorContracts';
const PAGE_PARAM = 'page';
// ---------------- URL and Query helpers (SDK-safe) -----------------
// Returns a plain object of query params. Works with:
// - pm.request.url.query (SDK v8+ as QueryList) using .toObject()
// - URL that has no query or is a raw string
function getQueryObject(url) {
try {
// // pm.request.url can be a Url object or a string. Normalize to raw string.
const raw = (typeof url === 'string') ? url : (url && (url.toString ? url.toString() : url.raw || ''));
// Try SDK path first if it's a Url object with .query
if (url && url.query && typeof url.query.toObject === 'function') {
const obj = url.query.toObject();
// toObject may return undefined/null on empty query
return obj && typeof obj === 'object' ? { ...obj } : {};
}
// Fallback: parse the raw string
if (typeof raw === 'string') {
const qIndex = raw.indexOf('?');
if (qIndex === -1) return {};
const queryStr = raw.substring(qIndex + 1);
if (!queryStr) return {};
return queryStr.split('&').reduce((acc, pair) => {
if (!pair) return acc;
const [k, v] = pair.split('=');
if (!k) return acc;
acc[decodeURIComponent(k)] = v !== undefined ? decodeURIComponent(v) : '';
return acc;
}, {});
}
} catch (e) {
// fallthrough
}
return {};
}
function setQueryObject(url, updates) {
// Returns a new raw URL string with given query params merged
const raw = (typeof url === 'string') ? url : (url && (url.toString ? url.toString() : url.raw || ''));
const qIndex = raw.indexOf('?');
const base = qIndex === -1 ? raw : raw.substring(0, qIndex);
const current = getQueryObject(url);
const merged = { ...current, ...updates };
// Filter out empty/undefined to avoid adding stray keys
const parts = Object.keys(merged)
.filter(k => merged[k] !== undefined && merged[k] !== null && merged[k] !== '')
.map(k => encodeURIComponent(k) + '=' + encodeURIComponent(String(merged[k])));
return parts.length ? base + '?' + parts.join('&') : base;
}
// ---------------- Response shape helpers -----------------
function isObject(x) { return x && typeof x === 'object' && !Array.isArray(x); }
function getItemsFromResponseBody(rb) {
// Supports either an array payload or an object with an array at known keys
if (Array.isArray(rb)) return rb;
if (isObject(rb)) {
// Try common keys: 'items', 'data', 'results'
if (Array.isArray(rb.items)) return rb.items;
if (Array.isArray(rb.data)) return rb.data;
if (Array.isArray(rb.results)) return rb.results;
}
return [];
}
function safeJson(body) {
try { return JSON.parse(body); } catch (e) { return null; }
}
// ---------------- Aggregation store -----------------
// Map: pid -> { contributorCount, department }
const aggregate = {};
function extractDepartment(item) {
try {
const owner0 = Array.isArray(item.ownerSet) && item.ownerSet.length > 0 ? item.ownerSet[0] : null;
const ou = owner0 && owner0.organizationUnit ? owner0.organizationUnit : null;
const idAb = ou && typeof ou.idAb === 'string' ? ou.idAb : null;
const desc = ou && typeof ou.description === 'string' ? ou.description : null;
if (idAb && desc) return idAb + ' - ' + desc;
return '';
} catch (e) {
return '';
}
}
function considerItems(items) {
items.forEach(it => {
const contributors = Array.isArray(it.contributorSet) ? it.contributorSet : [];
if (contributors.length >= 2) {
const pid = (it.pid != null) ? String(it.pid) : '';
if (!pid) return;
const contributorCount = contributors.length;
const dept = extractDepartment(it);
if (!aggregate[pid]) {
aggregate[pid] = { contributorCount, department: dept || '' };
} else {
// keep max contributor count seen (in case of variations) and first non-empty department
aggregate[pid].contributorCount = Math.max(aggregate[pid].contributorCount, contributorCount);
if (!aggregate[pid].department && dept) {
aggregate[pid].department = dept;
}
}
}
});
}
// ---------------- Paging orchestration -----------------
const initialStatus = res.getStatus();
const is2xx = initialStatus >= 200 && initialStatus < 300;
if (!is2xx) {
test('Request failed - not aggregating on non-2xx', function () {
expect(is2xx).to.eql(true);
});
return;
}
const rb = safeJson(JSON.stringify(res.getBody()));
const initialItems = rb ? getItemsFromResponseBody(rb) : [];
considerItems(initialItems);
// Derive total pages from header 'Page-Count' or 'page-count'
const pageCountHeader = res.getHeader('Page-Count') || res.getHeader('page-count') || res.getHeader('X-Total-Pages');
const totalPages = pageCountHeader ? parseInt(pageCountHeader, 10) : 1;
// Figure out current page from request URL (query param 'page')
const currentQuery = getQueryObject(req.getUrl());
const currentPage = parseInt(currentQuery[PAGE_PARAM] || '1', 10) || 1;
// Build a function that fetches page N and aggregates
function fetchPage(n) {
return new Promise((resolve) => {
//console.log("Setting current page to: " + n);
const nextUrl = setQueryObject(req.getUrl(), { [PAGE_PARAM]: String(n) });
const reqHeaders = req.getHeaders();
console.log("Setting headers: " + JSON.stringify(reqHeaders));
setTimeout(async function () {
console.log("Calling next URL... (" + nextUrl + ")");
await bru.sendRequest({ url: nextUrl, method: 'GET', headers: reqHeaders }, async function(err, res) {
if (err || !res) {
console.log("Error fetching page " + n + " (err: " + JSON.stringify(err) + ")");
test('Error fetching page ' + n, function () {
expect(err).to.eql(null);
});
return resolve(false);
}
const ok = res.status >= 200 && res.status < 300;
console.log("Next URL response: " + ok);
if (!ok) {
test('Non-2xx on page ' + n + ' - stop further paging', function () {
expect(ok).to.eql(true);
});
return resolve(false);
}
const body = res.data;
const json = safeJson(body);
const items = json ? getItemsFromResponseBody(json) : [];
considerItems(items);
return resolve(true);
});
}, RATE_LIMIT_DELAY_MS);
});
}
async function run() {
console.log("Running...");
console.log("Total pages found: " + totalPages);
// If there are more pages, iterate
for (let p = currentPage + 1; p <= totalPages; p++) {
const cont = await fetchPage(p);
if (!cont) break;
}
// Prepare output array
const output = Object.keys(aggregate).map(pid => ({
pid,
contributorCount: aggregate[pid].contributorCount,
department: aggregate[pid].department || ''
}));
// Save to environment
bru.setVar(TARGET_ENV_VAR, JSON.stringify(output));
console.log(JSON.stringify(output));
// Basic summary tests
test('Aggregated items have required properties', function () {
output.forEach(item => {
expect(item).to.have.property('pid');
expect(item.pid).to.be.a('string');
expect(item).to.have.property('contributorCount');
expect(item.contributorCount).to.be.a('number');
expect(item).to.have.property('department');
expect(item.department).to.be.a('string');
});
});
// Optional: Log summary count
test('Total multi-contributor contracts aggregated', function () {
expect(output.length).to.be.at.least(0);
});
}
run();
})();
actions:
- type: set-variable
phase: after-response
selector:
expression: ""
method: jsonq
variable:
name: multiContributorContracts
scope: runtime
settings:
encodeUrl: true
timeout: 0
followRedirects: true
maxRedirects: 5
@@ -0,0 +1,278 @@
info:
name: SCRIPT - Get Contracts with two or more owners
type: http
seq: 4
http:
method: GET
url: "{{IrisApiUrl}}/contracts?year=2026"
params:
- name: year
value: "2026"
type: query
- name: wfState
value: signed
type: query
disabled: true
- name: page
value: "1"
type: query
disabled: true
auth: inherit
runtime:
scripts:
- type: after-response
code: |-
// Aggregates contracts with 2+ contributors across all pages and reports summary.
// // Fixes TypeError: pm.request.url.query.toObject(...).find is not a function by avoiding Array.prototype.find on toObject() result.
// Adds robust helpers for working with query params across Postman SDK versions and edge cases.
//
// Requirements addressed:
// 1) Read Page-Count header to know total pages
// 2) Iteratively call same endpoint for pages from current+1 to Page-Count, preserving other query params
// 3) Aggregate items where contributorSet exists and has length >= 2
// 4) Build a map pid -> contributorCount across all pages (including initial)
// 5) Print summary in Test Results and set env var `multiContributorContracts` with [{ pid, contributorCount }]
// 6) Robust error handling, rate limiting, early stop on non-2xx; handle JSON array or paginated object response shapes
// 7) Augment aggregation with department (ownerSet[0].organizationUnit.idAb + " - " + description). Keep first non-empty.
(function () {
const RATE_LIMIT_DELAY_MS = 200; // small delay between page fetches
const TARGET_ENV_VAR = 'multiOwnerContracts';
const PAGE_PARAM = 'page';
// ---------------- URL and Query helpers (SDK-safe) -----------------
// Returns a plain object of query params. Works with:
// - pm.request.url.query (SDK v8+ as QueryList) using .toObject()
// - URL that has no query or is a raw string
function getQueryObject(url) {
try {
// // pm.request.url can be a Url object or a string. Normalize to raw string.
const raw = (typeof url === 'string') ? url : (url && (url.toString ? url.toString() : url.raw || ''));
// Try SDK path first if it's a Url object with .query
if (url && url.query && typeof url.query.toObject === 'function') {
const obj = url.query.toObject();
// toObject may return undefined/null on empty query
return obj && typeof obj === 'object' ? { ...obj } : {};
}
// Fallback: parse the raw string
if (typeof raw === 'string') {
const qIndex = raw.indexOf('?');
if (qIndex === -1) return {};
const queryStr = raw.substring(qIndex + 1);
if (!queryStr) return {};
return queryStr.split('&').reduce((acc, pair) => {
if (!pair) return acc;
const [k, v] = pair.split('=');
if (!k) return acc;
acc[decodeURIComponent(k)] = v !== undefined ? decodeURIComponent(v) : '';
return acc;
}, {});
}
} catch (e) {
// fallthrough
}
return {};
}
function setQueryObject(url, updates) {
// Returns a new raw URL string with given query params merged
const raw = (typeof url === 'string') ? url : (url && (url.toString ? url.toString() : url.raw || ''));
const qIndex = raw.indexOf('?');
const base = qIndex === -1 ? raw : raw.substring(0, qIndex);
const current = getQueryObject(url);
const merged = { ...current, ...updates };
// Filter out empty/undefined to avoid adding stray keys
const parts = Object.keys(merged)
.filter(k => merged[k] !== undefined && merged[k] !== null && merged[k] !== '')
.map(k => encodeURIComponent(k) + '=' + encodeURIComponent(String(merged[k])));
return parts.length ? base + '?' + parts.join('&') : base;
}
// ---------------- Response shape helpers -----------------
function isObject(x) { return x && typeof x === 'object' && !Array.isArray(x); }
function getItemsFromResponseBody(rb) {
// Supports either an array payload or an object with an array at known keys
if (Array.isArray(rb)) return rb;
if (isObject(rb)) {
// Try common keys: 'items', 'data', 'results'
if (Array.isArray(rb.items)) return rb.items;
if (Array.isArray(rb.data)) return rb.data;
if (Array.isArray(rb.results)) return rb.results;
}
return [];
}
function safeJson(body) {
try { return JSON.parse(body); } catch (e) { return null; }
}
// ---------------- Aggregation store -----------------
// Map: pid -> { contributorCount, department }
const aggregate = {};
function extractDepartment(item) {
try {
const owner0 = Array.isArray(item.ownerSet) && item.ownerSet.length > 0 ? item.ownerSet[0] : null;
const ou = owner0 && owner0.organizationUnit ? owner0.organizationUnit : null;
const idAb = ou && typeof ou.idAb === 'string' ? ou.idAb : null;
const desc = ou && typeof ou.description === 'string' ? ou.description : null;
if (idAb && desc) return idAb + ' - ' + desc;
return '';
} catch (e) {
return '';
}
}
function considerItems(items) {
items.forEach(it => {
const owners = Array.isArray(it.ownerSet) ? it.ownerSet : [];
if (owners.length >= 2) {
const pid = (it.pid != null) ? String(it.pid) : '';
if (!pid) return;
const ownersCount = owners.length;
if (!aggregate[pid]) {
aggregate[pid] = { ownersCount: ownersCount };
} else {
// keep max owner count seen (in case of variations) and first non-empty department
aggregate[pid].ownersCount = Math.max(aggregate[pid].ownersCount, ownersCount);
}
/*
const contributorCount = contributors.length;
const dept = extractDepartment(it);
if (!aggregate[pid]) {
aggregate[pid] = { contributorCount, department: dept || '' };
} else {
// keep max contributor count seen (in case of variations) and first non-empty department
aggregate[pid].contributorCount = Math.max(aggregate[pid].contributorCount, contributorCount);
if (!aggregate[pid].department && dept) {
aggregate[pid].department = dept;
}
}
*/
}
});
}
// ---------------- Paging orchestration -----------------
const initialStatus = res.getStatus();
const is2xx = initialStatus >= 200 && initialStatus < 300;
if (!is2xx) {
test('Request failed - not aggregating on non-2xx', function () {
expect(is2xx).to.eql(true);
});
return;
}
const rb = safeJson(JSON.stringify(res.getBody()));
const initialItems = rb ? getItemsFromResponseBody(rb) : [];
considerItems(initialItems);
// Derive total pages from header 'Page-Count' or 'page-count'
const pageCountHeader = res.getHeader('Page-Count') || res.getHeader('page-count') || res.getHeader('X-Total-Pages');
const totalPages = pageCountHeader ? parseInt(pageCountHeader, 10) : 1;
// Figure out current page from request URL (query param 'page')
const currentQuery = getQueryObject(req.getUrl());
const currentPage = parseInt(currentQuery[PAGE_PARAM] || '1', 10) || 1;
// Build a function that fetches page N and aggregates
function fetchPage(n) {
return new Promise((resolve) => {
//console.log("Setting current page to: " + n);
const nextUrl = setQueryObject(req.getUrl(), { [PAGE_PARAM]: String(n) });
const reqHeaders = req.getHeaders();
console.log("Setting headers: " + JSON.stringify(reqHeaders));
setTimeout(async function () {
console.log("Calling next URL... (" + nextUrl + ")");
await bru.sendRequest({ url: nextUrl, method: 'GET', headers: reqHeaders }, async function(err, res) {
if (err || !res) {
console.log("Error fetching page " + n + " (err: " + JSON.stringify(err) + ")");
test('Error fetching page ' + n, function () {
expect(err).to.eql(null);
});
return resolve(false);
}
const ok = res.status >= 200 && res.status < 300;
console.log("Next URL response: " + ok);
if (!ok) {
test('Non-2xx on page ' + n + ' - stop further paging', function () {
expect(ok).to.eql(true);
});
return resolve(false);
}
const body = res.data;
const json = safeJson(body);
const items = json ? getItemsFromResponseBody(json) : [];
considerItems(items);
return resolve(true);
});
}, RATE_LIMIT_DELAY_MS);
});
}
async function run() {
console.log("Running...");
console.log("Total pages found: " + totalPages);
// If there are more pages, iterate
for (let p = currentPage + 1; p <= totalPages; p++) {
const cont = await fetchPage(p);
if (!cont) break;
}
// Prepare output array
const output = Object.keys(aggregate).map(pid => ({
pid,
ownersCount: aggregate[pid].ownersCount
/*
contributorCount: aggregate[pid].contributorCount,
department: aggregate[pid].department || ''
*/
}));
// Save to environment
bru.setVar(TARGET_ENV_VAR, JSON.stringify(output));
console.log(JSON.stringify(output));
// Basic summary tests
test('Aggregated items have required properties', function () {
output.forEach(item => {
expect(item).to.have.property('pid');
expect(item.pid).to.be.a('string');
expect(item).to.have.property('ownersCount');
expect(item.contributorCount).to.be.a('number');
/*
expect(item).to.have.property('department');
expect(item.department).to.be.a('string');
*/
});
});
// Optional: Log summary count
test('Total multi-contributor contracts aggregated', function () {
expect(output.length).to.be.at.least(0);
});
}
run();
})();
actions:
- type: set-variable
phase: after-response
selector:
expression: ""
method: jsonq
variable:
name: multiOwnerContracts
scope: runtime
settings:
encodeUrl: true
timeout: 0
followRedirects: true
maxRedirects: 5
@@ -0,0 +1,18 @@
info:
name: Contracts
type: folder
seq: 2
request:
auth: inherit
docs:
content: |-
# IRIS GW (Gateway) REST API documentation (v1)
Link: <https://air.unipr.it/sr/doc/rest/gw-rest-api.jsp>
## Contratti
Link: <https://air.unipr.it/sr/doc/rest/gw-rest-api.jsp#contracts>
type: text/markdown
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,7 @@
info:
name: WfItems
type: folder
seq: 3
request:
auth: inherit
@@ -0,0 +1,80 @@
info:
name: "[Runner] Get All Contracts"
type: http
seq: 1
http:
method: GET
url: "{{IrisApiUrl}}/contracts;full?page={{runnerCurrentPage}}&sort=pid&dir=asc"
params:
- name: page
value: "{{runnerCurrentPage}}"
type: query
- name: sort
value: pid
type: query
description: |-
The usable fields for sorting are:
- id
- pid
- year
- name
- startDate
- lastModified
- wfItemType.identifier (only for item with validation flow)
- wfItemType.description (only for item with validation flow)
The actual usable sorting filters for a specific resource type are specified in the REST Service Details
- name: dir
value: asc
type: query
auth: inherit
runtime:
scripts:
- type: after-response
code: |-
test("Status code is 200", function () {
expect(res.getStatus()).to.equal(200);
// Get pagination headers
var currentPage = parseInt(res.getHeader("Page"));
var totalPages = parseInt(res.getHeader("Page-Count"));
// If first loop, reset results array
if (currentPage == 1)
{
bru.setVar("runnerResultsArray", JSON.stringify([]));
}
// Update result array
let resultsArray = JSON.parse(bru.getVar("runnerResultsArray"));
var results = res.getBody();
resultsArray = resultsArray.concat(results);
bru.setVar("runnerResultsArray", JSON.stringify(resultsArray));
// Loop decision
if (currentPage == totalPages)
{
// Loop has finished, reset variables and stop
bru.setVar("runnerCurrentPage", 1);
bru.deleteVar("runnerTotalPages");
// //pm.collectionVariables.unset("runnerResultsArray"); // Do not unset, so you can find results in the env var!
}
else
{
// Still having pages, update pagination values
bru.setVar("runnerCurrentPage", ++currentPage);
bru.setVar("runnerTotalPages", totalPages);
// Set next request and wait for 1 second before sending the next request. This is to avoid hitting the rate limit.
bru.runner.setNextRequest(req.getName());
setTimeout(function(){}, [1000]);
}
});
settings:
encodeUrl: true
timeout: 0
followRedirects: true
maxRedirects: 5
@@ -0,0 +1,7 @@
info:
name: "[Runner] Get All Contracts"
type: folder
seq: 1
request:
auth: inherit
@@ -0,0 +1,9 @@
name: IRIS - Prod
color: "#2E8A54"
variables:
- name: IrisApiUrl
value: https://air.unipr.it/gw/rest/api
- name: IrisApiUsername
value: "{{process.env.IrisApiUsername}}"
- name: IrisApiPassword
value: "{{process.env.IrisApiPassword}}"
@@ -0,0 +1,400 @@
opencollection: 1.0.0
info:
name: IRIS GW (Gateway) REST API (v1)
config:
proxy:
inherit: true
config:
protocol: http
hostname: ""
port: ""
auth:
username: ""
password: ""
bypassProxy: ""
request:
headers:
- name: Accept
value: "*/*"
auth:
type: basic
username: "{{IrisApiUsername}}"
password: "{{IrisApiPassword}}"
variables:
- name: runnerCurrentPage
value: "1"
- name: runnerResultsArray
value: ""
scripts:
- type: after-response
code: |-
// GO TO THE END OF THE TEST SCRIPT.
var template = String.raw`
<style>
.fill,
body,
html {
height: 100%
}
#json_vl,
.td_head,
.td_row_even,
.td_row_odd {
font-size: small
}
#json_pnl,
#xxa,
.navbar-header,
.navbar-nav,
.navbar-nav>li,
.td_head {
float: left
}
.fill {
min-height: 100%
}
#json_vl {
font-family: Consolas, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace
}
#widget {
width: 100%
}
.top_size {
height: 51px
}
#all_panels {
height: 100%;
min-height: 100%
}
#aboutLnk {
position: fixed;
right: 10px;
top: 15px
}
#inner_text {
display: block;
position: absolute;
height: auto;
bottom: 0;
top: 0;
left: 0;
right: 0;
margin-top: 51px;
margin-bottom: 0
}
#json_pnl {
background-color: #ccc;
width: 33.3%
}
#xxa {
background-color: #E8E8E8;
width: 66.7%
}
#table_pnl,
#tree_pnl {
background-color: #E8E8E8;
float: left;
width: 50%
}
#sharethis {
position: fixed;
right: 80px;
top: 10px
}
#inner_tbl {
padding-left: 2px
}
.td_row_even {
padding: 2px;
background-color: #F6F4F0
}
.td_row_odd {
padding: 2px;
background-color: #FFF
}
.td_head {
padding: 2px;
font-weight: 700
}
input,
p,
select,
td,
textarea,
th {
font-size: 1em
}
table,
td,
th {
border: 1px solid gray
}
textarea {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
display: block;
width: 100%;
height: 100%;
margin: 0;
padding: 4px;
border: 1px solid #333;
overflow-y: auto;
overflow-x: hidden
}
*,
html {
font-family: Verdana, Arial, Helvetica, sans-serif
}
form,
h1,
h2,
h3,
h4,
h5,
li,
p,
ul {
margin: 0;
padding: 0
}
img {
border: none
}
p {
margin: 0 0 1em
}
table {
font-size: 100%;
background-color: white;
}
ol.tree {
padding: 0 0 0 30px;
width: 300px
}
li {
position: relative;
margin-left: -15px;
list-style: none
}
li.file {
margin-left: -1px !important
}
li.file a {
background: url(leaf.png)0 5px no-repeat;
color: #000;
padding-left: 12px;
text-decoration: none;
display: block;
font-size: small
}
li.file a[href$='.css'],
li.file a[href$='.js'],
li.file a[href*='.pdf'],
li.file a[href*='.html'] {
background: url(http://www.thecssninja.com/demo/css_tree/document.png)no-repeat
}
li input {
position: absolute;
left: 0;
margin-left: 0;
opacity: 0;
z-index: 2;
cursor: pointer;
height: 1em;
width: 1em;
top: 0
}
li input+ol {
background: url(http://www.thecssninja.com/demo/css_tree/toggle-small-expand.png)40px -3px no-repeat;
margin: -20px 0 0 -44px;
height: 1em;
padding: 1.563em 0 0 80px
}
li label.lbl_array,
li label.lbl_obj {
display: block;
padding-left: 33px;
margin-bottom: 2px
}
li input+ol>li {
display: none;
margin-left: -14px !important;
padding-left: 1px
}
li label.lbl_obj {
background: url(folder.png)15px 1px no-repeat;
cursor: pointer
}
li label.lbl_array {
background: url(array.png)15px 1px no-repeat;
cursor: pointer
}
li input:checked+ol {
background: url(http://www.thecssninja.com/demo/css_tree/toggle-small.png)40px -3px no-repeat;
margin: -20px 0 0 -44px;
padding: 1.563em 0 0 80px;
height: auto
}
li input:checked+ol>li {
display: block;
margin: 0 0 .125em
}
li input:checked+ol>li:last-child {
margin: 0 0 .063em
}
.container {
width: 970px;
max-width: none !important
}
.col-xs-4 {
padding-top: 15px;
padding-bottom: 15px;
background-color: #eee;
background-color: rgba(86, 61, 124, .15);
border: 1px solid #ddd;
border: 1px solid rgba(86, 61, 124, .2)
}
</style>
<div id="html">
<input type="text" id="json">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!--<script src="json2table.js"></script>-->
<script>
$(function() {
// pm.getData((err, data) => {
$("#json").val(JSON.stringify(data.json));
json2table("#html");
});
});
function call(a) {
$("#json").val(JSON.stringify(a, void 0, 2));
json2table()
}
function json2table(selector) {
$(selector).html(buildTable(getJsonVar()));
}
function getJsonVar() {
try {
var a = $.parseJSON($("#json").val());
$("#json").val(JSON.stringify(a, void 0, 2));
return a
} catch (e) {
//return $("#error_msg").text(e.message), $("#errorModal").modal("show"), {}
alert(e);
}
}
function buildTable(a) {
var e = document.createElement("table"),
d, b;
if (isArray(a)) return buildArray(a);
for (var c in a) "object" != typeof a[c] || isArray(a[c]) ? "object" == typeof a[c] && isArray(a[c]) ? (d = e.insertRow(-1), b = d.insertCell(-1), b.colSpan = 2, b.innerHTML = '<div class="td_head">' + encodeText(c) + '</div><table style="width:100%">' + $(buildArray(a[c]), !1).html() + "</table>") : (d = e.insertRow(-1), b = d.insertCell(-1), b.innerHTML = "<div class='td_head'>" + encodeText(c) + "</div>", d = d.insertCell(-1), d.innerHTML = "<div class='td_row_even'>" +
encodeText(a[c]) + "</div>") : (d = e.insertRow(-1), b = d.insertCell(-1), b.colSpan = 2, b.innerHTML = '<div class="td_head">' + encodeText(c) + '</div><table style="width:100%">' + $(buildTable(a[c]), !1).html() + "</table>");
return e
}
function buildArray(a) {
var e = document.createElement("table"),
d, b, c = !1,
p = !1,
m = {},
h = -1,
n = 0,
l;
l = "";
if (0 == a.length) return "<div></div>";
d = e.insertRow(-1);
for (var f = 0; f < a.length; f++)
if ("object" != typeof a[f] || isArray(a[f])) "object" == typeof a[f] && isArray(a[f]) ? (b = d.insertCell(h), b.colSpan = 2, b.innerHTML = '<div class="td_head"></div><table style="width:100%">' + $(buildArray(a[f]), !1).html() + "</table>", c = !0) : p || (h += 1, p = !0, b = d.insertCell(h), m.empty = h, b.innerHTML = "<div class='td_head'>&nbsp;</div>");
else
for (var k in a[f]) l =
"-" + k, l in m || (c = !0, h += 1, b = d.insertCell(h), m[l] = h, b.innerHTML = "<div class='td_head'>" + encodeText(k) + "</div>");
c || e.deleteRow(0);
n = h + 1;
for (f = 0; f < a.length; f++)
if (d = e.insertRow(-1), td_class = isEven(f) ? "td_row_even" : "td_row_odd", "object" != typeof a[f] || isArray(a[f]))
if ("object" == typeof a[f] && isArray(a[f]))
for (h = m.empty, c = 0; c < n; c++) b = d.insertCell(c), b.className = td_class, l = c == h ? '<table style="width:100%">' + $(buildArray(a[f]), !1).html() + "</table>" : " ", b.innerHTML = "<div class='" + td_class + "'>" + encodeText(l) +
"</div>";
else
for (h = m.empty, c = 0; c < n; c++) b = d.insertCell(c), l = c == h ? a[f] : " ", b.className = td_class, b.innerHTML = "<div class='" + td_class + "'>" + encodeText(l) + "</div>";
else {
for (c = 0; c < n; c++) b = d.insertCell(c), b.className = td_class, b.innerHTML = "<div class='" + td_class + "'>&nbsp;</div>";
for (k in a[f]) c = a[f], l = "-" + k, h = m[l], b = d.cells[h], b.className = td_class, "object" != typeof c[k] || isArray(c[k]) ? "object" == typeof c[k] && isArray(c[k]) ? b.innerHTML = '<table style="width:100%">' + $(buildArray(c[k]), !1).html() + "</table>" : b.innerHTML =
"<div class='" + td_class + "'>" + encodeText(c[k]) + "</div>" : b.innerHTML = '<table style="width:100%">' + $(buildTable(c[k]), !1).html() + "</table>"
}
return e
}
function encodeText(a) {
return $("<div />").text(a).html()
}
function isArray(a) {
return "[object Array]" === Object.prototype.toString.call(a)
}
function isEven(a) {
return 0 == a % 2
}
</script>`;
// In case you only want a specific property, change it here.
//
// // Default: You can set the entire JSON response using pm.response.json()
let tableProps = {
json: res.getBody()
};
// pm.visualizer.set(template, tableProps);
bundled: false
extensions: {}