<commit_before>import { test, TestContext } from 'ava';
import * as when from 'when';

import { Future } from '../../src/future/future';
import { Try } from '../../src/try/try';

const error: Error = new Error('sample error');

const success: Future<string> = Future.create('hello');
const failure: Future<string> = Future.create(when.lift(() => { throw error; })());

test('Future#filter', async(t: TestContext) => {
  t.plan(2);

  const successfulFilter: string = await success.filter((v: string) => v === 'hello').promise;
  t.is(successfulFilter, 'hello');

  await t.throws(success.filter((v: string) => v === 'world').promise);
});

test('Future#flatMap', async(t: TestContext) => {
  t.plan(3);

  const successfulFlatMap: string = await success.flatMap(() => Future.create('world')).promise;
  t.is(successfulFlatMap, 'world');

  const failingFlatMap: when.Promise<void> = success.flatMap((): Future<void> => { throw error; }).promise;
  await t.throws(failingFlatMap);

  await t.throws(failure.flatMap(() => success).promise);
});

test('Future#foreach', async(t: TestContext) => {
  t.plan(2);

  let executions: number = 0;

  success.foreach(() => {
    executions += 1;
  });

  await success.promise;

  t.is(executions, 1);

  executions = 0;

  failure.foreach(() => {
    executions += 1;
  });

  try {
    await failure.promise;
  }
  catch (e) {
    // No-op: ignore exception
  }

  t.is(executions, 0);
});

test('Future#isCompleted', async(t: TestContext) => {
  t.plan(2);

  const delayedFuture: Future<void> = Future.create(
    when.promise((resolve: (value: void) => void): void => {
      setTimeout(resolve, 0);
    })
  );

  t.is(delayedFuture.isCompleted, false);

  await delayedFuture.promise;

  t.is(delayedFuture.isCompleted, true);
});

test('Future#map', async(t: TestContext) => {
  t.plan(2);

  const successfulMap: string = await success.map((v: string) => `${v} world`).promise;
  t.is(successfulMap, 'hello world');

  await t.throws(failure.map(() => 'world').promise);
});

test('Future#onComplete', async(t: TestContext) => {
  t.plan(2);

  success.onComplete((v: Try<string>) => {
    t.true(v.isSuccess);
  });

  await success.promise;

  failure.onComplete((v: Try<string>) => {
    t.false(v.isSuccess);
  });

  try {
    await failure.promise;
  }
  catch (error) {
    // Do nothing, the failure throwing an error is expected.
  }
});

test('Future#recover', async(t: TestContext) => {
  t.plan(4);

  const passthroughRecover: string = await success.recover((e: Error) => {
    if (e === error) {
      return 'world';
    }
    else {
      throw error;
    }
  }).promise;
  t.is(passthroughRecover, 'hello');

  const successfulRecover: string = await failure.recover((e: Error) => {
    if (e === error) {
      return 'world';
    }
    else {
      throw error;
    }
  }).promise;
  t.is(successfulRecover, 'world');

  await t.throws(
    failure.recover((e: Error) => {
      if (e !== error) {
        return 'world';
      }
      else {
        throw error;
      }
    }).promise
  );

  await t.throws(failure.recover((e: Error): string => { throw error; }).promise);
});

test('Future#recoverWith', async(t: TestContext) => {
  t.plan(4);

  const passthroughRecoverWith: string = await success.recoverWith((e: Error) => {
    if (e === error) {
      return Future.create('world');
    }
    else {
      throw error;
    }
  }).promise;
  t.is(passthroughRecoverWith, 'hello');

  const successfulRecoverWith: string = await failure.recoverWith((e: Error) => {
    if (e === error) {
      return Future.create('world');
    }
    else {
      throw error;
    }
  }).promise;
  t.is(successfulRecoverWith, 'world');

  await t.throws(
    failure.recoverWith((e: Error) => {
      if (e !== error) {
        return Future.create('world');
      }
      else {
        throw error;
      }
    }).promise
  );

  await t.throws(failure.recoverWith((e: Error): Future<string> => { throw error; }).promise);
});<commit_msg>test(future): work around when.js lack of PromiseLike<commit_after>import { test, TestContext } from 'ava';
import * as when from 'when';

import { Future } from '../../src/future/future';
import { Try } from '../../src/try/try';

// :TODO: Update when.js type definitions to return PromiseLikes to avoid manually typecasting.

const error: Error = new Error('sample error');

const success: Future<string> = Future.create('hello');
const failure: Future<string> = Future.create(when.lift(() => { throw error; })());

test('Future#filter', async(t: TestContext) => {
  t.plan(2);

  const successfulFilter: string = await success.filter((v: string) => v === 'hello').promise;
  t.is(successfulFilter, 'hello');

  await t.throws(success.filter((v: string) => v === 'world').promise as PromiseLike<string>);
});

test('Future#flatMap', async(t: TestContext) => {
  t.plan(3);

  const successfulFlatMap: string = await success.flatMap(() => Future.create('world')).promise;
  t.is(successfulFlatMap, 'world');

  const failingFlatMap: when.Promise<void> = success.flatMap((): Future<void> => { throw error; }).promise;
  await t.throws(failingFlatMap as PromiseLike<void>);

  await t.throws(failure.flatMap(() => success).promise as PromiseLike<string>);
});

test('Future#foreach', async(t: TestContext) => {
  t.plan(2);

  let executions: number = 0;

  success.foreach(() => {
    executions += 1;
  });

  await success.promise;

  t.is(executions, 1);

  executions = 0;

  failure.foreach(() => {
    executions += 1;
  });

  try {
    await failure.promise;
  }
  catch (e) {
    // No-op: ignore exception
  }

  t.is(executions, 0);
});

test('Future#isCompleted', async(t: TestContext) => {
  t.plan(2);

  const delayedFuture: Future<void> = Future.create(
    when.promise((resolve: (value: void) => void): void => {
      setTimeout(resolve, 0);
    })
  );

  t.is(delayedFuture.isCompleted, false);

  await delayedFuture.promise;

  t.is(delayedFuture.isCompleted, true);
});

test('Future#map', async(t: TestContext) => {
  t.plan(2);

  const successfulMap: string = await success.map((v: string) => `${v} world`).promise;
  t.is(successfulMap, 'hello world');

  await t.throws(failure.map(() => 'world').promise as PromiseLike<string>);
});

test('Future#onComplete', async(t: TestContext) => {
  t.plan(2);

  success.onComplete((v: Try<string>) => {
    t.true(v.isSuccess);
  });

  await success.promise;

  failure.onComplete((v: Try<string>) => {
    t.false(v.isSuccess);
  });

  try {
    await failure.promise;
  }
  catch (error) {
    // Do nothing, the failure throwing an error is expected.
  }
});

test('Future#recover', async(t: TestContext) => {
  t.plan(4);

  const passthroughRecover: string = await success.recover((e: Error) => {
    if (e === error) {
      return 'world';
    }
    else {
      throw error;
    }
  }).promise;
  t.is(passthroughRecover, 'hello');

  const successfulRecover: string = await failure.recover((e: Error) => {
    if (e === error) {
      return 'world';
    }
    else {
      throw error;
    }
  }).promise;
  t.is(successfulRecover, 'world');

  await t.throws(
    failure.recover((e: Error) => {
      if (e !== error) {
        return 'world';
      }
      else {
        throw error;
      }
    }).promise as PromiseLike<string>
  );

  await t.throws(failure.recover((e: Error): string => { throw error; }).promise as PromiseLike<string>);
});

test('Future#recoverWith', async(t: TestContext) => {
  t.plan(4);

  const passthroughRecoverWith: string = await success.recoverWith((e: Error) => {
    if (e === error) {
      return Future.create('world');
    }
    else {
      throw error;
    }
  }).promise;
  t.is(passthroughRecoverWith, 'hello');

  const successfulRecoverWith: string = await failure.recoverWith((e: Error) => {
    if (e === error) {
      return Future.create('world');
    }
    else {
      throw error;
    }
  }).promise;
  t.is(successfulRecoverWith, 'world');

  await t.throws(
    failure.recoverWith((e: Error) => {
      if (e !== error) {
        return Future.create('world');
      }
      else {
        throw error;
      }
    }).promise as PromiseLike<string>
  );

  await t.throws(failure.recoverWith((e: Error): Future<string> => { throw error; }).promise as PromiseLike<string>);
});
{'fraction_non_alphanumeric': 0.18175261449693472, 'fraction_numerical': 0.003606202668589975, 'mean_word_length': 3.279835390946502, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 87, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, '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': '5248346', 'n_tokens_mistral': 2854, 'n_tokens_neox': 2820, 'n_words': 612}