/* global describe, it */
import assert from 'assert';
import { run } from '../src';
import Most from 'most';

describe(`Cycle`, () => {
  describe("API", () => {
    it(`should have 'run'`, done => {
      assert.strictEqual(typeof run, `function`);
      done();
    });
  });

  describe(`run()`, () => {
    it(`should throw if the first argument is not a function`, done => {
      assert.throws(() => {
        run(`not a function`);
      }, /First argument given to Cycle\.run\(\) must be the 'main' function/i);
      done();
    });

    it(`should throw if the second argument is not an Object`, done => {
      assert.throws(() => {
        run(() => {}, `not an object`);
      });
      done();
    })

    it(`should throw if second argument is an empty object`, done => {
      assert.throws(() => {
        run(() => {}, {});
      }, /Second argument given to Cycle\.run\(\) must be an object with at least one/i)
      done();
    });

    it(`should return sources object and sinks object`, done => {
      const app = sources => ({
        other: sources.other.take(1).startWith(`a`)
      });

      const driver = () => Most.just('b');

      const { sinks, sources } = run( app, { other: driver } );

      assert.strictEqual(typeof sinks, 'object');
      assert.strictEqual(typeof sinks.other.observe, 'function');
      assert.strictEqual(typeof sources, 'object');
      assert.notStrictEqual(typeof sources.other, 'undefined');
      assert.notStrictEqual(sources.other, null);
      assert.strictEqual(typeof sources.other.observe, 'function');

      done();
    });

    it(`should run a simple application`, done => {
      const app = sources => ({
        Handshake: Most.just('world from')
      });

      const makeDriver = ({ greeting, name }) => {
        const driver = ( source$ ) => {
          const sink$ = source$
            .map(data => {
              const meaningfulData = `${greeting}, ${data} ${name}!`;
              return meaningfulData;
            });
          return sink$;
        };
        return driver;
      }

      const {sinks, sources} = run(app, {
        Handshake: makeDriver({
          greeting: 'Hello',
          name: 'Cycle'
        })
      });

      sources.Handshake.observe(value => {
        assert.strictEqual(value, `Hello, world from Cycle!`)
        done();
      });
    });
  });
});

@@ -48,16 +48,43 @@
 ssert';%0A
+import sinon from 'sinon';%0A
 import %7B
@@ -2380,23 +2380,667 @@
  %7D);%0A    %7D);
+%0A%0A    it(%60should report errors from main() to the console%60, done =%3E %7B%0A      const sandbox = sinon.sandbox.create();%0A      sandbox.stub(console, %60error%60);%0A%0A      const main = sources =%3E (%7B%0A        other: sources.other.take(1).startWith('a').map(() =%3E %7B%0A          throw new Error('malfunction')%0A        %7D)%0A      %7D);%0A%0A      const driver = () =%3E Most.just(%60b%60);%0A%0A      run(main, %7Bother: driver%7D);%0A%0A      setTimeout(() =%3E %7B%0A        sinon.assert.calledOnce(console.error);%0A        sinon.assert.calledWithExactly(%0A          console.error,%0A          sinon.match(%22malfunction%22)%0A        );%0A        sandbox.restore();%0A        done();%0A      %7D, 10);%0A    %7D);
 %0A  %7D);%0A%7D);%0A

add test for error logging