Skip to content
Open
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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ src/js/*
!src/js/__tests__
types
js
.claude/worktrees
.claude/
.DS_Store
src/version.ts
488 changes: 358 additions & 130 deletions README.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@absmartly/javascript-sdk",
"version": "1.14.0-beta.1",
"version": "2.0.0",
"description": "A/B Smartly Javascript SDK",
"homepage": "https://github.com/absmartly/javascript-sdk#README.md",
"bugs": "https://github.com/absmartly/javascript-sdk/issues",
Expand Down
41 changes: 41 additions & 0 deletions src/__tests__/abort-controller-shim.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,45 @@ describe("AbortController", () => {

expect(aborter[Symbol.toStringTag]).toEqual("AbortController");
});

describe("signal.reason", () => {
it("should set default reason on abort()", () => {
const controller = new AbortController();
controller.abort();
expect(controller.signal.aborted).toBe(true);
expect(controller.signal.reason).toBeInstanceOf(Error);
expect(controller.signal.reason.message).toBe("The operation was aborted.");
});

it("should set custom reason on abort(reason)", () => {
const controller = new AbortController();
const customReason = new Error("custom abort");
controller.abort(customReason);
expect(controller.signal.reason).toBe(customReason);
});

it("should have undefined reason before abort", () => {
const controller = new AbortController();
expect(controller.signal.reason).toBeUndefined();
});
});

describe("dispatchEvent onabort handling", () => {
it("should call onabort handler on abort dispatch", () => {
const signal = new AbortSignal();
const handler = jest.fn();
signal.onabort = handler;
signal.dispatchEvent({ type: "abort" });
expect(handler).toHaveBeenCalledTimes(1);
expect(handler).toHaveBeenCalledWith({ type: "abort" });
});

it("should not call onabort for non-abort events", () => {
const signal = new AbortSignal();
const handler = jest.fn();
signal.onabort = handler;
signal.dispatchEvent({ type: "other" });
expect(handler).not.toHaveBeenCalled();
});
});
});
15 changes: 15 additions & 0 deletions src/__tests__/client.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1121,7 +1121,7 @@
});

it("getAgent() should return default agent when not specified", () => {
const { agent: _, ...optionsWithoutAgent } = clientOptions;

Check warning on line 1124 in src/__tests__/client.test.js

View workflow job for this annotation

GitHub Actions / build

'_' is assigned a value but never used
const client = new Client(optionsWithoutAgent);
expect(client.getAgent()).toEqual("javascript-client");
});
Expand Down Expand Up @@ -1188,4 +1188,19 @@
done();
});
});

describe("timeout option", () => {
it("should accept an explicit timeout of 0 (nullish coalescing, not falsy)", () => {
const client = new Client({
endpoint,
agent,
environment,
apiKey,
application,
timeout: 0,
});

expect(client).toBeInstanceOf(Client);
});
});
});
65 changes: 65 additions & 0 deletions src/__tests__/constructor-options.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Constructor option-merging tests for SDK and Client.
//
// These deliberately use the real SDK and Client constructors (no jest.mock),
// so they exercise the actual _extractClientOptions / option-merge logic
// rather than Jest doubles, which would make the assertions vacuous.

import SDK from "../sdk";
import Client from "../client";

describe("SDK and Client constructor option merging", () => {
it("should extract client options from SDK options and pass them to the real Client", () => {
const sdk = new SDK({
agent: "test-agent",
apiKey: "key",
application: "app",
endpoint: "http://localhost",
environment: "test",
timeout: 5000,
});

const client = sdk.getClient();
expect(client).toBeInstanceOf(Client);
expect(client.getAgent()).toBe("test-agent");
expect(client.getEnvironment()).toBe("test");
expect(client.getApplication()).toEqual({ name: "app", version: 0 });
});

it("should accept the SDK application option as an object", () => {
const sdk = new SDK({
agent: "test",
apiKey: "key",
application: { name: "myapp", version: "1.2.3" },
endpoint: "http://localhost",
environment: "prod",
});

expect(sdk.getClient().getApplication()).toEqual({ name: "myapp", version: "1.2.3" });
});

it("should merge provided Client options with the defaults", () => {
const client = new Client({
endpoint: "http://test",
agent: "custom-agent",
environment: "prod",
apiKey: "key123",
application: "myapp",
timeout: 10000,
});

expect(client.getAgent()).toBe("custom-agent");
expect(client.getEnvironment()).toBe("prod");
expect(client.getApplication()).toEqual({ name: "myapp", version: 0 });
});

it("should fall back to the default agent when it is omitted", () => {
const client = new Client({
endpoint: "http://test",
environment: "prod",
apiKey: "key123",
application: "myapp",
});

expect(client.getAgent()).toBe("javascript-client");
});
});
Loading