import {TestScheduler} from 'rxjs/testing';
import {MAX_DATE, MIN_DATE, isWithinIntervalObservable} from './in-range.pipe';
import {interval} from 'date-fns';
import {MAX_DELAY} from './in-range.pipe';

/**
 * Test macro
 */
function test(range: [number | undefined, number | undefined], subscribe: string, expected: string) {
  const testScheduler = new TestScheduler((actual, expected) => {
    expect(actual).withContext(actual.map(JSON.stringify).join('\n')).toEqual(expected);
  });

  it(`should emit "${expected}" when "${subscribe}" for range ${range[0] ?? ''}..${range[1] ?? ''}`, () => {
    testScheduler.run(({expectObservable}) => {
      expectObservable(
        isWithinIntervalObservable(
          interval(new Date(range[0] ?? MIN_DATE), new Date(range[1] ?? MAX_DATE)),
          testScheduler,
        ),
        subscribe,
      ).toBe(expected, {t: true, f: false});
    });
  });
}

describe('isWithinIntervalObservable', () => {
  test([500, undefined], '1s ^', '1s (t|)');
  test([1000, undefined], '500ms ^', '500ms f 499ms (t|)');

  test([undefined, 500], '1s ^', '1s (f|)');
  test([undefined, 1000], '500ms ^', '500ms t 499ms (f|)');

  test([1000, 2000], '500ms ^', '500ms f 499ms t 999ms (f|)');

  test([500, 1000], '1500ms ^', '1500ms (f|)');
  test([500, 1000], '1s ^', '1000ms (f|)');
  test([500, 1000], '999ms ^', '999ms t (f|)');
  test([500, 1000], '500ms ^', '500ms t 499ms (f|)');
  test([500, 1000], '499ms ^', '499ms f t 499ms (f|)');

  test([500, 1000], '^ 750ms !', 'f 499ms t');

  // Long interval test case: emit `true` and then complete (EMPTY) because `end` is beyond the delay limit
  test([500, 500 + MAX_DELAY + 2000], '1s ^', '1s (t|)');
});
