@simplysm/capacitor-plugin-intent 12.16.41 → 14.0.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.
Files changed (42) hide show
  1. package/android/build.gradle +1 -0
  2. package/android/src/main/kotlin/kr/co/simplysm/capacitor/intent/IntentPlugin.kt +365 -0
  3. package/dist/Intent.d.ts +75 -0
  4. package/dist/Intent.d.ts.map +1 -0
  5. package/dist/Intent.js +99 -0
  6. package/dist/Intent.js.map +1 -0
  7. package/dist/IntentPlugin.d.ts +72 -0
  8. package/dist/IntentPlugin.d.ts.map +1 -0
  9. package/dist/IntentPlugin.js +2 -0
  10. package/dist/IntentPlugin.js.map +1 -0
  11. package/dist/index.d.ts +3 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +4 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/web/IntentWeb.d.ts +21 -0
  16. package/dist/web/IntentWeb.d.ts.map +1 -0
  17. package/dist/web/IntentWeb.js +28 -0
  18. package/dist/web/IntentWeb.js.map +1 -0
  19. package/package.json +15 -10
  20. package/src/Intent.ts +56 -25
  21. package/src/IntentPlugin.ts +81 -0
  22. package/src/index.ts +2 -1
  23. package/src/web/IntentWeb.ts +27 -16
  24. package/README.md +0 -188
  25. package/android/src/main/java/kr/co/simplysm/capacitor/intent/IntentPlugin.java +0 -376
  26. package/dist/src/IIntentPlugin.d.ts +0 -63
  27. package/dist/src/IIntentPlugin.js +0 -1
  28. package/dist/src/Intent.d.ts +0 -64
  29. package/dist/src/Intent.js +0 -80
  30. package/dist/src/index.d.ts +0 -2
  31. package/dist/src/index.js +0 -2
  32. package/dist/src/web/IntentWeb.d.ts +0 -19
  33. package/dist/src/web/IntentWeb.js +0 -24
  34. package/src/IIntentPlugin.ts +0 -65
  35. package/tests/slice1-directory-and-config.spec.ts +0 -50
  36. package/tests/slice2-java-renaming.spec.ts +0 -34
  37. package/tests/slice3-typescript-renaming.spec.ts +0 -76
  38. package/tests/slice4-docs-and-deprecation.spec.ts +0 -31
  39. package/tests/slice5-start-activity-for-result-android.spec.md +0 -98
  40. package/tests/slice5-start-activity-for-result-types.spec.ts +0 -40
  41. package/tests/slice6-start-activity-for-result-web.spec.ts +0 -34
  42. package/tsconfig.json +0 -8
@@ -1,50 +0,0 @@
1
- import { existsSync, readFileSync } from "fs";
2
- import { resolve } from "path";
3
-
4
- const pkgRoot = resolve(import.meta.dirname, "..");
5
- const monoRoot = resolve(pkgRoot, "../..");
6
-
7
- describe("Slice 1: 디렉토리 이동 및 설정 파일 변경", () => {
8
- // Scenario: 디렉토리 이동
9
- test("패키지가 packages/capacitor-plugin-intent/ 경로에 존재한다", () => {
10
- expect(existsSync(resolve(monoRoot, "packages/capacitor-plugin-intent"))).toBe(true);
11
- });
12
-
13
- test("packages/capacitor-plugin-broadcast/ 경로는 존재하지 않는다", () => {
14
- expect(existsSync(resolve(monoRoot, "packages/capacitor-plugin-broadcast"))).toBe(false);
15
- });
16
-
17
- // Scenario: npm 패키지명 변경
18
- test("package.json의 name이 @simplysm/capacitor-plugin-intent이다", () => {
19
- const pkg = JSON.parse(readFileSync(resolve(pkgRoot, "package.json"), "utf-8"));
20
- expect(pkg.name).toBe("@simplysm/capacitor-plugin-intent");
21
- });
22
-
23
- // Scenario: package.json 메타데이터 갱신
24
- test("package.json의 description에 Intent가 포함된다", () => {
25
- const pkg = JSON.parse(readFileSync(resolve(pkgRoot, "package.json"), "utf-8"));
26
- expect(pkg.description).toContain("Intent");
27
- });
28
-
29
- test("package.json의 repository.directory가 packages/capacitor-plugin-intent이다", () => {
30
- const pkg = JSON.parse(readFileSync(resolve(pkgRoot, "package.json"), "utf-8"));
31
- expect(pkg.repository.directory).toBe("packages/capacitor-plugin-intent");
32
- });
33
-
34
- // Scenario: simplysm.js 설정 키 변경
35
- test("simplysm.js에서 capacitor-plugin-intent 키로 패키지가 등록되어 있다", async () => {
36
- const config = (await import(resolve(monoRoot, "simplysm.js"))).default();
37
- expect(config.packages["capacitor-plugin-intent"]).toBeDefined();
38
- });
39
-
40
- test("simplysm.js에서 capacitor-plugin-broadcast 키는 존재하지 않는다", async () => {
41
- const config = (await import(resolve(monoRoot, "simplysm.js"))).default();
42
- expect(config.packages["capacitor-plugin-broadcast"]).toBeUndefined();
43
- });
44
-
45
- // Scenario: build.gradle namespace 변경
46
- test("build.gradle namespace가 kr.co.simplysm.capacitor.intent이다", () => {
47
- const gradle = readFileSync(resolve(pkgRoot, "android/build.gradle"), "utf-8");
48
- expect(gradle).toContain('namespace "kr.co.simplysm.capacitor.intent"');
49
- });
50
- });
@@ -1,34 +0,0 @@
1
- import { existsSync, readFileSync } from "fs";
2
- import { resolve } from "path";
3
-
4
- const pkgRoot = resolve(import.meta.dirname, "..");
5
- const javaBase = resolve(pkgRoot, "android/src/main/java/kr/co/simplysm/capacitor");
6
-
7
- describe("Slice 2: Java 소스 리네이밍", () => {
8
- // Scenario: Java 패키지 경로 변경
9
- test("IntentPlugin.java가 intent/ 경로에 존재한다", () => {
10
- expect(existsSync(resolve(javaBase, "intent/IntentPlugin.java"))).toBe(true);
11
- });
12
-
13
- test("이전 broadcast/ 디렉토리는 존재하지 않는다", () => {
14
- expect(existsSync(resolve(javaBase, "broadcast"))).toBe(false);
15
- });
16
-
17
- // Scenario: Java 패키지 선언 변경
18
- test("package 선언이 kr.co.simplysm.capacitor.intent이다", () => {
19
- const java = readFileSync(resolve(javaBase, "intent/IntentPlugin.java"), "utf-8");
20
- expect(java).toContain("package kr.co.simplysm.capacitor.intent;");
21
- });
22
-
23
- // Scenario: Java 클래스명 변경
24
- test("클래스명이 IntentPlugin이다", () => {
25
- const java = readFileSync(resolve(javaBase, "intent/IntentPlugin.java"), "utf-8");
26
- expect(java).toContain("public class IntentPlugin extends Plugin");
27
- });
28
-
29
- // Scenario: Capacitor 플러그인 등록명 변경
30
- test('@CapacitorPlugin(name = "Intent")로 등록된다', () => {
31
- const java = readFileSync(resolve(javaBase, "intent/IntentPlugin.java"), "utf-8");
32
- expect(java).toContain('@CapacitorPlugin(name = "Intent")');
33
- });
34
- });
@@ -1,76 +0,0 @@
1
- import { existsSync, readFileSync } from "fs";
2
- import { resolve } from "path";
3
-
4
- const pkgRoot = resolve(import.meta.dirname, "..");
5
- const srcDir = resolve(pkgRoot, "src");
6
-
7
- describe("Slice 3: TypeScript 소스 리네이밍", () => {
8
- // Scenario: 메인 클래스 파일 및 클래스명 변경
9
- test("Intent.ts에 abstract class Intent가 존재한다", () => {
10
- expect(existsSync(resolve(srcDir, "Intent.ts"))).toBe(true);
11
- const content = readFileSync(resolve(srcDir, "Intent.ts"), "utf-8");
12
- expect(content).toContain("abstract class Intent");
13
- });
14
-
15
- test('registerPlugin<IIntentPlugin>("Intent", ...) 호출이 존재한다', () => {
16
- const content = readFileSync(resolve(srcDir, "Intent.ts"), "utf-8");
17
- expect(content).toContain('registerPlugin<IIntentPlugin>("Intent"');
18
- });
19
-
20
- // Scenario: 플러그인 인터페이스 파일 및 타입명 변경
21
- test("IIntentPlugin.ts에 IIntentPlugin, IIntentResult 인터페이스가 존재한다", () => {
22
- expect(existsSync(resolve(srcDir, "IIntentPlugin.ts"))).toBe(true);
23
- const content = readFileSync(resolve(srcDir, "IIntentPlugin.ts"), "utf-8");
24
- expect(content).toContain("interface IIntentPlugin");
25
- expect(content).toContain("interface IIntentResult");
26
- });
27
-
28
- // Scenario: Web stub 파일 및 클래스명 변경
29
- test("IntentWeb.ts에 class IntentWeb extends WebPlugin implements IIntentPlugin이 존재한다", () => {
30
- expect(existsSync(resolve(srcDir, "web/IntentWeb.ts"))).toBe(true);
31
- const content = readFileSync(resolve(srcDir, "web/IntentWeb.ts"), "utf-8");
32
- expect(content).toContain("class IntentWeb extends WebPlugin implements IIntentPlugin");
33
- });
34
-
35
- // Scenario: index.ts export 경로 갱신
36
- test('index.ts에 export * from "./Intent"와 export * from "./IIntentPlugin"이 존재한다', () => {
37
- const content = readFileSync(resolve(srcDir, "index.ts"), "utf-8");
38
- expect(content).toContain('export * from "./Intent"');
39
- expect(content).toContain('export * from "./IIntentPlugin"');
40
- });
41
-
42
- // Scenario: subscribe API 보존
43
- test("Intent.subscribe API가 존재하고 함수를 반환한다", async () => {
44
- const mod = await import(resolve(srcDir, "Intent.ts"));
45
- expect(typeof mod.Intent.subscribe).toBe("function");
46
- });
47
-
48
- // Scenario: send API 보존
49
- test("Intent.send API가 존재한다", async () => {
50
- const mod = await import(resolve(srcDir, "Intent.ts"));
51
- expect(typeof mod.Intent.send).toBe("function");
52
- });
53
-
54
- // Scenario: getLaunchIntent API 보존
55
- test("Intent.getLaunchIntent API가 존재한다", async () => {
56
- const mod = await import(resolve(srcDir, "Intent.ts"));
57
- expect(typeof mod.Intent.getLaunchIntent).toBe("function");
58
- });
59
-
60
- // Scenario: unsubscribeAll API 보존
61
- test("Intent.unsubscribeAll API가 존재한다", async () => {
62
- const mod = await import(resolve(srcDir, "Intent.ts"));
63
- expect(typeof mod.Intent.unsubscribeAll).toBe("function");
64
- });
65
-
66
- // Scenario: Web 환경에서 stub 동작
67
- test("IntentWeb이 IIntentPlugin의 모든 메서드를 구현한다", async () => {
68
- const mod = await import(resolve(srcDir, "web/IntentWeb.ts"));
69
- const web = new mod.IntentWeb();
70
- expect(typeof web.subscribe).toBe("function");
71
- expect(typeof web.unsubscribe).toBe("function");
72
- expect(typeof web.unsubscribeAll).toBe("function");
73
- expect(typeof web.send).toBe("function");
74
- expect(typeof web.getLaunchIntent).toBe("function");
75
- });
76
- });
@@ -1,31 +0,0 @@
1
- import { readFileSync } from "fs";
2
- import { resolve } from "path";
3
-
4
- const pkgRoot = resolve(import.meta.dirname, "..");
5
- const monoRoot = resolve(pkgRoot, "../..");
6
-
7
- describe("Slice 4: 문서 갱신 및 npm deprecated", () => {
8
- // Scenario: 패키지 README 갱신
9
- test("패키지 README.md에 @simplysm/capacitor-plugin-intent 설치 안내가 있다", () => {
10
- const readme = readFileSync(resolve(pkgRoot, "README.md"), "utf-8");
11
- expect(readme).toContain("@simplysm/capacitor-plugin-intent");
12
- });
13
-
14
- test("패키지 README.md에 broadcast/Broadcast 문자열이 존재하지 않는다", () => {
15
- const readme = readFileSync(resolve(pkgRoot, "README.md"), "utf-8");
16
- // BroadcastReceiver는 Android API 용어이므로 제외하지 않음 — 여기서는 플러그인 이름 참조만 검사
17
- expect(readme).not.toMatch(/capacitor-plugin-broadcast/);
18
- expect(readme).not.toMatch(/\bBroadcast\b/);
19
- });
20
-
21
- // Scenario: 루트 README 갱신
22
- test("루트 README.md에 capacitor-plugin-intent 항목이 존재한다", () => {
23
- const readme = readFileSync(resolve(monoRoot, "README.md"), "utf-8");
24
- expect(readme).toContain("capacitor-plugin-intent");
25
- });
26
-
27
- test("루트 README.md에 capacitor-plugin-broadcast 항목은 존재하지 않는다", () => {
28
- const readme = readFileSync(resolve(monoRoot, "README.md"), "utf-8");
29
- expect(readme).not.toContain("capacitor-plugin-broadcast");
30
- });
31
- });
@@ -1,98 +0,0 @@
1
- # Slice 1: startActivityForResult Android 수동 테스트
2
-
3
- ## 전제 조건
4
-
5
- - Capacitor 앱이 Android 디바이스/에뮬레이터에서 실행 중이다
6
- - `capacitor-plugin-intent`가 플러그인으로 등록되어 있다
7
-
8
- ## Scenario: action만 지정하여 Activity 시작
9
-
10
- ### 수행 절차
11
- 1. `Intent.startActivityForResult({ action: "android.intent.action.PICK" })` 호출
12
- 2. Android 시스템이 해당 action을 처리할 수 있는 앱 목록을 표시하는지 확인
13
-
14
- ### 기대 결과
15
- - 해당 action을 처리하는 Activity가 열린다
16
-
17
- ## Scenario: action + uri 지정
18
-
19
- ### 수행 절차
20
- 1. `Intent.startActivityForResult({ action: "android.intent.action.VIEW", uri: "content://contacts/people/1" })` 호출
21
-
22
- ### 기대 결과
23
- - Intent의 data에 해당 URI가 설정되어 Activity가 열린다
24
-
25
- ## Scenario: extras 지정
26
-
27
- ### 수행 절차
28
- 1. `Intent.startActivityForResult({ action: "com.example.ACTION", extras: { "key": "value" } })` 호출
29
-
30
- ### 기대 결과
31
- - Intent의 extra에 해당 데이터가 포함되어 Activity가 열린다
32
-
33
- ## Scenario: package + component로 명시적 Activity 지정
34
-
35
- ### 수행 절차
36
- 1. 대상 앱의 패키지명과 Activity 클래스명을 확인
37
- 2. `Intent.startActivityForResult({ action: "android.intent.action.MAIN", package: "com.example.app", component: "com.example.app.MainActivity" })` 호출
38
-
39
- ### 기대 결과
40
- - 지정된 패키지의 지정된 Activity가 직접 열린다
41
-
42
- ## Scenario: type(MIME type) 지정
43
-
44
- ### 수행 절차
45
- 1. `Intent.startActivityForResult({ action: "android.intent.action.GET_CONTENT", type: "image/*" })` 호출
46
-
47
- ### 기대 결과
48
- - Intent의 MIME type이 설정되어 이미지 선택 Activity가 열린다
49
-
50
- ## Scenario: uri + type 동시 지정
51
-
52
- ### 수행 절차
53
- 1. `Intent.startActivityForResult({ action: "android.intent.action.VIEW", uri: "content://media/images", type: "image/png" })` 호출
54
-
55
- ### 기대 결과
56
- - Intent에 setDataAndType으로 URI와 MIME type이 함께 설정된다
57
-
58
- ## Scenario: 대상 Activity가 RESULT_OK로 종료
59
-
60
- ### 수행 절차
61
- 1. `Intent.startActivityForResult({ action: "android.intent.action.GET_CONTENT", type: "image/*" })` 호출
62
- 2. 열린 Activity에서 이미지를 선택
63
-
64
- ### 기대 결과
65
- - Promise가 resolve되고 `{ resultCode: -1, data: "content://...", extras: {...} }` 형태의 결과를 반환한다
66
-
67
- ## Scenario: 대상 Activity가 RESULT_CANCELED로 종료 (사용자 뒤로가기)
68
-
69
- ### 수행 절차
70
- 1. `Intent.startActivityForResult({ action: "android.intent.action.GET_CONTENT", type: "image/*" })` 호출
71
- 2. 열린 Activity에서 뒤로가기 버튼 누름
72
-
73
- ### 기대 결과
74
- - Promise가 resolve되고 `{ resultCode: 0 }`을 반환한다
75
-
76
- ## Scenario: 대상 Activity가 data 없이 종료
77
-
78
- ### 수행 절차
79
- 1. data를 반환하지 않는 Activity를 시작하고 정상 완료
80
-
81
- ### 기대 결과
82
- - 반환값의 `data` 필드는 undefined이다
83
-
84
- ## Scenario: 대상 Activity가 extras 없이 종료
85
-
86
- ### 수행 절차
87
- 1. extras를 반환하지 않는 Activity를 시작하고 정상 완료
88
-
89
- ### 기대 결과
90
- - 반환값의 `extras` 필드는 undefined이다
91
-
92
- ## Scenario: 존재하지 않는 앱으로 Activity 시작 시도
93
-
94
- ### 수행 절차
95
- 1. `Intent.startActivityForResult({ action: "android.intent.action.MAIN", package: "com.nonexistent.app", component: "com.nonexistent.app.MainActivity" })` 호출
96
-
97
- ### 기대 결과
98
- - ActivityNotFoundException이 발생하여 Promise가 reject된다
@@ -1,40 +0,0 @@
1
- import { resolve } from "path";
2
-
3
- const pkgRoot = resolve(import.meta.dirname, "..");
4
- const srcDir = resolve(pkgRoot, "src");
5
-
6
- describe("Slice 1: startActivityForResult TypeScript 인터페이스", () => {
7
- test("IIntentPlugin에 startActivityForResult 메서드가 정의되어 있다", async () => {
8
- const mod = await import(resolve(srcDir, "IIntentPlugin.ts"));
9
-
10
- // IStartActivityForResultOptions 타입이 export되어야 한다
11
- expect(mod.IStartActivityForResultOptions).toBeUndefined; // interface는 런타임에 없지만 export 확인
12
-
13
- // IActivityResult 타입이 export되어야 한다
14
- expect(mod.IActivityResult).toBeUndefined;
15
- });
16
-
17
- test("IStartActivityForResultOptions에 필수 필드 action과 선택 필드들이 정의되어 있다", async () => {
18
- const content = (await import("fs")).readFileSync(resolve(srcDir, "IIntentPlugin.ts"), "utf-8");
19
- expect(content).toContain("interface IStartActivityForResultOptions");
20
- expect(content).toMatch(/action\s*:\s*string/);
21
- expect(content).toMatch(/uri\?\s*:\s*string/);
22
- expect(content).toMatch(/extras\?\s*:\s*Record<string,\s*unknown>/);
23
- expect(content).toMatch(/package\?\s*:\s*string/);
24
- expect(content).toMatch(/component\?\s*:\s*string/);
25
- expect(content).toMatch(/type\?\s*:\s*string/);
26
- });
27
-
28
- test("IActivityResult에 resultCode, data?, extras? 필드가 정의되어 있다", async () => {
29
- const content = (await import("fs")).readFileSync(resolve(srcDir, "IIntentPlugin.ts"), "utf-8");
30
- expect(content).toContain("interface IActivityResult");
31
- expect(content).toMatch(/resultCode\s*:\s*number/);
32
- expect(content).toMatch(/data\?\s*:\s*string/);
33
- expect(content).toMatch(/extras\?\s*:\s*Record<string,\s*unknown>/);
34
- });
35
-
36
- test("IIntentPlugin.startActivityForResult 메서드 시그니처가 올바르다", async () => {
37
- const content = (await import("fs")).readFileSync(resolve(srcDir, "IIntentPlugin.ts"), "utf-8");
38
- expect(content).toMatch(/startActivityForResult\s*\(\s*options\s*:\s*IStartActivityForResultOptions\s*\)\s*:\s*Promise<IActivityResult>/);
39
- });
40
- });
@@ -1,34 +0,0 @@
1
- import { resolve } from "path";
2
-
3
- const pkgRoot = resolve(import.meta.dirname, "..");
4
- const srcDir = resolve(pkgRoot, "src");
5
-
6
- describe("Slice 2: startActivityForResult TypeScript 래퍼 및 웹 stub", () => {
7
- // Scenario: Intent.startActivityForResult static 메서드 존재
8
- test("Intent.startActivityForResult static 메서드가 존재한다", async () => {
9
- const mod = await import(resolve(srcDir, "Intent.ts"));
10
- expect(typeof mod.Intent.startActivityForResult).toBe("function");
11
- });
12
-
13
- // Scenario: 웹에서 startActivityForResult 호출
14
- test("IntentWeb.startActivityForResult가 resultCode 0으로 resolve한다", async () => {
15
- const mod = await import(resolve(srcDir, "web/IntentWeb.ts"));
16
- const web = new mod.IntentWeb();
17
-
18
- // alert를 mock
19
- globalThis.alert = vi.fn();
20
-
21
- const result = await web.startActivityForResult({ action: "test.ACTION" });
22
- expect(result).toEqual({ resultCode: 0 });
23
- expect(globalThis.alert).toHaveBeenCalledWith(
24
- "[Intent] 웹 환경에서는 startActivityForResult를 지원하지 않습니다.",
25
- );
26
- });
27
-
28
- // index.ts에서 새 타입이 export되는지 확인
29
- test("index.ts에서 IStartActivityForResultOptions, IActivityResult가 re-export된다", async () => {
30
- const content = (await import("fs")).readFileSync(resolve(srcDir, "IIntentPlugin.ts"), "utf-8");
31
- expect(content).toContain("export interface IStartActivityForResultOptions");
32
- expect(content).toContain("export interface IActivityResult");
33
- });
34
- });
package/tsconfig.json DELETED
@@ -1,8 +0,0 @@
1
- {
2
- "extends": "../../tsconfig.base.json",
3
- "compilerOptions": {
4
- "lib": ["ES2021", "DOM"],
5
- "outDir": "./dist"
6
- },
7
- "exclude": ["dist", "node_modules"]
8
- }