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
10 changes: 5 additions & 5 deletions packages/cli/src/commands/wrapper/postinstall-wrapper.mts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import fs, { existsSync } from 'node:fs'
import fs from 'node:fs'

import { debug, debugDir } from '@socketsecurity/lib/debug'
import { getDefaultLogger } from '@socketsecurity/lib/logger'
Expand All @@ -16,8 +16,8 @@ export async function postinstallWrapper() {
const bashRcPath = getBashRcPath()
const zshRcPath = getZshRcPath()
const socketWrapperEnabled =
(existsSync(bashRcPath) && checkSocketWrapperSetup(bashRcPath)) ||
(existsSync(zshRcPath) && checkSocketWrapperSetup(zshRcPath))
(fs.existsSync(bashRcPath) && checkSocketWrapperSetup(bashRcPath)) ||
(fs.existsSync(zshRcPath) && checkSocketWrapperSetup(zshRcPath))

if (!socketWrapperEnabled) {
await setupSocketWrapper(
Expand Down Expand Up @@ -78,10 +78,10 @@ async function setupSocketWrapper(query: string): Promise<void> {
const bashRcPath = getBashRcPath()
const zshRcPath = getZshRcPath()
try {
if (existsSync(bashRcPath)) {
if (fs.existsSync(bashRcPath)) {
await addSocketWrapper(bashRcPath)
}
if (existsSync(zshRcPath)) {
if (fs.existsSync(zshRcPath)) {
await addSocketWrapper(zshRcPath)
}
} catch (e) {
Expand Down
6 changes: 3 additions & 3 deletions packages/cli/src/commands/wrapper/remove-socket-wrapper.mts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { readFileSync, writeFileSync } from 'node:fs'
import fs from 'node:fs'

import { getDefaultLogger } from '@socketsecurity/lib/logger'
const logger = getDefaultLogger()

export function removeSocketWrapper(filepath: string): void {
let content: string | undefined
try {
content = readFileSync(filepath, 'utf8')
content = fs.readFileSync(filepath, 'utf8')
} catch (e) {
logger.fail(`There was an error removing the alias${e ? ':' : '.'}`)
if (e) {
Expand All @@ -22,7 +22,7 @@ export function removeSocketWrapper(filepath: string): void {
)
const updatedContent = linesWithoutSocketAlias.join('\n')
try {
writeFileSync(filepath, updatedContent, 'utf8')
fs.writeFileSync(filepath, updatedContent, 'utf8')
} catch (e) {
if (e) {
logger.error(e)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,12 @@
/**
* Unit tests for checkSocketWrapperSetup.
*
* Purpose:
* Tests checking Socket wrapper installation status. Validates detection of installed wrappers across package managers.
*
* Test Coverage:
* - Core functionality validation
* - Edge case handling
* - Error scenarios
* - Input validation
*
* Testing Approach:
* Comprehensive unit testing of module functionality with mocked dependencies
* where appropriate.
*
* Related Files:
* - src/checkSocketWrapperSetup.mts (implementation)
* @fileoverview Unit tests for checkSocketWrapperSetup.
*/

import fs from 'node:fs'

import { beforeEach, describe, expect, it, vi } from 'vitest'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'

import { checkSocketWrapperSetup } from '../../../../src/commands/../../../../src/commands/wrapper/check-socket-wrapper-setup.mts'

// Mock the dependencies.
vi.mock('node:fs')
import { checkSocketWrapperSetup } from '../../../../src/commands/wrapper/check-socket-wrapper-setup.mts'

const mockLogger = vi.hoisted(() => ({
fail: vi.fn(),
Expand All @@ -42,13 +23,19 @@ vi.mock('@socketsecurity/lib/logger', () => ({
}))

describe('checkSocketWrapperSetup', () => {
let readFileSyncSpy: ReturnType<typeof vi.spyOn>

beforeEach(() => {
vi.clearAllMocks()
readFileSyncSpy = vi.spyOn(fs, 'readFileSync')
})

afterEach(() => {
readFileSyncSpy.mockRestore()
})

it('detects npm alias in file', () => {
const mockReadFileSync = vi.mocked(fs.readFileSync) as any
mockReadFileSync.mockReturnValue('alias npm="socket npm"\nother content')
readFileSyncSpy.mockReturnValue('alias npm="socket npm"\nother content')

const result = checkSocketWrapperSetup('/home/user/.bashrc')

Expand All @@ -57,17 +44,15 @@ describe('checkSocketWrapperSetup', () => {
})

it('detects npx alias in file', () => {
const mockReadFileSync = vi.mocked(fs.readFileSync) as any
mockReadFileSync.mockReturnValue('alias npx="socket npx"\nother content')
readFileSyncSpy.mockReturnValue('alias npx="socket npx"\nother content')

const result = checkSocketWrapperSetup('/home/user/.bashrc')

expect(result).toBe(true)
})

it('detects both aliases in file', () => {
const mockReadFileSync = vi.mocked(fs.readFileSync) as any
mockReadFileSync.mockReturnValue(
readFileSyncSpy.mockReturnValue(
'alias npm="socket npm"\nalias npx="socket npx"\nother content',
)

Expand All @@ -77,39 +62,36 @@ describe('checkSocketWrapperSetup', () => {
})

it('returns false when no aliases found', () => {
const mockReadFileSync = vi.mocked(fs.readFileSync) as any
mockReadFileSync.mockReturnValue('some other content\nno aliases here')
readFileSyncSpy.mockReturnValue('some other content\nno aliases here')

const result = checkSocketWrapperSetup('/home/user/.bashrc')

expect(result).toBe(false)
})

it('returns false for empty file', () => {
const mockReadFileSync = vi.mocked(fs.readFileSync) as any
mockReadFileSync.mockReturnValue('')
readFileSyncSpy.mockReturnValue('')

const result = checkSocketWrapperSetup('/home/user/.bashrc')

expect(result).toBe(false)
})

it('logs instructions when wrapper is set up', async () => {
await import('@socketsecurity/lib/logger')
const mockReadFileSync = vi.mocked(fs.readFileSync) as any
mockReadFileSync.mockReturnValue('alias npm="socket npm"')
it('logs instructions when wrapper is set up', () => {
readFileSyncSpy.mockReturnValue('alias npm="socket npm"')

checkSocketWrapperSetup('/home/user/.bashrc')

expect(mockLogger.log).toHaveBeenCalledWith(
'The Socket npm/npx wrapper is set up in your bash profile (/home/user/.bashrc).',
)
expect(mockLogger.log).toHaveBeenCalledWith(' source /home/user/.bashrc')
expect(mockLogger.log).toHaveBeenCalledWith(
' source /home/user/.bashrc',
)
})

it('ignores partial alias matches', () => {
const mockReadFileSync = vi.mocked(fs.readFileSync) as any
mockReadFileSync.mockReturnValue(
readFileSyncSpy.mockReturnValue(
'alias npm="other-tool npm"\nalias npx="other-tool npx"',
)

Expand All @@ -119,8 +101,7 @@ describe('checkSocketWrapperSetup', () => {
})

it('handles multiline file with aliases mixed in', () => {
const mockReadFileSync = vi.mocked(fs.readFileSync) as any
mockReadFileSync.mockReturnValue(
readFileSyncSpy.mockReturnValue(
`#!/bin/bash
# User bashrc
export PATH=$PATH:/usr/local/bin
Expand All @@ -135,26 +116,20 @@ export NODE_ENV=development`,
})

it('is case-sensitive for alias detection', () => {
const mockReadFileSync = vi.mocked(fs.readFileSync) as any
mockReadFileSync.mockReturnValue('ALIAS NPM="SOCKET NPM"')
readFileSyncSpy.mockReturnValue('ALIAS NPM="SOCKET NPM"')

const result = checkSocketWrapperSetup('/home/user/.bashrc')

expect(result).toBe(false)
})

it('handles files with Windows line endings', () => {
const mockReadFileSync = vi.mocked(fs.readFileSync) as any
// When splitting on \n, Windows line endings leave \r at the end of lines,
// so 'alias npm="socket npm"\r' !== 'alias npm="socket npm"'.
// The function doesn't handle Windows line endings properly.
mockReadFileSync.mockReturnValue(
readFileSyncSpy.mockReturnValue(
'line1\r\nalias npm="socket npm"\r\nalias npx="socket npx"\r\n',
)

const result = checkSocketWrapperSetup('/home/user/.bashrc')

// The function splits by \n, leaving \r at the end, so exact match fails.
expect(result).toBe(false)
})
})
Loading
Loading