スクリプトAPI
リクエスト前スクリプトとテストスクリプトで使えるすべてのもの。pmオブジェクト、expect、JSON Schemaヘルパー、ライブラリ、そして使えないもの。
スクリプトは、リクエストの送信前(リクエスト前)またはレスポンスの到着後(テスト)に実行されるJavaScriptです。
PostmanのAPIであるpmを使うので、Postmanコレクションのスクリプトはそのまま動作します。このページでは、そのすべてを一覧にしています。
アプリでの書き方と結果の読み方は、スクリプトとテストを参照してください。
スクリプトが実行される場所
- リクエストのスクリプトはスクリプトタブにあり、リクエストの横に
<slug>.pre.jsと<slug>.test.jsとして保存されます。フォルダとワークスペースにもスクリプトがあります(_folder.pre.js、_folder.test.js)。ワークスペースのファイルを参照してください。 - 各リクエストでは、最初にワークスペースのスクリプトが、次に外側から順に各フォルダのスクリプトが、最後にリクエスト自身のスクリプトが実行されます。1つのイベントのすべてのスクリプトは、1つのサンドボックスを共有します。
- MCPの呼び出しにはスクリプトがありません。
- Echolotの外部(読み込み、Git、別のエディタ)から来たスクリプトは、スクリプトを確認…で読んでからスクリプトを信頼した場合にだけ実行されます。
- コマンドラインツールも、
echolot runとecholot sendでスクリプトを実行します。
サンドボックス
スクリプトは、Echolot内のサンドボックス化されたJavaScriptエンジン(QuickJS)で実行されます。ファイルシステムも、独自のネットワークも、Node.jsモジュールもありません。外に出る唯一の方法は、Echolotを通じて送信するpm.sendRequestです。
| 制限 | 値 |
|---|---|
| 1つのイベントのすべてのスクリプトに許されるJavaScriptの実行時間 | 5秒 |
| メモリ | 128 MB |
すべてのpm.sendRequestの応答を待つ時間 | 30秒 |
| スクリプトから見えるレスポンスボディ | 最初の32 MB |
例外を投げたり制限を超えたりしたスクリプトは、スクリプトエラーとして報告され、失敗したテストとして数えられます。
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 () => { … }) | Promiseを返すテストは、Promiseが解決されれば成功します。 |
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ではそのうちの1つ、includeの後では少なくともこれら)。 |
.members(array) | 配列が同じメンバーを持つ(includeでは少なくともこれら、orderedではこの順序で)。 |
.oneOf(array) | 値が配列の項目のいずれかである。 |
.satisfy(fn)、.satisfies | fn(value)が真を返す。 |
.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 } }です。後ろの2つは、指定がなければContent-Typeが設定されます。- URL内の
{{variables}}は、リクエストの環境で埋め込まれます。 - コールバックは
(error, response)を受け取ります。responseはpm.responseと同様です。コールバックがない場合は、Promiseを返します。 - このリクエストには独自の認証がなく(ワークスペースの認証は適用されません)、スクリプトも実行されません。
- エージェントの
pm.sendRequestは、ほかの送信と同じように、エージェントの承認を通ります。
実行の制御
| 呼び出し | 動作 |
|---|---|
pm.execution.setNextRequest(name) | 実行中に、次にそのリクエストへ進みます。nullで実行を終了します。pm.setNextRequest、postman.setNextRequestも同じです。 |
pm.execution.skipRequest() | リクエスト前スクリプトで、このリクエストを送信しません。 |
pm.cookies
このやり取りのCookie。リクエストが送信したものと、レスポンスが設定したものです。リストで、pm.cookies.get(name)、has(name)、toObject()、そして{ name, key, value }を返すone(name)があります。
リスト
ヘッダー、クエリパラメータ、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
方法は3つあり、すべてEcholot独自のJSON Schemaバリデータを使います。
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")も同じ) | Latin-1テキストのBase64と、その逆変換。 |
古い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した内容がワークスペースのファイルに書き込まれることはありません。