Scripting API
Всё, чем могут пользоваться скрипты перед запросом и тестовые скрипты: объект pm, expect, помощники JSON Schema и библиотеки, а также то, чего там нет.
Скрипты — это JavaScript, который выполняется перед отправкой запроса (скрипты перед запросом) или после получения
ответа (тестовые скрипты). Они используют API pm из Postman, поэтому скрипты из коллекций Postman запускаются без
изменений. На этой странице перечислено всё. О том, как писать их в приложении и читать результаты, см.
скрипты и тесты.
Где выполняются скрипты
- Скрипты запроса находятся на его вкладке Скрипты и сохраняются как
<slug>.pre.jsи<slug>.test.jsрядом с запросом. Скрипты есть и у папок, и у рабочего пространства (_folder.pre.js,_folder.test.js); см. файлы рабочего пространства. - Для каждого запроса сначала выполняется скрипт рабочего пространства, затем скрипты папок снаружи внутрь, затем собственный скрипт запроса. Все скрипты одного события работают в одной песочнице.
- У вызовов MCP скриптов нет.
- Скрипты, пришедшие извне Echolot (импорт, Git, другой редактор), выполняются, только когда вы им доверитесь: Доверять скриптам, после того как прочитаете их через Просмотреть скрипты….
- Утилита командной строки тоже запускает скрипты — в
echolot runиecholot send.
Песочница
Скрипты выполняются в изолированном движке JavaScript (QuickJS) внутри Echolot: без файловой системы, без собственной
сети и без модулей Node.js. Единственный выход наружу — pm.sendRequest, который отправляет запрос через Echolot.
| Ограничение | Значение |
|---|---|
| Время работы JavaScript для всех скриптов одного события | 5 секунд |
| Память | 128 МБ |
Ожидание каждого ответа на pm.sendRequest | 30 секунд |
| Тело ответа, которое видит скрипт | Первые 32 МБ |
Скрипт, который выбрасывает исключение или превышает ограничение, считается ошибкой скрипта, а она засчитывается как непройденный тест.
pm.test
pm.test("Status is 200", () => {
pm.response.to.have.status(200);
});
pm.test("Has products", () => {
const body = pm.response.json();
pm.expect(body.items).to.be.an("array").that.is.not.empty;
});| Форма | Что значит |
|---|---|
pm.test(name, fn) | Именованный тест. Проходит, если fn завершается без исключения. |
pm.test(name, async () => { … }) | Тест, который возвращает промис, проходит, когда промис выполняется. |
pm.test(name, done => { … }) | Тест с аргументом проходит, когда вызывает done(), и падает при done(error) или если не вызывает его вовсе. |
pm.test.skip(name, fn) | Пропущенный тест: он в списке, но не учитывается. |
tests[name] = condition | Старая форма: проходит, если условие истинно. |
Тесты в скриптах перед запросом тоже учитываются.
pm.expect
pm.expect(value) (или expect(value)) — утверждение в стиле Chai. Сообщения о сбоях читаются так же, как у Chai:
expected 401 to equal 200.
Слова-связки, которые улучшают читаемость и ничего не делают: to, be, been, is, that, which, and,
has, have, with, at, of, same, but, does, still, also.
Флаги: not (отрицание), deep (сравнение по значению), nested (пути с точками в property), own, any,
all, ordered.
| Утверждение | Проходит, когда |
|---|---|
.equal(x), .equals, .eq | Значение равно x (===; с deep — по значению). |
.eql(x), .eqls | Значение глубоко равно x. |
.above(n), .gt, .greaterThan | Значение больше n. |
.least(n), .gte, .greaterThanOrEqual | Значение не меньше n. |
.below(n), .lt, .lessThan | Значение меньше n. |
.most(n), .lte, .lessThanOrEqual | Значение не больше n. |
.within(a, b) | Значение между a и b, включая оба. |
.closeTo(x, delta), .approximately | Значение отличается от x не более чем на delta. |
.a(type), .an(type) | Тип значения — type: string, number, boolean, object, array, null, undefined, regexp, date, error, function. |
.instanceof(C), .instanceOf | Значение — экземпляр C. |
.include(x), .includes, .contain, .contains | Строка содержит x, в массиве есть x, в объекте есть ключи и значения x. |
.ok | Значение истинно. |
.true, .false, .null, .undefined, .NaN | Значение именно такое. |
.exist, .exists | Значение не null и не undefined. |
.empty | В строке или массиве нет элементов, в объекте — ключей, в Map или Set — записей. |
.finite | Значение — конечное число. |
.property(name), .property(name, value) | У объекта есть свойство, при заданном значении — с этим значением. Дальше продолжается со значением свойства. Также .ownProperty, .haveOwnProperty. |
.lengthOf(n), .length(n) | length значения (или размер Map или Set) равен n. |
.match(regex), .matches | Строка соответствует регулярному выражению. |
.string(s) | Строка содержит s. |
.keys(…), .key | У объекта именно эти ключи (с any — один из них; после include — как минимум эти). |
.members(array) | В массиве те же элементы (с include — как минимум эти; с ordered — в этом порядке). |
.oneOf(array) | Значение — один из элементов массива. |
.satisfy(fn), .satisfies | fn(value) возвращает true. |
.throw(), .throws, .Throw | Функция выбрасывает исключение (если заданы, — с сообщением, которое содержит строку или соответствует регулярному выражению, либо определённого класса). |
.jsonSchema(schema) | Значение соответствует JSON Schema. См. JSON Schema. |
Для ответа expect принимает и утверждения Postman об ответе:
pm.expect(pm.response).to.have.status(200), .header(name), .jsonBody(…), .body(…), .responseTime(…), а также
pm.expect(pm.response).to.be.ok, .success, .json и остальные, перечисленные ниже.
pm.response
В тестовых скриптах — ответ.
| Член | Что значит |
|---|---|
code | Код состояния: 200. |
status | Поясняющая фраза: "OK". Также reason(). |
headers | Заголовки в виде списка. pm.response.headers.get("Content-Type"). |
responseTime | Время в миллисекундах. |
responseSize | Размер тела в байтах. Также size(), который возвращает { body, header, total }. |
text() | Тело как текст. |
json(reviver) | Тело, разобранное как JSON; выбрасывает исключение, если это не JSON. |
Утверждения об ответе: pm.response.to.have.… и pm.response.to.not.have.…:
| Утверждение | Проходит, когда |
|---|---|
status(200), status("OK") | Код равен 200 или фраза — OK. Также statusCode(n), statusReason(text). |
header(name), header(name, value) | Заголовок есть, при заданном значении — с этим значением. |
body(), body(text), body(regex), body(object) | Тело не пустое, равно тексту, соответствует выражению или является этим JSON. |
jsonBody(), jsonBody(path), jsonBody(path, value), jsonBody(object) | Тело — JSON, в нём есть путь с точками, с этим значением, или оно равно объекту. |
responseTime(ms) | Ответ занял не более ms. |
pm.response.to.be.…:
| Свойство | Проходит, когда код |
|---|---|
info | от 100 до 199 |
success | от 200 до 299 |
ok | 200 |
accepted | 202 |
redirection | от 300 до 399 |
clientError | от 400 до 499 |
serverError | 500 или больше |
error | 400 или больше |
badRequest, unauthorized (или unauthorised), forbidden, notFound, rateLimited | 400, 401, 403, 404, 429 |
json, html, xml, text | (Content-Type содержит это слово) |
withBody | (тело не пустое) |
pm.request
Запрос. В скрипте перед запросом то, что вы в нём измените, и будет отправлено.
| Член | Что значит |
|---|---|
url | URL в виде объекта; см. ниже. String(pm.request.url) — это текст. |
method | Метод; его можно изменить. |
headers | Заголовки в виде списка. |
body | Тело: { mode: "raw", raw: "…" } или undefined. |
name, id | Название запроса и его путь в рабочем пространстве. |
addHeader(item), removeHeader(name), upsertHeader(item) | Изменяют заголовки. Элемент — { key, value } или "Name: value". |
addQueryParams(params), removeQueryParams(names) | Изменяют параметры запроса: "a=1&b=2", { key, value } или массивы таких значений. |
to.have.header(name, value) | Утверждение о заголовках запроса. |
pm.request.headers.upsert({ key: "X-Request-Id", value: pm.variables.replaceIn("{{$guid}}") });
pm.request.url.addQueryParams("per_page=50");У объекта url есть protocol, host (массив меток), port, path (массив сегментов), query (список), hash, а
также getHost(), getPath(), getQueryString(), getPathWithQuery(), getRemote(), update(text),
addQueryParams(…), removeQueryParams(…), toString(). URL, который вы не меняете, сохраняет свой точный текст,
включая {{variables}}; Echolot подставляет их после скриптов.
Переменные
| Область | Что это |
|---|---|
pm.environment | Переменные активного окружения. pm.environment.name — его название. |
pm.collectionVariables | Переменные рабочего пространства. |
pm.globals | Глобальные переменные. |
pm.iterationData | Текущая строка прогона на данных. Только чтение. |
pm.variables | Все области сразу, ближайшая первой. set и unset меняют только локальные значения. |
У каждой области есть get(name), has(name), set(name, value), unset(name), clear(), toObject() и
replaceIn(text). set превращает объекты в текст JSON.
pm.variables.get ищет в таком порядке: локальные значения, строка данных, переменные папки и запроса, окружение,
рабочее пространство, глобальные переменные.
// Pre-request: sign the body
const signature = CryptoJS.HmacSHA256(pm.request.body.raw, pm.environment.get("apiSecret")).toString();
pm.request.headers.upsert({ key: "X-Signature", value: signature });
// Test: keep the new order's ID for the next requests
pm.collectionVariables.set("orderId", pm.response.json().id);Что сохраняет set. Значения, которые задают скрипты, — это «текущие значения» Postman: они живут, пока открыто
окно в приложении или выполняется команда в командной строке, и при разрешении запросов важнее сохранённых значений
своей области. В файлы рабочего пространства они не записываются никогда. Чтобы сохранить значение из ответа,
используйте захват из ответа. Локальные значения из pm.variables.set забываются, когда
начинается прогон.
replaceIn(text) подставляет {{variables}} из перечисленных выше областей. Из динамических значений он знает
{{$guid}}, {{$randomUUID}}, {{$timestamp}}, {{$isoTimestamp}} и {{$randomInt}}; все остальные {{$…}}
остаются как есть, чтобы Echolot подставил их при отправке запроса.
pm.info
| Член | Что значит |
|---|---|
eventName | "prerequest" или "test". |
iteration | Итерация прогона, начиная с 0. |
iterationCount | Сколько итераций в прогоне. |
requestName | Название запроса. |
requestId | Путь запроса в рабочем пространстве. |
pm.sendRequest
Отправляет из скрипта другой запрос через Echolot: прокси, сертификаты и cookie действуют, как для любого запроса.
pm.sendRequest("https://demo.echolot.dev/v1/categories", (error, response) => {
if (error) { console.error(error); return; }
pm.collectionVariables.set("firstCategory", response.json().items[0].id);
});
// or with a promise
pm.sendRequest({
url: pm.variables.replaceIn("{{baseURL}}/auth/token"),
method: "POST",
header: { "Content-Type": "application/json" },
body: { mode: "raw", raw: JSON.stringify({ email: "heidi@alpenglow.ch", password: pm.environment.get("password") }) }
}).then(response => {
pm.environment.set("token", response.json().access_token);
});- Первый аргумент — URL или объект с
url,method(по умолчаниюGET),header(массив{ key, value }, объект или список) иbody. body— строка,{ mode: "raw", raw },{ mode: "urlencoded", urlencoded: [{ key, value }] }или{ mode: "graphql", graphql: { query, variables } }. Два последних задаютContent-Type, если вы его не указали.{{variables}}в URL подставляются с учётом окружения запроса.- Колбэк получает
(error, response);responseпохож наpm.response. Без колбэка возвращается промис. - У запроса нет собственной авторизации (авторизация рабочего пространства не применяется), и скрипты он не запускает.
pm.sendRequestагента проходит через одобрения агента, как другие его отправки.
Управление прогоном
| Вызов | Что делает |
|---|---|
pm.execution.setNextRequest(name) | В прогоне: следующим продолжить с этого запроса. null завершает прогон. Также pm.setNextRequest, postman.setNextRequest. |
pm.execution.skipRequest() | В скрипте перед запросом: не отправлять этот запрос. |
pm.cookies
Cookie этого обмена: те, что отправил запрос, и те, что установил ответ. Это список с
pm.cookies.get(name), has(name), toObject() и one(name), который возвращает { name, key, value }.
Списки
Заголовки, параметры запроса и cookie — это списки свойств Postman:
| Метод | Что делает |
|---|---|
get(key) | Значение; регистр ключей не учитывается. |
one(key) | Весь элемент, { key, value, disabled }. |
has(key), has(key, value) | Есть ли он (с этим значением). |
add(item), append(item), upsert(item) | Добавляют элемент или добавляют либо заменяют его. |
remove(key), remove(fn), clear() | Удаляют элементы. |
toObject(), all(), count(), idx(i) | Элементы в виде объекта, в виде массива, их количество, элемент по индексу. |
each(fn), map(fn), filter(fn), find(fn) | Перебирают элементы. |
toString() | Строки вида Name: value. |
console
console.log, info, warn, error, debug и trace пишут в Консоль запроса, а в командной строке — под
── console ──. Объекты выводятся как JSON.
Таймеры
setTimeout, setInterval и setImmediate выполняют свои функции после скрипта, в порядке их задержек, не ожидая
по-настоящему. setInterval срабатывает один раз. clearTimeout и остальные отменяют.
JSON Schema
Три способа, все на собственном валидаторе JSON Schema в Echolot:
const schema = {
type: "object",
required: ["sku", "price"],
properties: { sku: { type: "string" }, price: { type: "object" } }
};
// Chai
pm.expect(pm.response.json()).to.have.jsonSchema(schema);
// ajv
const Ajv = require("ajv");
const validate = new Ajv().compile(schema);
pm.test("Matches the schema", () => pm.expect(validate(pm.response.json()), JSON.stringify(validate.errors)).to.be.true);
// tv4
pm.test("Matches the schema", () => pm.expect(tv4.validate(pm.response.json(), schema)).to.be.true);| Помощник | Что в нём |
|---|---|
require("ajv") | Класс: new Ajv(options), validate(schema, data), compile(schema) (функция с .errors), addSchema(schema, key), getSchema(key), errorsText(errors) и errors. addFormat и addKeyword принимаются и ничего не делают. |
tv4 (также require("tv4")) | validate(data, schema) с tv4.error, validateResult(data, schema), validateMultiple(data, schema). |
.jsonSchema(schema) | Утверждение Chai, показанное выше. |
Проверка по JSON Schema работает и без скрипта: это проверка JSON Schema на вкладке Тесты.
Библиотеки
| Название | Что в ней |
|---|---|
CryptoJS (также require("crypto-js")) | MD5, SHA1, SHA256, SHA384, SHA512, HmacMD5, HmacSHA1, HmacSHA256, HmacSHA384, HmacSHA512; enc.Hex, enc.Utf8, enc.Base64, enc.Latin1; lib.WordArray.create(bytes) и lib.WordArray.random(n). У результатов есть toString(encoder). |
_ (также require("lodash")) | Функции lodash, которыми пользуются для коллекций: each/forEach, map, filter, reject, find, findIndex, some, every, reduce, includes/contains, get, has, set, keys, values, size, проверки is… (isArray, isString, isEmpty, isEqual и остальные), startsWith, endsWith, trim, toLower, toUpper, capitalize, parseInt, toNumber, toString, first/head, last, tail, initial, uniq, flatten, compact, concat, range, times, sortBy, groupBy, keyBy, countBy, pick, omit, assign/extend, clone, cloneDeep, merge, random, sample, sum, max, min, noop, identity, now, uniqueId. |
require("uuid") | v4() — случайный UUID. |
btoa, atob (также require("btoa"), require("atob")) | Base64 для текста в Latin-1 и обратно. |
Старые глобальные объекты Postman
Скрипты из старых коллекций используют их, и они работают:
| Глобальный объект | Что это |
|---|---|
tests["name"] = condition | Тест. |
responseBody, responseCode (code, name, detail), responseHeaders, responseTime | Ответ. |
request (url, method, headers, data, name, description) | Запрос. |
environment, globals, data, iteration | Переменные в виде объектов, строка данных, итерация. |
postman.setEnvironmentVariable, getEnvironmentVariable, clearEnvironmentVariable, clearEnvironmentVariables | Окружение. |
postman.setGlobalVariable, getGlobalVariable, clearGlobalVariable, clearGlobalVariables | Глобальные переменные. |
postman.getResponseHeader(name), postman.getResponseCookie(name), postman.setNextRequest(name) | Ответ и прогон. |
"text".has("x") | Содержит ли строка другую. |
Чего там нет
- Другие модули:
requireчего-либо, не перечисленного выше (cheerio,xml2js,moment, собственные модули Node), выбрасывает «The module … is not available in Echolot scripts.» - Настоящее ожидание: таймеры работают без задержки, а
fetchиXMLHttpRequestотсутствуют. Используйтеpm.sendRequest. - Файлы и процессы: скрипты не могут читать и записывать файлы или запускать программы.
pm.visualizer.setпринимается, так что скрипты, которые его используют, работают, но Echolot визуализацию не показывает.xml2Json,pm.requireи библиотека пакетов Postman, а такжеpm.vault.- Секреты в файлах: скрипты читают секретные переменные, как любые другие, но то, что они задают через
set, никогда не попадает в файлы рабочего пространства.
Динамические значения
Все динамические значения Echolot с аргументами и примерами, сгруппированные так же, как в списке подсказок, который появляется после двух открывающих фигурных скобок.
Сочетания клавиш
Все сочетания клавиш Echolot — из меню и со страниц, сгруппированные по тому, где ими пользуются.