import { expect } from 'chai';
import { cookie, ICookieServerContext, ServerCookie } from '.';

describe('cookie', () => {
  describe('read cookie', () => {
    const obj = { text: 'MyText', number: 1234, flag: true };
    const cookies = {
      TEXT: 'Hello',
      OBJECT: JSON.stringify(obj),
    };
    const ctx: ICookieServerContext = {
      req: { cookies },
      res: {
        setHeader(key: string, value: any) {
          return;
        },
      },
    };

    it('stores the key on the property function', () => {
      const prop = cookie.prop('MY_KEY');
      expect(prop.key).to.eql('MY_KEY');
    });

    it('store options on the property function', () => {
      const prop = cookie.prop('MY_KEY', { path: '/foo' });
      expect(prop.options).to.eql({ path: '/foo' });
    });

    it('sets the [isProp] flag on the property function', () => {
      const prop = cookie.prop('MY_KEY');
      expect(prop.isProp).to.eql(true);
    });

    it('reads string', () => {
      const prop = cookie.prop<string>('TEXT');
      const result = prop(undefined, { ctx });
      expect(result).to.eql('Hello');
    });

    it('reads object', () => {
      type MyObject = {
        text: string;
        number: number;
      };
      const prop = cookie.prop<MyObject>('OBJECT');
      const result = prop(undefined, { ctx });
      expect(result).to.eql(obj);
      expect(result && result.text).to.eql('MyText');
      expect(result && result.number).to.eql(1234);
    });

    it('has no default value', () => {
      const prop = cookie.prop('FOO');
      expect(prop()).to.eql(undefined);
    });

    it('has a default value from prop [options]', () => {
      const prop = cookie.prop('FOO');
      expect(prop(undefined, { default: 'hello' })).to.eql('hello');
    });

    it('has a default value from the curried [defaultOptions]', () => {
      const prop = cookie.prop('FOO', { default: 'Yo' });
      expect(prop()).to.eql('Yo');
    });

    it('overrides the curried [defaultOptions] with prop [options]', () => {
      const prop = cookie.prop('FOO', { default: 'Yo' });
      expect(prop(undefined, { default: 'hello' })).to.eql('hello');
    });
  });

  describe('ServerCookie', () => {
    const myCookies = {
      foo: cookie.prop('FOO'),
      bar: cookie.prop('BAR'),
      baz: cookie.prop('BAZ', { expires: 30 }),
    };

    it('has no cookies by default', () => {
      const server = new ServerCookie();
      expect(server.cookies).to.eql([]);
    });

    it('adds cookies', () => {
      const server = new ServerCookie();
      server
        .add(myCookies.foo, 'one')
        .add(myCookies.bar, { bar: 123 })
        .add(myCookies.baz, 'three');

      expect(server.cookies.length).to.eql(3);

      expect(server.cookies[0].key).to.eql('FOO');
      expect(server.cookies[0].value).to.eql('one');
      expect(server.cookies[0].options).to.eql(undefined);

      expect(server.cookies[1].key).to.eql('BAR');
      expect(server.cookies[1].value).to.eql({ bar: 123 });
      expect(server.cookies[1].options).to.eql(undefined);

      expect(server.cookies[2].key).to.eql('BAZ');
      expect(server.cookies[2].value).to.eql('three');
      expect(server.cookies[2].options).to.eql({ expires: 30 });
    });

    it('clears all cookies', () => {
      const server = new ServerCookie();
      server.add(myCookies.foo, 'one').add(myCookies.bar, { bar: 123 });
      expect(server.cookies.length).to.eql(2);
      server.clear();
      expect(server.cookies.length).to.eql(0);
    });

    it('constructs "Set-Cookie" header', () => {
      const server = new ServerCookie();
      server.add(myCookies.foo, 'my-value');
      const header = server.header;
      expect(header).to.eql(
        '__TDB_TEMP__=%7B%22FOO%22%3A%7B%22key%22%3A%22FOO%22%2C%22value%22%3A%22my-value%22%7D%7D',
      );
    });
  });
});
