<commit_before>import {
  ClientTransaction,
  ClientTransactionUser,
  IncomingRequestMessage,
  IncomingResponseMessage,
  InviteClientTransaction,
  InviteServerTransaction,
  Levels,
  LoggerFactory,
  NonInviteClientTransaction,
  NonInviteServerTransaction,
  OutgoingRequestMessage,
  ServerTransaction,
  ServerTransactionUser,
  Transaction,
  TransactionState,
  TransactionUser,
  Transport,
  URI
} from "../../../src/core";

// TODO: Mocking the Requests and Responses isn't ideal and would rather use
// the actual implementations, but the current implementations depend on UA
// and thus drag in basically the entire project which is definately worse.
// So perhaps in the future...

/** Mocked incoming request factory function. */
const makeMockIncomingRequest = (method: string): jasmine.SpyObj<IncomingRequestMessage> => {
  const request = jasmine.createSpyObj<IncomingRequestMessage>("IncomingRequest", ["method", "viaBranch"]);
  request.method = method;
  request.viaBranch = "z9hG4bK" + Math.floor(Math.random() * 10000000);
  return request;
};

/** Mocked incoming response factory function. */
const makeMockIncomingResponse = (statusCode: number, toTag: string): jasmine.SpyObj<IncomingResponseMessage> => {
  const response =
    jasmine.createSpyObj<IncomingResponseMessage>("IncomingResponse", ["statusCode", "toTag", "getHeader"]);
  response.statusCode = statusCode;
  response.toTag = toTag;
  response.getHeader.and.callFake((name: string) => {
    return `[${name}]`;
  });
  return response;
};

type Mutable<T> = { -readonly [P in keyof T ]: T[P] };
const defaultURI = new URI("sip", "john", "onsip.com");

/** Mocked outgoing request factory function. */
const makeMockOutgoingRequest = (ruri: URI = defaultURI): jasmine.SpyObj<OutgoingRequestMessage> => {
  const request = jasmine.createSpyObj<Mutable<OutgoingRequestMessage>>("OutgoingRequest", [
    "callId",
    "cseq",
    "method",
    "ruri",
    "getHeader",
    "setViaHeader",
    "toString"
  ]);
  request.callId = "onsip";
  request.cseq = 42;
  request.method = "METHOD";
  request.ruri = ruri;
  request.toString.and.returnValue("request");
  request.getHeader.and.callFake((name: string) => {
    if (name === "via" && request.headers.via) {
      return request.headers.via[0];
    }
    return `[${name}]`;
  });
  request.setViaHeader.and.callFake((branch: string, scheme: string = "WSS") => {
    request.headers.via = [branch];
  });
  request.headers = {};
  return request as jasmine.SpyObj<OutgoingRequestMessage>;
};

/** Mocked transaction user factory function. */
const makeTransactionUser = (): jasmine.SpyObj<Required<TransactionUser>> => {
  const user = jasmine.createSpyObj<Required<TransactionUser>>("TransactionUser", [
    "loggerFactory",
    "onTransportError",
    "onStateChange"
  ]);
  const loggerFactory = new LoggerFactory();
  loggerFactory.level = Levels.debug;
  user.loggerFactory = loggerFactory;
  return user;
};

/** Mocked client transaction user factory function. */
const makeClientTransactionUser = (): jasmine.SpyObj<Required<ClientTransactionUser>> => {
  const user = jasmine.createSpyObj<Required<ClientTransactionUser>>("ClientTransactionUser", [
    "loggerFactory",
    "onRequestTimeout",
    "onTransportError",
    "onStateChange",
    "receiveResponse"
  ]);
  const loggerFactory = new LoggerFactory();
  loggerFactory.level = Levels.debug;
  user.loggerFactory = loggerFactory;
  return user;
};

/** Mocked server transaction user factory function. */
const makeServerTransactionUser = (): jasmine.SpyObj<Required<ServerTransactionUser>> => {
  return makeTransactionUser();
};

/** Mocked transport factory function. */
const makeMockTransport = (): jasmine.SpyObj<Transport> => {
  const transport = jasmine.createSpyObj<Transport>("Transport", [
    "send"
  ]);
  (transport.protocol as any) = "TEST";
  transport.send.and.returnValue(Promise.resolve());
  return transport;
};

// Helper types for factory functions.
type TransactionFactory = (transport: Transport, user: TransactionUser) => Transaction;
type ClientTransactionFactory = (
  request: OutgoingRequestMessage,
  transport: Transport,
  user: ClientTransactionUser
) => ClientTransaction;
type ServerTransactionFactory = (
  request: IncomingRequestMessage,
  transport: Transport,
  user: ServerTransactionUser
) => ServerTransaction;

// https://tools.ietf.org/html/rfc3261#section-17
describe("Transactions", () => {
  const ruri = "sip:<EMAIL>";
  const _1xxStatusCodesToTest = [100, 180, 183];
  const _2xxStatusCodesToTest = [200, 202];
  const _3xxStatusCodesToTest = [300, 301];
  const _4xxStatusCodesToTest = [404, 480];
  const _5xxStatusCodesToTest = [500, 503];
  const _6xxStatusCodesToTest = [603, 699];

  const executeTransactionTests = (transactionFactory: TransactionFactory) => {
    let transport: jasmine.SpyObj<Transport>;
    let user: jasmine.SpyObj<Required<TransactionUser>>;
    let transaction: Transaction;

    describe("is a Transaction, so after construction it...", () => {
      beforeEach(() => {
        transport = makeMockTransport();
        user = makeTransactionUser();
        transaction = transactionFactory(transport, user);
        spyOn(transaction, "emit");
      });

      afterEach(() => {
        transaction.dispose();
      });

      it("has the correct 'kind' [DEPRECATED]", () => {
        if (transaction instanceof InviteClientTransaction) {
          expect(transaction.kind).toEqual("ict");<commit_msg>New API -  update transaction tests<commit_after>import {
  ClientTransaction,
  ClientTransactionUser,
  IncomingRequestMessage,
  IncomingResponseMessage,
  InviteClientTransaction,
  InviteServerTransaction,
  Levels,
  LoggerFactory,
  NonInviteClientTransaction,
  NonInviteServerTransaction,
  OutgoingRequestMessage,
  ServerTransaction,
  ServerTransactionUser,
  Transaction,
  TransactionState,
  TransactionUser,
  Transport,
  URI
} from "../../../src/core";

// TODO: Mocking the Requests and Responses isn't ideal and would rather use
// the actual implementations, but the current implementations depend on UA
// and thus drag in basically the entire project which is definately worse.
// So perhaps in the future...

/** Mocked incoming request factory function. */
const makeMockIncomingRequest = (method: string): jasmine.SpyObj<IncomingRequestMessage> => {
  const request = jasmine.createSpyObj<IncomingRequestMessage>("IncomingRequest", ["method", "viaBranch"]);
  request.method = method;
  request.viaBranch = "z9hG4bK" + Math.floor(Math.random() * 10000000);
  return request;
};

/** Mocked incoming response factory function. */
const makeMockIncomingResponse = (statusCode: number, toTag: string): jasmine.SpyObj<IncomingResponseMessage> => {
  const response =
    jasmine.createSpyObj<IncomingResponseMessage>("IncomingResponse", ["statusCode", "toTag", "getHeader"]);
  response.statusCode = statusCode;
  response.toTag = toTag;
  response.getHeader.and.callFake((name: string) => {
    return `[${name}]`;
  });
  return response;
};

type Mutable<T> = { -readonly [P in keyof T ]: T[P] };
const defaultURI = new URI("sip", "example", "onsip.com");

/** Mocked outgoing request factory function. */
const makeMockOutgoingRequest = (ruri: URI = defaultURI): jasmine.SpyObj<OutgoingRequestMessage> => {
  const request = jasmine.createSpyObj<Mutable<OutgoingRequestMessage>>("OutgoingRequest", [
    "callId",
    "cseq",
    "method",
    "ruri",
    "getHeader",
    "setViaHeader",
    "toString"
  ]);
  request.callId = "onsip";
  request.cseq = 42;
  request.method = "METHOD";
  request.ruri = ruri;
  request.toString.and.returnValue("request");
  request.getHeader.and.callFake((name: string) => {
    if (name === "via" && request.headers.via) {
      return request.headers.via[0];
    }
    return `[${name}]`;
  });
  request.setViaHeader.and.callFake((branch: string, scheme: string = "WSS") => {
    request.headers.via = [branch];
  });
  request.headers = {};
  return request as jasmine.SpyObj<OutgoingRequestMessage>;
};

/** Mocked transaction user factory function. */
const makeTransactionUser = (): jasmine.SpyObj<Required<TransactionUser>> => {
  const user = jasmine.createSpyObj<Required<TransactionUser>>("TransactionUser", [
    "loggerFactory",
    "onTransportError",
    "onStateChange"
  ]);
  const loggerFactory = new LoggerFactory();
  loggerFactory.level = Levels.debug;
  user.loggerFactory = loggerFactory;
  return user;
};

/** Mocked client transaction user factory function. */
const makeClientTransactionUser = (): jasmine.SpyObj<Required<ClientTransactionUser>> => {
  const user = jasmine.createSpyObj<Required<ClientTransactionUser>>("ClientTransactionUser", [
    "loggerFactory",
    "onRequestTimeout",
    "onTransportError",
    "onStateChange",
    "receiveResponse"
  ]);
  const loggerFactory = new LoggerFactory();
  loggerFactory.level = Levels.debug;
  user.loggerFactory = loggerFactory;
  return user;
};

/** Mocked server transaction user factory function. */
const makeServerTransactionUser = (): jasmine.SpyObj<Required<ServerTransactionUser>> => {
  return makeTransactionUser();
};

/** Mocked transport factory function. */
const makeMockTransport = (): jasmine.SpyObj<Transport> => {
  const transport = jasmine.createSpyObj<Transport>("Transport", [
    "send"
  ]);
  (transport.protocol as any) = "TEST";
  transport.send.and.returnValue(Promise.resolve());
  return transport;
};

// Helper types for factory functions.
type TransactionFactory = (transport: Transport, user: TransactionUser) => Transaction;
type ClientTransactionFactory = (
  request: OutgoingRequestMessage,
  transport: Transport,
  user: ClientTransactionUser
) => ClientTransaction;
type ServerTransactionFactory = (
  request: IncomingRequestMessage,
  transport: Transport,
  user: ServerTransactionUser
) => ServerTransaction;

// https://tools.ietf.org/html/rfc3261#section-17
describe("Transactions", () => {
  const ruri = "sip:<EMAIL>";
  const _1xxStatusCodesToTest = [100, 180, 183];
  const _2xxStatusCodesToTest = [200, 202];
  const _3xxStatusCodesToTest = [300, 301];
  const _4xxStatusCodesToTest = [404, 480];
  const _5xxStatusCodesToTest = [500, 503];
  const _6xxStatusCodesToTest = [603, 699];

  const executeTransactionTests = (transactionFactory: TransactionFactory) => {
    let transport: jasmine.SpyObj<Transport>;
    let user: jasmine.SpyObj<Required<TransactionUser>>;
    let transaction: Transaction;

    describe("is a Transaction, so after construction it...", () => {
      beforeEach(() => {
        transport = makeMockTransport();
        user = makeTransactionUser();
        transaction = transactionFactory(transport, user);
        spyOn(transaction, "emit");
      });

      afterEach(() => {
        transaction.dispose();
      });

      it("has the correct 'kind' [DEPRECATED]", () => {
        if (transaction instanceof InviteClientTransaction) {
          expect(transaction.kind).toEqual("ict");
{'fraction_non_alphanumeric': 0.13175338236629439, 'fraction_numerical': 0.011622627803504948, 'mean_word_length': 4.579533941236069, 'pattern_counts': {'":': 0, '<': 53, '<?xml version=': 0, '>': 91, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5268696', 'n_tokens_mistral': 3318, 'n_tokens_neox': 3194, 'n_words': 721}