// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
import FauxtonAPI from '../../../core/api';
import {
  getSource,
  getTarget,
  continuous,
  createTarget,
  addDocIdAndRev,
  getDocUrl,
  encodeFullUrl,
  decodeFullUrl,
  getCredentialsFromUrl,
  removeCredentialsFromUrl,
  removeSensitiveUrlInfo,
  supportNewApi,
  fetchReplicationDocs
} from '../api';
import Constants from '../constants';
import fetchMock from 'fetch-mock';

describe('Replication API', () => {

  describe("removeSensiteiveUrlInfo", () => {
    it('removes password username', () => {
      const url = 'http://tester:testerpass@127.0.0.1/fancy/db/name';

      const res = removeSensitiveUrlInfo(url);

      expect(res).toBe('http://127.0.0.1/fancy/db/name');
    });

    // see https://issues.apache.org/jira/browse/COUCHDB-3257
    // CouchDB accepts and returns invalid urls
    it('does not throw on invalid urls', () => {
      const url = 'http://tester:tes#terpass@127.0.0.1/fancy/db/name';

      const res = removeSensitiveUrlInfo(url);

      expect(res).toBe('http://tester:tes#terpass@127.0.0.1/fancy/db/name');
    });
  });

  describe('getSource', () => {

    it('encodes remote db', () => {
      const remoteSource = 'http://remote-couchdb.com/my/db/here';
      const source = getSource({
        replicationSource: Constants.REPLICATION_SOURCE.REMOTE,
        remoteSource
      });

      expect(source.url).toEqual('http://remote-couchdb.com/my%2Fdb%2Fhere');
    });

    it('returns local source with auth info and encoded', () => {
      const localSource = 'my/db';
      const source = getSource({
        replicationSource: Constants.REPLICATION_SOURCE.LOCAL,
        localSource,
        sourceAuth: {
          username: 'the-user',
          password: 'password'
        },
        sourceAuthType: Constants.REPLICATION_AUTH_METHOD.BASIC
      }, {origin: 'http://dev:6767'});

      expect(source.headers).toEqual({Authorization:"Basic dGhlLXVzZXI6cGFzc3dvcmQ="});
      expect(source.url).toMatch(/my%2Fdb/);
    });

    it('returns local source with auth info and encoded when use relative url', () => {
      const localSource = 'my/db';
      const source = getSource({
        replicationSource: Constants.REPLICATION_SOURCE.LOCAL,
        localSource,
        sourceAuth: {
          username: 'the-user',
          password: 'password'
        },
        sourceAuthType: Constants.REPLICATION_AUTH_METHOD.BASIC
      }, {origin: 'http://dev:6767', pathname:'/db/_utils'});

      expect(source.headers).toEqual({Authorization:"Basic dGhlLXVzZXI6cGFzc3dvcmQ="});
      expect(source.url).toMatch(/\/db\/my%2Fdb/);
    });

    it('returns remote source url and auth header', () => {
      const source = getSource({
        replicationSource: Constants.REPLICATION_SOURCE.REMOTE,
        remoteSource: 'http://my-couchdb.com/my-db',
        localSource: "local",
        sourceAuth: {
          username: 'the-user',
          password: 'password'
        },
        sourceAuthType: Constants.REPLICATION_AUTH_METHOD.BASIC
      }, {origin: 'http://dev:6767'});

      expect(source.headers).toEqual({Authorization:"Basic dGhlLXVzZXI6cGFzc3dvcmQ="});
      expect(source.url).toBe('http://my-couchdb.com/my-db');
    });

    it('returns source with no auth', () => {
      const source = getSource({
        replicationSource: Constants.REPLICATION_SOURCE.REMOTE,
        remoteSource: 'http://my-couchdb.com/my-db',
        localSource: "local",
        sourceAuth: {
          username: 'the-user',
          password: 'password'
        },
        sourceAuthType: Constants.REPLICATION_AUTH_METHOD.NO_AUTH
      }, {origin: 'http://dev:6767'});

      expect(source.headers).toEqual({});

      const source2 = getSource({
        replicationSource: Constants.REPLICATION_SOURCE.REMOTE,
        remoteSource: 'http://my-couchdb.com/my-db',
        localSource: "local"
      }, {origin: 'http://dev:6767'});

      expect(source2.headers).toEqual({});
    });

    it('returns source with custom auth', () => {
      FauxtonAPI.registerExtension('Replication:Auth', {
        typeValue: 'TEST_CUSTOM_AUTH',
        typeLabel: 'Test Custom Auth',
        setCredentials: (repSourceOrTarget, auth) => {
          repSourceOrTarget.auth = {
            auth_creds: auth.creds
          };
        }
      });
      const source = getSource({
        replicationSource: Constants.REPLICATION_SOURCE.REMOTE,
        remoteSource: 'http://my-couchdb.com/my-db',
        localSource: "local",
        sourceAuth: { creds: 'sample_creds' },
        sourceAuthType: 'TEST_CUSTOM_AUTH'
      }, {origin: 'http://dev:6767'});

      expect(source.auth).toEqual({ auth_creds: 'sample_creds' });
    });
  });

  describe('getTarget', () => {

    it('returns remote encoded target', () => {
      const remoteTarget = 'http://remote-couchdb.com/my/db';

      const url = getTarget({
        replicationTarget: Constants.REPLICATION_TARGET.NEW_REMOTE_DATABASE,
        remoteTarget: remoteTarget
      }).url;
      expect(url).toBe("http://remote-couchdb.com/my%2Fdb");
    });

    it("encodes username and password for remote", () => {
      const remoteTarget = 'http://remote-couchdb.com/my/db';
      const target = getTarget({
        replicationTarget: Constants.REPLICATION_TARGET.NEW_REMOTE_DATABASE,
        remoteTarget: remoteTarget,
        targetAuth: {
          username: 'jimi',
          password: 'my-password'
        },
        targetAuthType: Constants.REPLICATION_AUTH_METHOD.BASIC
      });

      expect(target.url).toEqual('http://remote-couchdb.com/my%2Fdb');
      expect(target.headers).toEqual({Authorization:"Basic amltaTpteS1wYXNzd29yZA=="});
    });

    it('returns existing local database', () => {
      const target = getTarget({
        replicationTarget: Constants.REPLICATION_TARGET.EXISTING_LOCAL_DATABASE,
        localTarget: 'my-existing/db',
        targetAuth: {
          username: 'the-user',
          password: 'password'
        },
        targetAuthType: Constants.REPLICATION_AUTH_METHOD.BASIC
      });

      expect(target.headers).toEqual({Authorization:"Basic dGhlLXVzZXI6cGFzc3dvcmQ="});
      expect(target.url).toMatch(/my-existing%2Fdb/);
    });

    it('returns existing local database even with relative urls', () => {
      const target = getTarget({
        replicationTarget: Constants.REPLICATION_TARGET.EXISTING_LOCAL_DATABASE,
        localTarget: 'my-existing/db',
        targetAuth: {
          username: 'the-user',
          password: 'password'
        },
        targetAuthType: Constants.REPLICATION_AUTH_METHOD.BASIC
      }, {origin:'http://dev:6767', pathname:'/db/_utils'});

      expect(target.headers).toEqual({Authorization:"Basic dGhlLXVzZXI6cGFzc3dvcmQ="});
      expect(target.url).toMatch(/my-existing%2Fdb/);
    });

    it('returns new local database', () => {
      const target = getTarget({
        replicationTarget: Constants.REPLICATION_TARGET.NEW_LOCAL_DATABASE,
        replicationSource: Constants.REPLICATION_SOURCE.LOCAL,
        localTarget: 'my-new/db',
        targetAuth: {
          username: 'the-user',
          password: 'password'
        },
        targetAuthType: Constants.REPLICATION_AUTH_METHOD.BASIC
      });

      expect(target.headers).toEqual({Authorization:"Basic dGhlLXVzZXI6cGFzc3dvcmQ="});
      expect(target.url).toMatch(/my-new%2Fdb/);
    });

    it('returns new local for remote source', () => {
      const target = getTarget({
        replicationTarget: Constants.REPLICATION_TARGET.NEW_LOCAL_DATABASE,
        replicationSource: Constants.REPLICATION_SOURCE.REMOTE,
        localTarget: 'my-new/db',
        targetAuth: {
          username: 'the-user',
          password: 'password'
        },
        targetAuthType: Constants.REPLICATION_AUTH_METHOD.BASIC
      }, {origin: 'http://dev:5555'});

      expect(target.headers).toEqual({Authorization:"Basic dGhlLXVzZXI6cGFzc3dvcmQ="});
      expect(target.url).toMatch(/my-new%2Fdb/);
    });

    it("doesn't encode username and password if it is not supplied", () => {
      const location = {
        host: "dev:8000",
        hostname: "dev",
        href: "http://dev:8000/#database/animaldb/_all_docs",
        origin: "http://dev:8000",
        pathname: "/",
        port: "8000",
        protocol: "http:",
      };

      const target = getTarget({
        replicationTarget: Constants.REPLICATION_TARGET.NEW_LOCAL_DATABASE,
        replicationSource: Constants.REPLICATION_SOURCE.REMOTE,
        localTarget: 'my-new/db'
      }, location);

      expect(target.url).toBe("http://dev:8000/my-new%2Fdb");
      expect(target.headers).toEqual({});

      const targetNoAuth = getTarget({
        replicationTarget: Constants.REPLICATION_TARGET.NEW_LOCAL_DATABASE,
        replicationSource: Constants.REPLICATION_SOURCE.REMOTE,
        localTarget: 'my-new/db',
        targetAuthType: Constants.REPLICATION_AUTH_METHOD.NO_AUTH
      }, location);
      expect(targetNoAuth.headers).toEqual({});
    });

    it('returns target with custom auth', () => {
      FauxtonAPI.registerExtension('Replication:Auth', {
        typeValue: 'TEST_CUSTOM_AUTH',
        typeLabel: 'Test Custom Auth',
        setCredentials: (repSourceOrTarget, auth) => {
          repSourceOrTarget.auth = {
            auth_creds: auth.creds
          };
        }
      });
      const target = getTarget({
        replicationTarget: Constants.REPLICATION_TARGET.NEW_LOCAL_DATABASE,
        replicationSource: Constants.REPLICATION_SOURCE.LOCAL,
        localTarget: 'my-new/db',
        targetAuth: { creds: 'sample_creds' },
        targetAuthType: 'TEST_CUSTOM_AUTH'
      });

      expect(target.auth).toEqual({ auth_creds: 'sample_creds' });
    });

  });

  describe('continuous', () => {

    it('returns true for continuous', () => {
      expect(continuous(Constants.REPLICATION_TYPE.CONTINUOUS)).toBeTruthy();
    });

    it('returns false for once', () => {
      expect(continuous(Constants.REPLICATION_TYPE.ONE_TIME)).toBeFalsy();
    });
  });

  describe('create target', () => {

    it('returns true for new local', () => {
      expect(createTarget(Constants.REPLICATION_TARGET.NEW_LOCAL_DATABASE)).toBeTruthy();
    });

    it('returns true for new remote', () => {
      expect(createTarget(Constants.REPLICATION_TARGET.NEW_REMOTE_DATABASE)).toBeTruthy();
    });

    it('returns false for existing', () => {
      expect(createTarget(Constants.REPLICATION_TARGET.EXISTING_REMOTE_DATABASE)).toBeFalsy();
    });

  });

  describe('addDocId', () => {

    it('adds doc id if it exists', () => {
      const docId = 'docId';

      expect(addDocIdAndRev(docId, null,  {})).toEqual({
        _id: docId
      });
    });

    it('adds doc and Rev if it exists', () => {
      const docId = 'docId';
      const _rev = "1-rev123";

      expect(addDocIdAndRev(docId, _rev, {})).toEqual({
        _id: docId,
        _rev: _rev
      });
    });

    it('does not add doc id if it does not exists', () => {
      expect(addDocIdAndRev(null, null, {})).toEqual({});
    });
  });

  describe("getDocUrl", () => {
    it("scrubs passwords and decodes", () => {
      const url = "http://userone:theirpassword@couchdb-host.com/my%2Fdb%2fhere";
      const cleanedUrl = "http://couchdb-host.com/my/db/here";

      expect(getDocUrl(url)).toEqual(cleanedUrl);
    });
  });

  describe("encodeFullUrl", () => {
    it("encodes db correctly", () => {
      const url = "http://dev:5984/boom/aaaa";
      const encodedUrl = encodeFullUrl(url);

      expect(encodedUrl).toBe("http://dev:5984/boom%2Faaaa");
    });

  });

  describe("decodeFullUrl", () => {

    it("encodes db correctly", () => {
      const url = "http://dev:5984/boom%2Faaaa";
      const encodedUrl = decodeFullUrl(url);

      expect(encodedUrl).toBe("http://dev:5984/boom/aaaa");
    });

  });

  describe("getCredentialsFromUrl", () => {

    it("can get username and password", () => {
      const {username, password } = getCredentialsFromUrl("https://bob:marley@my-couchdb.com/db");

      expect(username).toBe('bob');
      expect(password).toBe('marley');
    });

    it("can get username and password with special characters", () => {
      const {username, password } = getCredentialsFromUrl("http://bob:m@:/rley@my-couchdb.com/db");

      expect(username).toBe('bob');
      expect(password).toBe('m@:/rley');
    });

    it("returns nothing for no username and password", () => {
      const {username, password } = getCredentialsFromUrl("http://my-couchdb.com/db");

      expect(username).toBe('');
      expect(password).toBe('');
    });
  });

  describe("removeCredentialsFromUrl", () => {

    it("can remove username and password", () => {
      const url = removeCredentialsFromUrl("https://bob:marley@my-couchdb.com/db");
      expect(url).toBe('https://my-couchdb.com/db');
    });

    it("returns url if no password", () => {
      const url = removeCredentialsFromUrl("https://my-couchdb.com/db");
      expect(url).toBe('https://my-couchdb.com/db');
    });

    it("can remove username and password with special characters", () => {
      const url = removeCredentialsFromUrl("https://bob:m@:/rley@my-couchdb.com/db");
      expect(url).toBe('https://my-couchdb.com/db');
    });
  });

  describe('supportNewApi', () => {
    afterEach(() => {
      fetchMock.reset();
    });

    it('returns true for support', () => {
      fetchMock.getOnce('./_scheduler/jobs', {});
      return supportNewApi(true)
        .then(resp => {
          expect(resp).toBeTruthy();
        });
    });

    it('returns false for no support', () => {
      fetchMock.getOnce('./_scheduler/jobs', {
        status: 404,
        body: {error: "missing"}
      });

      return supportNewApi(true)
        .then(resp => {
          expect(resp).toBeFalsy();
        });
    });

  });

  describe('setCredentials', () => {

    afterEach(() => {
      fetchMock.reset();
    });

    it('returns true for support', () => {
      fetchMock.getOnce('./_scheduler/jobs', {});
      return supportNewApi(true)
        .then(resp => {
          expect(resp).toBeTruthy();
        });
    });

    it('returns false for no support', () => {
      fetchMock.getOnce('./_scheduler/jobs', {
        status: 404,
        body: {error: "missing"}
      });

      return supportNewApi(true)
        .then(resp => {
          expect(resp).toBeFalsy();
        });
    });

  });

  describe("fetchReplicationDocs", () => {
    const _repDocs = {
      "total_rows":2,
      "offset":0,
      "rows":[
        {
          "id":"_design/_replicator",
          "key":"_design/_replicator",
          "value":{
            "rev":"1-1390740c4877979dbe8998382876556c"
          },
          "doc":{"_id":"_design/_replicator",
            "_rev":"1-1390740c4877979dbe8998382876556c",
            "language":"javascript",
            "validate_doc_update":"\n    function(newDoc, oldDoc, userCtx) {\n        function reportError(error_msg) {\n            log('Error writing document `' + newDoc._id +\n                '\\' to the replicator database: ' + error_msg);\n            throw({forbidden: error_msg});\n        }\n\n        function validateEndpoint(endpoint, fieldName) {\n            if ((typeof endpoint !== 'string') &&\n                ((typeof endpoint !== 'object') || (endpoint === null))) {\n\n                reportError('The `' + fieldName + '\\' property must exist' +\n                    ' and be either a string or an object.');\n            }\n\n            if (typeof endpoint === 'object') {\n                if ((typeof endpoint.url !== 'string') || !endpoint.url) {\n                    reportError('The url property must exist in the `' +\n                        fieldName + '\\' field and must be a non-empty string.');\n                }\n\n                if ((typeof endpoint.auth !== 'undefined') &&\n                    ((typeof endpoint.auth !== 'object') ||\n                        endpoint.auth === null)) {\n\n                    reportError('`' + fieldName +\n                        '.auth\\' must be a non-null object.');\n                }\n\n                if ((typeof endpoint.headers !== 'undefined') &&\n                    ((typeof endpoint.headers !== 'object') ||\n                        endpoint.headers === null)) {\n\n                    reportError('`' + fieldName +\n                        '.headers\\' must be a non-null object.');\n                }\n            }\n        }\n\n        var isReplicator = (userCtx.roles.indexOf('_replicator') >= 0);\n        var isAdmin = (userCtx.roles.indexOf('_admin') >= 0);\n\n        if (oldDoc && !newDoc._deleted && !isReplicator &&\n            (oldDoc._replication_state === 'triggered')) {\n            reportError('Only the replicator can edit replication documents ' +\n                'that are in the triggered state.');\n        }\n\n        if (!newDoc._deleted) {\n            validateEndpoint(newDoc.source, 'source');\n            validateEndpoint(newDoc.target, 'target');\n\n            if ((typeof newDoc.create_target !== 'undefined') &&\n                (typeof newDoc.create_target !== 'boolean')) {\n\n                reportError('The `create_target\\' field must be a boolean.');\n            }\n\n            if ((typeof newDoc.continuous !== 'undefined') &&\n                (typeof newDoc.continuous !== 'boolean')) {\n\n                reportError('The `continuous\\' field must be a boolean.');\n            }\n\n            if ((typeof newDoc.doc_ids !== 'undefined') &&\n                !isArray(newDoc.doc_ids)) {\n\n                reportError('The `doc_ids\\' field must be an array of strings.');\n            }\n\n            if ((typeof newDoc.selector !== 'undefined') &&\n                (typeof newDoc.selector !== 'object')) {\n\n                reportError('The `selector\\' field must be an object.');\n            }\n\n            if ((typeof newDoc.filter !== 'undefined') &&\n                ((typeof newDoc.filter !== 'string') || !newDoc.filter)) {\n\n                reportError('The `filter\\' field must be a non-empty string.');\n            }\n\n            if ((typeof newDoc.doc_ids !== 'undefined') &&\n                (typeof newDoc.selector !== 'undefined')) {\n\n                reportError('`doc_ids\\' field is incompatible with `selector\\'.');\n            }\n\n            if ( ((typeof newDoc.doc_ids !== 'undefined') ||\n                  (typeof newDoc.selector !== 'undefined')) &&\n                 (typeof newDoc.filter !== 'undefined') ) {\n\n                reportError('`filter\\' field is incompatible with `selector\\' and `doc_ids\\'.');\n            }\n\n            if ((typeof newDoc.query_params !== 'undefined') &&\n                ((typeof newDoc.query_params !== 'object') ||\n                    newDoc.query_params === null)) {\n\n                reportError('The `query_params\\' field must be an object.');\n            }\n\n            if (newDoc.user_ctx) {\n                var user_ctx = newDoc.user_ctx;\n\n                if ((typeof user_ctx !== 'object') || (user_ctx === null)) {\n                    reportError('The `user_ctx\\' property must be a ' +\n                        'non-null object.');\n                }\n\n                if (!(user_ctx.name === null ||\n                    (typeof user_ctx.name === 'undefined') ||\n                    ((typeof user_ctx.name === 'string') &&\n                        user_ctx.name.length > 0))) {\n\n                    reportError('The `user_ctx.name\\' property must be a ' +\n                        'non-empty string or null.');\n                }\n\n                if (!isAdmin && (user_ctx.name !== userCtx.name)) {\n                    reportError('The given `user_ctx.name\\' is not valid');\n                }\n\n                if (user_ctx.roles && !isArray(user_ctx.roles)) {\n                    reportError('The `user_ctx.roles\\' property must be ' +\n                        'an array of strings.');\n                }\n\n                if (!isAdmin && user_ctx.roles) {\n                    for (var i = 0; i < user_ctx.roles.length; i++) {\n                        var role = user_ctx.roles[i];\n\n                        if (typeof role !== 'string' || role.length === 0) {\n                            reportError('Roles must be non-empty strings.');\n                        }\n                        if (userCtx.roles.indexOf(role) === -1) {\n                            reportError('Invalid role (`' + role +\n                                '\\') in the `user_ctx\\'');\n                        }\n                    }\n                }\n            } else {\n                if (!isAdmin) {\n                    reportError('The `user_ctx\\' property is missing (it is ' +\n                       'optional for admins only).');\n                }\n            }\n        } else {\n            if (!isAdmin) {\n                if (!oldDoc.user_ctx || (oldDoc.user_ctx.name !== userCtx.name)) {\n                    reportError('Replication documents can only be deleted by ' +\n                        'admins or by the users who created them.');\n                }\n            }\n        }\n    }\n"
          }
        },
        {
          "id":"_design/filters",
          "key":"_design/filters",
          "value":{
            "rev":"1-1390740c4877979dbe8998382876556c"
          },
          "doc":{
            "_id":"_design/filters",
            "_rev":"1-1390740c4877979dbe8998382876556c",
            "filters": {
              "afilter": "\n function (doc, req) { if (doc.type === 'a-doc') { return true; } \n return false }"
            }
          }
        },
        {
          "id":"c94d4839d1897105cb75e1251e0003ea",
          "key":"c94d4839d1897105cb75e1251e0003ea",
          "value":{
            "rev":"3-4559cb522de85ce03bd0e1991025e89a"
          },
          "doc":{"_id":"c94d4839d1897105cb75e1251e0003ea",
            "_rev":"3-4559cb522de85ce03bd0e1991025e89a",
            "user_ctx":{
              "name":"tester",
              "roles":["_admin", "_reader", "_writer"]},
            "source":{
              "headers":{
                "Authorization":"Basic dGVzdGVyOnRlc3RlcnBhc3M="
              },
              "url":"http://dev:5984/animaldb"},
            "target":{
              "headers":{
                "Authorization":"Basic dGVzdGVyOnRlc3RlcnBhc3M="},
              "url":"http://dev:5984/animaldb-clone"
            },
            "create_target":true,
            "continuous":false,
            "owner":"tester",
            "_replication_state":"completed",
            "_replication_state_time":"2017-02-28T12:16:28+00:00",
            "_replication_id":"0ce2939af29317b5dbe11c15570ddfda",
            "_replication_stats":{
              "revisions_checked":14,
              "missing_revisions_found":14,
              "docs_read":14,
              "docs_written":14,
              "changes_pending":null,
              "doc_write_failures":0,
              "checkpointed_source_seq":"15-g1AAAAJDeJyV0N0NgjAQAOAKRnlzBJ3AcKWl9Uk20ZbSEII4gm6im-gmugke1AQJ8aFpck3u50vuakJIVIaGrJqzKSADKrYxPqixECii123bVmWoFidMLGVsqEjYtP0voTcY9f6rzHqFKcglsz5K1imHkcJTnoJVPsqxUy4jxepEioJ7KM0cI7nih9BtkDSlkAif2zjp7qRHJwW9lLNdDkZ6S08nvQZJMsNT4b_d20k_d4oVE1aK6VT1AXTajes"
            }
          }
        }
      ]};

    const _schedDocs = {
      "offset": 0,
      "docs": [
        {
          "database":"_replicator",
          "doc_id":"c94d4839d1897105cb75e1251e0003ea",
          "id":null,
          "state":"completed",
          "error_count":0,
          "info":{
            "revisions_checked":0,
            "missing_revisions_found":0,
            "docs_read":0,
            "docs_written":0,
            "changes_pending":null,
            "doc_write_failures":0,
            "checkpointed_source_seq":"56-g1AAAAGweJzLYWBgYMlgTmFQTElKzi9KdUhJMjTQy00tyixJTE_VS87JL01JzCvRy0styQEqZUpkSLL___9_VgZzIm8uUIDd1NIkNSk5LYVBAW6AKXb9aLYY47ElyQFIJtVDLeIBW2ScbGJiYGJKjBloNhnisSmPBUgyNAApoGX7QbaJg21LTDEwNE8zR_aWCVGW4VCFZNkBiGVgr3GALTNLSzQ0T0xEtgyHm7MAbEaMZw"},
          "last_updated":"2017-03-07T14:46:17Z",
          "start_time":"2017-03-07T14:46:16Z"
        }
      ],
      "total": 1
    };

    describe('old api', () => {
      afterEach(() => {
        fetchMock.reset();
      });

      it("returns parsedReplicationDocs and ignores all design docs", () => {
        const pageLimit = 20;
        fetchMock.getOnce('./_scheduler/jobs', 404);
        fetchMock.get(`./_replicator/_all_docs?include_docs=true&limit=${pageLimit + 1}`, _repDocs);
        return supportNewApi(true)
          .then(() => fetchReplicationDocs(pageLimit))
          .then(docs => {
            expect(docs.length).toBe(1);
            expect(docs[0]._id).toBe("c94d4839d1897105cb75e1251e0003ea");
          });
      });
    });

    describe('new api', () => {
      afterEach(() => {
        fetchMock.reset();
      });

      it("returns parsedReplicationDocs", () => {
        const pageLimit = 20;
        fetchMock.getOnce('./_scheduler/jobs', 200);
        fetchMock.get(`./_replicator/_all_docs?include_docs=true&limit=${pageLimit + 1}`, _repDocs);
        fetchMock.get('./_scheduler/docs?include_docs=true', _schedDocs);
        return supportNewApi(true)
          .then(() => fetchReplicationDocs(pageLimit))
          .then(docs => {
            expect(docs.length).toBe(1);
            expect(docs[0]._id).toBe("c94d4839d1897105cb75e1251e0003ea");
            expect(docs[0].stateTime.toDateString()).toBe((new Date('2017-03-07T14:46:17')).toDateString());
          });
      });
    });
  });
});
