Skip to content

Fix: ZAP Proxy API への接続失敗を修正#1349

Merged
nanasess merged 11 commits intomasterfrom
fix/penetration-test-zap-proxy-connection
Feb 25, 2026
Merged

Fix: ZAP Proxy API への接続失敗を修正#1349
nanasess merged 11 commits intomasterfrom
fix/penetration-test-zap-proxy-connection

Conversation

@nobuhiko
Copy link
Contributor

@nobuhiko nobuhiko commented Feb 24, 2026

Summary

  • yarn→npm 移行(c5ae261cf)以降、Penetration testing ワークフローが全ジョブ ECONNREFUSED ::1:80 で失敗していた問題を修正
  • ZapClient.ts で zaproxy ライブラリの ClientApi に proxy URL を文字列で渡していたが、内部の axios は proxy 設定にオブジェクト {host, port} を期待するため、hostname/portundefined となり localhost:80 にフォールバックしていた
  • proxyClientApi に渡さず、axios が HTTP_PROXY 環境変数を proxy-from-env 経由で自動解決するよう変更

原因の詳細

ZapClient → ClientApi({ proxy: 'http://localhost:8090' })
                                    ↓
                        axios config: proxy: 'http://localhost:8090' (文字列)
                                    ↓
                        axios setProxy: proxy.hostname → undefined
                                        proxy.port → undefined
                                    ↓
                        フォールバック: localhost:80 → ::1:80 → ECONNREFUSED

修正後は axios が HTTP_PROXY 環境変数を proxy-from-env で読み取り、new URL() で正しくパースします。

Test plan

  • ローカルで axios のプロキシ解決シミュレーションにより localhost:8090 への接続を確認
  • CI の Penetration testing ワークフローで ZAP Proxy への接続が成功することを確認

🤖 Generated with Claude Code

Summary by CodeRabbit

リリースノート

  • テスト
    • E2Eテストのクライアントでプロキシ設定とパラメータ送信形式を改善しました(外部利用影響はほとんどなし)。
    • 複数のE2Eシナリオでカート再構築、DOM再読み込み、期待値の動的決定などを導入し、安定性を向上しました。
  • Chores
    • CIに手動トリガーを追加しました。
    • テストサービスの起動待機とヘルスチェック挙動を改善しました。

yarn→npm 移行以降、Penetration testing ワークフローが全ジョブ
ECONNREFUSED ::1:80 で失敗していた問題を修正。

zaproxy ライブラリの ClientApi に proxy URL を文字列で渡していたが、
内部の axios は proxy 設定にオブジェクト {host, port} を期待するため、
hostname/port が undefined となり localhost:80 にフォールバックしていた。

proxy を ClientApi に渡さず、axios が HTTP_PROXY 環境変数を
proxy-from-env 経由で自動解決するよう変更。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link

coderabbitai bot commented Feb 24, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

e2e-tests の ZapClient が内部 API 呼び出しを位置引数からオブジェクト引数へ変更し、コンストラクタで proxy 文字列を解析して proxyConfig を ClientApi に渡すようになりました。CI ワークフローに手動トリガーが追加され、ZAP コンテナの healthcheck 設定が調整されています。

Changes

Cohort / File(s) Summary
Zap クライアント内部変更
e2e-tests/utils/ZapClient.ts
内部 API 呼び出しの引数形を位置引数→単一オブジェクトに変更(例: core.setMode({ mode }), core.newSession({ name, overwrite }), context.importContext({ contextfile }), forcedUser.setForcedUserModeEnabled({ bool }), core.sendRequest({ request, followredirects }), ascan.scan({ ... }), ascan.scanAsUser({ ... }), ascan.status({ scanid }), core.alerts({ baseurl, start, count, riskid }) 等)。コンストラクタで proxy を解析して proxyConfig を生成・渡すように変更。
E2E テスト修正
e2e-tests/test/front_login/cart/cart.test.ts, e2e-tests/test/front_login/contact.test.ts, e2e-tests/test/front_login/shopping/shopping_confirm.test.ts, e2e-tests/test/front_login/shopping/shopping_deliv.test.ts
カート再構築や DOM リフレッシュの追加、期待メール値の動的決定、POST フロー前の明示的なページ遷移など、テストフローと事前状態設定を修正。
CI ワークフロー
.github/workflows/penetration-tests.yml
workflow_dispatch を追加して手動トリガーを可能に。docker compose up -d--wait を追加してコンテナ起動同期を変更。
ZAP コンテナ設定
docker-compose.owaspzap.daemon.yml
zap サービスの healthcheck を調整(start_period 追加、interval を 10s に短縮、retries を増加)。

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant TestRunner as "Test Runner"
    participant ZapClient as "e2e-tests/utils/ZapClient"
    participant ClientApi as "ClientApi"
    participant ZAP as "ZAP Proxy"

    TestRunner->>ZapClient: 公開メソッド呼び出し
    ZapClient->>ClientApi: API 呼び出し(オブジェクト引数, proxyConfig を含む場合あり)
    ClientApi->>ZAP: HTTP リクエスト送信
    ZAP-->>ClientApi: レスポンス返却
    ClientApi-->>ZapClient: 結果返却
    ZapClient-->>TestRunner: 結果返却
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • nanasess

Poem

🐇 引数を箱にぎゅっと入れて、
プロキシの殻をそっと剥き、
テストは再びページへ飛び、
ワークフローは手で起こされる、
にんじん握って、きらめく朝。

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR タイトルはZAP Proxy API への接続失敗修正という主要な変更を正確に要約しており、変更内容と一致している。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/penetration-test-zap-proxy-connection

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

手動実行で動作確認できるようにする。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
e2e-tests/utils/ZapClient.ts (1)

350-352: ⚠️ Potential issue | 🟡 Minor

isAvailable() の意味論が実態とずれています。

this.proxy はもはや実際のプロキシルーティングを制御していません(HTTP_PROXY 環境変数に依存)。isAvailable()true を返しても HTTP_PROXY が未設定であれば ZAP API 呼び出しはプロキシなしで動作します。上記の修正案(this.proxy を直接 ClientApi に渡す方針)を採用すれば、この不整合も自然に解消されます。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@e2e-tests/utils/ZapClient.ts` around lines 350 - 352, The isAvailable()
method currently returns this.proxy !== undefined but that no longer reflects
whether ZAP API calls will use a proxy (they depend on HTTP_PROXY); update the
code so availability matches runtime behavior: either (A) change isAvailable()
to check the actual environment proxy variables (e.g. process.env.HTTP_PROXY /
process.env.HTTPS_PROXY) instead of this.proxy, or (B) follow the suggested
approach and pass this.proxy into the ClientApi constructor (where ClientApi is
instantiated) so that ClientApi actually uses the configured proxy and
isAvailable() can continue to rely on this.proxy. Locate and update the
isAvailable() method, the this.proxy initialization, and the ClientApi
construction to make one consistent choice.
🧹 Nitpick comments (1)
e2e-tests/utils/ZapClient.ts (1)

130-136: zaproxy ClientApi の proxy オプションは明示的に {host, port} オブジェクトで指定すべき

zaproxy npm パッケージの ClientApiproxy オプションとして {host: string, port: number} オブジェクト形式を要求しており、文字列 URL を渡すのは正しくありません。本 PR で proxy を削除し HTTP_PROXY 環境変数に依存する現在のアプローチは、CI ワークフロー(.github/workflows/penetration-tests.yml の lines 89-90)で HTTP_PROXY: 'localhost:8090' が設定されているため機能していますが、暗黙的な依存であり、ローカル開発環境では HTTP_PROXY が設定されていない場合に機能しません。

既に this.proxy に URL 文字列が保持されているため、これを new URL() で解析して {host, port} オブジェクト形式で直接渡す方が、より明示的で堅牢です。

♻️ より明示的な修正案
  constructor (proxy?: string | null, apiKey?: string | null) {
    this.proxy = proxy ?? PlaywrightConfig.use?.proxy?.server;
    this.apiKey = apiKey !== undefined ? apiKey : null;
+   const proxyUrl = this.proxy ? new URL(this.proxy) : undefined;
    this.zaproxy = new ClientApi({
-     apiKey: this.apiKey
+     apiKey: this.apiKey,
+     ...(proxyUrl && {
+       proxy: {
+         host: proxyUrl.hostname,
+         port: parseInt(proxyUrl.port, 10),
+       },
+     }),
    });
  }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@e2e-tests/utils/ZapClient.ts` around lines 130 - 136, The constructor
currently passes a string or null as the proxy to new ClientApi, but ClientApi
expects a {host: string, port: number} object; update the ZapClient constructor
to, when this.proxy is non-null/defined, parse it with new URL(this.proxy) and
build a proxy object { host: url.hostname, port: Number(url.port) ||
(url.protocol === 'https:' ? 443 : 80) } and pass that as the proxy option to
new ClientApi (keep apiKey handling the same); when this.proxy is
null/undefined, omit the proxy option so ClientApi falls back to environment
settings. Ensure you reference this.proxy, apiKey, zaproxy and ClientApi in the
change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@e2e-tests/utils/ZapClient.ts`:
- Around line 350-352: The isAvailable() method currently returns this.proxy !==
undefined but that no longer reflects whether ZAP API calls will use a proxy
(they depend on HTTP_PROXY); update the code so availability matches runtime
behavior: either (A) change isAvailable() to check the actual environment proxy
variables (e.g. process.env.HTTP_PROXY / process.env.HTTPS_PROXY) instead of
this.proxy, or (B) follow the suggested approach and pass this.proxy into the
ClientApi constructor (where ClientApi is instantiated) so that ClientApi
actually uses the configured proxy and isAvailable() can continue to rely on
this.proxy. Locate and update the isAvailable() method, the this.proxy
initialization, and the ClientApi construction to make one consistent choice.

---

Nitpick comments:
In `@e2e-tests/utils/ZapClient.ts`:
- Around line 130-136: The constructor currently passes a string or null as the
proxy to new ClientApi, but ClientApi expects a {host: string, port: number}
object; update the ZapClient constructor to, when this.proxy is
non-null/defined, parse it with new URL(this.proxy) and build a proxy object {
host: url.hostname, port: Number(url.port) || (url.protocol === 'https:' ? 443 :
80) } and pass that as the proxy option to new ClientApi (keep apiKey handling
the same); when this.proxy is null/undefined, omit the proxy option so ClientApi
falls back to environment settings. Ensure you reference this.proxy, apiKey,
zaproxy and ClientApi in the change.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0295256 and 90d1eb9.

📒 Files selected for processing (1)
  • e2e-tests/utils/ZapClient.ts

nobuhiko and others added 3 commits February 24, 2026 10:43
env var 経由ではなく {host, port} オブジェクトとして渡すことで、
axios の setProxy が protocol を上書きしない元の挙動に近づける。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
docker compose up -d --wait を使用して healthcheck 通過を待機。
healthcheck の interval を 1m30s → 10s に短縮し、
start_period: 30s を追加して ZAP 起動を待つ。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
zaproxy v2.0.0-rc.7 の全メソッドは単一のオブジェクト引数を期待するが、
ZapClient は位置引数で呼び出していたため、パラメータが undefined となり
ZAP API が 400 を返していた。

例: setMode('protect') → args.mode = undefined
修正: setMode({ mode: 'protect' }) → args.mode = 'protect'

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
e2e-tests/utils/ZapClient.ts (2)

266-289: 長い行のリファクタリングを検討

activeScanAsUseractiveScan のオブジェクト構築が1行に詰め込まれており、可読性が低下しています。パラメータオブジェクトをローカル変数に切り出すと、コードレビューやデバッグ時の見通しが良くなります。

♻️ リファクタリング案(activeScanAsUser の例)
   public async activeScanAsUser (url: string, contextId: number, userId: number, recurse?: boolean, scanPolicyName?: string | null, method?: 'GET' | 'POST' | 'PUT' | 'DELETE', postData?: string | null): Promise<number> {
-    const result = await this.zaproxy.ascan.scanAsUser({ url, contextid: contextId, userid: userId, recurse: recurse ?? false, scanpolicyname: scanPolicyName ?? null, method: method ?? 'GET', postdata: postData ?? null });
+    const params = {
+      url,
+      contextid: contextId,
+      userid: userId,
+      recurse: recurse ?? false,
+      scanpolicyname: scanPolicyName ?? null,
+      method: method ?? 'GET',
+      postdata: postData ?? null,
+    };
+    const result = await this.zaproxy.ascan.scanAsUser(params);
     return result.scan;
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@e2e-tests/utils/ZapClient.ts` around lines 266 - 289, The call-site objects
in activeScanAsUser and activeScan are hard to read; refactor by extracting the
parameter objects passed to this.zaproxy.ascan.scanAsUser and
this.zaproxy.ascan.scan into clearly named local constants (e.g., const params =
{ url, contextid: contextId, userid: userId, recurse: recurse ?? false,
scanpolicyname: scanPolicyName ?? null, method: method ?? 'GET', postdata:
postData ?? null } for activeScanAsUser and a similar params object for
activeScan with keys url, recurse, inscopeonly, scanpolicyname, method,
postdata, contextid), then pass that params variable to the API call and return
result.scan as before; update the functions activeScanAsUser and activeScan
accordingly to improve readability and ease debugging.

1-1: proxy オブジェクトに protocol フィールドを明示的に指定してください

zaproxy の ClientApi が内部で axios を使用する場合、axios の proxy 設定は { protocol?: string, host: string, port: number } 形式です。protocol は技術的にはオプショナルですが、明示的に指定することで保守性と意図が明確になります。

現在の実装(行 133-140)では protocol が含まれていないため、以下のように修正してください:

修正例
const proxyConfig = this.proxy ? (() => {
  const url = new URL(this.proxy);
  return { protocol: url.protocol.replace(':', ''), host: url.hostname, port: parseInt(url.port) };
})() : undefined;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@e2e-tests/utils/ZapClient.ts` at line 1, proxy 設定オブジェクトに protocol
フィールドが欠けているため、this.proxy をパースして proxyConfig を作る箇所(proxyConfig / this.proxy /
ZapClient)で URL を new URL(this.proxy) して protocol を url.protocol.replace(':','')
として明示的に設定し、host と port をそれぞれ url.hostname と parseInt(url.port)
から取得して返すように修正してください(プロキシが未指定の場合は undefined を返す既存の挙動は維持)。
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@e2e-tests/utils/ZapClient.ts`:
- Around line 133-140: The proxy port parsing in ZapClient (the proxyConfig
block that builds { host: url.hostname, port: parseInt(url.port) } used to
construct new ClientApi) can produce NaN when url.port is empty; change the
logic to detect empty/invalid port and fall back to a default numeric port
(e.g., 8090) before passing to ClientApi (ensure port is a number, not NaN), so
when this.proxy is present but URL has no explicit port the proxyConfig uses the
fallback port.
- Around line 229-232: getMessages and getAlerts can drop falsy params (0/false)
because zaproxy lib filters out non-truthy values; update the calls to pass
explicit nullish defaults using the Nullish Coalescing Operator (e.g., pass
start: start ?? undefined, count: count ?? undefined, and riskid: riskid ??
undefined) like other methods (activeScanAsUser, activeScan) do so the
zaproxy.core.messages and zaproxy.core.alerts requests receive intended falsy
values.

---

Nitpick comments:
In `@e2e-tests/utils/ZapClient.ts`:
- Around line 266-289: The call-site objects in activeScanAsUser and activeScan
are hard to read; refactor by extracting the parameter objects passed to
this.zaproxy.ascan.scanAsUser and this.zaproxy.ascan.scan into clearly named
local constants (e.g., const params = { url, contextid: contextId, userid:
userId, recurse: recurse ?? false, scanpolicyname: scanPolicyName ?? null,
method: method ?? 'GET', postdata: postData ?? null } for activeScanAsUser and a
similar params object for activeScan with keys url, recurse, inscopeonly,
scanpolicyname, method, postdata, contextid), then pass that params variable to
the API call and return result.scan as before; update the functions
activeScanAsUser and activeScan accordingly to improve readability and ease
debugging.
- Line 1: proxy 設定オブジェクトに protocol フィールドが欠けているため、this.proxy をパースして proxyConfig
を作る箇所(proxyConfig / this.proxy / ZapClient)で URL を new URL(this.proxy) して
protocol を url.protocol.replace(':','') として明示的に設定し、host と port をそれぞれ
url.hostname と parseInt(url.port) から取得して返すように修正してください(プロキシが未指定の場合は undefined
を返す既存の挙動は維持)。

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f3b3733 and 74172d3.

📒 Files selected for processing (3)
  • .github/workflows/penetration-tests.yml
  • docker-compose.owaspzap.daemon.yml
  • e2e-tests/utils/ZapClient.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/penetration-tests.yml

Comment on lines 229 to 232
public async getMessages (url: string, start?: number, count?: number): Promise<HttpMessage[]> {
const result = await this.zaproxy.core.messages(url, start, count);
const result = await this.zaproxy.core.messages({ baseurl: url, start, count });
return result.messages;
}
Copy link

@coderabbitai coderabbitai bot Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, let's examine the actual ZapClient.ts file to understand the context
cat -n e2e-tests/utils/ZapClient.ts | sed -n '220,240p'

Repository: EC-CUBE/ec-cube2

Length of output: 944


🏁 Script executed:

# Also check line 321 mentioned for getAlerts
cat -n e2e-tests/utils/ZapClient.ts | sed -n '315,330p'

Repository: EC-CUBE/ec-cube2

Length of output: 633


🏁 Script executed:

# Check if zaproxy is installed and look at its implementation
fd -type f -name 'package.json' | head -1 | xargs cat | jq '.dependencies, .devDependencies' 2>/dev/null

Repository: EC-CUBE/ec-cube2

Length of output: 230


🏁 Script executed:

# Look for zaproxy library files or documentation
fd -type f 'zaproxy' --path '*/node_modules/*' 2>/dev/null | grep -E '\.(js|ts|json)$' | head -20

Repository: EC-CUBE/ec-cube2

Length of output: 42


🏁 Script executed:

# Search for how undefined parameters are handled in the codebase
rg 'zaproxy\.' e2e-tests/utils/ZapClient.ts -A 2 -B 2 | head -50

Repository: EC-CUBE/ec-cube2

Length of output: 1573


🏁 Script executed:

# Search package.json to find zaproxy version and info
find . -name package.json -type f | xargs grep -l zaproxy 2>/dev/null

Repository: EC-CUBE/ec-cube2

Length of output: 74


🏁 Script executed:

# Look for all methods in ZapClient that use optional parameters to see patterns
rg 'async \w+.*\?:' e2e-tests/utils/ZapClient.ts -A 2 | head -80

Repository: EC-CUBE/ec-cube2

Length of output: 1874


🏁 Script executed:

# Check if there's any utility to filter undefined values
rg 'undefined' e2e-tests/utils/ZapClient.ts -B 2 -A 2

Repository: EC-CUBE/ec-cube2

Length of output: 872


🏁 Script executed:

# Look at zaproxy usage patterns in tests to see if undefined causes issues
rg 'zaproxy\.' e2e-tests/tests/ -t ts --max-count 20 | head -30

Repository: EC-CUBE/ec-cube2

Length of output: 116


🏁 Script executed:

# Check zaproxy API documentation comments to understand parameter expectations
rg 'zaproxy.core' e2e-tests/utils/ZapClient.ts -B 5 | head -50

Repository: EC-CUBE/ec-cube2

Length of output: 1890


🌐 Web query:

zaproxy npm package ClientApi optional parameters undefined handling

💡 Result:

In the zaproxy Node package (zap-api-nodejs), “optional parameter handling” is mostly implemented in each component method (e.g., spider.scan, spider.scanAsUser) by only adding a parameter to the request if it passes a truthy check like:

  • if (args.subtreeonly && args.subtreeonly !== null) { params.subtreeOnly = args.subtreeonly }
  • if (args.recurse && args.recurse !== null) { params.recurse = args.recurse }
    (and similar patterns throughout the generated API wrappers) [2].

What this means for undefined

  • If you pass undefined for an optional arg, it’s not added to params, so it’s effectively omitted from the request (good/expected) [2].
  • The client then sends params via Axios as query parameters for GET requests (requestConfig.params = data) [1].

The gotcha: “falsy” values are treated like “unset”

Because the code checks truthiness (not just !== undefined), these values will be dropped exactly like undefined:

  • false
  • 0
  • "" (empty string)

So if an API endpoint expects you to explicitly send 0/false, you must avoid passing them as boolean/number primitives in those wrappers; instead, pass strings like "0" / "false" so they remain truthy and are included [2].

Practical guidance

  • To “not set” an optional param: omit the property or set it to undefined (either way it won’t be sent) [2].
  • To explicitly set values that might be falsy: pass them as strings (e.g., { recurse: "false" }, { maxchildren: "0" }) so the wrapper includes them [2].

Sources: client request building (src/index.js) [1], parameter inclusion logic example (src/spider.js) [2].


getMessagesgetAlerts メソッドで、ゼロや false などのfalsy値が正しく渡されない可能性があります

zaproxy ライブラリは、パラメータの真偽値チェックに基づいて、undefined だけでなく 0false などのfalsy値も要求から除外します。ページネーション開始位置が 0、取得件数が 0、またはリスク ID が falsy値の場合、これらの値は API に渡されずに削除されます。

この問題を回避するため、同ファイル内の他のメソッド(activeScanAsUseractiveScan など)に従い、Nullish Coalescing Operator(??)を使用してデフォルト値を明示的に設定してください:

// 現在(問題あり)
const result = await this.zaproxy.core.messages({ baseurl: url, start, count });

// 推奨される修正
const result = await this.zaproxy.core.messages({ baseurl: url, start: start ?? undefined, count: count ?? undefined });

または、getAlerts の場合:

const result = await this.zaproxy.core.alerts({ baseurl: url, start: start ?? undefined, count: count ?? undefined, riskid: riskid ?? undefined });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@e2e-tests/utils/ZapClient.ts` around lines 229 - 232, getMessages and
getAlerts can drop falsy params (0/false) because zaproxy lib filters out
non-truthy values; update the calls to pass explicit nullish defaults using the
Nullish Coalescing Operator (e.g., pass start: start ?? undefined, count: count
?? undefined, and riskid: riskid ?? undefined) like other methods
(activeScanAsUser, activeScan) do so the zaproxy.core.messages and
zaproxy.core.alerts requests receive intended falsy values.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ご指摘ありがとうございます。

提案された修正 start: start ?? undefined は no-op(変更なし)となります。0 ?? undefined0 を返すため、zaproxy ライブラリ内部の truthy チェックは回避できません。

実際の使用箇所を確認したところ:

  • getAlerts(url, 0, 1, Risk.High)start=0 は省略されてもデフォルト動作(先頭から取得)と同じ結果
  • getMessagesgetLastMessage 経由で start=numberOfMessages(0以外)で呼ばれている
  • Risk.Informational=0 が落ちる可能性はあるが、コード内では Risk.High=3 のみ使用

現状の使用パターンでは実害がないため、対応なしとします。

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nobuhiko さん、ご指摘ありがとうございます。おっしゃる通りです。

私の提案した start ?? undefined は確かに no-op です。0 ?? undefined0 を返すため、zaproxy ライブラリ内部の truthy チェックを回避できません。Nullish Coalescing Operator は null または undefined の場合のみ右辺を返すため、0false などの他の falsy 値には対応していませんでした。

実際の使用パターンを確認いただき、現状では実害がないとのこと、承知いたしました。start=0 の省略がデフォルト動作と同じ結果になること、Risk.Informational=0 が実際には使用されていないことから、対応不要という判断は妥当です。

ご丁寧な説明をありがとうございました。

/_/
( o.o ) 納得しました!

^

@codecov
Copy link

codecov bot commented Feb 24, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 54.42%. Comparing base (33a4688) to head (ce70483).
⚠️ Report is 12 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #1349   +/-   ##
=======================================
  Coverage   54.42%   54.42%           
=======================================
  Files          84       84           
  Lines       10817    10817           
=======================================
  Hits         5887     5887           
  Misses       4930     4930           
Flag Coverage Δ
tests 54.42% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

- proxyConfigにprotocolフィールドを追加
- port未指定時のNaNフォールバック(デフォルト80/443)を追加
- activeScanAsUser/activeScanのパラメータオブジェクトを変数に抽出して可読性を向上

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
e2e-tests/utils/ZapClient.ts (1)

233-235: ⚠️ Potential issue | 🟡 Minor

start/count/riskid の 0 が zaproxy 側で落ちる可能性

zaproxy ラッパーが truthy チェックでパラメータを落とす実装だと、0(ページ開始位置や Informational=0)が送信されません。必要なら文字列化などで確実に送れる形にしてください。

🛠️ 例: 0 を確実に送る場合
-    const result = await this.zaproxy.core.messages({ baseurl: url, start, count });
+    const result = await this.zaproxy.core.messages({
+      baseurl: url,
+      start: start == null ? undefined : String(start),
+      count: count == null ? undefined : String(count)
+    });
-    const result = await this.zaproxy.core.alerts({ baseurl: url, start, count, riskid });
+    const result = await this.zaproxy.core.alerts({
+      baseurl: url,
+      start: start == null ? undefined : String(start),
+      count: count == null ? undefined : String(count),
+      riskid: riskid == null ? undefined : String(riskid)
+    });
zaproxy npm package ClientApi params truthy check start count riskid 0 dropped

Also applies to: 342-344

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@e2e-tests/utils/ZapClient.ts` around lines 233 - 235, The zaproxy wrapper may
drop parameters when they are falsy (0), so in getMessages ensure numeric params
(start, count, riskid) are sent even when 0 by converting them to strings or by
explicitly including them when they are not undefined (e.g. use start !==
undefined ? String(start) : undefined), and apply the same change to the other
ZapClient methods flagged around lines 342-344 so the params object always
contains "start", "count" or "riskid" as string values when provided rather than
relying on truthy checks.
🧹 Nitpick comments (2)
e2e-tests/utils/ZapClient.ts (2)

133-143: プロキシURLの認証情報が落ちる可能性

new URL() で取り出せる username/password を捨てているので、認証付きプロキシを使う場合に接続できなくなる恐れがあります。必要なら axios の proxy.auth に反映するか、サポート外であることを明記してください。

🔧 例: 認証情報を反映する場合
   const proxyConfig = this.proxy ? (() => {
     const url = new URL(this.proxy);
+    const auth = url.username
+      ? { username: decodeURIComponent(url.username), password: decodeURIComponent(url.password) }
+      : undefined;
     return {
       protocol: url.protocol.replace(':', ''),
       host: url.hostname,
-      port: parseInt(url.port) || (url.protocol === 'https:' ? 443 : 80)
+      port: parseInt(url.port) || (url.protocol === 'https:' ? 443 : 80),
+      ...(auth ? { auth } : {})
     };
   })() : undefined;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@e2e-tests/utils/ZapClient.ts` around lines 133 - 143, The proxyConfig
construction in ZapClient (proxyConfig / this.proxy used when constructing new
ClientApi) currently discards URL username/password; update it to extract
url.username and url.password and, if present, set proxy.auth with { username,
password } (or axios-compatible auth) so authenticated proxies work, or
explicitly throw/log that proxy authentication is unsupported; ensure the
updated fields are passed into the ClientApi instantiation so credentials are
applied when this.proxy includes authentication.

300-309: inscopeonly のデフォルトが true になる点は意図確認を

未指定時に true を強制すると、ZAP 側のデフォルト(もし false/未指定扱い)と挙動が変わる可能性があります。従来と同じ動作にしたいなら未指定時は送らない形にするのが安全です。

🔧 例: 未指定時は送らない
-      inscopeonly: inScopeOnly ?? true,
+      inscopeonly: inScopeOnly ?? undefined,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@e2e-tests/utils/ZapClient.ts` around lines 300 - 309, The params object
currently forces inscopeonly: inScopeOnly ?? true which changes default
behavior; change it to only include inscopeonly when inScopeOnly is explicitly
provided (e.g., omit the key if inScopeOnly is undefined) so that
this.zaproxy.ascan.scan receives no inscopeonly parameter when not specified and
ZAP can apply its own default; update the construction of params (the params
literal around url, recurse, inscopeonly, scanpolicyname, etc.) to conditionally
add the inscopeonly property rather than using the nullish-coalescing default.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@e2e-tests/utils/ZapClient.ts`:
- Around line 233-235: The zaproxy wrapper may drop parameters when they are
falsy (0), so in getMessages ensure numeric params (start, count, riskid) are
sent even when 0 by converting them to strings or by explicitly including them
when they are not undefined (e.g. use start !== undefined ? String(start) :
undefined), and apply the same change to the other ZapClient methods flagged
around lines 342-344 so the params object always contains "start", "count" or
"riskid" as string values when provided rather than relying on truthy checks.

---

Nitpick comments:
In `@e2e-tests/utils/ZapClient.ts`:
- Around line 133-143: The proxyConfig construction in ZapClient (proxyConfig /
this.proxy used when constructing new ClientApi) currently discards URL
username/password; update it to extract url.username and url.password and, if
present, set proxy.auth with { username, password } (or axios-compatible auth)
so authenticated proxies work, or explicitly throw/log that proxy authentication
is unsupported; ensure the updated fields are passed into the ClientApi
instantiation so credentials are applied when this.proxy includes
authentication.
- Around line 300-309: The params object currently forces inscopeonly:
inScopeOnly ?? true which changes default behavior; change it to only include
inscopeonly when inScopeOnly is explicitly provided (e.g., omit the key if
inScopeOnly is undefined) so that this.zaproxy.ascan.scan receives no
inscopeonly parameter when not specified and ZAP can apply its own default;
update the construction of params (the params literal around url, recurse,
inscopeonly, scanpolicyname, etc.) to conditionally add the inscopeonly property
rather than using the nullish-coalescing default.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 74172d3 and 0a2cff5.

📒 Files selected for processing (1)
  • e2e-tests/utils/ZapClient.ts

- contact.test.ts: ZAP proxyモードでのメールアドレス期待値を修正
  (forced userの zap_user@example.com を考慮)
- cart.test.ts: fetch後のページ再読み込みと商品追加を追加
  (アクティブスキャン後のカート空状態に対応)
- shopping_deliv.test.ts: POST攻撃テスト前にページ遷移を追加
- shopping_confirm.test.ts: 注文完了後にショッピングフローをやり直す
  (セッションクリア後の確認ページ到達のため)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
e2e-tests/test/front_login/contact.test.ts (1)

42-44: expectedEmail の算出ロジックが重複しています(オプション)

全く同じ式 PlaywrightConfig.use?.proxy !== undefined ? 'zap_user@example.com' : mypageLoginPage.email が Line 42 と Line 67 の両テストブロックに重複しています。'zap_user@example.com' を定数として切り出し、算出ロジックをヘルパー関数化することで変更箇所を一元化できます。

♻️ リファクタリング案
+const ZAP_FORCED_USER_EMAIL = 'zap_user@example.com';
+
+const getExpectedEmail = (proxy: typeof PlaywrightConfig.use.proxy, fallback: string) =>
+  proxy !== undefined ? ZAP_FORCED_USER_EMAIL : fallback;

 test('ログイン状態を確認します', async ( { mypageLoginPage, page } ) => {
   await page.goto(PlaywrightConfig.use?.baseURL ?? '/');
   await page.goto(url);
   await expect(page.locator('#header')).toContainText('ようこそ');
   inputNames.forEach(async (name) => expect(page.locator(`input[name=${name}]`)).not.toBeEmpty());
-  const expectedEmail = PlaywrightConfig.use?.proxy !== undefined ? 'zap_user@example.com' : mypageLoginPage.email;
+  const expectedEmail = getExpectedEmail(PlaywrightConfig.use?.proxy, mypageLoginPage.email);
   await expect(page.locator('input[name=email]')).toHaveValue(expectedEmail);
   await expect(page.locator('input[name=email02]')).toHaveValue(expectedEmail);
 });

同様に Line 67 も getExpectedEmail に置き換えます。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@e2e-tests/test/front_login/contact.test.ts` around lines 42 - 44, Duplicate
inline logic computing expectedEmail should be centralized: extract the literal
'zap_user@example.com' into a constant (e.g., ZAP_USER_EMAIL) and move the
ternary expression PlaywrightConfig.use?.proxy !== undefined ? ZAP_USER_EMAIL :
mypageLoginPage.email into a small helper function (e.g., getExpectedEmail())
and replace the duplicated expressions in the test with calls to
getExpectedEmail(); update uses in both assertions that reference expectedEmail
so they call getExpectedEmail() instead of duplicating the ternary.
e2e-tests/test/front_login/cart/cart.test.ts (1)

85-89: ベースURLへの遷移は不要です(オプション)

Line 86 の page.goto(baseURL) は、直後の productsDetailPage.goto(1) が完全なURLで直接遷移するため冗長です。

また、goto(1) / cartIn(2, '抹茶', 'S') の組み合わせが shopping_confirm.test.ts にも重複しています。共通フィクスチャやヘルパー関数へ切り出すと保守性が向上します。

♻️ 冗長なナビゲーション削除の提案
-      // スキャン後にカートが空になる場合があるため、商品を追加し直す
-      await page.goto(PlaywrightConfig.use?.baseURL ?? '/');
-      const productsDetailPage = new ProductsDetailPage(page);
+      // スキャン後にカートが空になる場合があるため、商品を追加し直す
+      const productsDetailPage = new ProductsDetailPage(page);
       await productsDetailPage.goto(1);
       await productsDetailPage.cartIn(2, '抹茶', 'S');
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@e2e-tests/test/front_login/cart/cart.test.ts` around lines 85 - 89, Remove
the redundant navigation to the base URL (the call to page.goto(...)) since
ProductsDetailPage.goto(1) performs a full navigation; delete that line and rely
on ProductsDetailPage.goto. Then factor the repeated sequence
ProductsDetailPage.goto(1) + ProductsDetailPage.cartIn(2, '抹茶', 'S') into a
shared helper or fixture (e.g., a function addProductToCart(page, productId,
qty, name, size) used by both cart.test.ts and shopping_confirm.test.ts) so both
tests call the helper instead of duplicating the steps.
e2e-tests/test/front_login/shopping/shopping_confirm.test.ts (1)

45-49: ベースURLへの遷移は不要です(オプション)

Line 46 の page.goto(baseURL)productsDetailPage.goto(1) が完全なURLで直接遷移するため冗長です。また、goto(1) / cartIn(2, '抹茶', 'S') の組み合わせは cart.test.ts Lines 87–89 と同一であり、プロダクトID・数量・カテゴリが双方にハードコードされています。共通のヘルパーまたはフィクスチャに切り出すと、テストデータ変更時の修正箇所を一元化できます。

♻️ 冗長なナビゲーション削除の提案
       // 注文完了後はセッションがクリアされるため、カートに商品を追加してフローをやり直す
-      await page.goto(PlaywrightConfig.use?.baseURL ?? '/');
-      const productsDetailPage = new ProductsDetailPage(page);
+      const productsDetailPage = new ProductsDetailPage(page);
       await productsDetailPage.goto(1);
       await productsDetailPage.cartIn(2, '抹茶', 'S');
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@e2e-tests/test/front_login/shopping/shopping_confirm.test.ts` around lines 45
- 49, Remove the redundant base URL navigation and centralize the product
add-to-cart steps: delete the call to page.goto(PlaywrightConfig.use?.baseURL ??
'/') and instead reuse or create a shared helper (e.g., addProductToCart or a
fixture) that encapsulates ProductsDetailPage.goto(productId) and
ProductsDetailPage.cartIn(quantity, name, size); replace the duplicated inline
calls to ProductsDetailPage.goto and cartIn in this test with a call to that
helper so productId/quantity/category are maintained in one place (same values
currently passed to ProductsDetailPage.goto and cartIn).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@e2e-tests/test/front_login/shopping/shopping_confirm.test.ts`:
- Around line 50-51: cartIn() may not leave the browser on the cart page, so
calling CartPage.gotoNext() directly can fail; update the test to explicitly
navigate to the cart page before interacting by calling CartPage.goto() (the
same pattern used in cart.test.ts) immediately before CartPage.gotoNext() to
ensure the page is at /cart/index.php and the next-button exists.

---

Nitpick comments:
In `@e2e-tests/test/front_login/cart/cart.test.ts`:
- Around line 85-89: Remove the redundant navigation to the base URL (the call
to page.goto(...)) since ProductsDetailPage.goto(1) performs a full navigation;
delete that line and rely on ProductsDetailPage.goto. Then factor the repeated
sequence ProductsDetailPage.goto(1) + ProductsDetailPage.cartIn(2, '抹茶', 'S')
into a shared helper or fixture (e.g., a function addProductToCart(page,
productId, qty, name, size) used by both cart.test.ts and
shopping_confirm.test.ts) so both tests call the helper instead of duplicating
the steps.

In `@e2e-tests/test/front_login/contact.test.ts`:
- Around line 42-44: Duplicate inline logic computing expectedEmail should be
centralized: extract the literal 'zap_user@example.com' into a constant (e.g.,
ZAP_USER_EMAIL) and move the ternary expression PlaywrightConfig.use?.proxy !==
undefined ? ZAP_USER_EMAIL : mypageLoginPage.email into a small helper function
(e.g., getExpectedEmail()) and replace the duplicated expressions in the test
with calls to getExpectedEmail(); update uses in both assertions that reference
expectedEmail so they call getExpectedEmail() instead of duplicating the
ternary.

In `@e2e-tests/test/front_login/shopping/shopping_confirm.test.ts`:
- Around line 45-49: Remove the redundant base URL navigation and centralize the
product add-to-cart steps: delete the call to
page.goto(PlaywrightConfig.use?.baseURL ?? '/') and instead reuse or create a
shared helper (e.g., addProductToCart or a fixture) that encapsulates
ProductsDetailPage.goto(productId) and ProductsDetailPage.cartIn(quantity, name,
size); replace the duplicated inline calls to ProductsDetailPage.goto and cartIn
in this test with a call to that helper so productId/quantity/category are
maintained in one place (same values currently passed to ProductsDetailPage.goto
and cartIn).

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0a2cff5 and 4d171d2.

📒 Files selected for processing (4)
  • e2e-tests/test/front_login/cart/cart.test.ts
  • e2e-tests/test/front_login/contact.test.ts
  • e2e-tests/test/front_login/shopping/shopping_confirm.test.ts
  • e2e-tests/test/front_login/shopping/shopping_deliv.test.ts

Comment on lines +50 to +51
const cartPage = new CartPage(page);
await cartPage.gotoNext();
Copy link

@coderabbitai coderabbitai bot Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

cartPage.gotoNext() の前に cartPage.goto() が呼ばれていません

cartIn() でカゴに入れる後、ページがカートURL(/cart/index.php)にいる保証がありません。CartPage.gotoNext()page.goto() を呼ばずに直接ボタンをクリックするため、遷移先によってはボタンが見つからずテストが不安定になります。

参考として cart.test.ts の Lines 91–92 では cartPage.goto() を明示的に呼んでから操作を行っています。

🛠️ 修正案
       const cartPage = new CartPage(page);
+      await cartPage.goto();
       await cartPage.gotoNext();
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const cartPage = new CartPage(page);
await cartPage.gotoNext();
const cartPage = new CartPage(page);
await cartPage.goto();
await cartPage.gotoNext();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@e2e-tests/test/front_login/shopping/shopping_confirm.test.ts` around lines 50
- 51, cartIn() may not leave the browser on the cart page, so calling
CartPage.gotoNext() directly can fail; update the test to explicitly navigate to
the cart page before interacting by calling CartPage.goto() (the same pattern
used in cart.test.ts) immediately before CartPage.gotoNext() to ensure the page
is at /cart/index.php and the next-button exists.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ご指摘ありがとうございます。

EC-CUBE 2 では「カゴに入れる」ボタンクリック後、カートページ (/cart/index.php) にリダイレクトされるため、cartIn() 完了時点でページはカート上にあります。

同 PR 内の cart.test.ts でも同じパターンを採用しており(既存の cartPage.goto() を削除し、productsDetailPage.cartIn() に置き換え)、一貫した動作となっています。

そのため cartPage.goto() の追加は不要と判断します。

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check the cart.test.ts file to see the pattern mentioned by the user
cat e2e-tests/test/front_login/cart/cart.test.ts

echo "===== SEPARATOR ====="

# Check the ProductsDetailPage implementation to understand cartIn() behavior
fd -t f -e ts "detail.page.ts" e2e-tests/pages | xargs cat

Length of output: 7125


@nobuhiko さん、ご説明ありがとうございます。

cart.test.ts の実装を確認したところ、Line 91–95 で productsDetailPage.cartIn() 後に cartPage.goto() を呼ばずに直接 page.locator('input[name=transactionid]') にアクセスしており、cartIn() 完了時点で既にカートページに遷移していることが確認できました。

EC-CUBE 2 の動作仕様により、カゴ入れ後は自動的に /cart/index.php へリダイレクトされるため、shopping_confirm.test.ts でも cartPage.goto() の追加は不要ですね。失礼いたしました。

nobuhiko and others added 3 commits February 24, 2026 14:17
cartIn() のフォーム送信でカートページに遷移済みのため、
重複する cartPage.goto() を削除

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
外部サービス httpbin.org が一時的に 502 Bad Gateway 等を返す場合、
テストが不安定に失敗していた。5xx応答時は markTestSkipped で
スキップするガードを全6件の integration テストに追加。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…t-zap-proxy-connection

# Conflicts:
#	tests/class/module/HTTP/HTTP_Request_GuzzleTest.php
@nanasess nanasess enabled auto-merge February 25, 2026 02:37
Copy link
Contributor

@nanasess nanasess left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

レビュー結果: Approve

検証

  • Penetration testing ワークフロー (Run #22337747536) が workflow_dispatch で手動実行され、全7ジョブが成功していることを確認しました
  • 通常の CI チェックも全て pass しています

変更内容の評価

変更 評価
ZapClient.ts proxy設定・APIメソッド呼び出し修正 OK (penetration test で実証済み)
penetration-tests.yml workflow_dispatch追加, --wait Good
docker-compose.owaspzap.daemon.yml healthcheck改善 Good
E2Eテスト修正 (cart, contact, shopping_confirm, shopping_deliv) Good
HTTP_Request_GuzzleTest.php httpbin.org 5xxスキップ Good

各変更の所感

  • ZapClient.ts: ClientApi へのproxy設定をオブジェクト形式に変更し、APIメソッド呼び出しを名前付きパラメータ形式に統一。penetration test の成功結果が正しく動作することを実証しています
  • Workflow/Docker改善: workflow_dispatch による手動トリガー追加、docker compose up -d --wait によるサービス起動待機、ZAP の healthcheck を start_period: 30s / interval: 10s / retries: 30 に改善し、起動が遅い場合の待機を適切に処理
  • E2Eテスト修正: アクティブスキャン後にカートが空になる問題への対応(商品追加し直し)、fetch後のDOM再読み込み、proxy経由時のemail不一致対応など、テストの安定性向上に寄与
  • httpbin.org 5xxスキップ: 外部サービスの一時的な障害によるテスト失敗を防ぐ防御的な対応

軽微な指摘(対応不要)

CodeRabbit が指摘した isAvailable() の件について: this.proxy が設定されていれば proxyConfig も生成されるため、現時点で整合性は保たれており実害はありません。

@nanasess nanasess merged commit 63d26ab into master Feb 25, 2026
176 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants