@hungvv/super-ads-skills 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +71 -13
- package/dist/cli.js +8 -2
- package/package.json +1 -1
- package/skills/README.md +4 -0
- package/skills/adspro-to-superads/SKILL.md +157 -732
- package/skills/adspro-to-superads/references/global-invariant-check.md +49 -0
- package/skills/adspro-to-superads/references/migration-contract.md +57 -0
- package/skills/adspro-to-superads/references/phase-0-inventory.md +39 -0
- package/skills/adspro-to-superads/references/phase-1-2-gradle-manifest.md +85 -0
- package/skills/adspro-to-superads/references/phase-3-config-migration.md +159 -0
- package/skills/adspro-to-superads/references/phase-4-wrapper-observability.md +70 -0
- package/skills/adspro-to-superads/references/phase-5-7-callsites-layout-cleanup.md +73 -0
- package/skills/adspro-to-superads/references/principles-and-authority.md +73 -0
- package/skills/adspro-to-superads/references/user-questions.md +53 -0
- package/skills/adspro-to-superads/snippets/ads-api-quick.md +20 -0
- package/skills/adspro-to-superads/templates/migration-inventory.md +42 -0
- package/skills/super-ads-ab-test/SKILL.md +91 -23
- package/skills/super-ads-adb-test/SKILL.md +85 -36
- package/skills/super-ads-adb-test/{references → examples}/scenarios-sample.md +5 -5
- package/skills/super-ads-add-placement/SKILL.md +145 -50
- package/skills/super-ads-add-placement/references/call-site-api.md +33 -0
- package/skills/super-ads-add-placement/snippets/app-open.md +25 -0
- package/skills/super-ads-add-placement/snippets/fullscreen-nav.md +14 -0
- package/skills/super-ads-add-placement/snippets/inline-banner-native.md +19 -0
- package/skills/super-ads-add-placement/snippets/preload-event.md +13 -0
- package/skills/super-ads-add-placement/snippets/reward.md +17 -0
- package/skills/super-ads-config/SKILL.md +94 -36
- package/skills/super-ads-debug/SKILL.md +87 -37
- package/skills/super-ads-debug/references/logging-setup.md +2 -0
- package/skills/super-ads-debug/scripts/filter-logads.sh +21 -0
- package/skills/super-ads-debug-override/SKILL.md +154 -81
- package/skills/super-ads-debug-override/snippets/arm-override.md +9 -0
- package/skills/super-ads-debug-override/snippets/check-module.md +8 -0
- package/skills/super-ads-debug-override/snippets/clear-override.md +9 -0
- package/skills/super-ads-debug-override/snippets/confirm-active.md +16 -0
- package/skills/super-ads-guide/SKILL.md +129 -0
- package/skills/super-ads-guide/references/compatibility.md +26 -0
- package/skills/super-ads-guide/references/sdk-version-check.md +50 -0
- package/skills/super-ads-integrate/SKILL.md +145 -47
- package/skills/super-ads-integrate/references/application-setup.md +2 -21
- package/skills/super-ads-integrate/references/gradle-setup.md +1 -13
- package/skills/super-ads-integrate/snippets/consent-request.md +12 -0
- package/skills/super-ads-integrate/templates/application-oncreate.md +17 -0
- package/skills/super-ads-integrate/templates/gradle-dependencies.md +17 -0
- package/skills/super-ads-release-check/SKILL.md +85 -32
- package/skills/super-ads-show-rate/SKILL.md +87 -36
- package/skills/super-ads-show-rate/references/collect-snippet.md +2 -36
- package/skills/super-ads-show-rate/scripts/show-rate.sh +25 -0
- package/skills/super-ads-show-rate/snippets/show-events-logger.md +26 -0
- package/skills/super-ads-upgrade/SKILL.md +137 -0
- package/skills/super-ads-upgrade/references/upgrade-hops.md +26 -0
- package/skills/super-ads-upgrade/templates/changelog-template.md +39 -0
- package/skills/super-ads-add-placement/references/call-site-snippets.md +0 -90
- /package/skills/super-ads-ab-test/{references → templates}/firebase-handoff-template.md +0 -0
- /package/skills/super-ads-config/{references → examples}/patch-examples.md +0 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Câu hỏi phải hỏi user (Nhóm A-D)
|
|
2
|
+
|
|
3
|
+
Mỗi câu hỏi phải có **phương án khuyến nghị** và nêu **hệ quả**. Agent không được tự chọn thay
|
|
4
|
+
user ở nhóm A và B. Gộp câu hỏi cùng nhóm vào **một** lần hỏi.
|
|
5
|
+
|
|
6
|
+
- Nhóm B: hỏi khi lập inventory Phase 0.
|
|
7
|
+
- Nhóm A và D: hỏi **trước** Phase 3.
|
|
8
|
+
- Nhóm C: hỏi **một lần** đầu Phase 4.
|
|
9
|
+
|
|
10
|
+
Mọi câu trả lời ghi vào mục "Decisions" trong `migration-inventory.md`.
|
|
11
|
+
|
|
12
|
+
## Nhóm A — tính năng không chuyển được (loại C)
|
|
13
|
+
|
|
14
|
+
| Tình huống | Câu hỏi | Phương án gợi ý |
|
|
15
|
+
|---|---|---|
|
|
16
|
+
| App dùng `AdmobNativePip` | SuperAds không có native PIP. Xử lý placement này thế nào? | (1) Bỏ PIP, chuyển thành `NATIVE` thường ở cùng vị trí — khuyến nghị; (2) Giữ AdsPro riêng cho PIP — không khuyến nghị, hai SDK cùng tồn tại; (3) Tạm tắt placement |
|
|
17
|
+
| App dùng `AdmobNativeCollapsibleHalfSize` | Không có half-size. Dùng gì thay? | (1) `NATIVE_COLLAPSIBLE` với layout expanded nhỏ hơn — khuyến nghị; (2) Bỏ, dùng `NATIVE` |
|
|
18
|
+
| Space có `adsType` không nằm trong bảng map | `adsType` này không có format tương ứng. Ý định sản phẩm là gì? | Liệt kê 2–3 format gần nhất kèm khác biệt hành vi |
|
|
19
|
+
|
|
20
|
+
## Nhóm B — behavior không suy ra được từ code
|
|
21
|
+
|
|
22
|
+
| Tình huống | Câu hỏi | Phương án gợi ý |
|
|
23
|
+
|---|---|---|
|
|
24
|
+
| Code cũ nav ở cả hai callback, hoặc nav ngoài callback | Placement này nav khi ad *hiện* hay khi ad *đóng*? | Mặc định SDK là `NAVIGATE_ON_DISMISS`; nêu hệ quả UX từng lựa chọn |
|
|
25
|
+
| `load()` gọi trong `onCreate` của Activity, không thuộc màn nào | Preload này nên gắn với event màn nào? | Đề xuất màn gần nhất trong flow + phương án preload ngay sau init |
|
|
26
|
+
| Không rõ preload áp cho phiên nào | Preload cho người mở lần đầu, người quay lại, hay cả hai? | Khuyến nghị **cả hai** (`_fo` + `_fn`) nếu code cũ preload vô điều kiện |
|
|
27
|
+
| Reload cũ vừa có timer vừa có click | Giữ cả `reload.auto` và `reload.click`, hay chỉ một? | Chain chỉ nhận click |
|
|
28
|
+
| Space trong JSON nhưng zero call site (vd `Banner_chung`) | Giữ placement này hay bỏ? | (1) Giữ, ghi vào Documented exclusions — khuyến nghị (an toàn cho RC); (2) Bỏ khỏi config |
|
|
29
|
+
| Hai space khác nhau nhưng cùng ý nghĩa | Gộp hay giữ tách? | Khuyến nghị **giữ tách** để bảo toàn analytics |
|
|
30
|
+
| Event cũ mang `previous_screen`/`next_screen` trong bundle | Event khai trong JSON không mang được cặp screen. Bỏ cặp screen, hay giữ tracking app-side? | (1) Bỏ, dùng `adItemId` — khuyến nghị; (2) Collect `TrackerEvent.Impression` rồi tự ghép screen từ state app |
|
|
31
|
+
| Tên event analytics cũ rải rác trong Kotlin | Tên nào đưa vào `tracking.event*`, tên nào giữ app-side? | Event AB/theo placement vào JSON; event bespoke cần ngữ cảnh app thì giữ trên flow |
|
|
32
|
+
|
|
33
|
+
## Nhóm C — quyết định kiến trúc (đầu Phase 4)
|
|
34
|
+
|
|
35
|
+
| Câu hỏi | Phương án gợi ý |
|
|
36
|
+
|---|---|
|
|
37
|
+
| Nhà cho wrapper: moi ruột `AdsUtils.kt` cũ, hay tạo `AdsSP.kt` mới? | (1) Moi ruột file cũ — **khuyến nghị**, giữ path nên ~40 màn không đổi import; (2) File mới kiểu SlideShow — sạch tên nhưng phải sửa import ở mọi màn |
|
|
38
|
+
| Nhà cho `EventScreen`: thêm vào file base có sẵn hay tạo file mới? | (1) Thêm vào file base sẵn có; (2) File mới `EventScreen.kt` nếu package base không có nhà hợp lý |
|
|
39
|
+
| Có dọn tham số inert trong migration không? | Khuyến nghị **không** — tách commit riêng sau khi verify xong |
|
|
40
|
+
| Config: một file JSON asset, hay thêm nhánh Remote Config ngay? | Khuyến nghị asset trước, RC sau khi verify |
|
|
41
|
+
|
|
42
|
+
## Nhóm D — hạ tầng (hỏi ngay khi phát hiện)
|
|
43
|
+
|
|
44
|
+
| Tình huống | Câu hỏi |
|
|
45
|
+
|---|---|
|
|
46
|
+
| Config có network nhưng thiếu module | Config có `"network": "CloudX"` nhưng chưa có `SuperAdsCloudX`. Thêm module hay bỏ network khỏi config? |
|
|
47
|
+
| Thiếu `io.cloudx.APP_KEY` / `applovin.sdk.key` | Cung cấp key, hay bỏ network đó? |
|
|
48
|
+
| App chưa có `screenName()` / registry tracking | Không có gì dựng chuỗi event preload. Wire tracking screen trước, hay preload theo cách khác? |
|
|
49
|
+
| App có RC key timing ads (tên tuỳ app, vd `keyTimeBetweenAdInter`) | JSON chỉ có `show.timeBetweenMs` cố định. Ops còn chỉnh nóng qua RC không? |
|
|
50
|
+
| Có native-sau-inter | Production: mấy native/lần inter? RC/AB nào (nếu có) tắt native phụ? Counter `% N` ra pos nào? Điền JSON theo đo, không theo template |
|
|
51
|
+
| Click reload cùng space, khác layout | Tách twin SuperAds theo Bảng D, chung unit nếu AdsPro chung `ids[]` |
|
|
52
|
+
| `minimumFetchIntervalInSeconds` | SlideShow đặt `0` (fetch mọi lần). Giữ `0` hay đặt giá trị an toàn hơn cho production? |
|
|
53
|
+
| App đã có AppsFlyer / Adjust / Meta | Giữ nguyên kênh nào? `SuperAdsTracking` là **mặc định nên có** (Phase 1) — thiếu nó là mất `ad_impression` / `ad_click` Firebase (`MIGRATION.md:452`). Chỉ bỏ khi app tự bắn doanh thu Firebase ở chỗ khác và user xác nhận |
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Ads API — tra nhanh
|
|
2
|
+
|
|
3
|
+
```kotlin
|
|
4
|
+
// Init
|
|
5
|
+
Ads.init(application, configProvider = { getConfig(...) }, isDebug = isDebug)
|
|
6
|
+
Ads.isPremium = purchased
|
|
7
|
+
// Consent TRƯỚC preload/show/app open (core không tự chặn): Activity đầu
|
|
8
|
+
Ads.gdpr.requestAndShowIfRequired(activity, isDebug, timeoutMs = /* timeout AdsPro của app */) { onConsentDone(); next() }
|
|
9
|
+
|
|
10
|
+
// Inline (native / banner)
|
|
11
|
+
Ads.show(placementId, activity, AdTarget.AdView(container, lifecycle), callback)
|
|
12
|
+
|
|
13
|
+
// Fullscreen / reward
|
|
14
|
+
Ads.show(placementId, activity, callback = NavAdCallback { ... })
|
|
15
|
+
Ads.show(placementId, activity, callback = RewardAdCallback(true) { ... })
|
|
16
|
+
|
|
17
|
+
// Preload — KHÔNG gọi thủ công. EventScreen + preload.eventActive.
|
|
18
|
+
Ads.dispatchEvent(activity, "create_open_screen_5_fo")
|
|
19
|
+
```
|
|
20
|
+
```
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# migration-inventory.md — mẫu Bảng A-D
|
|
2
|
+
|
|
3
|
+
## Bảng A — placement identity + behavior
|
|
4
|
+
|
|
5
|
+
| spaceName | adsType | ids[] | layout collapsed | layout expanded | show API cũ | nav từ callback nào | reload trigger cũ | space reload cũ | RC key | placement | format | mode.show | mode.navigate | status |
|
|
6
|
+
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
7
|
+
| Native_Home | native | 1 | native_collap_small | - | show | - | click | Native_Reload | config_ads_22_4 | Native_Home | NATIVE | LOAD_AND_SHOW | - | TODO |
|
|
8
|
+
| Interstitial_Chung | interstitial | 1 | - | - | show + gate LOADED | onAdDismissed | - | - | config_ads_22_4 | Interstitial_Chung | INTER | SHOW_LOADED | NAVIGATE_ON_DISMISS | TODO |
|
|
9
|
+
|
|
10
|
+
Cột `placement` = nguyên văn `spaceName`. **MUST NOT CHANGE.**
|
|
11
|
+
|
|
12
|
+
## Bảng B — preload moment (một hàng mỗi call site `load()`)
|
|
13
|
+
|
|
14
|
+
| File:line | space | màn đang đứng | screenName() | thời điểm | chuỗi event | status |
|
|
15
|
+
|---|---|---|---|---|---|---|
|
|
16
|
+
| LanguageFragment.kt:45 | Native_Onboarding | Language | open_screen_1 | onViewReady | create_open_screen_1_fo | TODO |
|
|
17
|
+
|
|
18
|
+
Không gom nhiều `load()` của cùng space thành một hàng. Mỗi thời điểm là một hàng.
|
|
19
|
+
|
|
20
|
+
## Bảng C — cặp reload
|
|
21
|
+
|
|
22
|
+
| placement nguồn | trigger | placement đích | chu kỳ (ms) | key JSON | status |
|
|
23
|
+
|---|---|---|---|---|---|
|
|
24
|
+
| Native_Home | click | Native_Reload | - | reload.click.placementID | TODO |
|
|
25
|
+
| Native_Record_Video | auto | Native_Record_Video_ReLoad_15s | 15000 | reload.auto.placementID + show.timeAutoReloadMs | TODO |
|
|
26
|
+
|
|
27
|
+
## Bảng D — click reload theo layout (khi app có click reload)
|
|
28
|
+
|
|
29
|
+
Bảng C gom trigger. Bảng D vì SDK bind layout trên **adItem đích**. Hàng mẫu chỉ hiểu cột —
|
|
30
|
+
điền space/layout/unit **của app này**. Tách twin **chỉ khi** layout hoặc unit lúc click khác nhau.
|
|
31
|
+
|
|
32
|
+
| nguồn | layout lúc show | unit AdsPro lúc click | SuperAds reload placement | unit | layout đích | self-click? |
|
|
33
|
+
|---|---|---|---|---|---|---|
|
|
34
|
+
| *(space)* | *(xml)* | *(ids click)* | *(space reload cũ hoặc twin mới)* | *(khớp AdsPro)* | *(= layout show)* | *(click lại cùng space?)* |
|
|
35
|
+
|
|
36
|
+
Space reload **zero call site** → Exclusions, không làm đích vì tên.
|
|
37
|
+
|
|
38
|
+
## Các mục khác trong cùng file
|
|
39
|
+
|
|
40
|
+
- **Decisions** — câu trả lời nhóm A/B/C/D.
|
|
41
|
+
- **Inert parameters** — tham số giữ chữ ký nhưng không còn tác dụng.
|
|
42
|
+
- **Documented exclusions** — space được giữ / bỏ có lý do (vd `Banner_chung` zero call site).
|
|
@@ -1,33 +1,50 @@
|
|
|
1
1
|
---
|
|
2
2
|
schema: 1
|
|
3
3
|
name: super-ads-ab-test
|
|
4
|
-
description: Use when the user wants a Firebase A/B test of SuperAds config
|
|
5
|
-
version: 1.
|
|
4
|
+
description: Use when the user wants a Firebase A/B test of SuperAds config, generating two variant JSON files and handoff steps
|
|
5
|
+
version: 1.1.0
|
|
6
6
|
group: Ads
|
|
7
|
+
superAds: ">=4.0.0 <5.0.0"
|
|
7
8
|
---
|
|
8
9
|
|
|
9
10
|
# Tạo A/B test config SuperAds cho Firebase
|
|
10
11
|
|
|
11
12
|
Agent làm đúng 3 việc: **chốt A/B là gì với user** → **sinh 2 file config** → **bàn giao hướng dẫn Firebase**. Agent **không** thao tác Firebase Console, **không** sửa code app, **không** sửa asset hay working config.
|
|
12
13
|
|
|
13
|
-
| Cần | Tài liệu |
|
|
14
|
-
|---|---|
|
|
15
|
-
| Mẫu tin nhắn bàn giao Firebase (bắt buộc dùng) | [references/firebase-handoff-template.md](references/firebase-handoff-template.md) |
|
|
16
|
-
| Hợp đồng SDK (activation, `ab_variant`, provenance) | `MIGRATION.md`, mục "A/B test bằng remote config" |
|
|
17
|
-
| Đối soát sau khi chạy (BigQuery, quy tắc lọc) | [../super-ads-release-check/references/firebase-ab-checklist.md](../super-ads-release-check/references/firebase-ab-checklist.md) |
|
|
18
|
-
| Tool sinh variant | `make_ab_variants` (`tools/ai_agent_tools/src/mcp/tools.js:254-278`): generate-only, tự chặn variant lệch ngoài path được đổi, trả `validationA` / `validationB` |
|
|
19
|
-
| Overload nạp JSON có cờ activated | `SA/api/Ads.kt:197` |
|
|
20
|
-
| Luật tên event | `super-ads-tracking/src/main/java/com/android/fullhd/super_ads/tracking/gateway/FirebaseEventName.kt:33-40` |
|
|
21
|
-
|
|
22
14
|
## When to use
|
|
23
15
|
- "Làm A/B test cooldown inter 30s vs 60s", "test bật/tắt native ở màn X", "chia 2 nhóm config qua Firebase".
|
|
24
16
|
|
|
25
|
-
## When NOT to use
|
|
17
|
+
## 🚫 When NOT to use
|
|
26
18
|
- Chỉ đổi một giá trị config cho mọi user → `super-ads-config`.
|
|
27
19
|
- Chạy app với config khác asset để test cục bộ → `super-ads-debug-override`.
|
|
28
20
|
- Đọc kết quả / đối soát experiment đã chạy → `super-ads-release-check` (checklist Firebase A/B).
|
|
29
21
|
|
|
30
|
-
##
|
|
22
|
+
## 📋 Prerequisites
|
|
23
|
+
- Định tuyến skill và kiểm version SDK: xem [super-ads-guide](../super-ads-guide/SKILL.md).
|
|
24
|
+
- Skill này nhắm SuperAds `>=4.0.0 <5.0.0`. App dùng SuperAds thấp hơn ⇒ **dừng** và khuyến nghị (không ép) nâng cấp qua [super-ads-upgrade](../super-ads-upgrade/SKILL.md) trước khi tiếp tục.
|
|
25
|
+
- MCP `super-ads` đã kết nối (`read_working_config`, `make_ab_variants`).
|
|
26
|
+
- App đã có đường nạp Remote Config có cờ activated (kiểm ở Workflow bước 1). Hợp đồng SDK (activation, `ab_variant`, provenance): `MIGRATION.md`, mục "A/B test bằng remote config".
|
|
27
|
+
|
|
28
|
+
## ⚡ Quick Reference
|
|
29
|
+
|
|
30
|
+
| Cần | Tài liệu |
|
|
31
|
+
|---|---|
|
|
32
|
+
| Mẫu tin nhắn bàn giao Firebase (bắt buộc dùng) | [templates/firebase-handoff-template.md](templates/firebase-handoff-template.md) |
|
|
33
|
+
| Đối soát sau khi chạy (BigQuery, quy tắc lọc) | [../super-ads-release-check/references/firebase-ab-checklist.md](../super-ads-release-check/references/firebase-ab-checklist.md) |
|
|
34
|
+
|
|
35
|
+
Skill này không có `references/`, `snippets/`, `examples/` hay `scripts/` riêng.
|
|
36
|
+
|
|
37
|
+
## 🏗️ Recommended Architecture
|
|
38
|
+
Hai file variant chỉ khác nhau ở các path đã chốt và `global.version`. Cả hai mang **cùng** activation event để Firebase đếm user ở cả hai nhóm; `ab_variant` (`<exp>_A` / `<exp>_B`) dùng khi phân tích.
|
|
39
|
+
|
|
40
|
+
## Workflow
|
|
41
|
+
|
|
42
|
+
### Stop conditions
|
|
43
|
+
- App không có `loadFromJson(json, firebaseActivated = true)` đọc từ Remote Config (bước 1).
|
|
44
|
+
- User chưa xác nhận bảng A/B (bước 2).
|
|
45
|
+
- Working config không phải asset app đang nạp.
|
|
46
|
+
- Version trùng, tên event sai luật hoặc trùng exposure.
|
|
47
|
+
- `make_ab_variants` báo invariant / validation lỗi, hoặc `diffAB` lệch bảng đã chốt.
|
|
31
48
|
|
|
32
49
|
### 1. Kiểm app có đường nạp Remote Config đúng (điểm dừng)
|
|
33
50
|
Tìm trong code app lời gọi `Ads.loadFromJson(json, firebaseActivated = true)` và **tên tham số Remote Config** mà chỗ đó đọc (app mẫu: `ads_config_v2` trong `app/src/main/java/com/android/hd/ads2026/RemoteConfigAbLoader.kt`). Đồng thời xác nhận giá trị chỉ được nạp khi đến từ remote sau `fetchAndActivate()`.
|
|
@@ -67,25 +84,76 @@ Rồi trình **bảng xác nhận** và chờ user trả lời "đúng" (hoặc
|
|
|
67
84
|
7. Đối chiếu `diffAB` với bảng đã chốt: hai file chỉ được khác nhau ở các path trong bảng + `global.version`. Khác thêm ⇒ dừng, báo user.
|
|
68
85
|
|
|
69
86
|
### 4. Bàn giao Firebase
|
|
70
|
-
Điền [
|
|
87
|
+
Điền [templates/firebase-handoff-template.md](templates/firebase-handoff-template.md) và gửi user, đủ mọi mục. Kết thúc ở đây: user tự cấu hình Firebase.
|
|
71
88
|
|
|
72
|
-
##
|
|
73
|
-
|
|
89
|
+
## 🔧 API Reference
|
|
90
|
+
|
|
91
|
+
| Mục | Mô tả | Nguồn |
|
|
92
|
+
|---|---|---|
|
|
93
|
+
| `make_ab_variants` | Generate-only, tự chặn variant lệch ngoài path được đổi, trả `validationA` / `validationB` | `tools/ai_agent_tools/src/mcp/tools.js:254-278` |
|
|
94
|
+
| Overload nạp JSON có cờ activated | `Ads.loadFromJson(json, firebaseActivated = true)` | `SA/api/Ads.kt:197` |
|
|
95
|
+
| Luật tên event | Giới hạn tên activation / exposure | `super-ads-tracking/src/main/java/com/android/fullhd/super_ads/tracking/gateway/FirebaseEventName.kt:33-40` |
|
|
96
|
+
|
|
97
|
+
## ✅ Best Practices
|
|
74
98
|
- Điểm dừng ở bước 1 và bước 2; không có xác nhận "đúng" của user thì không sinh file.
|
|
75
99
|
- `global.version` của A và B khác nhau, ổn định, không trùng version asset.
|
|
76
100
|
- Activation event **cùng tên** ở A và B; mỗi experiment một tên riêng.
|
|
77
101
|
- Nói rõ cho user: tên tham số Remote Config, file nào vào Baseline / Variant, tên activation event, goal, các event và param tracking.
|
|
78
102
|
|
|
79
|
-
|
|
103
|
+
## ❌ Anti-patterns
|
|
80
104
|
- Không thao tác Firebase Console, không gọi API Firebase.
|
|
81
105
|
- Không sửa code app, asset hay working config: không `apply_patch`, `replace_working_config`, `sync_to_source`.
|
|
82
106
|
- Không tự chọn giá trị thử nghiệm, % user hay tên experiment thay user.
|
|
83
107
|
- Không khai `activation_event` vào asset.
|
|
84
108
|
- Không đặt tên activation trùng tên exposure hay tên reserved.
|
|
85
109
|
|
|
86
|
-
##
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
110
|
+
## ⚠️ Common Issues
|
|
111
|
+
|
|
112
|
+
| Problem | Cause | Solution |
|
|
113
|
+
|---|---|---|
|
|
114
|
+
| Firebase không đếm được user | App gọi `loadFromJson(json)` không cờ activated nên activation event không bắn | Dừng ở bước 1, trỏ user tới `MIGRATION.md`, không tự viết code app |
|
|
115
|
+
| `make_ab_variants` báo invariant / validation lỗi | Variant lệch ngoài path được đổi hoặc config không hợp lệ | Dừng, báo user, không ghi file |
|
|
116
|
+
|
|
117
|
+
## Files created
|
|
118
|
+
Hai file variant (JSON) trong gốc repo của app, do agent ghi sau khi user xác nhận bảng A/B:
|
|
119
|
+
- `super-ads-ab-test/<exp>/variant_A.json`
|
|
120
|
+
- `super-ads-ab-test/<exp>/variant_B.json`
|
|
121
|
+
|
|
122
|
+
## Files modified
|
|
123
|
+
Chỉ `.gitignore` ở gốc repo (thêm dòng `/super-ads-ab-test/` nếu chưa có). Không sửa code app, asset hay working config.
|
|
124
|
+
|
|
125
|
+
## Verification
|
|
126
|
+
- `invariantsA` / `invariantsB` không có vi phạm; `validationA` / `validationB` không có error.
|
|
127
|
+
- `diffAB` chỉ khác nhau ở các path trong bảng đã chốt + `global.version`.
|
|
128
|
+
- `<exp>_A` ≠ `<exp>_B`, cả hai ≠ `global.version` hiện tại; tên activation hợp lệ và không trùng exposure.
|
|
129
|
+
|
|
130
|
+
## Checklist
|
|
131
|
+
- [ ] App có đường nạp `loadFromJson(json, firebaseActivated = true)` từ Remote Config.
|
|
132
|
+
- [ ] User xác nhận bảng A/B.
|
|
133
|
+
- [ ] Working config đúng là asset app đang nạp.
|
|
134
|
+
- [ ] Hai file variant sinh xong, `diffAB` khớp bảng.
|
|
135
|
+
- [ ] `.gitignore` có `/super-ads-ab-test/`.
|
|
136
|
+
- [ ] Đã gửi bản bàn giao Firebase đủ mọi mục.
|
|
137
|
+
|
|
138
|
+
## 📈 Performance Notes
|
|
139
|
+
> **Not applicable for this skill.**
|
|
140
|
+
|
|
141
|
+
## 🔒 Security Notes
|
|
142
|
+
> **Not applicable for this skill.**
|
|
143
|
+
|
|
144
|
+
## 🔄 Migration Guide
|
|
145
|
+
> **Not applicable for this skill.**
|
|
146
|
+
|
|
147
|
+
## Output
|
|
148
|
+
Đường dẫn hai file variant, bảng A/B đã chốt, và bản bàn giao Firebase đã điền từ template (tham số Remote Config, file Baseline / Variant, activation event, goal, event và param tracking).
|
|
149
|
+
|
|
150
|
+
## Examples
|
|
151
|
+
- [templates/firebase-handoff-template.md](templates/firebase-handoff-template.md): mẫu bàn giao đã có đủ mục để điền.
|
|
152
|
+
|
|
153
|
+
## 📚 References
|
|
154
|
+
- [super-ads-guide](../super-ads-guide/SKILL.md), [super-ads-upgrade](../super-ads-upgrade/SKILL.md)
|
|
155
|
+
- [super-ads-config](../super-ads-config/SKILL.md), [super-ads-debug-override](../super-ads-debug-override/SKILL.md), [super-ads-release-check](../super-ads-release-check/SKILL.md)
|
|
156
|
+
- `MIGRATION.md`, mục "A/B test bằng remote config"
|
|
157
|
+
|
|
158
|
+
## 🏷️ Tags
|
|
159
|
+
`super-ads` `ab-test` `firebase` `remote-config` `variants` `experiment`
|
|
@@ -1,54 +1,53 @@
|
|
|
1
1
|
---
|
|
2
2
|
schema: 1
|
|
3
3
|
name: super-ads-adb-test
|
|
4
|
-
description: Use when
|
|
5
|
-
version: 1.
|
|
4
|
+
description: Use when verifying SuperAds behaviour on a device or emulator by running do/expect scenarios without editing the app
|
|
5
|
+
version: 1.1.0
|
|
6
6
|
group: Ads
|
|
7
|
+
superAds: ">=4.0.0 <5.0.0"
|
|
7
8
|
---
|
|
8
9
|
|
|
9
10
|
# Test SuperAds trên thiết bị (không sửa app)
|
|
10
11
|
|
|
11
12
|
Chạy kịch bản `do` / `expect` trên thiết bị: build + cài app, điều khiển UI, thu Logcat, so từng bước với kỳ vọng, báo `PASS` / `FAIL` / `SKIP` / `UNKNOWN` kèm bằng chứng.
|
|
12
13
|
|
|
13
|
-
| Bước | Tài liệu |
|
|
14
|
-
|---|---|
|
|
15
|
-
| Định dạng kịch bản | [references/scenario-format.md](references/scenario-format.md) |
|
|
16
|
-
| Kịch bản mẫu | [references/scenarios-sample.md](references/scenarios-sample.md) |
|
|
17
|
-
| Regex log theo sự kiện | [references/log-assertions.md](references/log-assertions.md) |
|
|
18
|
-
| App mẫu trong repo (ví dụ) | [references/sample-app-notes.md](references/sample-app-notes.md) |
|
|
19
|
-
| Bật log SDK | [../super-ads-debug/references/logging-setup.md](../super-ads-debug/references/logging-setup.md) |
|
|
20
|
-
|
|
21
14
|
## When to use
|
|
22
15
|
- Kiểm một placement mới gắn, một thay đổi config, hoặc tái hiện lỗi trên máy thật.
|
|
23
16
|
- Chạy lặp lại cùng một kịch bản trước/sau khi sửa (dùng cho `super-ads-debug`, `super-ads-show-rate`, `super-ads-add-placement`).
|
|
24
17
|
|
|
25
|
-
## When NOT to use
|
|
18
|
+
## 🚫 When NOT to use
|
|
26
19
|
- Kiểm logic SDK không cần máy: bộ JVM/Robolectric `ScenarioRunner` (`./gradlew superAdsLogicVerification`, `super-ads-test/README-scenarios.md:9-20`).
|
|
27
20
|
- Instrumentation với ad thật cho SDK: `scripts/verify-all.sh`, `super-ads-test/README-real-ads-instrumentation.md`.
|
|
28
|
-
- Tìm nguyên nhân một lỗi:
|
|
21
|
+
- Tìm nguyên nhân một lỗi: [super-ads-debug](../super-ads-debug/SKILL.md) (skill này chỉ chạy và báo kết quả).
|
|
22
|
+
|
|
23
|
+
## 📋 Prerequisites
|
|
24
|
+
- Routing và kiểm version SDK: [super-ads-guide](../super-ads-guide/SKILL.md).
|
|
25
|
+
- Skill này nhắm SuperAds `>=4.0.0 <5.0.0`. App dùng SuperAds thấp hơn thì **dừng** và khuyến nghị (không ép) nâng cấp bằng [super-ads-upgrade](../super-ads-upgrade/SKILL.md) trước khi tiếp tục.
|
|
26
|
+
- Có thiết bị: `adb devices` có ít nhất một máy ở trạng thái `device`. Nhiều máy thì chỉ định serial (`adb -s <serial>`), như `scripts/verify-all.sh:21-22`.
|
|
27
|
+
- Coi applicationId, Activity khởi động, tag log, màn hình là **tham số**. Đọc từ `build.gradle`, `AndroidManifest.xml`, code `Application` của app đang test.
|
|
28
|
+
- Biết config đang nạp (lời gọi `Ads.init` trong `Application`); chỉ dùng placement có thật trong đó.
|
|
29
|
+
- Log SDK đã bật ở bản đang cài (cách bật: [logging-setup.md](../super-ads-debug/references/logging-setup.md) mục 2).
|
|
30
|
+
|
|
31
|
+
## ⚡ Quick Reference
|
|
32
|
+
| Cần | Mở |
|
|
33
|
+
|---|---|
|
|
34
|
+
| Định dạng kịch bản (`do` / `expect`, quy tắc) | [references/scenario-format.md](references/scenario-format.md) |
|
|
35
|
+
| Kịch bản mẫu S1-S6 | [examples/scenarios-sample.md](examples/scenarios-sample.md) |
|
|
36
|
+
| Regex log theo sự kiện (thành công, blocked, error) | [references/log-assertions.md](references/log-assertions.md) |
|
|
37
|
+
| App mẫu trong repo (ví dụ) | [references/sample-app-notes.md](references/sample-app-notes.md) |
|
|
38
|
+
| Bật log SDK, file `.logads` | [../super-ads-debug/references/logging-setup.md](../super-ads-debug/references/logging-setup.md) |
|
|
29
39
|
|
|
30
|
-
|
|
40
|
+
Trạng thái kết quả: `PASS` / `FAIL` / `SKIP (lý do)` / `UNKNOWN (lý do)`.
|
|
41
|
+
|
|
42
|
+
## 🏗️ Recommended Architecture
|
|
43
|
+
Thứ tự nguồn sự thật:
|
|
31
44
|
1. Code SDK (chuỗi log, mã lỗi) và code app đang test (màn hình, id, tag log).
|
|
32
45
|
2. Config đang được app nạp.
|
|
33
46
|
3. Tài liệu skill. Nhãn nút, id view trong tài liệu là của app mẫu.
|
|
34
47
|
|
|
35
|
-
##
|
|
36
|
-
**MUST**
|
|
37
|
-
- Coi applicationId, Activity khởi động, tag log, màn hình là **tham số**. Đọc từ `build.gradle`, `AndroidManifest.xml`, code `Application` của app đang test.
|
|
38
|
-
- Đọc config đang nạp trước (lời gọi `Ads.init` trong `Application`), chỉ dùng placement có thật trong đó.
|
|
39
|
-
- Mỗi kịch bản: bắt đầu từ trạng thái log sạch (`adb logcat -c`, hoặc đánh dấu thời điểm để lấy file `.logads` mới) → `launch` → các bước → lưu file log riêng. Nguồn log ưu tiên là file `.logads`, Logcat là dự phòng ([logging-setup.md](../super-ads-debug/references/logging-setup.md) mục 6).
|
|
40
|
-
- Mỗi kết luận `PASS` / `FAIL` trích dòng log hoặc trạng thái UI làm bằng chứng.
|
|
41
|
-
- Trả lại trạng thái máy đã đổi (mạng, xoay màn) kể cả khi kịch bản fail.
|
|
42
|
-
- Có nhiều máy thì chỉ định serial (`adb -s <serial>`), như `scripts/verify-all.sh:21-22`.
|
|
43
|
-
|
|
44
|
-
**MUST NOT**
|
|
45
|
-
- Không sửa code, manifest, Gradle, asset config của app. Kể cả "tạm thời".
|
|
46
|
-
- Không ghi đè file config của app bằng working config `tmp-*.json` của MCP.
|
|
47
|
-
- Không bấm vào ad thật (click) trên bản production, và không chạy với unit thật khi chưa được user đồng ý (rủi ro invalid traffic).
|
|
48
|
-
- Không báo `PASS` cho kỳ vọng `never` khi không có bằng chứng dương rằng lời gọi đã tới SDK ([log-assertions.md](references/log-assertions.md) mục 4).
|
|
49
|
-
- Không chạy `network off` trên emulator/LDPlayer: mất luôn kết nối adb.
|
|
48
|
+
## Workflow
|
|
50
49
|
|
|
51
|
-
|
|
50
|
+
### Dừng và hỏi user khi
|
|
52
51
|
- `adb devices` không có máy nào ở trạng thái `device`.
|
|
53
52
|
- Logcat không có dòng `SuperAdsSDK` sau `launch`: logger chưa bật ở bản đang cài. Muốn bật thì phải sửa app, nên hỏi user (cách bật: [logging-setup.md](../super-ads-debug/references/logging-setup.md) mục 2).
|
|
54
53
|
- Kịch bản cần config khác với config app đang nạp. App có hook override (bản debug có `ConfigOverrideReceiver`) ⇒ dùng `super-ads-debug-override`, không phải sửa app. Không có hook ⇒ đưa user lựa chọn:
|
|
@@ -58,7 +57,7 @@ Chạy kịch bản `do` / `expect` trên thiết bị: build + cài app, điề
|
|
|
58
57
|
- Config dùng unit thật và kịch bản có click hoặc show nhiều lần.
|
|
59
58
|
- Build lỗi. Báo nguyên văn lỗi, không tự sửa Gradle.
|
|
60
59
|
|
|
61
|
-
|
|
60
|
+
### Phase 1: Chuẩn bị
|
|
62
61
|
1. `adb devices -l`. Chọn serial; ghi model và loại (máy thật hay emulator).
|
|
63
62
|
2. Lấy tham số app: `applicationId` (`build.gradle`), Activity LAUNCHER (`AndroidManifest.xml`), tag log của app (`Application`), file config đang nạp.
|
|
64
63
|
3. Build và cài bản debug: `./gradlew :<appModule>:assembleDebug`, rồi `adb -s <serial> install -r <apk>`. Ghi `versionName`.
|
|
@@ -68,7 +67,7 @@ Chạy kịch bản `do` / `expect` trên thiết bị: build + cài app, điề
|
|
|
68
67
|
|
|
69
68
|
**Verify:** app đã cài (`adb shell pm path <pkg>` trả đường dẫn), có công cụ điều khiển UI.
|
|
70
69
|
|
|
71
|
-
|
|
70
|
+
### Phase 2: Kiểm điều kiện quan sát
|
|
72
71
|
1. Chọn nguồn log. **File `.logads`** (khi app debuggable và `isDebug = true` hoặc đã bật ghi file): ghi lại thời điểm bắt đầu, sau kịch bản lấy file mới nhất bằng `adb -s <serial> exec-out run-as <pkg> cat cache/logads/<file>.logads > <scenario>.logads`; mỗi kịch bản một file (app phải chạy lại để có file mới, hoặc cắt theo giờ). **Logcat** (dự phòng): `adb logcat -c`, rồi ghi log nền `adb -s <serial> logcat -v time -s SuperAdsSDK:V <AppTag>:V > <scenario>.log`.
|
|
73
72
|
2. `launch` app, chờ 5–10s.
|
|
74
73
|
3. Có dòng `SuperAdsSDK` không? Không có thì Stop.
|
|
@@ -76,26 +75,56 @@ Chạy kịch bản `do` / `expect` trên thiết bị: build + cài app, điề
|
|
|
76
75
|
|
|
77
76
|
**Verify:** file log có dòng của SDK sau khi launch.
|
|
78
77
|
|
|
79
|
-
|
|
80
|
-
- Lấy kịch bản từ [scenarios-sample.md](
|
|
78
|
+
### Phase 3: Chạy kịch bản
|
|
79
|
+
- Lấy kịch bản từ [scenarios-sample.md](examples/scenarios-sample.md), hoặc viết mới theo [scenario-format.md](references/scenario-format.md).
|
|
81
80
|
- Với mỗi kịch bản: kiểm `needs` với config đang nạp. Không đạt thì `SKIP` kèm lý do.
|
|
82
81
|
- Thực hiện từng `do`. Sau mỗi `expect`, grep file log hoặc đọc cây UI. Kỳ vọng đầu tiên fail thì dừng kịch bản đó, giữ log, chạy bước trả lại trạng thái.
|
|
83
82
|
|
|
84
83
|
**Verify:** mỗi kịch bản có kết quả và file log riêng.
|
|
85
84
|
|
|
86
|
-
|
|
85
|
+
### Phase 4: Báo cáo
|
|
87
86
|
Bảng `kịch bản | kết quả | bằng chứng | ghi chú`. Kèm serial, model, `versionName`, config đang nạp (`global.version`), đường dẫn các file log.
|
|
88
|
-
`FAIL` thì chuyển sang
|
|
87
|
+
`FAIL` thì chuyển sang [super-ads-debug](../super-ads-debug/SKILL.md) với file log làm đầu vào.
|
|
89
88
|
|
|
90
89
|
**Verify:** không có dòng `PASS` nào thiếu bằng chứng.
|
|
91
90
|
|
|
92
|
-
##
|
|
91
|
+
## 🔧 API Reference
|
|
92
|
+
Bước `do` (`launch`, `tap`, `select`, `wait`, `back`, `home`/`resume`, `rotate`, `network`) và `expect` (`log`, `logCount`, `never`, `ui`): [references/scenario-format.md](references/scenario-format.md). Regex theo sự kiện: [references/log-assertions.md](references/log-assertions.md).
|
|
93
|
+
|
|
94
|
+
## ✅ Best Practices
|
|
95
|
+
- Mỗi kịch bản: bắt đầu từ trạng thái log sạch (`adb logcat -c`, hoặc đánh dấu thời điểm để lấy file `.logads` mới) → `launch` → các bước → lưu file log riêng. Nguồn log ưu tiên là file `.logads`, Logcat là dự phòng ([logging-setup.md](../super-ads-debug/references/logging-setup.md) mục 6).
|
|
96
|
+
- Mỗi kết luận `PASS` / `FAIL` trích dòng log hoặc trạng thái UI làm bằng chứng.
|
|
97
|
+
- Trả lại trạng thái máy đã đổi (mạng, xoay màn) kể cả khi kịch bản fail.
|
|
98
|
+
- Chờ theo dòng log (`expect … within`) thay vì ngủ cố định.
|
|
99
|
+
|
|
100
|
+
## ❌ Anti-patterns
|
|
101
|
+
- Sửa code, manifest, Gradle, asset config của app. Kể cả "tạm thời".
|
|
102
|
+
- Ghi đè file config của app bằng working config `tmp-*.json` của MCP.
|
|
103
|
+
- Bấm vào ad thật (click) trên bản production, hoặc chạy với unit thật khi chưa được user đồng ý (rủi ro invalid traffic).
|
|
104
|
+
- Báo `PASS` cho kỳ vọng `never` khi không có bằng chứng dương rằng lời gọi đã tới SDK ([log-assertions.md](references/log-assertions.md) mục 4).
|
|
105
|
+
- Chạy `network off` trên emulator/LDPlayer: mất luôn kết nối adb.
|
|
93
106
|
- Dùng `sleep` cố định thay cho chờ dòng log.
|
|
94
107
|
- Grep tag Logcat theo `name` (`AdSFl`, `RuleMg`…). Tag luôn là `SuperAdsSDK`, `name` nằm trong message.
|
|
95
108
|
- Mở màn test bằng `am start` khi Activity không exported.
|
|
96
109
|
- Bấm nút `Dismiss` của màn test để kiểm dismiss-reload (nút đó gọi `Ads.dismissByPlacement`, không kích reload).
|
|
97
110
|
- Khớp theo tên lỗi hay tên rule. Dùng `code = N` (tên rule trên bản R8 có thể đã bị đổi).
|
|
98
111
|
|
|
112
|
+
## ⚠️ Common Issues
|
|
113
|
+
**Không có dòng `SuperAdsSDK` sau `launch`.**
|
|
114
|
+
Cause: logger chưa bật ở bản đang cài. Solution: dừng và hỏi user; bật logger là sửa app ([logging-setup.md](../super-ads-debug/references/logging-setup.md) mục 2).
|
|
115
|
+
|
|
116
|
+
**Kịch bản cần config khác với config đang nạp.**
|
|
117
|
+
Cause: config app không thỏa `needs`. Solution: `super-ads-debug-override` nếu có hook; không thì đưa user ba lựa chọn ở "Dừng và hỏi user khi".
|
|
118
|
+
|
|
119
|
+
## Files created
|
|
120
|
+
Skill này không tạo file nào trong app; nó chỉ ghi file log mỗi kịch bản (`<scenario>.logads` hoặc `<scenario>.log`) ngoài source.
|
|
121
|
+
|
|
122
|
+
## Files modified
|
|
123
|
+
Skill này không sửa file nào của app. Chỉ khi user chọn phương án sửa config để chạy kịch bản thì mới có thay đổi (đó là sửa app, cần duyệt).
|
|
124
|
+
|
|
125
|
+
## Verification
|
|
126
|
+
Mỗi phase có dòng **Verify** riêng ở Workflow. Kết thúc: không có dòng `PASS` nào thiếu bằng chứng, và `git status` của app sạch như trước khi chạy.
|
|
127
|
+
|
|
99
128
|
## Checklist
|
|
100
129
|
- [ ] Đã chọn serial, đã cài đúng bản, có `versionName`.
|
|
101
130
|
- [ ] Logcat có log SDK.
|
|
@@ -103,5 +132,25 @@ Bảng `kịch bản | kết quả | bằng chứng | ghi chú`. Kèm serial, mo
|
|
|
103
132
|
- [ ] Trạng thái máy đã được trả lại.
|
|
104
133
|
- [ ] Không file nào của app bị sửa (`git status` của app sạch như trước khi chạy).
|
|
105
134
|
|
|
135
|
+
## 📈 Performance Notes
|
|
136
|
+
> **Not applicable for this skill.**
|
|
137
|
+
|
|
138
|
+
## 🔒 Security Notes
|
|
139
|
+
> **Not applicable for this skill.**
|
|
140
|
+
|
|
141
|
+
## 🔄 Migration Guide
|
|
142
|
+
> **Not applicable for this skill.**
|
|
143
|
+
|
|
106
144
|
## Output
|
|
107
145
|
Bảng kết quả theo kịch bản, thông tin thiết bị/bản build/config, đường dẫn log, các kịch bản `SKIP` / `UNKNOWN` kèm lý do, và việc cần làm tiếp (vd chuyển `super-ads-debug`).
|
|
146
|
+
|
|
147
|
+
## Examples
|
|
148
|
+
Kịch bản hoàn chỉnh S1-S6 (cooldown 101, native inline, collapsible dismiss-reload, App Open guard 108, premium 103, mất mạng 104): [examples/scenarios-sample.md](examples/scenarios-sample.md).
|
|
149
|
+
|
|
150
|
+
## 📚 References
|
|
151
|
+
- [super-ads-guide](../super-ads-guide/SKILL.md), [super-ads-upgrade](../super-ads-upgrade/SKILL.md)
|
|
152
|
+
- [super-ads-debug](../super-ads-debug/SKILL.md), [super-ads-show-rate](../super-ads-show-rate/SKILL.md), [super-ads-debug-override](../super-ads-debug-override/SKILL.md)
|
|
153
|
+
- [Bật log SDK](../super-ads-debug/references/logging-setup.md)
|
|
154
|
+
|
|
155
|
+
## 🏷️ Tags
|
|
156
|
+
`superads` `adb` `device-test` `scenario` `logcat` `do-expect`
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
# Bộ kịch bản mẫu
|
|
2
2
|
|
|
3
|
-
> Định dạng: [scenario-format.md](scenario-format.md). Regex: [log-assertions.md](log-assertions.md).
|
|
4
|
-
> `<P>` là placement **lấy từ config đang được nạp**, không phải tên cố định. Nhãn nút theo app mẫu ([sample-app-notes.md](sample-app-notes.md)); app khác thì thay bằng màn tương đương.
|
|
3
|
+
> Định dạng: [scenario-format.md](../references/scenario-format.md). Regex: [log-assertions.md](../references/log-assertions.md).
|
|
4
|
+
> `<P>` là placement **lấy từ config đang được nạp**, không phải tên cố định. Nhãn nút theo app mẫu ([sample-app-notes.md](../references/sample-app-notes.md)); app khác thì thay bằng màn tương đương.
|
|
5
5
|
> `SA/` = `super-ads/src/main/java/com/android/fullhd/super_ads/`.
|
|
6
6
|
|
|
7
7
|
Mỗi kịch bản ghi `needs` (điều kiện config). Đọc config trước khi chạy: điều kiện sai thì **bỏ qua kịch bản và ghi lý do**, không chỉnh config cho vừa.
|
|
8
8
|
|
|
9
9
|
## S1. Inter show rồi bị chặn bởi cooldown (101)
|
|
10
10
|
- needs: `<P>` fullscreen, `show.timeBetweenMs` của adItem đầu > thời gian thao tác (vd ≥ 10000), mạng bật, không premium.
|
|
11
|
-
- App mẫu: `<P>` = `InterChain` (adItem `chain_inter`, `show.timeBetweenMs = 15000`), mở qua Playground. Màn `Interstitial` (`test_inter`) không có cooldown nên kịch bản sẽ `SKIP` ở đó ([sample-app-notes.md](sample-app-notes.md)).
|
|
11
|
+
- App mẫu: `<P>` = `InterChain` (adItem `chain_inter`, `show.timeBetweenMs = 15000`), mở qua Playground. Màn `Interstitial` (`test_inter`) không có cooldown nên kịch bản sẽ `SKIP` ở đó ([sample-app-notes.md](../references/sample-app-notes.md)).
|
|
12
12
|
- steps:
|
|
13
13
|
1. `launch` → `tap text:"🎮 Playground (chọn placement)"` → `select id:spinnerCategory value:"INTERSTITIAL_NATIVE_CHAIN"` → `select id:spinnerPlacement value:"<P>"` → `tap id:btnShow`
|
|
14
14
|
2. `expect log '\[AdSFl\] info=adEventSink Impression: public=<P> ' within 30s`
|
|
@@ -23,7 +23,7 @@ Mỗi kịch bản ghi `needs` (điều kiện config). Đọc config trước k
|
|
|
23
23
|
|
|
24
24
|
## S3. Collapsible: người dùng bấm đóng → dismiss-reload
|
|
25
25
|
- needs: `<P>` collapsible có `reload.dismiss.placementID`.
|
|
26
|
-
- App mẫu: `<P>` = `native_collapsible_dismiss_reload` hoặc `test_native_collapsible_reload_dismiss`, mở qua Playground (`select id:spinnerCategory value:"NATIVE_COLLAPSIBLE"` → `select id:spinnerPlacement value:"<P>"`). Màn `Native Collapsible` (`test_native_collapsible`) không có `reload.*` ([sample-app-notes.md](sample-app-notes.md)).
|
|
26
|
+
- App mẫu: `<P>` = `native_collapsible_dismiss_reload` hoặc `test_native_collapsible_reload_dismiss`, mở qua Playground (`select id:spinnerCategory value:"NATIVE_COLLAPSIBLE"` → `select id:spinnerPlacement value:"<P>"`). Màn `Native Collapsible` (`test_native_collapsible`) không có `reload.*` ([sample-app-notes.md](../references/sample-app-notes.md)).
|
|
27
27
|
- steps: `launch` → mở Playground, chọn `<P>` như trên → `tap id:btnShow` → chờ Impression → bấm **nút đóng của chính ad** (không phải nút `Dismiss` của màn test, nút đó gọi `Ads.dismissByPlacement`, `app/src/main/java/com/android/hd/ads2026/test/BaseTestActivity.kt:107-110`) → `expect log '\[ReloadCoord\] info=onSwapCommitted OK: currentPlacementId <P> ->' within 30s`.
|
|
28
28
|
- Lý do: chỉ đóng do người dùng bấm mới reload; `Ads.dismissByPlacement()` (nút `Dismiss` của màn test) thì không (`SA/show/ReloadCoordinator.kt:225-229`).
|
|
29
29
|
|
|
@@ -38,7 +38,7 @@ Mỗi kịch bản ghi `needs` (điều kiện config). Đọc config trước k
|
|
|
38
38
|
- steps: bật premium → show `<P>` → `expect log '\[RuleMg Block\] action=SHOW .*code = 103'` → `never '...Impression: public=<P> '`.
|
|
39
39
|
|
|
40
40
|
## S6. Mất mạng (104)
|
|
41
|
-
- needs: **máy thật qua USB** (xem `network` trong [scenario-format.md](scenario-format.md)).
|
|
41
|
+
- needs: **máy thật qua USB** (xem `network` trong [scenario-format.md](../references/scenario-format.md)).
|
|
42
42
|
- steps: `network off` → show `<P>` → `expect log '\[RuleMg Block\] action=SHOW .*code = 104' within 5s` → `network on` (luôn chạy, kể cả khi fail).
|
|
43
43
|
|
|
44
44
|
## Báo cáo mỗi kịch bản
|