@ahnseungchan/device-farm 0.1.0 → 0.1.1
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/CHANGELOG.md +7 -0
- package/README.md +204 -102
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
`@ahnseungchan/device-farm`의 바뀐 점을 적는다.
|
|
4
4
|
|
|
5
|
+
## [0.1.1] - 2026-11-11
|
|
6
|
+
|
|
7
|
+
### Docs
|
|
8
|
+
|
|
9
|
+
- README를 WebViewKit 형식으로 개편: 가운데 정렬 로고·배지·바로가기, 구조 다이어그램(SVG), Why 비교표, 긴 내용은 접기(`<details>`), Contributing
|
|
10
|
+
- 로고·구조 다이어그램을 `docs/assets/`에 추가(npm에서도 보이도록 GitHub 절대 URL로 링크, 패키지에는 넣지 않음)
|
|
11
|
+
|
|
5
12
|
## [0.1.0] - 2026-11-11
|
|
6
13
|
|
|
7
14
|
### Added
|
package/README.md
CHANGED
|
@@ -1,72 +1,95 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/Ahnseungc/device-farm/main/docs/assets/logo.svg?sanitize=true" width="96" alt="device-farm 로고: 초록 바탕의 폰에서 새싹이 자란다" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">device-farm</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<b>WebView로 만든 모바일 앱을 실기기에서 QA 자동화하는 디바이스팜.</b><br />
|
|
9
|
+
내 프로젝트에 설치하고 <code>farm.config.ts</code> 하나로 점검할 앱을 정한다.
|
|
10
|
+
</p>
|
|
11
|
+
|
|
12
|
+
<p align="center">
|
|
13
|
+
<a href="https://www.npmjs.com/package/@ahnseungchan/device-farm"><img src="https://img.shields.io/npm/v/@ahnseungchan/device-farm" alt="npm" /></a>
|
|
14
|
+
<a href="https://github.com/Ahnseungc/device-farm/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue" alt="license" /></a>
|
|
15
|
+
<a href="https://nodejs.org/"><img src="https://img.shields.io/node/v/@ahnseungchan/device-farm" alt="node" /></a>
|
|
16
|
+
</p>
|
|
17
|
+
|
|
18
|
+
<p align="center">
|
|
19
|
+
<a href="#설치">설치</a> ·
|
|
20
|
+
<a href="#quick-start">Quick start</a> ·
|
|
21
|
+
<a href="#cli">CLI</a> ·
|
|
22
|
+
<a href="#claude-code-mcp">Claude Code</a> ·
|
|
23
|
+
<a href="#안전">안전</a> ·
|
|
24
|
+
<a href="https://github.com/Ahnseungc/device-farm/blob/main/CHANGELOG.md">Changelog</a>
|
|
25
|
+
</p>
|
|
26
|
+
|
|
27
|
+
<p align="center">
|
|
28
|
+
<img src="https://raw.githubusercontent.com/Ahnseungc/device-farm/main/docs/assets/architecture.svg?sanitize=true" width="760" alt="device-farm 구조: farm.config.ts를 읽은 웹 화면·CLI·MCP가 Android(adb+CDP)·iOS(Appium) 기기를 조작하고 결과를 test-results에 남긴다" />
|
|
29
|
+
</p>
|
|
10
30
|
|
|
11
31
|
## Why
|
|
12
32
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
|
16
|
-
|
|
|
17
|
-
|
|
|
18
|
-
|
|
|
19
|
-
|
|
|
20
|
-
|
|
|
33
|
+
손으로 하는 QA는 기기 수와 화면 수에 비례해 늘어납니다. device-farm은 그 반복을 실기기 위에서 자동으로 돌립니다.
|
|
34
|
+
|
|
35
|
+
| 손으로 하는 QA | device-farm |
|
|
36
|
+
| ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------- |
|
|
37
|
+
| 새 빌드가 나오면 기기마다 깔고 화면을 하나씩 열어 본다 | Firebase App Distribution·TestFlight 새 빌드를 받아 연결된 기기에 깔고, 고정 주소 화면을 딥링크로 열어 기준 화면과 비교 |
|
|
38
|
+
| 버튼을 다 눌러 봤는지 기억에 의존한다 | 화면의 버튼을 하나씩 눌러 반응(이동·팝업·반응 없음·오류)을 남기고, 결과가 **화면 지도**가 된다 |
|
|
39
|
+
| 시나리오 테스트를 코드로 짜고 고친다 | 사람이 기기를 움직이면 녹화해 플로우 후보로 올리고, 확정한 것만 돈다 |
|
|
40
|
+
| 뒤로·연타·백그라운드 같은 엣지 케이스는 운에 맡긴다 | 시드 고정 카오스 탐색으로 재현 가능한 무작위 조작 |
|
|
41
|
+
| 정책 문서·피그마 문구와 화면을 눈으로 대조한다 | Confluence 정책·피그마 문구를 화면 글자와 맞춰 본다 |
|
|
42
|
+
| 탐색 자동화가 실제 결제·탈퇴를 누를까 무섭다 | 쓰기 요청 가드와 금지 버튼 목록. 가드를 못 걸면 시작하지 않는다 |
|
|
21
43
|
|
|
22
44
|
점검할 앱은 코드에 없습니다. 패키지 id·웹 주소·하단 탭·금지어·시나리오처럼 앱마다 다른 값은 전부 `farm.config.ts`로 **주입**합니다.
|
|
45
|
+
Android는 adb + Chrome DevTools Protocol(Playwright), iOS는 Appium(XCUITest·WebDriverAgent)으로 앱 안 WebView를 직접 조작합니다.
|
|
23
46
|
|
|
24
47
|
## Features
|
|
25
48
|
|
|
26
|
-
- **빌드 점검**: 새 빌드 감시 → 설치 → 고정 주소 화면 점검. 앱 오류 문구·로그인 튕김·빈 화면·기준 화면 픽셀 비교로
|
|
27
|
-
- **버튼 눌러보기·화면 지도**: 버튼별 반응을
|
|
28
|
-
- **플로우**: 홈에서 버튼·링크만 눌러 가는 시나리오. 녹화, 화면 지도 조립, PRD로 LLM 후보 생성(선택)
|
|
29
|
-
- **데이터 QA**: 화면이 부르는 GET API를 다시 불러 합계·표시 값을 규칙으로 맞춰 본다(LLM 없음)
|
|
30
|
-
- **탐색·카오스 탐색**: 너비 우선 탐색과 시드 고정 카오스(뒤로·연타·로딩 중 뒤로·백그라운드·재시작)
|
|
31
|
-
- **정책·피그마 대조**: Confluence 정책 바뀜 감지, 규칙 뽑기, 피그마 문구
|
|
32
|
-
- **원격 조작**: 웹 화면에서 기기 화면을 보며(Android H.264, iOS MJPEG) 직접 누른다. 조작 중인 기기는
|
|
33
|
-
- **Claude Code MCP**:
|
|
49
|
+
- **빌드 점검**: 새 빌드 감시 → 설치 → 고정 주소 화면 점검. 앱 오류 문구·로그인 튕김·빈 화면·기준 화면 픽셀 비교로 판정.
|
|
50
|
+
- **버튼 눌러보기·화면 지도**: 버튼별 반응을 기록하고 화면 간 이동을 지도로 쌓는다. 지도 블록을 이어 붙여 플로우를 만든다.
|
|
51
|
+
- **플로우**: 홈에서 버튼·링크만 눌러 가는 시나리오. 녹화, 화면 지도 조립, PRD로 LLM 후보 생성(선택).
|
|
52
|
+
- **데이터 QA**: 화면이 부르는 GET API를 다시 불러 합계·표시 값을 규칙으로 맞춰 본다(LLM 없음).
|
|
53
|
+
- **탐색·카오스 탐색**: 너비 우선 탐색과 시드 고정 카오스(뒤로·연타·로딩 중 뒤로·백그라운드·재시작).
|
|
54
|
+
- **정책·피그마 대조**: Confluence 정책 바뀜 감지, 규칙 뽑기, 피그마 문구 대조.
|
|
55
|
+
- **원격 조작**: 웹 화면에서 기기 화면을 보며(Android H.264, iOS MJPEG) 직접 누른다. 조작 중인 기기는 잠근다.
|
|
56
|
+
- **Claude Code MCP**: Claude가 MCP 도구로 기기를 탐색하고, 찾은 경로를 플로우 후보로 올린다.
|
|
57
|
+
|
|
58
|
+
## 설치
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
npm install -D @ahnseungchan/device-farm
|
|
62
|
+
```
|
|
34
63
|
|
|
35
|
-
|
|
64
|
+
| 준비물 | 언제 필요 |
|
|
65
|
+
| -------------------------------------------------------------------------- | -------------------------- |
|
|
66
|
+
| macOS, Node.js 22 이상 | 항상 |
|
|
67
|
+
| `adb`(Android platform-tools), USB 디버깅을 켠 기기 | Android |
|
|
68
|
+
| WebView 디버깅을 켠 dev 빌드: `WebView.setWebContentsDebuggingEnabled(true)` | Android |
|
|
69
|
+
| Xcode, Appium + XCUITest 드라이버(WebDriverAgent), `isInspectable = true`인 빌드 | iOS |
|
|
70
|
+
| Firebase 서비스 계정, App Store Connect API 키 | 새 빌드 자동 받기(선택) |
|
|
71
|
+
| Confluence API 토큰, Figma 토큰 | 정책·피그마 대조(선택) |
|
|
36
72
|
|
|
37
|
-
|
|
38
|
-
| --- | --- |
|
|
39
|
-
| macOS, Node.js 22 이상 | 항상 |
|
|
40
|
-
| `adb`(Android platform-tools), USB 디버깅을 켠 기기 | Android |
|
|
41
|
-
| WebView 디버깅을 켠 dev 빌드: `WebView.setWebContentsDebuggingEnabled(true)` | Android |
|
|
42
|
-
| Xcode, Appium + XCUITest 드라이버(WebDriverAgent), `isInspectable = true`인 빌드 | iOS |
|
|
43
|
-
| Firebase 서비스 계정, App Store Connect API 키 | 새 빌드 자동 받기(선택) |
|
|
44
|
-
| Confluence API 토큰, Figma 토큰 | 정책·피그마 대조(선택) |
|
|
73
|
+
호스트 맥·기기 준비: [docs/operations.md](https://github.com/Ahnseungc/device-farm/blob/main/docs/operations.md)
|
|
45
74
|
|
|
46
|
-
|
|
75
|
+
<details>
|
|
76
|
+
<summary><b>점검할 앱이 맞춰야 할 것</b></summary>
|
|
47
77
|
|
|
48
78
|
1. **WebView 디버깅**이 켜진 빌드. 디바이스팜은 이 디버깅 소켓으로 들어간다.
|
|
49
79
|
2. **경로형 딥링크**: `<scheme>://<웹 경로>`를 받으면 그 웹 경로를 WebView로 연다.
|
|
50
80
|
3. **하단 탭이 웹 링크**(`a[href]` 또는 `role=link`)이고, 화면 상단 뒤로 버튼에 이름(`aria-label`)이 있다.
|
|
51
81
|
4. 점검용 계정으로 로그인해 둔다. 로그인 화면으로 튕기면 「로그인 필요」로 남는다.
|
|
52
82
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
## 설치
|
|
56
|
-
|
|
57
|
-
```bash
|
|
58
|
-
npm install -D @ahnseungchan/device-farm
|
|
59
|
-
```
|
|
83
|
+
</details>
|
|
60
84
|
|
|
61
85
|
## Quick start
|
|
62
86
|
|
|
63
87
|
```bash
|
|
64
|
-
npx device-farm init
|
|
65
|
-
|
|
66
|
-
npx device-farm dev # http://127.0.0.1:5173 (--port 로 변경)
|
|
88
|
+
npx device-farm init # farm.config.ts, .env.example 생성(이미 있으면 건너뜀)
|
|
89
|
+
npx device-farm dev # http://127.0.0.1:5173 (--port 로 변경)
|
|
67
90
|
```
|
|
68
91
|
|
|
69
|
-
`init`이
|
|
92
|
+
`init`이 만든 `farm.config.ts`를 내 앱 값으로 고칩니다. 필수 값만 남기면 이 정도입니다.
|
|
70
93
|
|
|
71
94
|
```ts
|
|
72
95
|
// farm.config.ts
|
|
@@ -83,66 +106,129 @@ export default defineAppConfig({
|
|
|
83
106
|
});
|
|
84
107
|
```
|
|
85
108
|
|
|
86
|
-
`.gitignore`에 `.env`와 `test-results/`를 넣어 두세요.
|
|
109
|
+
토큰이 필요하면 `.env.example`을 `.env`로 복사해 채우고, `.gitignore`에 `.env`와 `test-results/`를 넣어 두세요.
|
|
110
|
+
결과(실행 기록·스크린샷·기준 화면·화면 지도)는 전부 작업 폴더의 `test-results/`에 쌓입니다.
|
|
87
111
|
|
|
88
|
-
|
|
112
|
+
<details>
|
|
113
|
+
<summary><b>데이터 QA 규칙 예시</b></summary>
|
|
89
114
|
|
|
90
|
-
|
|
115
|
+
```ts
|
|
116
|
+
import { defineAppConfig, equalWon, formatWon, numberAt, textHas } from "@ahnseungchan/device-farm";
|
|
117
|
+
|
|
118
|
+
export default defineAppConfig({
|
|
119
|
+
// ...필수 값
|
|
120
|
+
apiOrigin: "https://api-dev.app.example.com",
|
|
121
|
+
qa: {
|
|
122
|
+
sessionPath: "/api/auth/session",
|
|
123
|
+
screens: [
|
|
124
|
+
{
|
|
125
|
+
path: "/cart",
|
|
126
|
+
name: "장바구니",
|
|
127
|
+
apis: { cart: "/v1/users/{userId}/cart" },
|
|
128
|
+
rules: [
|
|
129
|
+
{
|
|
130
|
+
id: "total-shown",
|
|
131
|
+
title: "받은 합계가 화면에 그대로 보인다",
|
|
132
|
+
check: (context) => {
|
|
133
|
+
const shown = `${formatWon(numberAt(context, "cart", "totalWon"))}원`;
|
|
134
|
+
return textHas(context.text, shown) ? null : `화면에 없음: 합계 「${shown}」`;
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
],
|
|
138
|
+
},
|
|
139
|
+
],
|
|
140
|
+
},
|
|
141
|
+
});
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
`npx device-farm qa --device <id> [--path /cart]`로 돌립니다. 전체 예시는 `init`이 만든 `farm.config.ts`에 있습니다.
|
|
145
|
+
|
|
146
|
+
</details>
|
|
147
|
+
|
|
148
|
+
## 앱 설정
|
|
91
149
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
|
96
|
-
|
|
|
97
|
-
| `
|
|
98
|
-
| `
|
|
99
|
-
| `
|
|
100
|
-
| `
|
|
101
|
-
| `
|
|
102
|
-
| `
|
|
103
|
-
| `
|
|
104
|
-
| `
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
|
110
|
-
|
|
|
111
|
-
| `
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
150
|
+
`defineAppConfig()`가 빠진 값을 기본값으로 채웁니다. 타입은 `AppConfigInput`·`AppConfig`로 패키지에서 가져올 수 있습니다.
|
|
151
|
+
설정 파일은 `FARM_CONFIG` → 작업 폴더 `farm.config.ts` → `farm.config.example.ts` 순으로 찾고, 비밀 값은 작업 폴더 `.env`에서 읽습니다.
|
|
152
|
+
|
|
153
|
+
| 필드 | 필수 | 설명 |
|
|
154
|
+
| ------------------------------------ | ---- | ---------------------------------------------------------------------------- |
|
|
155
|
+
| `name` | ✓ | 앱 이름. 화면 제목·프롬프트에 쓴다 |
|
|
156
|
+
| `appIds` | ✓ | `{ dev, prod }` Android 패키지 = iOS 번들 id. 다르면 `iosBundleIds` |
|
|
157
|
+
| `homePath`·`homeTabName`·`tabPaths` | ✓ | 홈 경로, 홈 탭 이름, 하단 탭 이름 → 경로 |
|
|
158
|
+
| `web` | | `{ dev, prod }` WebView 웹 주소. 비면 `FARM_WEB_ORIGIN_DEV`·`FARM_WEB_ORIGIN_PROD` |
|
|
159
|
+
| `apiOrigin` | | API 호스트(웹과 다를 때). 가드가 내부로 보고 데이터 QA가 부른다 |
|
|
160
|
+
| `deepLink` | | `{ scheme, homeHost }` 경로형 딥링크 |
|
|
161
|
+
| `guard` | | 기본 금지어·금지 API에 **더할** 값, 늘 통과시킬 `pushTokenRequests` |
|
|
162
|
+
| `scenarios`·`excludedScenarioPaths` | | 고정 주소 화면 점검 목록과 뺄 경로 |
|
|
163
|
+
|
|
164
|
+
<details>
|
|
165
|
+
<summary><b>전체 필드</b></summary>
|
|
166
|
+
|
|
167
|
+
| 필드 | 설명 |
|
|
168
|
+
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
169
|
+
| `inPageBackNames` | 화면 상단 뒤로 버튼 이름. 기본 `["뒤로가기", "Back"]` |
|
|
170
|
+
| `loginPaths`·`appErrorText` | 로그인 화면 경로, 앱 오류 문구. 기본 `["/login"]`, `"Application error"` |
|
|
171
|
+
| `android.mainActivity` | WebView 액티비티. 다른 네이티브 화면이 위에 있으면 뒤로 키로 닫는다 |
|
|
172
|
+
| `webview` | `stackResetScript`(WebView 스택 닫기 브리지), `sheetCloseName`(시트 닫기 버튼) |
|
|
173
|
+
| `guard` | `extraForbiddenButtonWords`·`extraForbiddenClickNames`·`extraForbiddenApiPatterns`, `pushTokenRequests`, 누르지 않을 `avoidedNamePattern`·`noPressPathPattern` |
|
|
174
|
+
| `qa` | `{ screens, sessionPath }` 데이터 QA 화면·규칙, 로그인 세션 경로 |
|
|
175
|
+
| `policy.confluence` | `{ cloudId, spaceKey, titleQuery, siteUrl }` 정책 정본 |
|
|
176
|
+
| `figma` | `{ frontRepo, ref, appDir }` 화면 → 피그마 노드를 뽑을 프론트 체크아웃 |
|
|
177
|
+
| `install` | `sources`(플랫폼·빌드별 `firebase`/`testflight`), `firebase`(앱 id), `testflightDevAppName` |
|
|
178
|
+
| `ios` | `{ teamId, wdaBundleId }` WDA 서명. 비면 `IOS_TEAM_ID`·`IOS_WDA_BUNDLE_ID` |
|
|
179
|
+
| `access.allowedDomains` | 화면에 들어올 수 있는 Tailscale 계정 도메인. 비면 이 맥에서만 |
|
|
180
|
+
|
|
181
|
+
데이터 QA 도우미 `equalWon`·`formatWon`·`numberAt`·`textHas`·`pick`도 패키지 루트에서 내보냅니다. 환경 변수 목록은 `.env.example`에 있습니다.
|
|
182
|
+
|
|
183
|
+
</details>
|
|
116
184
|
|
|
117
185
|
## CLI
|
|
118
186
|
|
|
119
187
|
모든 명령은 작업 폴더(내 프로젝트) 기준으로 설정·`.env`를 읽고 결과를 씁니다. `npx device-farm <명령> --help`로 옵션을 볼 수 있습니다.
|
|
120
188
|
|
|
121
|
-
| 명령
|
|
122
|
-
|
|
|
123
|
-
| `device-farm init`
|
|
124
|
-
| `device-farm dev [--port 5173]`
|
|
125
|
-
| `device-farm check --build dev\|prod --version 2.1.5
|
|
126
|
-
| `device-farm explore
|
|
127
|
-
| `device-farm chaos --device <serial
|
|
128
|
-
| `device-farm record --device <serial
|
|
129
|
-
| `device-farm qa --device <id
|
|
130
|
-
| `device-farm policy-watch
|
|
131
|
-
| `device-farm policy-check --device <id
|
|
132
|
-
| `device-farm explore-allowlist`
|
|
133
|
-
| `device-farm mcp`
|
|
189
|
+
| 명령 | 하는 일 |
|
|
190
|
+
| ----------------------------------------- | --------------------------------------------------------------------- |
|
|
191
|
+
| `device-farm init` | `farm.config.ts`·`.env.example` 생성 |
|
|
192
|
+
| `device-farm dev [--port 5173]` | 화면 + API 서버(127.0.0.1). 새 빌드 감시·정책 감시가 함께 돈다 |
|
|
193
|
+
| `device-farm check --build dev\|prod --version 2.1.5` | 떠 있는 서버에 빌드 점검을 시키고 끝날 때까지 진행을 출력 |
|
|
194
|
+
| `device-farm explore` | 탐색 점검(서버 필요) |
|
|
195
|
+
| `device-farm chaos --device <serial>` | 카오스 탐색(Android dev) |
|
|
196
|
+
| `device-farm record --device <serial>` | 사람 조작 녹화 → 화면 지도·플로우 후보 |
|
|
197
|
+
| `device-farm qa --device <id>` | 데이터 QA만 |
|
|
198
|
+
| `device-farm policy-watch` | 정책 바뀜 감지·규칙 뽑기·피그마 문구 |
|
|
199
|
+
| `device-farm policy-check --device <id>` | 정책·피그마 대조를 기기 한 대에서 |
|
|
200
|
+
| `device-farm explore-allowlist` | OpenAPI(`FARM_OPENAPI_URL`)의 쓰기 API를 허용 목록에 deny로 추가 |
|
|
201
|
+
| `device-farm mcp` | Claude Code용 MCP 서버(stdio) |
|
|
202
|
+
|
|
203
|
+
<details>
|
|
204
|
+
<summary><b>명령별 옵션</b></summary>
|
|
134
205
|
|
|
206
|
+
```bash
|
|
207
|
+
device-farm dev [--port 5173]
|
|
208
|
+
device-farm check --build dev|prod --version 2.1.5 [--devices all|id,id] [--port 5173]
|
|
209
|
+
device-farm explore [--devices all|id,id] [--build dev] [--port 5173]
|
|
210
|
+
device-farm chaos --device <Android serial> [--seed 42] [--episodes 3] [--steps 50] [--minutes 60] [--no-guard]
|
|
211
|
+
device-farm record --device <Android serial> [--seconds 300] [--name "플로우 이름"]
|
|
212
|
+
device-farm qa --device <id> [--path /cart]
|
|
213
|
+
device-farm policy-watch [--extract <pageId>] [--figma]
|
|
214
|
+
device-farm policy-check --device <id> [--path /my/orders]
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
`check`·`explore`는 떠 있는 `dev` 서버에 작업을 시킵니다. 포트를 바꿨다면 같은 `--port`를 넘기세요.
|
|
135
218
|
탐색 허용 목록 `explore/allowlist.json`, 입력칸 테스트 값 `explore/form-values.json`, 정책 등록 `policy/sources.json`은 작업 폴더에 두고 커밋합니다. 허용 목록이 없으면 모든 쓰기 요청을 막습니다.
|
|
136
219
|
|
|
137
|
-
|
|
220
|
+
</details>
|
|
138
221
|
|
|
139
|
-
|
|
222
|
+
## Claude Code (MCP)
|
|
140
223
|
|
|
141
224
|
```bash
|
|
225
|
+
# 내 프로젝트 폴더에서
|
|
142
226
|
claude mcp add --scope project device-farm -- npx device-farm mcp
|
|
143
227
|
```
|
|
144
228
|
|
|
145
|
-
도구 흐름: `device_start` → `device_look` / `device_press` / `device_go_home` / `device_report_issue` → `device_finish`.
|
|
229
|
+
- 도구 흐름: `device_start` → `device_look` / `device_press` / `device_go_home` / `device_report_issue` → `device_finish`.
|
|
230
|
+
- 끝나면 화면 지도에 합치고, 홈부터 다시 돌 수 있는 경로면 플로우 후보로 올린다. 보고서는 `test-results/agent/<시각>/report.json`.
|
|
231
|
+
- 탐색은 Android dev 빌드에서 쓰기 요청 가드를 켠 채로만 돈다. 사용자의 Claude Code 계정으로 돌고 API 키는 필요 없다.
|
|
146
232
|
|
|
147
233
|
이 저장소는 Claude Code 플러그인(`.claude-plugin`, `skills/run-check`·`chaos-explore`·`policy-figma-check`)으로도 쓸 수 있습니다. 저장소를 받아 `npm install`한 뒤 플러그인으로 추가하세요.
|
|
148
234
|
|
|
@@ -150,26 +236,39 @@ claude mcp add --scope project device-farm -- npx device-farm mcp
|
|
|
150
236
|
|
|
151
237
|
- 탐색·버튼 눌러보기·카오스·MCP 탐색은 **Android dev 빌드**에서, 쓰기 요청 가드를 켠 채로 돈다. 가드를 못 걸면 시작하지 않는다(fail closed).
|
|
152
238
|
- 가드 판단 순서: 읽기(GET·HEAD·OPTIONS) 통과 → `pushTokenRequests` 통과 → 금지 경로 차단 → 허용 목록 allow 통과 → deny·모름 차단.
|
|
153
|
-
- 기본 금지 버튼(구매·결제·매도·매수·송금·출금·탈퇴·주문·환불·해지·삭제·로그아웃 등)은 목록에서 빠지고, 눌러도 거절한다. 앱 설정은 금지어를
|
|
239
|
+
- 기본 금지 버튼(구매·결제·매도·매수·송금·출금·탈퇴·주문·환불·해지·삭제·로그아웃 등)은 목록에서 빠지고, 눌러도 거절한다. 앱 설정은 금지어를 더할 뿐 빼지 못한다. 비밀번호·PIN 화면은 누르지 않고 나가기만 한다.
|
|
154
240
|
- `chaos --no-guard`는 쓰기 요청을 막지 않는다. **dev 서버에서만** 쓴다. 금지 버튼은 그대로 누르지 않는다.
|
|
155
241
|
- 화면 서버는 127.0.0.1에만 열린다. 밖에서는 `tailscale serve`로만 들어오고, `access.allowedDomains`로 계정 도메인을 제한한다.
|
|
156
242
|
|
|
157
243
|
## FAQ
|
|
158
244
|
|
|
159
|
-
|
|
245
|
+
<details>
|
|
246
|
+
<summary><b>기기 없이 화면만 열어 볼 수 있나요?</b></summary>
|
|
247
|
+
|
|
160
248
|
네. `npx device-farm init && npx device-farm dev`면 예시 설정으로 화면이 열립니다. 기기 목록은 비어 있고 점검은 돌지 않습니다.
|
|
161
249
|
|
|
162
|
-
|
|
250
|
+
</details>
|
|
251
|
+
|
|
252
|
+
<details>
|
|
253
|
+
<summary><b>iOS도 탐색·카오스가 되나요?</b></summary>
|
|
254
|
+
|
|
163
255
|
빌드 점검·원격 조작은 iOS(Appium)를 지원합니다. 탐색·카오스·녹화·MCP 탐색은 지금 Android dev 빌드만 지원합니다.
|
|
164
256
|
|
|
165
|
-
|
|
257
|
+
</details>
|
|
258
|
+
|
|
259
|
+
<details>
|
|
260
|
+
<summary><b><code>check</code>가 서버에 연결할 수 없다고 합니다.</b></summary>
|
|
261
|
+
|
|
166
262
|
`check`·`explore`는 떠 있는 `device-farm dev` 서버에 작업을 시킵니다. 다른 터미널에서 `dev`를 먼저 켜고, 포트를 바꿨다면 같은 `--port`를 넘기세요.
|
|
167
263
|
|
|
168
|
-
|
|
169
|
-
|
|
264
|
+
</details>
|
|
265
|
+
|
|
266
|
+
<details>
|
|
267
|
+
<summary><b>LLM 키가 꼭 필요한가요?</b></summary>
|
|
268
|
+
|
|
269
|
+
아니요. 점검·탐색·카오스·데이터 QA는 규칙으로만 판정합니다. PRD로 플로우 후보를 만들 때(`FLOW_LLM_*`)와 정책 판정에만 씁니다.
|
|
170
270
|
|
|
171
|
-
|
|
172
|
-
작업 폴더의 `test-results/`. 커밋하지 마세요.
|
|
271
|
+
</details>
|
|
173
272
|
|
|
174
273
|
## 문서
|
|
175
274
|
|
|
@@ -179,17 +278,20 @@ claude mcp add --scope project device-farm -- npx device-farm mcp
|
|
|
179
278
|
- [설계: 카오스 탐색](https://github.com/Ahnseungc/device-farm/blob/main/docs/design-chaos.md)
|
|
180
279
|
- [설계: 정책·피그마 대조](https://github.com/Ahnseungc/device-farm/blob/main/docs/design-policy-figma.md)
|
|
181
280
|
|
|
182
|
-
##
|
|
281
|
+
## Contributing
|
|
282
|
+
|
|
283
|
+
이슈와 PR 환영합니다. 재현 방법이 있는 버그 리포트, 문서 보완 모두 도움이 됩니다.
|
|
183
284
|
|
|
184
285
|
```bash
|
|
185
286
|
git clone https://github.com/Ahnseungc/device-farm.git && cd device-farm
|
|
186
287
|
npm install
|
|
187
|
-
npm run
|
|
188
|
-
npm run
|
|
189
|
-
npm run build # dist/: bin·설정 타입(tsup), 화면(vite build), init 템플릿
|
|
288
|
+
npm run typecheck && npm test && npm run build
|
|
289
|
+
npm run dev # 화면 개발(vite dev). 저장소 루트 farm.config.ts → farm.config.example.ts
|
|
190
290
|
```
|
|
191
291
|
|
|
192
|
-
npm workspaces 모노레포입니다. 의존 방향은 `core ← devices ← engine ← server ← apps`이고 `tools/boundaries.test.ts`가 지킵니다. 배포 패키지는 워크스페이스를 `dist/`에 묶어
|
|
292
|
+
npm workspaces 모노레포입니다. 의존 방향은 `core ← devices ← engine ← server ← apps`이고 `tools/boundaries.test.ts`가 지킵니다. 배포 패키지는 워크스페이스를 `dist/`에 묶어 냅니다(tsup + vite build).
|
|
293
|
+
|
|
294
|
+
릴리스: `package.json`·`CHANGELOG.md`의 버전을 올리고 `npm run publish:npm`(`prepublishOnly`가 typecheck·test·build를 돈다), `v<version>` 태그를 push합니다.
|
|
193
295
|
|
|
194
296
|
## License
|
|
195
297
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ahnseungchan/device-farm",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "실기기 WebView 앱 QA 자동화 디바이스팜. Android(adb+CDP)·iOS(Appium) 기기에서 기준 화면 비교, 버튼 눌러보기·화면 지도, 플로우 녹화, 카오스 탐색, 정책·피그마 대조를 돌리고 Claude Code MCP로 연결한다.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|