npm package: @smartesting/lynqa-sdk
Description: TypeScript REST client for the Lynqa API by Smartesting.
Author: Smartesting
Latest version: 1.1.4

# Lynqa SDK

Official TypeScript SDK for the [Lynqa](https://api.lynqa.smartesting.com) API
by [Smartesting](https://smartesting.com). Provides a typed REST client and all the models needed to interact with the
Lynqa platform programmatically.

## Installation

```bash
npm install @smartesting/lynqa-sdk
# or
yarn add @smartesting/lynqa-sdk
```

## Quick start

```typescript
import { LynqaClient, RunStatus } from '@smartesting/lynqa-sdk'

const client = new LynqaClient('https://api.lynqa.smartesting.com', 'your-api-key')

const testRunId = await client.addTestRun({
  url: 'https://your-app.com',
  steps: [
    { action: 'Click on the login button' },
    { action: 'Fill in the email field with "user@example.com"' },
    { action: 'Fill in the password field with "password"' },
    { action: 'Submit the form', expectedResult: 'The user is redirected to the dashboard' }
  ]
})

const status = await client.getTestRunStatus(testRunId)
console.log(status.status) // 'waiting' | 'running' | 'success' | 'failed' | 'error' | 'stopped'
```

## Authentication

All requests are authenticated with an API key passed via the `x-api-key` header. You can generate an API key from your
Lynqa workspace settings.

## `LynqaClient`

### Constructor

```typescript
new LynqaClient(serverUrl
:
string, apiKey
:
string, adapterFactory ? : HttpClientAdapterFactory
)
```

| Parameter        | Type                       | Description                                                                 |
| ---------------- | -------------------------- | --------------------------------------------------------------------------- |
| `serverUrl`      | `string`                   | Base URL of the Lynqa API (e.g. `https://api.lynqa.smartesting.com`)        |
| `apiKey`         | `string`                   | Your Lynqa API key                                                          |
| `adapterFactory` | `HttpClientAdapterFactory` | Optional. HTTP adapter factory. Defaults to `FetchHttpClientAdapter.create` |

### Methods

#### `addTestRun(body, source?)`

Submit a new manual test run.

```typescript
const testRunId = await client.addTestRun({
  url: 'https://your-app.com',
  name: 'Login flow',
  steps: [
    { action: 'Click the login button', expectedResult: 'Login form appears' },
    { action: 'Fill email with "user@example.com"' },
    { action: 'Click submit', expectedResult: 'Dashboard is displayed' }
  ],
  context: {
    clientLanguage: 'en-US',
    secrets: [{ name: 'PASSWORD', value: 'my-secret' }]
  }
})
```

#### `addGherkinTestRun(body, source?)`

Submit a Gherkin (BDD) test run.

```typescript
const testRunId = await client.addGherkinTestRun({
  url: 'https://your-app.com',
  scenario: `
    Given I am on the login page
    When I fill in "user@example.com" as email
    And I fill in "password" as password
    And I click the submit button
    Then I should be redirected to the dashboard
  `
})
```

#### `getTestRunStatus(testRunId)`

Get the current status of a test run.

```typescript
const status = await client.getTestRunStatus(testRunId)
// { status: RunStatus, start?: Date, end?: Date, expiration?: Date }
```

#### `getTestRunFullStatus(testRunId)`

Get the full status including per-step results, screenshots, and assertions.

```typescript
const fullStatus = await client.getTestRunFullStatus(testRunId)
// { status, stepStatuses: StepReport[], steps: [...] }
```

#### `getTestRunStepStatus(testRunId, stepIndex)`

Get the status of a single step.

```typescript
const stepReport = await client.getTestRunStepStatus(testRunId, 0)
```

#### `getTestRun(testRunId)`

Retrieve the full test definition and run metadata.

```typescript
const testRun = await client.getTestRun(testRunId)
```

#### `stopTestRuns(...testRunIds)`

Stop one or multiple running test runs.

```typescript
const { stoppedTestRunIds } = await client.stopTestRuns(id1, id2)
```

#### `queryTestRuns(options?)`

List test runs with optional filtering and pagination.

```typescript
const { testRuns, nextCursor } = await client.queryTestRuns({
  testRunIds: ['id1', 'id2'], // optional filter by IDs
  limit: 20,
  cursor: 'last-seen-id' // for pagination
})
```

#### `getTestExecutionCredits()`

Get the remaining test execution credits for the authenticated account.

```typescript
const credits = await client.getTestExecutionCredits()
```

#### `getScreenshot(testRunId, screenshotId)`

Retrieve a screenshot as a base64-encoded string.

```typescript
const { data } = await client.getScreenshot(testRunId, screenshotId)
// data is a base64 string
```

## HTTP Adapters

The SDK ships with two built-in adapters. You can also provide your own.

### `FetchHttpClientAdapter` (default)

Uses the native `fetch` API.

```typescript
import { LynqaClient, FetchHttpClientAdapter } from '@smartesting/lynqa-sdk'

const client = new LynqaClient(url, apiKey, FetchHttpClientAdapter.create)
```

### `AxiosHttpClientAdapter`

Uses axios. Useful in Node.js environments where you need proxy support, interceptors, or
other axios features.

```typescript
import { LynqaClient, AxiosHttpClientAdapter } from '@smartesting/lynqa-sdk'

const client = new LynqaClient(url, apiKey, AxiosHttpClientAdapter.create)
```

### Custom adapter

Implement `AbstractHttpClientAdapter` to use any HTTP library:

```typescript
import { AbstractHttpClientAdapter, LynqaClientError, RequestConfig } from '@smartesting/lynqa-sdk'

class MyAdapter extends AbstractHttpClientAdapter {
  static create(apiUrl: string, apiKey: string) {
    return new MyAdapter(apiUrl, apiKey)
  }

  async request<T>(url: string, config?: RequestConfig): Promise<T> {
    // this.apiUrl — base URL
    // this.apiKey — API key to send as x-api-key header
    // config.method, config.body, config.apiConsumer
    // throw LynqaClientError on non-2xx responses
  }
}
```

## Error handling

All client methods throw `LynqaClientError` on non-2xx responses.

```typescript
import { LynqaClientError } from '@smartesting/lynqa-sdk'

try {
  await client.addTestRun({ url: '...', steps: [] })
} catch (err) {
  if (err instanceof LynqaClientError) {
    console.error(err.statusCode) // HTTP status code
    console.error(err.error) // error type string
    console.error(err.message) // human-readable message
  }
}
```

## Types reference

### Tests

| Type             | Description                                                           |
| ---------------- | --------------------------------------------------------------------- |
| `RawTest`        | Input payload for `addTestRun`                                        |
| `RawGherkinTest` | Input payload for `addGherkinTestRun`                                 |
| `TestStep`       | A single manual test step with `action` and optional `expectedResult` |
| `GherkinStep`    | A BDD step with `keyword` (`Given`/`When`/`Then`/`And`) and `text`    |
| `AnyTest`        | Union of manual and Gherkin test definitions                          |
| `TestRunContext` | Optional context: `clientLanguage`, `clientDatetime`, `secrets`       |
| `TestData`       | A `{ name, value }` secret passed into the test context               |
| `Attachment`     | A `{ id, name }` reference to an uploaded file                        |
| `RawAttachment`  | A `{ name, data }` base64-encoded file to upload inline               |
| `Guidance`       | A `{ text }` hint for the AI agent                                    |

### Test runs

| Type                    | Description                                                             |
| ----------------------- | ----------------------------------------------------------------------- |
| `TestRun`               | Full test run object including steps and metadata                       |
| `LightTestRun`          | Lightweight summary used in list responses                              |
| `TestRunStatus`         | `{ status, start?, end?, expiration?, statusMessage?, initialReport? }` |
| `TestRunFullStatus`     | `TestRunStatus` + `stepStatuses: StepReport[]` + steps                  |
| `StepReport`            | Per-step execution result (status, commands, assertions, screenshot)    |
| `AssertionsReport`      | `{ assertions: AssertionChecking[], screenshot: string }`               |
| `AssertionChecking`     | `{ assertion: string, checked: boolean }`                               |
| `QueryTestRunsResponse` | `{ testRuns: LightTestRunWithExpiration[], nextCursor }`                |
| `StoppedTestRuns`       | `{ stoppedTestRunIds: string[] }`                                       |

### Enums

```typescript
enum RunStatus {
  WAITING = 'waiting',
  RUNNING = 'running',
  SUCCESS = 'success',
  FAILED = 'failed',
  ERROR = 'error',
  STOPPED = 'stopped',
  NOT_RUN = 'not_run'
}

enum TestType {
  MANUAL = 'manual',
  GHERKIN = 'gherkin'
}

enum GherkinKeyword {
  GIVEN = 'Given',
  WHEN = 'When',
  THEN = 'Then',
  AND = 'And'
}
```