Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions src/platforms/slack/commands/auth.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { afterAll, beforeEach, describe, expect, mock, test } from 'bun:test'
import { mkdirSync, rmSync } from 'node:fs'
import { homedir } from 'node:os'
import { join } from 'node:path'
import { getExtractionErrorMessage } from '@/platforms/slack/commands/auth'
import { CredentialManager } from '@/platforms/slack/credential-manager'
import { type ExtractedWorkspace, TokenExtractor } from '@/platforms/slack/token-extractor'

Expand Down Expand Up @@ -351,6 +352,28 @@ describe('Output Formatting', () => {
})
})

describe('getExtractionErrorMessage', () => {
test('returns cookie failure message for missing_cookie', () => {
expect(getExtractionErrorMessage(['missing_cookie'])).toContain('Cookie extraction failed')
})

test('returns session expired message for invalid_auth', () => {
expect(getExtractionErrorMessage(['invalid_auth'])).toContain('session has expired')
})

test('prioritizes missing_cookie over invalid_auth', () => {
expect(getExtractionErrorMessage(['invalid_auth', 'missing_cookie'])).toContain('Cookie extraction failed')
})

test('returns generic message for unknown error codes', () => {
expect(getExtractionErrorMessage(['unknown_error'])).toContain('Extracted tokens are invalid')
})

test('returns generic message for empty failure list', () => {
expect(getExtractionErrorMessage([])).toContain('Extracted tokens are invalid')
})
})

describe('Error Handling', () => {
beforeEach(() => {
rmSync(testSlackDir, { recursive: true, force: true })
Expand Down
21 changes: 19 additions & 2 deletions src/platforms/slack/commands/auth.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Command } from 'commander'
import { handleError } from '@/shared/utils/error-handler'
import { formatOutput } from '@/shared/utils/output'
import { SlackClient } from '../client'
import { SlackClient, SlackError } from '../client'
import { CredentialManager } from '../credential-manager'
import { TokenExtractor } from '../token-extractor'

Expand Down Expand Up @@ -58,6 +58,7 @@ async function extractAction(options: { pretty?: boolean; debug?: boolean }): Pr
const config = await credManager.load()

const validWorkspaces = []
const failureReasons: string[] = []
for (const ws of workspaces) {
if (options.debug) {
console.error(`[debug] Testing credentials for ${ws.workspace_id}...`)
Expand All @@ -74,18 +75,24 @@ async function extractAction(options: { pretty?: boolean; debug?: boolean }): Pr
console.error(`[debug] ✓ Valid: ${authInfo.team} (${authInfo.user})`)
}
} catch (error) {
const code = error instanceof SlackError ? error.code : undefined
if (code && !failureReasons.includes(code)) {
failureReasons.push(code)
}
if (options.debug) {
console.error(`[debug] ✗ Invalid: ${(error as Error).message}`)
}
}
}

if (validWorkspaces.length === 0) {
const errorMessage = getExtractionErrorMessage(failureReasons)
console.log(
formatOutput(
{
error: 'Extracted tokens are invalid. Make sure you are logged into the Slack desktop app.',
error: errorMessage,
extracted_count: workspaces.length,
hint: options.debug ? undefined : 'Run with --debug for more details.',
},
options.pretty,
),
Expand Down Expand Up @@ -171,6 +178,16 @@ async function statusAction(options: { pretty?: boolean }): Promise<void> {
}
}

export function getExtractionErrorMessage(failureReasons: string[]): string {
if (failureReasons.includes('missing_cookie')) {
return 'Cookie extraction failed. Make sure the Slack desktop app is installed and grant Keychain access when prompted.'
}
if (failureReasons.includes('invalid_auth')) {
return 'Slack session has expired. Sign into the Slack desktop app, wait a few seconds, then re-run this command.'
}
return 'Extracted tokens are invalid. Make sure you are logged into the Slack desktop app.'
}

export const authCommand = new Command('auth')
.description('Authentication commands')
.addCommand(
Expand Down