Agent Skills: SalesLoft Local Dev Loop

|

UncategorizedID: jeremylongshore/claude-code-plugins-plus-skills/salesloft-local-dev-loop

Install this agent skill to your local

pnpm dlx add-skill https://github.com/jeremylongshore/claude-code-plugins-plus-skills/tree/HEAD/plugins/saas-packs/salesloft-pack/skills/salesloft-local-dev-loop

Skill Files

Browse the full folder contents for salesloft-local-dev-loop.

Download Skill

Loading file tree…

plugins/saas-packs/salesloft-pack/skills/salesloft-local-dev-loop/SKILL.md

Skill Metadata

Name
salesloft-local-dev-loop
Description
|

SalesLoft Local Dev Loop

Overview

Set up a local development workflow for SalesLoft integrations with API mocking, environment separation, and fast iteration. SalesLoft has no official sandbox -- use test data tagging and request recording for safe development.

Prerequisites

  • Completed salesloft-install-auth setup
  • Node.js 18+ with Vitest
  • Separate SalesLoft test workspace (recommended)

Instructions

Step 1: Create API Client Wrapper

// src/salesloft/client.ts
import axios, { AxiosInstance } from 'axios';

export function createClient(token?: string): AxiosInstance {
  return axios.create({
    baseURL: process.env.SALESLOFT_BASE_URL || 'https://api.salesloft.com/v2',
    headers: {
      Authorization: `Bearer ${token || process.env.SALESLOFT_API_KEY}`,
      'Content-Type': 'application/json',
    },
  });
}

Step 2: Create Fixtures from Real API Shape

// tests/fixtures/salesloft.ts
export const mockPerson = {
  data: {
    id: 1001, display_name: 'Test User', email_address: 'test@example.com',
    first_name: 'Test', last_name: 'User', title: 'Engineer',
    phone: '+1-555-0100', company_name: 'Acme Corp',
    tags: ['dev_test'], created_at: '2025-01-15T10:00:00Z',
  },
};

export const mockPeopleList = {
  data: [mockPerson.data],
  metadata: { paging: { per_page: 25, current_page: 1, total_pages: 1, total_count: 1 } },
};

export const mockCadence = {
  data: {
    id: 500, name: 'Test Outbound', team_cadence: false,
    current_state: 'active', added_stage: 'prospecting',
    cadence_framework_id: null, counts: { people_count: 10 },
  },
};

export const mockActivity = {
  data: {
    id: 2001, action_type: 'email', person_id: 1001,
    cadence_id: 500, step_id: 100, due_at: '2025-02-01T09:00:00Z',
  },
};

Step 3: Write Tests Against Real API Shape

// tests/salesloft.test.ts
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { createClient } from '../src/salesloft/client';
import { mockPeopleList, mockCadence } from './fixtures/salesloft';

vi.mock('axios', () => ({
  default: { create: vi.fn(() => ({
    get: vi.fn(), post: vi.fn(), put: vi.fn(), delete: vi.fn(),
  }))},
}));

describe('SalesLoft People API', () => {
  it('lists people with pagination metadata', async () => {
    const client = createClient('test-token');
    vi.mocked(client.get).mockResolvedValue({ data: mockPeopleList });

    const { data } = await client.get('/people.json', { params: { per_page: 25 } });
    expect(data.metadata.paging.total_count).toBe(1);
    expect(data.data[0].email_address).toBe('test@example.com');
  });

  it('filters people by cadence membership', async () => {
    const client = createClient('test-token');
    vi.mocked(client.get).mockResolvedValue({ data: mockPeopleList });

    const { data } = await client.get('/people.json', {
      params: { cadence_id: 500, per_page: 25 },
    });
    expect(data.data.length).toBeGreaterThan(0);
  });
});

Step 4: Environment Separation

# .env.development
SALESLOFT_BASE_URL=https://api.salesloft.com/v2
SALESLOFT_API_KEY=dev-token-here
SALESLOFT_TAG_PREFIX=dev_test_

# .env.test
SALESLOFT_BASE_URL=http://localhost:3001/mock
SALESLOFT_API_KEY=mock-token
{
  "scripts": {
    "dev": "tsx watch src/index.ts",
    "test": "vitest",
    "test:integration": "dotenv -e .env.development vitest run --config vitest.integration.ts"
  }
}

Output

 PASS  tests/salesloft.test.ts
  SalesLoft People API
    ✓ lists people with pagination metadata (2ms)
    ✓ filters people by cadence membership (1ms)

Error Handling

| Error | Cause | Solution | |-------|-------|----------| | ECONNREFUSED | Mock server not running | Use vi.mock instead of live mock server | | 401 in integration tests | Token expired | Refresh dev token from SalesLoft portal | | Stale mock data | API response shape changed | Record fresh responses with interceptor |

Resources

Next Steps

Proceed to salesloft-sdk-patterns for production client patterns.