Skip to content

Commit 70cda8e

Browse files
committed
docs: document AliasMap usage for Pest v3 truncated ID compatibility
1 parent 5f221a4 commit 70cda8e

2 files changed

Lines changed: 54 additions & 2 deletions

File tree

packages/phpunit/README.md

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,33 @@ namespace: App\Tests\Unit App
281281
└─ with data set "two"
282282
```
283283

284-
### 4. Format test output (Printer)
284+
### 4. Resolve test items by ID at runtime (`AliasMap`)
285+
286+
When test results arrive via Teamcity events, you need to look up the corresponding UI item by its ID. `AliasMap<T>` is a drop-in replacement for `Map<string, T>` that handles a Pest v3 bug automatically.
287+
288+
**The problem**: Pest v3's `Str::beforeLast()` mixes `mb_strrpos` (char offset) with `substr` (byte offset). The `` character (U+2192) is 3 UTF-8 bytes but 1 char, so `testSuiteStarted` / `testSuiteFinished` event IDs are truncated by 2 bytes per `` — making a direct `Map.get()` miss the item.
289+
290+
**The solution**: Use `AliasMap` instead of a plain `Map`. Every `set()` call automatically registers the truncated alias alongside the real ID, so `get()` finds the item regardless of which variant the event carries.
291+
292+
```typescript
293+
import { AliasMap } from '@vscode-phpunit/phpunit';
294+
295+
// Build from your test items — truncated aliases registered automatically
296+
const testItemById = new AliasMap<MyItem>(
297+
items.map((item) => [item.id, item]),
298+
);
299+
300+
// Lookup works for both the full and the Pest v3 truncated ID
301+
const fullId = 'tests/Unit/Foo.php::`something` → it passes';
302+
const truncatedId = 'tests/Unit/Foo.php::`something` → it pass'; // truncated by Pest v3
303+
304+
testItemById.get(fullId); // → MyItem ✓
305+
testItemById.get(truncatedId); // → MyItem ✓ (alias registered automatically)
306+
```
307+
308+
`AliasMap` is framework-agnostic — it works with VS Code `TestItem`, plain objects, or any other type.
309+
310+
### 5. Format test output (Printer)
285311

286312
`Printer` transforms structured test events into human-readable output with configurable templates and ANSI colors. Output is written through the `OutputWriter` interface, keeping the printer decoupled from any specific output target.
287313

packages/phpunit/README.zh-TW.md

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,33 @@ namespace: App\Tests\Unit App
280280
└─ with data set "two"
281281
```
282282

283-
### 4. 格式化測試輸出(Printer)
283+
### 4. 執行期間依 ID 反查測試項目(`AliasMap`
284+
285+
當 Teamcity 事件帶來測試結果時,你需要依 ID 找回對應的 UI 項目。`AliasMap<T>``Map<string, T>` 的直接替代品,能自動處理 Pest v3 的一個已知 bug。
286+
287+
**問題根源**:Pest v3 的 `Str::beforeLast()` 混用了 `mb_strrpos`(字元偏移)與 `substr`(位元組偏移)。``(U+2192)是 3 個 UTF-8 位元組但只算 1 個字元,導致 `testSuiteStarted` / `testSuiteFinished` 事件的 ID 每出現一個 `` 就被截短 2 個位元組 — 直接用 `Map.get()` 就會找不到項目。
288+
289+
**解法**:改用 `AliasMap`。每次呼叫 `set()` 時,它會自動同時登錄截短版的別名 ID,讓 `get()` 無論收到哪個版本都能命中。
290+
291+
```typescript
292+
import { AliasMap } from '@vscode-phpunit/phpunit';
293+
294+
// 從測試項目建立 — 截短別名自動登錄
295+
const testItemById = new AliasMap<MyItem>(
296+
items.map((item) => [item.id, item]),
297+
);
298+
299+
// 無論完整 ID 或 Pest v3 截短 ID 都能查到
300+
const fullId = 'tests/Unit/Foo.php::`something` → it passes';
301+
const truncatedId = 'tests/Unit/Foo.php::`something` → it pass'; // Pest v3 截短版
302+
303+
testItemById.get(fullId); // → MyItem ✓
304+
testItemById.get(truncatedId); // → MyItem ✓ (別名自動登錄)
305+
```
306+
307+
`AliasMap` 與框架無關,可搭配 VS Code `TestItem`、純物件或任何其他型別使用。
308+
309+
### 5. 格式化測試輸出(Printer)
284310

285311
`Printer` 將結構化測試事件轉換為可讀的輸出,支援可設定的模板與 ANSI 色彩。輸出透過 `OutputWriter` 介面寫入,讓 Printer 與具體輸出目標解耦。
286312

0 commit comments

Comments
 (0)