Unable to visualize response after update latest update

After updating to the latest version of Postman, I am encountering an issue with the Visualizer feature in the “post-response” in the Scripts tab. Specifically, the pm object, which is essential for Postman-specific scripting, is throwing a ReferenceError: pm is not defined. This error occurs when trying to execute a script for a custom visualization of API responses.

My response has a unique structure, so I can’t directly use post-bot to generate visualization.

This is my script for the visualization, which worked for the older version:

var template = `
<style>
    .fill,
    body,
    html {
        height: 100%;
    }

    table,
    td,
    th {
        border: 1px solid gray;
    }

    /* Additions for table cell and header styling */
    .my-table th,
    .my-table td {
        max-width: 120px;
        padding: 5px;
        border: 1px solid #ddd;
        text-align: left; 
        vertical-align: top; 
    }

    /* Specific styling for table headers */
    .my-table th,
    .my-table td {
        white-space: normal; 
        word-wrap: break-word;
    }

    /* Reduce the font size for all table content */
    .my-table,
    .my-table th,
    .my-table td {
        font-size: 0.8em; 
    }

    .my-table th {
        position: sticky;
        top: 0;
        background-color: #f0f0f0; 
        z-index: 1;
    }

    table {
        table-layout: fixed; 
        width: 100%;
    }

    /* Alternate row coloring */
    .my-table tr:nth-child(odd) {
        background-color: #f9f9f9; /* Light grey for odd rows */
    }
    .my-table tr:nth-child(even) {
        background-color: #ffffff; /* White for even rows */
    }

    *,
    html {
        font-family: Verdana, Arial, Helvetica, sans-serif;
    }

    form,
    h1,
    h2,
    h3,
    h4,
    h5,
    li,
    p,
    ul {
        margin: 0;
        padding: 0;
    }

    .container {
        width: 100%;
        max-width: none !important;
    }

    /* Additional CSS for key-value pairs */
    .key-value-pair {
        background-color: #e8e8e8; /* Light gray background */
        border: 1px solid #ccc; /* Light border for distinction */
        border-radius: 4px; /* Rounded corners */
        padding: 5px; /* Some padding around the text */
        margin: 5px 0; /* Margin for spacing between pairs */
        font-family: monospace; /* Monospaced font for better readability */
    }

    /* Style adjustments for better spacing and alignment */
    .key-value-pair::before {
        display: inline-block;
        margin-right: 5px;
        color: #333;
    }
</style>
<div id="html">
    <input type="text" id="json" hidden />
    <div id="container"></div>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script>
        $(function () {
            pm.getData((err, data) => {
                if (err) {
                    console.error("Error getting data:", err);
                    $("#container").text("Error getting data.");
                    return;
                }

                // Clear previous contents
                $("#container").empty();

                // Check if the outputs array is present
                if (Array.isArray(data.json.outputs)) {
                    data.json.outputs.forEach((item) => {
                        // Check for items with a structure applicable for table rendering
                        if (
                            item.value &&
                            Array.isArray(item.value) &&
                            item.value.some((val) => val.metadata || val.data)
                        ) {
                            const tableData = transformDatagridData(item.value);
                            $("#container").append($("<h4>").text(item.name)); // Add a header for each table
                            $("#container").append(buildTable(tableData));
                        } else {
                            // For other items, display them as key-value pairs
                            $("#container").append(
                                $('<div class="key-value-pair">').append($("<span>").text(item.name)).append(": " + item.value)
                                
                            );
                        }
                    });
                } else {
                    $("#container").text(
                        "The data is not an array as expected."
                    );
                }
            });
        });

        function transformDatagridData(value) {
            // Assume value is an array with one item that has metadata and one that has data
            const metadataItem = value.find((item) => item.metadata);
            const dataItem = value.find((item) => item.data);
            if (!metadataItem || !dataItem) {
                return { headers: [], rows: [] };
            }

            const metadata = metadataItem.metadata;
            const data = dataItem.data;

            // Create headers array from metadata
            const headers = metadata.map((col) => Object.keys(col)[0]);

            // Transform data array into array of objects
            const dataRows = data.map((row) => {
                return row.reduce((acc, val, index) => {
                    // acc is the accumulator object
                    // val is the current value in the row
                    // index is the current index of val in the row to find the corresponding header name in headers
                    acc[headers[index]] = val;
                    return acc;
                }, {});
            });

            return { headers, rows: dataRows };
        }

        function buildTable(data) {
            const table = $("<table/>").addClass("my-table");

            // Build the header
            const thead = $("<thead/>");
            const headerRow = $("<tr/>");
            data.headers.forEach((header) => {
                headerRow.append($("<th/>").text(header));
            });
            thead.append(headerRow);
            table.append(thead);

            // Build the body
            const tbody = $("<tbody/>");
            data.rows.forEach((row) => {
                const tr = $("<tr/>");
                data.headers.forEach((header) => {
                    tr.append($("<td/>").text(row[header]));
                });
                tbody.append(tr);
            });
            table.append(tbody);

            return table;
        }
    </script>
</div>
`;

// Change to use the entire JSON response
let tableProps = {
    json: pm.response.json(),
};

pm.visualizer.set(template, tableProps);

Could you confirm if there have been changes in the latest Postman update that affect the pm object or the Visualizer feature? If so, could you provide guidance on how to adapt the script for compatibility with the updated version?

Thank you for your assistance!

Hey @lli-1und1 :wave:

I’ve raised this with the team to investigate - Thank you for also creating the GH Issue for this. :pray:

Are you able to see the expected visualized response, when using the web platform?

https://go.postman.co

Hi @danny-dainton,

I cannot use the web app because our domain is not public. Currently I can only use the old version V11.23.3 to ensure that the script works

You can download and use the Postman Agent with the web app for non public usage.

Thank you, now I can confirm that the script works, when using the web platform.

1 Like