import { fillInMsgTemplate } from "../../../../src/lib/logger/formatter";
import {LOG_VERDACCIO_ERROR, LOG_VERDACCIO_BYTES} from "../../../../src/api/middleware";
import { HTTP_STATUS } from "@verdaccio/commons-api";

// the following mocks avoid use colors, thus the strings can be matched

jest.mock('kleur', () => {
  // we emulate colors with this pattern color[msg]
  return {
    green: r => `g[${r}]`,
    yellow: r => `y[${r}]`,
    black: r => `b[${r}]`,
    blue: r => `bu[${r}]`,
    red: r => `r[${r}]`,
    cyan: r => `c[${r}]`,
    magenta: r => `m[${r}]`,
    white: r => `w[${r}]`,
  }
});

jest.mock('util', () => {
  // we need to override only one method, but still we need others
  const originalModule = jest.requireActual('util');
  return {
    ...originalModule,
    inspect: r => r,
  }
});


describe('Logger Parser', () => {
  describe('basic messages', () => {
    test('number object property', () => {
      expect(fillInMsgTemplate('foo:@{foo}', {foo: 1}, false)).toEqual('foo:1');
    });

    test('string object property', () => {
      expect(fillInMsgTemplate('foo:@{foo}', {foo: 'bar'}, false)).toEqual('foo:bar');
    });

    test('empty message no object property', () => {
      expect(fillInMsgTemplate('foo', undefined, false)).toEqual('foo');
    });

    test('string no object property', () => {
      expect(fillInMsgTemplate('foo', null, false)).toEqual('foo');
    });

    test('string no object property with break line ', () => {
      expect(fillInMsgTemplate('foo \n bar', null, false)).toEqual('foo \n bar');
    });

    test('string no object property with colors', () => {
      expect(fillInMsgTemplate('foo', null, true)).toEqual('foo');
    });

    test('string object property with colors', () => {
      expect(fillInMsgTemplate('foo:@{foo}', {foo: 'bar'}, true)).toEqual(`foo:${'g[bar]'}`);
    });
  })

  describe('middleware log messages', () => {
    describe('test errors log', () => {
      const middlewareObject = { name: 'verdaccio',
        request: {
          method: 'POST',
          url: '/-/npm/v1/user'
        },
        user: 'userTest2001',
        remoteIP: '::ffff:127.0.0.1',
        status: HTTP_STATUS.UNAUTHORIZED,
        error: 'some error',
        msg: '@{status}, user: @{user}(@{remoteIP}), req: \'@{request.method} @{request.url}\', error: @{!error}'
      };

      test('should display error log', () => {
        const expectedErrorMessage = `401, user: userTest2001(::ffff:127.0.0.1), req: 'POST /-/npm/v1/user', error: some error`;
        expect(fillInMsgTemplate(LOG_VERDACCIO_ERROR, middlewareObject, false))
        .toEqual(expectedErrorMessage);
      });

      test('should display error log with colors', () => {
        const expectedErrorMessage = `401, user: g[userTest2001](g[::ffff:127.0.0.1]), req: 'g[POST] g[/-/npm/v1/user]', error: r[some error]`;
        expect(fillInMsgTemplate(LOG_VERDACCIO_ERROR, middlewareObject, true))
        .toEqual(expectedErrorMessage);
      });
    });

    describe('test bytes log', () => {
      const middlewareObject = { name: 'verdaccio',
        hostname: 'macbook-touch',
        pid: 85621,
        sub: 'in',
        level: 35,
        request: {
          method: 'PUT',
          url: '/-/user/org.couchdb.user:userTest2002'
        },
        user: 'userTest2002',
        remoteIP: '::ffff:127.0.0.1',
        status: 201,
        error: undefined,
        bytes: { in: 50, out: 405 },
        msg:
        '@{status}, user: @{user}(@{remoteIP}), req: \'@{request.method} @{request.url}\', bytes: @{bytes.in}/@{bytes.out}',
        time: '2019-07-20T11:31:49.939Z',
        v: 0
      }

      test('should display log with bytes', () => {
        expect(fillInMsgTemplate(LOG_VERDACCIO_BYTES, middlewareObject, false))
        .toEqual(`201, user: userTest2002(::ffff:127.0.0.1), req: 'PUT /-/user/org.couchdb.user:userTest2002', bytes: 50/405`);
      });

      test('should display log with bytes with colors', () => {
        expect(fillInMsgTemplate(LOG_VERDACCIO_BYTES, middlewareObject, true))
        .toEqual(`201, user: g[userTest2002](g[::ffff:127.0.0.1]), req: 'g[PUT] g[/-/user/org.couchdb.user:userTest2002]', bytes: 50/405`);
      });
    });
  });
});
