agent-messenger 2.10.1 → 2.10.2
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/.claude-plugin/plugin.json +1 -1
- package/dist/package.json +1 -1
- package/dist/src/platforms/teams/token-extractor.d.ts.map +1 -1
- package/dist/src/platforms/teams/token-extractor.js +9 -2
- package/dist/src/platforms/teams/token-extractor.js.map +1 -1
- package/dist/src/shared/chromium/decryptor.d.ts +6 -0
- package/dist/src/shared/chromium/decryptor.d.ts.map +1 -1
- package/dist/src/shared/chromium/decryptor.js +26 -6
- package/dist/src/shared/chromium/decryptor.js.map +1 -1
- package/e2e/channeltalk.e2e.test.ts +13 -13
- package/e2e/channeltalkbot.e2e.test.ts +13 -13
- package/e2e/discord.e2e.test.ts +24 -24
- package/e2e/discordbot.e2e.test.ts +16 -16
- package/e2e/instagram.e2e.test.ts +10 -10
- package/e2e/kakaotalk.e2e.test.ts +7 -7
- package/e2e/line.e2e.test.ts +8 -8
- package/e2e/slack.e2e.test.ts +34 -34
- package/e2e/slackbot.e2e.test.ts +14 -14
- package/e2e/teams.e2e.test.ts +23 -23
- package/e2e/telegram.e2e.test.ts +8 -8
- package/e2e/webex.e2e.test.ts +14 -14
- package/e2e/whatsapp.e2e.test.ts +8 -8
- package/e2e/whatsappbot.e2e.test.ts +6 -6
- package/package.json +1 -1
- package/skills/agent-channeltalk/SKILL.md +1 -1
- package/skills/agent-channeltalkbot/SKILL.md +1 -1
- package/skills/agent-discord/SKILL.md +1 -1
- package/skills/agent-discordbot/SKILL.md +1 -1
- package/skills/agent-instagram/SKILL.md +1 -1
- package/skills/agent-kakaotalk/SKILL.md +1 -1
- package/skills/agent-line/SKILL.md +1 -1
- package/skills/agent-slack/SKILL.md +1 -1
- package/skills/agent-slackbot/SKILL.md +1 -1
- package/skills/agent-teams/SKILL.md +1 -1
- package/skills/agent-telegram/SKILL.md +1 -1
- package/skills/agent-webex/SKILL.md +1 -1
- package/skills/agent-wechatbot/SKILL.md +1 -1
- package/skills/agent-whatsapp/SKILL.md +1 -1
- package/skills/agent-whatsappbot/SKILL.md +1 -1
- package/src/platforms/channeltalk/client.test.ts +26 -26
- package/src/platforms/channeltalk/commands/auth.test.ts +16 -16
- package/src/platforms/channeltalk/commands/bot.test.ts +2 -2
- package/src/platforms/channeltalk/commands/chat.test.ts +3 -3
- package/src/platforms/channeltalk/commands/group.test.ts +4 -4
- package/src/platforms/channeltalk/commands/manager.test.ts +2 -2
- package/src/platforms/channeltalk/commands/message.test.ts +17 -17
- package/src/platforms/channeltalk/commands/snapshot.test.ts +7 -7
- package/src/platforms/channeltalk/commands/whoami.test.ts +3 -3
- package/src/platforms/channeltalk/credential-manager.test.ts +18 -18
- package/src/platforms/channeltalk/ensure-auth.test.ts +5 -5
- package/src/platforms/channeltalk/index.test.ts +23 -23
- package/src/platforms/channeltalk/token-extractor.test.ts +21 -21
- package/src/platforms/channeltalk/types.test.ts +12 -12
- package/src/platforms/channeltalkbot/client.test.ts +14 -14
- package/src/platforms/channeltalkbot/commands/auth.test.ts +16 -16
- package/src/platforms/channeltalkbot/commands/bot.test.ts +6 -6
- package/src/platforms/channeltalkbot/commands/chat.test.ts +9 -9
- package/src/platforms/channeltalkbot/commands/group.test.ts +6 -6
- package/src/platforms/channeltalkbot/commands/manager.test.ts +3 -3
- package/src/platforms/channeltalkbot/commands/message.test.ts +10 -10
- package/src/platforms/channeltalkbot/commands/snapshot.test.ts +7 -7
- package/src/platforms/channeltalkbot/commands/whoami.test.ts +4 -4
- package/src/platforms/channeltalkbot/credential-manager.test.ts +27 -27
- package/src/platforms/channeltalkbot/index.test.ts +15 -15
- package/src/platforms/discord/client.test.ts +28 -28
- package/src/platforms/discord/commands/auth.test.ts +7 -7
- package/src/platforms/discord/commands/channel.test.ts +7 -7
- package/src/platforms/discord/commands/dm.test.ts +4 -4
- package/src/platforms/discord/commands/file.test.ts +4 -4
- package/src/platforms/discord/commands/friend.test.ts +6 -6
- package/src/platforms/discord/commands/member.test.ts +5 -5
- package/src/platforms/discord/commands/mention.test.ts +5 -5
- package/src/platforms/discord/commands/message.test.ts +9 -9
- package/src/platforms/discord/commands/note.test.ts +6 -6
- package/src/platforms/discord/commands/profile.test.ts +4 -4
- package/src/platforms/discord/commands/reaction.test.ts +5 -5
- package/src/platforms/discord/commands/server.test.ts +7 -7
- package/src/platforms/discord/commands/snapshot.test.ts +6 -6
- package/src/platforms/discord/commands/thread.test.ts +6 -6
- package/src/platforms/discord/commands/user.test.ts +5 -5
- package/src/platforms/discord/commands/whoami.test.ts +6 -6
- package/src/platforms/discord/credential-manager.test.ts +16 -16
- package/src/platforms/discord/ensure-auth.test.ts +8 -8
- package/src/platforms/discord/index.test.ts +17 -17
- package/src/platforms/discord/listener.test.ts +33 -33
- package/src/platforms/discord/token-extractor.test.ts +53 -53
- package/src/platforms/discord/types.test.ts +26 -26
- package/src/platforms/discordbot/client.test.ts +31 -31
- package/src/platforms/discordbot/commands/auth.test.ts +18 -18
- package/src/platforms/discordbot/commands/channel.test.ts +11 -11
- package/src/platforms/discordbot/commands/file.test.ts +7 -7
- package/src/platforms/discordbot/commands/message.test.ts +25 -25
- package/src/platforms/discordbot/commands/reaction.test.ts +6 -6
- package/src/platforms/discordbot/commands/server.test.ts +12 -12
- package/src/platforms/discordbot/commands/snapshot.test.ts +13 -13
- package/src/platforms/discordbot/commands/thread.test.ts +10 -10
- package/src/platforms/discordbot/commands/user.test.ts +9 -9
- package/src/platforms/discordbot/commands/whoami.test.ts +4 -4
- package/src/platforms/discordbot/credential-manager.test.ts +28 -28
- package/src/platforms/instagram/client.test.ts +18 -18
- package/src/platforms/instagram/commands/auth.test.ts +11 -11
- package/src/platforms/instagram/commands/chat.test.ts +6 -6
- package/src/platforms/instagram/commands/message.test.ts +11 -11
- package/src/platforms/instagram/commands/shared.test.ts +12 -12
- package/src/platforms/instagram/commands/whoami.test.ts +3 -3
- package/src/platforms/instagram/credential-manager.test.ts +21 -21
- package/src/platforms/instagram/ensure-auth.test.ts +4 -4
- package/src/platforms/instagram/index.test.ts +9 -9
- package/src/platforms/instagram/listener.test.ts +8 -8
- package/src/platforms/instagram/token-extractor.test.ts +35 -35
- package/src/platforms/kakaotalk/client.test.ts +33 -33
- package/src/platforms/kakaotalk/commands/auth.test.ts +11 -11
- package/src/platforms/kakaotalk/commands/chat.test.ts +6 -6
- package/src/platforms/kakaotalk/commands/message.test.ts +7 -7
- package/src/platforms/kakaotalk/commands/whoami.test.ts +5 -5
- package/src/platforms/kakaotalk/credential-manager.test.ts +15 -15
- package/src/platforms/kakaotalk/index.test.ts +15 -15
- package/src/platforms/kakaotalk/listener.test.ts +17 -17
- package/src/platforms/line/client.test.ts +17 -17
- package/src/platforms/line/commands/auth.test.ts +8 -8
- package/src/platforms/line/commands/chat.test.ts +7 -7
- package/src/platforms/line/commands/friend.test.ts +6 -6
- package/src/platforms/line/commands/message.test.ts +7 -7
- package/src/platforms/line/commands/whoami.test.ts +6 -6
- package/src/platforms/line/credential-manager.test.ts +17 -17
- package/src/platforms/line/index.test.ts +10 -10
- package/src/platforms/line/listener.test.ts +15 -15
- package/src/platforms/line/types.test.ts +14 -14
- package/src/platforms/slack/cli.test.ts +8 -8
- package/src/platforms/slack/client.test.ts +151 -151
- package/src/platforms/slack/commands/activity.test.ts +13 -13
- package/src/platforms/slack/commands/auth.test.ts +34 -34
- package/src/platforms/slack/commands/bookmark.test.ts +9 -9
- package/src/platforms/slack/commands/channel.test.ts +17 -17
- package/src/platforms/slack/commands/drafts.test.ts +7 -7
- package/src/platforms/slack/commands/emoji.test.ts +3 -3
- package/src/platforms/slack/commands/file.test.ts +12 -12
- package/src/platforms/slack/commands/message.test.ts +19 -19
- package/src/platforms/slack/commands/pin.test.ts +7 -7
- package/src/platforms/slack/commands/reaction.test.ts +10 -10
- package/src/platforms/slack/commands/reminder.test.ts +9 -9
- package/src/platforms/slack/commands/saved.test.ts +7 -7
- package/src/platforms/slack/commands/sections.test.ts +5 -5
- package/src/platforms/slack/commands/snapshot.test.ts +13 -13
- package/src/platforms/slack/commands/unread.test.ts +6 -6
- package/src/platforms/slack/commands/user.test.ts +10 -10
- package/src/platforms/slack/commands/usergroup.test.ts +15 -15
- package/src/platforms/slack/commands/whoami.test.ts +6 -6
- package/src/platforms/slack/commands/workspace.test.ts +26 -26
- package/src/platforms/slack/credential-manager.test.ts +14 -14
- package/src/platforms/slack/ensure-auth.test.ts +21 -21
- package/src/platforms/slack/index.test.ts +12 -12
- package/src/platforms/slack/listener.test.ts +17 -17
- package/src/platforms/slack/token-extractor-node.test.ts +2 -2
- package/src/platforms/slack/token-extractor.test.ts +37 -37
- package/src/platforms/slack/types.test.ts +21 -21
- package/src/platforms/slackbot/client.test.ts +22 -22
- package/src/platforms/slackbot/commands/auth.test.ts +14 -14
- package/src/platforms/slackbot/commands/channel.test.ts +7 -7
- package/src/platforms/slackbot/commands/message.test.ts +13 -13
- package/src/platforms/slackbot/commands/reaction.test.ts +6 -6
- package/src/platforms/slackbot/commands/user.test.ts +7 -7
- package/src/platforms/slackbot/commands/whoami.test.ts +4 -4
- package/src/platforms/slackbot/credential-manager.test.ts +22 -22
- package/src/platforms/slackbot/types.test.ts +7 -7
- package/src/platforms/teams/client.test.ts +30 -30
- package/src/platforms/teams/commands/auth.test.ts +8 -8
- package/src/platforms/teams/commands/channel.test.ts +7 -7
- package/src/platforms/teams/commands/file.test.ts +4 -4
- package/src/platforms/teams/commands/message.test.ts +5 -5
- package/src/platforms/teams/commands/reaction.test.ts +4 -4
- package/src/platforms/teams/commands/snapshot.test.ts +7 -7
- package/src/platforms/teams/commands/team.test.ts +8 -8
- package/src/platforms/teams/commands/user.test.ts +4 -4
- package/src/platforms/teams/commands/whoami.test.ts +6 -6
- package/src/platforms/teams/credential-manager.test.ts +17 -17
- package/src/platforms/teams/ensure-auth.test.ts +13 -13
- package/src/platforms/teams/index.test.ts +15 -15
- package/src/platforms/teams/token-extractor.test.ts +109 -49
- package/src/platforms/teams/token-extractor.ts +7 -2
- package/src/platforms/teams/types.test.ts +26 -26
- package/src/platforms/telegram/app-config.test.ts +4 -4
- package/src/platforms/telegram/chat-utils.test.ts +12 -12
- package/src/platforms/telegram/client.test.ts +4 -4
- package/src/platforms/telegram/commands/auth.test.ts +16 -16
- package/src/platforms/telegram/commands/chat.test.ts +9 -9
- package/src/platforms/telegram/commands/message.test.ts +6 -6
- package/src/platforms/telegram/commands/shared.test.ts +3 -3
- package/src/platforms/telegram/commands/whoami.test.ts +3 -3
- package/src/platforms/telegram/credential-manager.test.ts +10 -10
- package/src/platforms/telegram/types.test.ts +6 -6
- package/src/platforms/webex/app-config.test.ts +8 -8
- package/src/platforms/webex/cli.test.ts +5 -5
- package/src/platforms/webex/client.test.ts +65 -65
- package/src/platforms/webex/commands/auth.test.ts +18 -18
- package/src/platforms/webex/commands/member.test.ts +5 -5
- package/src/platforms/webex/commands/message.test.ts +12 -12
- package/src/platforms/webex/commands/snapshot.test.ts +5 -5
- package/src/platforms/webex/commands/space.test.ts +10 -10
- package/src/platforms/webex/commands/whoami.test.ts +6 -6
- package/src/platforms/webex/credential-manager.test.ts +22 -22
- package/src/platforms/webex/encryption.test.ts +4 -4
- package/src/platforms/webex/ensure-auth.test.ts +5 -5
- package/src/platforms/webex/index.test.ts +5 -5
- package/src/platforms/webex/markdown-to-html.test.ts +33 -33
- package/src/platforms/webex/token-extractor.test.ts +23 -23
- package/src/platforms/webex/types.test.ts +27 -27
- package/src/platforms/wechatbot/client.test.ts +27 -27
- package/src/platforms/wechatbot/commands/auth.test.ts +15 -15
- package/src/platforms/wechatbot/commands/message.test.ts +8 -8
- package/src/platforms/wechatbot/commands/template.test.ts +9 -9
- package/src/platforms/wechatbot/commands/user.test.ts +7 -7
- package/src/platforms/wechatbot/commands/whoami.test.ts +5 -5
- package/src/platforms/wechatbot/credential-manager.test.ts +18 -18
- package/src/platforms/wechatbot/index.test.ts +10 -10
- package/src/platforms/wechatbot/types.test.ts +25 -25
- package/src/platforms/whatsapp/commands/auth.test.ts +13 -13
- package/src/platforms/whatsapp/commands/chat.test.ts +8 -8
- package/src/platforms/whatsapp/commands/message.test.ts +10 -10
- package/src/platforms/whatsapp/commands/whoami.test.ts +3 -3
- package/src/platforms/whatsapp/credential-manager.test.ts +23 -23
- package/src/platforms/whatsapp/ensure-auth.test.ts +4 -4
- package/src/platforms/whatsapp/index.test.ts +8 -8
- package/src/platforms/whatsapp/types.test.ts +42 -42
- package/src/platforms/whatsappbot/client.test.ts +27 -27
- package/src/platforms/whatsappbot/commands/auth.test.ts +14 -14
- package/src/platforms/whatsappbot/commands/message.test.ts +16 -16
- package/src/platforms/whatsappbot/commands/template.test.ts +9 -9
- package/src/platforms/whatsappbot/commands/whoami.test.ts +5 -5
- package/src/platforms/whatsappbot/credential-manager.test.ts +18 -18
- package/src/platforms/whatsappbot/index.test.ts +7 -7
- package/src/platforms/whatsappbot/types.test.ts +18 -18
- package/src/shared/chromium/browsers.test.ts +22 -22
- package/src/shared/chromium/cookie-reader.test.ts +13 -13
- package/src/shared/chromium/decryptor.test.ts +97 -32
- package/src/shared/chromium/decryptor.ts +27 -6
- package/src/shared/utils/concurrency.test.ts +6 -6
- package/src/shared/utils/derived-key-cache.test.ts +11 -11
- package/src/tui/utils.test.ts +31 -31
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, spyOn,
|
|
1
|
+
import { beforeEach, describe, expect, spyOn, it } from 'bun:test'
|
|
2
2
|
import { homedir } from 'node:os'
|
|
3
3
|
import { join } from 'node:path'
|
|
4
4
|
|
|
@@ -12,7 +12,7 @@ describe('InstagramTokenExtractor', () => {
|
|
|
12
12
|
})
|
|
13
13
|
|
|
14
14
|
describe('getBrowserCookiesPaths', () => {
|
|
15
|
-
|
|
15
|
+
it('returns darwin paths for all browsers on macOS', () => {
|
|
16
16
|
const darwinExtractor = new InstagramTokenExtractor('darwin')
|
|
17
17
|
const paths = darwinExtractor.getBrowserCookiesPaths()
|
|
18
18
|
|
|
@@ -26,7 +26,7 @@ describe('InstagramTokenExtractor', () => {
|
|
|
26
26
|
expect(paths).toContain(join(base, 'Chromium', 'Default', 'Cookies'))
|
|
27
27
|
})
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
it('returns linux paths for supported browsers', () => {
|
|
30
30
|
const linuxExtractor = new InstagramTokenExtractor('linux')
|
|
31
31
|
const paths = linuxExtractor.getBrowserCookiesPaths()
|
|
32
32
|
|
|
@@ -38,7 +38,7 @@ describe('InstagramTokenExtractor', () => {
|
|
|
38
38
|
expect(paths).toContain(join(base, 'chromium', 'Default', 'Cookies'))
|
|
39
39
|
})
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
it('returns win32 paths for all browsers on Windows', () => {
|
|
42
42
|
const winExtractor = new InstagramTokenExtractor('win32')
|
|
43
43
|
const paths = winExtractor.getBrowserCookiesPaths()
|
|
44
44
|
|
|
@@ -48,13 +48,13 @@ describe('InstagramTokenExtractor', () => {
|
|
|
48
48
|
expect(paths).toContain(join(localAppData, 'BraveSoftware', 'Brave-Browser', 'User Data', 'Default', 'Cookies'))
|
|
49
49
|
})
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
it('returns empty array for unsupported platform', () => {
|
|
52
52
|
const unsupportedExtractor = new InstagramTokenExtractor('freebsd' as NodeJS.Platform)
|
|
53
53
|
const paths = unsupportedExtractor.getBrowserCookiesPaths()
|
|
54
54
|
expect(paths).toEqual([])
|
|
55
55
|
})
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
it('includes Network/Cookies variant paths', () => {
|
|
58
58
|
const darwinExtractor = new InstagramTokenExtractor('darwin')
|
|
59
59
|
const paths = darwinExtractor.getBrowserCookiesPaths()
|
|
60
60
|
|
|
@@ -64,7 +64,7 @@ describe('InstagramTokenExtractor', () => {
|
|
|
64
64
|
})
|
|
65
65
|
|
|
66
66
|
describe('getLocalStatePaths', () => {
|
|
67
|
-
|
|
67
|
+
it('returns darwin Local State paths for all browsers', () => {
|
|
68
68
|
const darwinExtractor = new InstagramTokenExtractor('darwin')
|
|
69
69
|
const paths = darwinExtractor.getLocalStatePaths()
|
|
70
70
|
|
|
@@ -74,7 +74,7 @@ describe('InstagramTokenExtractor', () => {
|
|
|
74
74
|
expect(paths).toContain(join(base, 'BraveSoftware', 'Brave-Browser', 'Local State'))
|
|
75
75
|
})
|
|
76
76
|
|
|
77
|
-
|
|
77
|
+
it('returns linux Local State paths for supported browsers', () => {
|
|
78
78
|
const linuxExtractor = new InstagramTokenExtractor('linux')
|
|
79
79
|
const paths = linuxExtractor.getLocalStatePaths()
|
|
80
80
|
|
|
@@ -83,7 +83,7 @@ describe('InstagramTokenExtractor', () => {
|
|
|
83
83
|
expect(paths).toContain(join(base, 'microsoft-edge', 'Local State'))
|
|
84
84
|
})
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
it('returns win32 Local State paths for all browsers', () => {
|
|
87
87
|
const winExtractor = new InstagramTokenExtractor('win32')
|
|
88
88
|
const paths = winExtractor.getLocalStatePaths()
|
|
89
89
|
|
|
@@ -94,7 +94,7 @@ describe('InstagramTokenExtractor', () => {
|
|
|
94
94
|
})
|
|
95
95
|
|
|
96
96
|
describe('getKeychainVariants', () => {
|
|
97
|
-
|
|
97
|
+
it('returns all Chromium browser keychain variants', () => {
|
|
98
98
|
expect(extractor.getKeychainVariants()).toEqual([
|
|
99
99
|
{ service: 'Chrome Safe Storage', account: 'Chrome' },
|
|
100
100
|
{ service: 'Chrome Canary Safe Storage', account: 'Chrome Canary' },
|
|
@@ -108,59 +108,59 @@ describe('InstagramTokenExtractor', () => {
|
|
|
108
108
|
})
|
|
109
109
|
|
|
110
110
|
describe('isEncryptedValue', () => {
|
|
111
|
-
|
|
111
|
+
it('detects v10 encrypted values', () => {
|
|
112
112
|
const encrypted = Buffer.from('v10encrypted_data')
|
|
113
113
|
expect(extractor.isEncryptedValue(encrypted)).toBe(true)
|
|
114
114
|
})
|
|
115
115
|
|
|
116
|
-
|
|
116
|
+
it('detects v11 encrypted values', () => {
|
|
117
117
|
const encrypted = Buffer.from('v11encrypted_data')
|
|
118
118
|
expect(extractor.isEncryptedValue(encrypted)).toBe(true)
|
|
119
119
|
})
|
|
120
120
|
|
|
121
|
-
|
|
121
|
+
it('rejects non-encrypted values', () => {
|
|
122
122
|
const plain = Buffer.from('plain_text')
|
|
123
123
|
expect(extractor.isEncryptedValue(plain)).toBe(false)
|
|
124
124
|
})
|
|
125
125
|
|
|
126
|
-
|
|
126
|
+
it('rejects empty buffers', () => {
|
|
127
127
|
const empty = Buffer.alloc(0)
|
|
128
128
|
expect(extractor.isEncryptedValue(empty)).toBe(false)
|
|
129
129
|
})
|
|
130
130
|
|
|
131
|
-
|
|
131
|
+
it('rejects short buffers under 4 bytes', () => {
|
|
132
132
|
const short = Buffer.from('v1')
|
|
133
133
|
expect(extractor.isEncryptedValue(short)).toBe(false)
|
|
134
134
|
})
|
|
135
135
|
})
|
|
136
136
|
|
|
137
137
|
describe('isValidSessionId', () => {
|
|
138
|
-
|
|
138
|
+
it('accepts session IDs of 20 or more chars', () => {
|
|
139
139
|
const valid = 'abcdefghijklmnopqrstu'
|
|
140
140
|
expect(extractor.isValidSessionId(valid)).toBe(true)
|
|
141
141
|
})
|
|
142
142
|
|
|
143
|
-
|
|
143
|
+
it('accepts long session IDs', () => {
|
|
144
144
|
const valid = 'a'.repeat(100)
|
|
145
145
|
expect(extractor.isValidSessionId(valid)).toBe(true)
|
|
146
146
|
})
|
|
147
147
|
|
|
148
|
-
|
|
148
|
+
it('rejects session IDs shorter than 20 chars', () => {
|
|
149
149
|
expect(extractor.isValidSessionId('short')).toBe(false)
|
|
150
150
|
})
|
|
151
151
|
|
|
152
|
-
|
|
152
|
+
it('rejects empty string', () => {
|
|
153
153
|
expect(extractor.isValidSessionId('')).toBe(false)
|
|
154
154
|
})
|
|
155
155
|
|
|
156
|
-
|
|
156
|
+
it('rejects null and undefined', () => {
|
|
157
157
|
expect(extractor.isValidSessionId(null as unknown as string)).toBe(false)
|
|
158
158
|
expect(extractor.isValidSessionId(undefined as unknown as string)).toBe(false)
|
|
159
159
|
})
|
|
160
160
|
})
|
|
161
161
|
|
|
162
162
|
describe('extract', () => {
|
|
163
|
-
|
|
163
|
+
it('returns empty array when no cookie paths exist', async () => {
|
|
164
164
|
const linuxExtractor = new InstagramTokenExtractor('linux')
|
|
165
165
|
const spy = spyOn(linuxExtractor as any, 'copyAndExtract').mockResolvedValue(null)
|
|
166
166
|
|
|
@@ -170,7 +170,7 @@ describe('InstagramTokenExtractor', () => {
|
|
|
170
170
|
spy.mockRestore()
|
|
171
171
|
})
|
|
172
172
|
|
|
173
|
-
|
|
173
|
+
it('returns extracted cookies when found', async () => {
|
|
174
174
|
const mockCookies = {
|
|
175
175
|
sessionid: 'a'.repeat(25),
|
|
176
176
|
ds_user_id: '12345678',
|
|
@@ -193,7 +193,7 @@ describe('InstagramTokenExtractor', () => {
|
|
|
193
193
|
copyAndExtractSpy.mockRestore()
|
|
194
194
|
})
|
|
195
195
|
|
|
196
|
-
|
|
196
|
+
it('tries next path when first fails', async () => {
|
|
197
197
|
const mockCookies = {
|
|
198
198
|
sessionid: 'a'.repeat(25),
|
|
199
199
|
ds_user_id: '12345678',
|
|
@@ -219,7 +219,7 @@ describe('InstagramTokenExtractor', () => {
|
|
|
219
219
|
copyAndExtractSpy.mockRestore()
|
|
220
220
|
})
|
|
221
221
|
|
|
222
|
-
|
|
222
|
+
it('returns multiple entries when different ds_user_id values found across profiles', async () => {
|
|
223
223
|
const mockCookies1 = {
|
|
224
224
|
sessionid: 'a'.repeat(25),
|
|
225
225
|
ds_user_id: '11111111',
|
|
@@ -251,7 +251,7 @@ describe('InstagramTokenExtractor', () => {
|
|
|
251
251
|
copyAndExtractSpy.mockRestore()
|
|
252
252
|
})
|
|
253
253
|
|
|
254
|
-
|
|
254
|
+
it('deduplicates entries with the same ds_user_id across profiles', async () => {
|
|
255
255
|
const mockCookies = {
|
|
256
256
|
sessionid: 'a'.repeat(25),
|
|
257
257
|
ds_user_id: '12345678',
|
|
@@ -277,7 +277,7 @@ describe('InstagramTokenExtractor', () => {
|
|
|
277
277
|
})
|
|
278
278
|
|
|
279
279
|
describe('copyAndExtract', () => {
|
|
280
|
-
|
|
280
|
+
it('returns null when copy fails due to locked database', async () => {
|
|
281
281
|
const darwinExtractor = new InstagramTokenExtractor('darwin')
|
|
282
282
|
const copyFileSpy = spyOn(darwinExtractor as any, 'copyDatabaseToTemp').mockImplementation(() => {
|
|
283
283
|
throw new Error('EBUSY: resource busy or locked')
|
|
@@ -289,7 +289,7 @@ describe('InstagramTokenExtractor', () => {
|
|
|
289
289
|
copyFileSpy.mockRestore()
|
|
290
290
|
})
|
|
291
291
|
|
|
292
|
-
|
|
292
|
+
it('cleans up temp file after extraction', async () => {
|
|
293
293
|
const darwinExtractor = new InstagramTokenExtractor('darwin')
|
|
294
294
|
const copyFileSpy = spyOn(darwinExtractor as any, 'copyDatabaseToTemp').mockReturnValue('/tmp/test-cookies')
|
|
295
295
|
const extractSpy = spyOn(darwinExtractor as any, 'extractFromSQLite').mockResolvedValue(null)
|
|
@@ -308,7 +308,7 @@ describe('InstagramTokenExtractor', () => {
|
|
|
308
308
|
|
|
309
309
|
describe('decryption', () => {
|
|
310
310
|
describe('decryptAESGCM', () => {
|
|
311
|
-
|
|
311
|
+
it('returns null for data too short for AES-GCM', () => {
|
|
312
312
|
const invalidData = Buffer.from('too_short')
|
|
313
313
|
const key = Buffer.alloc(32, 0)
|
|
314
314
|
|
|
@@ -316,7 +316,7 @@ describe('InstagramTokenExtractor', () => {
|
|
|
316
316
|
expect(result).toBeNull()
|
|
317
317
|
})
|
|
318
318
|
|
|
319
|
-
|
|
319
|
+
it('returns null when AES-GCM decryption fails with wrong key', () => {
|
|
320
320
|
const fakeEncrypted = Buffer.concat([
|
|
321
321
|
Buffer.from('v10'),
|
|
322
322
|
Buffer.alloc(12, 1),
|
|
@@ -331,7 +331,7 @@ describe('InstagramTokenExtractor', () => {
|
|
|
331
331
|
})
|
|
332
332
|
|
|
333
333
|
describe('decryptAESCBC', () => {
|
|
334
|
-
|
|
334
|
+
it('strips 32-byte non-printable integrity hash prefix (Chromium v130+)', () => {
|
|
335
335
|
// given — AES-128-CBC encrypted buffer where decrypted result has a 32-byte non-printable prefix
|
|
336
336
|
const { createCipheriv, pbkdf2Sync } = require('node:crypto')
|
|
337
337
|
const key = pbkdf2Sync('peanuts', 'saltysalt', 1, 16, 'sha1')
|
|
@@ -351,7 +351,7 @@ describe('InstagramTokenExtractor', () => {
|
|
|
351
351
|
expect(result).toBe(actualValue)
|
|
352
352
|
})
|
|
353
353
|
|
|
354
|
-
|
|
354
|
+
it('returns plaintext as-is when no non-printable prefix detected', () => {
|
|
355
355
|
// given — AES-128-CBC encrypted buffer without integrity hash prefix
|
|
356
356
|
const { createCipheriv, pbkdf2Sync } = require('node:crypto')
|
|
357
357
|
const key = pbkdf2Sync('peanuts', 'saltysalt', 1, 16, 'sha1')
|
|
@@ -371,7 +371,7 @@ describe('InstagramTokenExtractor', () => {
|
|
|
371
371
|
})
|
|
372
372
|
|
|
373
373
|
describe('getKeychainPassword on macOS', () => {
|
|
374
|
-
|
|
374
|
+
it('tries multiple keychain variants until one succeeds', () => {
|
|
375
375
|
const darwinExtractor = new InstagramTokenExtractor('darwin')
|
|
376
376
|
const execSyncSpy = spyOn(darwinExtractor as any, 'execSecurityCommand')
|
|
377
377
|
.mockReturnValueOnce(null)
|
|
@@ -385,7 +385,7 @@ describe('InstagramTokenExtractor', () => {
|
|
|
385
385
|
execSyncSpy.mockRestore()
|
|
386
386
|
})
|
|
387
387
|
|
|
388
|
-
|
|
388
|
+
it('returns null when all keychain variants fail', () => {
|
|
389
389
|
const darwinExtractor = new InstagramTokenExtractor('darwin')
|
|
390
390
|
const execSyncSpy = spyOn(darwinExtractor as any, 'execSecurityCommand').mockReturnValue(null)
|
|
391
391
|
|
|
@@ -399,12 +399,12 @@ describe('InstagramTokenExtractor', () => {
|
|
|
399
399
|
})
|
|
400
400
|
|
|
401
401
|
describe('SQLite extraction', () => {
|
|
402
|
-
|
|
402
|
+
it('returns null when database path does not exist', async () => {
|
|
403
403
|
const result = await (extractor as any).extractFromSQLite('/nonexistent/path', '/nonexistent/path')
|
|
404
404
|
expect(result).toBeNull()
|
|
405
405
|
})
|
|
406
406
|
|
|
407
|
-
|
|
407
|
+
it('returns null when extraction throws', async () => {
|
|
408
408
|
const result = await (extractor as any).extractFromSQLite('/dev/null', '/dev/null')
|
|
409
409
|
expect(result).toBeNull()
|
|
410
410
|
})
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, mock,
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, mock, it } from 'bun:test'
|
|
2
2
|
|
|
3
3
|
import { KakaoTalkClient, KakaoTalkError } from './client'
|
|
4
4
|
|
|
@@ -82,19 +82,19 @@ describe('KakaoTalkClient', () => {
|
|
|
82
82
|
})
|
|
83
83
|
|
|
84
84
|
describe('constructor', () => {
|
|
85
|
-
|
|
85
|
+
it('creates client with required params', async () => {
|
|
86
86
|
const client = await new KakaoTalkClient().login({ oauthToken: 'token', userId: 'user1' })
|
|
87
87
|
expect(client).toBeInstanceOf(KakaoTalkClient)
|
|
88
88
|
client.close()
|
|
89
89
|
})
|
|
90
90
|
|
|
91
|
-
|
|
91
|
+
it('defaults deviceUuid when not provided', async () => {
|
|
92
92
|
const client = await new KakaoTalkClient().login({ oauthToken: 'token', userId: 'user1' })
|
|
93
93
|
expect(client).toBeInstanceOf(KakaoTalkClient)
|
|
94
94
|
client.close()
|
|
95
95
|
})
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
it('throws KakaoTalkError with code missing_token when oauthToken is empty', async () => {
|
|
98
98
|
await expect(new KakaoTalkClient().login({ oauthToken: '', userId: 'user1' })).rejects.toThrow(KakaoTalkError)
|
|
99
99
|
try {
|
|
100
100
|
await new KakaoTalkClient().login({ oauthToken: '', userId: 'user1' })
|
|
@@ -103,7 +103,7 @@ describe('KakaoTalkClient', () => {
|
|
|
103
103
|
}
|
|
104
104
|
})
|
|
105
105
|
|
|
106
|
-
|
|
106
|
+
it('throws KakaoTalkError with code missing_user_id when userId is empty', async () => {
|
|
107
107
|
await expect(new KakaoTalkClient().login({ oauthToken: 'token', userId: '' })).rejects.toThrow(KakaoTalkError)
|
|
108
108
|
try {
|
|
109
109
|
await new KakaoTalkClient().login({ oauthToken: 'token', userId: '' })
|
|
@@ -114,7 +114,7 @@ describe('KakaoTalkClient', () => {
|
|
|
114
114
|
})
|
|
115
115
|
|
|
116
116
|
describe('getChats', () => {
|
|
117
|
-
|
|
117
|
+
it('returns formatted chats from login snapshot', async () => {
|
|
118
118
|
const client = await new KakaoTalkClient().login({ oauthToken: 'token', userId: 'user1', deviceUuid: 'device1' })
|
|
119
119
|
const chats = await client.getChats()
|
|
120
120
|
|
|
@@ -133,7 +133,7 @@ describe('KakaoTalkClient', () => {
|
|
|
133
133
|
client.close()
|
|
134
134
|
})
|
|
135
135
|
|
|
136
|
-
|
|
136
|
+
it('sorts chats by recency (o field descending)', async () => {
|
|
137
137
|
const client = await new KakaoTalkClient().login({ oauthToken: 'token', userId: 'user1', deviceUuid: 'device1' })
|
|
138
138
|
const chats = await client.getChats()
|
|
139
139
|
|
|
@@ -144,7 +144,7 @@ describe('KakaoTalkClient', () => {
|
|
|
144
144
|
client.close()
|
|
145
145
|
})
|
|
146
146
|
|
|
147
|
-
|
|
147
|
+
it('filters by search term', async () => {
|
|
148
148
|
const client = await new KakaoTalkClient().login({ oauthToken: 'token', userId: 'user1', deviceUuid: 'device1' })
|
|
149
149
|
const chats = await client.getChats({ search: 'alice' })
|
|
150
150
|
|
|
@@ -154,7 +154,7 @@ describe('KakaoTalkClient', () => {
|
|
|
154
154
|
client.close()
|
|
155
155
|
})
|
|
156
156
|
|
|
157
|
-
|
|
157
|
+
it('falls back to LCHATLIST when login snapshot is empty (new device)', async () => {
|
|
158
158
|
// given — LOGINLIST returns empty chatDatas with eof:true (new device scenario)
|
|
159
159
|
const emptyLoginResult = {
|
|
160
160
|
chatDatas: [],
|
|
@@ -207,7 +207,7 @@ describe('KakaoTalkClient', () => {
|
|
|
207
207
|
client.close()
|
|
208
208
|
})
|
|
209
209
|
|
|
210
|
-
|
|
210
|
+
it('does not call LCHATLIST when login snapshot has chats', async () => {
|
|
211
211
|
const client = await new KakaoTalkClient().login({ oauthToken: 'token', userId: 'user1', deviceUuid: 'device1' })
|
|
212
212
|
await client.getChats()
|
|
213
213
|
|
|
@@ -216,7 +216,7 @@ describe('KakaoTalkClient', () => {
|
|
|
216
216
|
client.close()
|
|
217
217
|
})
|
|
218
218
|
|
|
219
|
-
|
|
219
|
+
it('paginates when all=true and not eof', async () => {
|
|
220
220
|
const loginResult = {
|
|
221
221
|
...DEFAULT_LOGIN_RESULT,
|
|
222
222
|
eof: false,
|
|
@@ -252,7 +252,7 @@ describe('KakaoTalkClient', () => {
|
|
|
252
252
|
client.close()
|
|
253
253
|
})
|
|
254
254
|
|
|
255
|
-
|
|
255
|
+
it('deduplicates chats by id', async () => {
|
|
256
256
|
const loginResult = {
|
|
257
257
|
...DEFAULT_LOGIN_RESULT,
|
|
258
258
|
eof: false,
|
|
@@ -287,7 +287,7 @@ describe('KakaoTalkClient', () => {
|
|
|
287
287
|
client.close()
|
|
288
288
|
})
|
|
289
289
|
|
|
290
|
-
|
|
290
|
+
it('wraps errors as KakaoTalkError', async () => {
|
|
291
291
|
mockLogin.mockRejectedValue(new Error('Connection refused'))
|
|
292
292
|
|
|
293
293
|
const client = await new KakaoTalkClient().login({ oauthToken: 'token', userId: 'user1', deviceUuid: 'device1' })
|
|
@@ -304,7 +304,7 @@ describe('KakaoTalkClient', () => {
|
|
|
304
304
|
client.close()
|
|
305
305
|
})
|
|
306
306
|
|
|
307
|
-
|
|
307
|
+
it('wraps getChatList failure as KakaoTalkError with code get_chats_failed', async () => {
|
|
308
308
|
const loginResult = { ...DEFAULT_LOGIN_RESULT, eof: false }
|
|
309
309
|
mockLogin.mockResolvedValue(loginResult)
|
|
310
310
|
mockGetChatList.mockRejectedValue(new Error('Network error'))
|
|
@@ -323,7 +323,7 @@ describe('KakaoTalkClient', () => {
|
|
|
323
323
|
})
|
|
324
324
|
|
|
325
325
|
describe('getMessages', () => {
|
|
326
|
-
|
|
326
|
+
it('returns formatted messages', async () => {
|
|
327
327
|
mockGetChatLogs.mockResolvedValueOnce({
|
|
328
328
|
body: {
|
|
329
329
|
status: 0,
|
|
@@ -357,7 +357,7 @@ describe('KakaoTalkClient', () => {
|
|
|
357
357
|
client.close()
|
|
358
358
|
})
|
|
359
359
|
|
|
360
|
-
|
|
360
|
+
it('respects count option', async () => {
|
|
361
361
|
const logs = Array.from({ length: 50 }, (_, i) => ({
|
|
362
362
|
logId: makeLong(i + 1),
|
|
363
363
|
chatId: 100,
|
|
@@ -382,7 +382,7 @@ describe('KakaoTalkClient', () => {
|
|
|
382
382
|
client.close()
|
|
383
383
|
})
|
|
384
384
|
|
|
385
|
-
|
|
385
|
+
it('sorts messages by sent_at ascending', async () => {
|
|
386
386
|
mockGetChatLogs.mockResolvedValueOnce({
|
|
387
387
|
body: {
|
|
388
388
|
status: 0,
|
|
@@ -405,7 +405,7 @@ describe('KakaoTalkClient', () => {
|
|
|
405
405
|
})
|
|
406
406
|
|
|
407
407
|
describe('sendMessage', () => {
|
|
408
|
-
|
|
408
|
+
it('returns send result on success', async () => {
|
|
409
409
|
mockSendMessage.mockResolvedValueOnce({
|
|
410
410
|
statusCode: 0,
|
|
411
411
|
body: { logId: makeLong(42), sendAt: 1700000099 },
|
|
@@ -425,7 +425,7 @@ describe('KakaoTalkClient', () => {
|
|
|
425
425
|
client.close()
|
|
426
426
|
})
|
|
427
427
|
|
|
428
|
-
|
|
428
|
+
it('reports failure when statusCode is non-zero', async () => {
|
|
429
429
|
mockSendMessage.mockResolvedValueOnce({
|
|
430
430
|
statusCode: -500,
|
|
431
431
|
body: { logId: makeLong(0), sendAt: 0 },
|
|
@@ -440,7 +440,7 @@ describe('KakaoTalkClient', () => {
|
|
|
440
440
|
client.close()
|
|
441
441
|
})
|
|
442
442
|
|
|
443
|
-
|
|
443
|
+
it('wraps transport errors as KakaoTalkError', async () => {
|
|
444
444
|
mockSendMessage.mockRejectedValue(new Error('Socket closed'))
|
|
445
445
|
|
|
446
446
|
const client = await new KakaoTalkClient().login({ oauthToken: 'token', userId: 'user1', deviceUuid: 'device1' })
|
|
@@ -476,7 +476,7 @@ describe('KakaoTalkClient', () => {
|
|
|
476
476
|
})
|
|
477
477
|
}
|
|
478
478
|
|
|
479
|
-
|
|
479
|
+
it('returns profile data on success', async () => {
|
|
480
480
|
mockFetch
|
|
481
481
|
.mockResolvedValueOnce(
|
|
482
482
|
makeJsonResponse({
|
|
@@ -507,7 +507,7 @@ describe('KakaoTalkClient', () => {
|
|
|
507
507
|
client.close()
|
|
508
508
|
})
|
|
509
509
|
|
|
510
|
-
|
|
510
|
+
it('throws not_authenticated when not logged in', async () => {
|
|
511
511
|
const client = new KakaoTalkClient()
|
|
512
512
|
try {
|
|
513
513
|
await client.getProfile()
|
|
@@ -518,7 +518,7 @@ describe('KakaoTalkClient', () => {
|
|
|
518
518
|
}
|
|
519
519
|
})
|
|
520
520
|
|
|
521
|
-
|
|
521
|
+
it('throws profile_request_failed when profile HTTP request fails', async () => {
|
|
522
522
|
mockFetch
|
|
523
523
|
.mockResolvedValueOnce(makeJsonResponse({}, 401))
|
|
524
524
|
.mockResolvedValueOnce(makeJsonResponse({ accountDisplayId: null }))
|
|
@@ -539,7 +539,7 @@ describe('KakaoTalkClient', () => {
|
|
|
539
539
|
client.close()
|
|
540
540
|
})
|
|
541
541
|
|
|
542
|
-
|
|
542
|
+
it('returns null account_display_id when more_settings request fails', async () => {
|
|
543
543
|
mockFetch
|
|
544
544
|
.mockResolvedValueOnce(
|
|
545
545
|
makeJsonResponse({
|
|
@@ -569,20 +569,20 @@ describe('KakaoTalkClient', () => {
|
|
|
569
569
|
})
|
|
570
570
|
|
|
571
571
|
describe('session lifecycle', () => {
|
|
572
|
-
|
|
572
|
+
it('lazy init: does not call login until first method call', async () => {
|
|
573
573
|
const client = await new KakaoTalkClient().login({ oauthToken: 'token', userId: 'user1', deviceUuid: 'device1' })
|
|
574
574
|
expect(mockLogin).not.toHaveBeenCalled()
|
|
575
575
|
client.close()
|
|
576
576
|
})
|
|
577
577
|
|
|
578
|
-
|
|
578
|
+
it('calls login on first method call', async () => {
|
|
579
579
|
const client = await new KakaoTalkClient().login({ oauthToken: 'token', userId: 'user1', deviceUuid: 'device1' })
|
|
580
580
|
await client.getChats()
|
|
581
581
|
expect(mockLogin).toHaveBeenCalledTimes(1)
|
|
582
582
|
client.close()
|
|
583
583
|
})
|
|
584
584
|
|
|
585
|
-
|
|
585
|
+
it('reuses session across multiple calls', async () => {
|
|
586
586
|
mockGetChatLogs.mockResolvedValue({
|
|
587
587
|
body: { status: 0, chatLogs: [], eof: true },
|
|
588
588
|
})
|
|
@@ -596,7 +596,7 @@ describe('KakaoTalkClient', () => {
|
|
|
596
596
|
client.close()
|
|
597
597
|
})
|
|
598
598
|
|
|
599
|
-
|
|
599
|
+
it('concurrent calls share a single login', async () => {
|
|
600
600
|
// Make login take some time
|
|
601
601
|
mockLogin.mockImplementation(() => new Promise((resolve) => setTimeout(() => resolve(DEFAULT_LOGIN_RESULT), 50)))
|
|
602
602
|
mockGetChatLogs.mockResolvedValue({
|
|
@@ -611,7 +611,7 @@ describe('KakaoTalkClient', () => {
|
|
|
611
611
|
client.close()
|
|
612
612
|
})
|
|
613
613
|
|
|
614
|
-
|
|
614
|
+
it('retries login after failure', async () => {
|
|
615
615
|
mockLogin.mockRejectedValueOnce(new Error('Connection refused')).mockResolvedValueOnce(DEFAULT_LOGIN_RESULT)
|
|
616
616
|
|
|
617
617
|
const client = await new KakaoTalkClient().login({ oauthToken: 'token', userId: 'user1', deviceUuid: 'device1' })
|
|
@@ -627,7 +627,7 @@ describe('KakaoTalkClient', () => {
|
|
|
627
627
|
client.close()
|
|
628
628
|
})
|
|
629
629
|
|
|
630
|
-
|
|
630
|
+
it('close cleans up session state', async () => {
|
|
631
631
|
const client = await new KakaoTalkClient().login({ oauthToken: 'token', userId: 'user1', deviceUuid: 'device1' })
|
|
632
632
|
await client.getChats()
|
|
633
633
|
|
|
@@ -635,7 +635,7 @@ describe('KakaoTalkClient', () => {
|
|
|
635
635
|
expect(mockClose).toHaveBeenCalledTimes(1)
|
|
636
636
|
})
|
|
637
637
|
|
|
638
|
-
|
|
638
|
+
it('methods throw client_closed after close', async () => {
|
|
639
639
|
const client = await new KakaoTalkClient().login({ oauthToken: 'token', userId: 'user1', deviceUuid: 'device1' })
|
|
640
640
|
await client.getChats()
|
|
641
641
|
client.close()
|
|
@@ -649,13 +649,13 @@ describe('KakaoTalkClient', () => {
|
|
|
649
649
|
}
|
|
650
650
|
})
|
|
651
651
|
|
|
652
|
-
|
|
652
|
+
it('close is idempotent', async () => {
|
|
653
653
|
const client = await new KakaoTalkClient().login({ oauthToken: 'token', userId: 'user1', deviceUuid: 'device1' })
|
|
654
654
|
client.close()
|
|
655
655
|
expect(() => client.close()).not.toThrow()
|
|
656
656
|
})
|
|
657
657
|
|
|
658
|
-
|
|
658
|
+
it('login failure closes the session to prevent socket leak', async () => {
|
|
659
659
|
mockLogin.mockRejectedValue(new Error('Auth failed'))
|
|
660
660
|
|
|
661
661
|
const client = await new KakaoTalkClient().login({ oauthToken: 'token', userId: 'user1', deviceUuid: 'device1' })
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, mock, spyOn,
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, mock, spyOn, it } from 'bun:test'
|
|
2
2
|
|
|
3
3
|
const originalConsoleLog = console.log
|
|
4
4
|
|
|
@@ -67,7 +67,7 @@ describe('auth commands', () => {
|
|
|
67
67
|
})
|
|
68
68
|
|
|
69
69
|
describe('list', () => {
|
|
70
|
-
|
|
70
|
+
it('outputs empty array when no accounts', async () => {
|
|
71
71
|
mockListAccounts.mockImplementation(() => Promise.resolve([]))
|
|
72
72
|
|
|
73
73
|
await authCommand.parseAsync(['list'], { from: 'user' })
|
|
@@ -76,7 +76,7 @@ describe('auth commands', () => {
|
|
|
76
76
|
expect(output).toEqual([])
|
|
77
77
|
})
|
|
78
78
|
|
|
79
|
-
|
|
79
|
+
it('outputs accounts list with is_current flag', async () => {
|
|
80
80
|
mockListAccounts.mockImplementation(() =>
|
|
81
81
|
Promise.resolve([
|
|
82
82
|
{
|
|
@@ -116,7 +116,7 @@ describe('auth commands', () => {
|
|
|
116
116
|
})
|
|
117
117
|
|
|
118
118
|
describe('use', () => {
|
|
119
|
-
|
|
119
|
+
it('switches to specified account', async () => {
|
|
120
120
|
mockGetAccount.mockImplementation(() =>
|
|
121
121
|
Promise.resolve({
|
|
122
122
|
account_id: 'user-1',
|
|
@@ -138,7 +138,7 @@ describe('auth commands', () => {
|
|
|
138
138
|
expect(output.account_id).toBe('user-1')
|
|
139
139
|
})
|
|
140
140
|
|
|
141
|
-
|
|
141
|
+
it('outputs error and exits when account not found', async () => {
|
|
142
142
|
mockGetAccount.mockImplementation(() => Promise.resolve(null))
|
|
143
143
|
|
|
144
144
|
await expect(authCommand.parseAsync(['use', 'nonexistent'], { from: 'user' })).rejects.toThrow('process.exit')
|
|
@@ -150,7 +150,7 @@ describe('auth commands', () => {
|
|
|
150
150
|
})
|
|
151
151
|
|
|
152
152
|
describe('status', () => {
|
|
153
|
-
|
|
153
|
+
it('outputs error and exits when no account configured', async () => {
|
|
154
154
|
mockGetAccount.mockImplementation(() => Promise.resolve(null))
|
|
155
155
|
|
|
156
156
|
await expect(authCommand.parseAsync(['status'], { from: 'user' })).rejects.toThrow('process.exit')
|
|
@@ -160,7 +160,7 @@ describe('auth commands', () => {
|
|
|
160
160
|
expect(output.error).toBeDefined()
|
|
161
161
|
})
|
|
162
162
|
|
|
163
|
-
|
|
163
|
+
it('outputs account info when account exists', async () => {
|
|
164
164
|
mockGetAccount.mockImplementation(() =>
|
|
165
165
|
Promise.resolve({
|
|
166
166
|
account_id: 'user-1',
|
|
@@ -184,7 +184,7 @@ describe('auth commands', () => {
|
|
|
184
184
|
expect(output.has_device_uuid).toBe(true)
|
|
185
185
|
})
|
|
186
186
|
|
|
187
|
-
|
|
187
|
+
it('outputs status for specific --account', async () => {
|
|
188
188
|
mockGetAccount.mockImplementation((id?: string) => {
|
|
189
189
|
if (id === 'user-2') {
|
|
190
190
|
return Promise.resolve({
|
|
@@ -210,7 +210,7 @@ describe('auth commands', () => {
|
|
|
210
210
|
})
|
|
211
211
|
|
|
212
212
|
describe('logout', () => {
|
|
213
|
-
|
|
213
|
+
it('removes current account and outputs success', async () => {
|
|
214
214
|
mockLoad.mockImplementation(() =>
|
|
215
215
|
Promise.resolve({
|
|
216
216
|
current_account: 'user-1',
|
|
@@ -237,7 +237,7 @@ describe('auth commands', () => {
|
|
|
237
237
|
expect(output.removed).toBe('user-1')
|
|
238
238
|
})
|
|
239
239
|
|
|
240
|
-
|
|
240
|
+
it('removes specific account with --account flag', async () => {
|
|
241
241
|
mockLoad.mockImplementation(() =>
|
|
242
242
|
Promise.resolve({
|
|
243
243
|
current_account: 'user-1',
|
|
@@ -274,7 +274,7 @@ describe('auth commands', () => {
|
|
|
274
274
|
expect(output.removed).toBe('user-2')
|
|
275
275
|
})
|
|
276
276
|
|
|
277
|
-
|
|
277
|
+
it('outputs error and exits when no account configured', async () => {
|
|
278
278
|
mockLoad.mockImplementation(() => Promise.resolve({ current_account: null, accounts: {} }))
|
|
279
279
|
|
|
280
280
|
await expect(authCommand.parseAsync(['logout'], { from: 'user' })).rejects.toThrow('process.exit')
|