Skip to content

Commit

Permalink
add rep footer and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mharrigan26 committed Feb 24, 2023
1 parent 9dd1a36 commit c878ceb
Show file tree
Hide file tree
Showing 14 changed files with 291 additions and 39 deletions.
38 changes: 32 additions & 6 deletions app/addons/replication/__tests__/actions.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
// License for the specific language governing permissions and limitations under
// the License.

import {replicate, getReplicationStateFrom, deleteDocs} from '../actions';
import {replicate, getReplicationStateFrom, deleteDocs, setPageLimit} from '../actions';
import ActionTypes from '../actiontypes';
import fetchMock from 'fetch-mock';
import FauxtonAPI from '../../../core/api';
Expand All @@ -33,6 +33,7 @@ describe("Replication Actions", () => {

it('creates a new database if it does not exist', () => {
const dispatch = () => {};
const pageLimit = 20;
fetchMock.postOnce('./_replicator', {
status: 404,
body: {
Expand Down Expand Up @@ -66,7 +67,8 @@ describe("Replication Actions", () => {
replicationTarget: "REPLICATION_TARGET_NEW_LOCAL_DATABASE",
replicationType: "",
username: "tester"
})(dispatch).then(() => {
}, pageLimit)(dispatch).then(() => {
finalPost.calls('./_replicator');
expect(finalPost.calls('./_replicator').length).toBe(3);

//fetchMock.done();
Expand All @@ -75,6 +77,7 @@ describe("Replication Actions", () => {

it('does not try to create new database if it already exist', () => {
const dispatch = () => {};
const pageLimit = 20;
const mockPost = fetchMock.postOnce('./_replicator', {
status: 200,
body: {
Expand All @@ -93,7 +96,8 @@ describe("Replication Actions", () => {
replicationTarget: "REPLICATION_TARGET_NEW_LOCAL_DATABASE",
replicationType: "",
username: "tester"
})(dispatch).then(() => {
}, pageLimit)(dispatch).then(() => {
mockPost.calls('./_replicator');
expect(mockPost.calls('./_replicator').length).toBe(1);
fetchMock.done();
});
Expand Down Expand Up @@ -255,22 +259,44 @@ describe("Replication Actions", () => {
}
}
];
const pageLimit = 20;

fetchMock.getOnce('./_scheduler/jobs', 404);
fetchMock.getOnce('./_replicator/_all_docs?include_docs=true&limit=100', {rows: []});
fetchMock.getOnce(`./_replicator/_all_docs?include_docs=true&limit=${pageLimit + 1}`, {rows: []});
fetchMock.postOnce('./_replicator/_bulk_docs', {
status: 200,
body: resp
});


const dispatch = ({type}) => {
if (ActionTypes.REPLICATION_CLEAR_SELECTED_DOCS === type) {
done();
}
};

deleteDocs(docs)(dispatch);
deleteDocs(docs, pageLimit)(dispatch);
});
});

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

it('sends request for new replications list', (done) => {
const pageLimit = 20;

fetchMock.getOnce('./_scheduler/jobs', 404);
fetchMock.getOnce(`./_replicator/_all_docs?include_docs=true&limit=${pageLimit + 1}`, {rows: []});

const dispatch = ({type, options}) => {
if (ActionTypes.REPLICATION_SET_PAGE_LIMIT === type) {
expect(options).toEqual(pageLimit);
done();
}
};

setPageLimit(pageLimit)(dispatch);
});
});
});
10 changes: 6 additions & 4 deletions app/addons/replication/__tests__/api.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -577,10 +577,11 @@ describe('Replication API', () => {
});

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=100', _repDocs);
fetchMock.get(`./_replicator/_all_docs?include_docs=true&limit=${pageLimit + 1}`, _repDocs);
return supportNewApi(true)
.then(fetchReplicationDocs)
.then(() => fetchReplicationDocs(pageLimit))
.then(docs => {
expect(docs.length).toBe(1);
expect(docs[0]._id).toBe("c94d4839d1897105cb75e1251e0003ea");
Expand All @@ -594,11 +595,12 @@ describe('Replication API', () => {
});

it("returns parsedReplicationDocs", () => {
const pageLimit = 20;
fetchMock.getOnce('./_scheduler/jobs', 200);
fetchMock.get('./_replicator/_all_docs?include_docs=true&limit=100', _repDocs);
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)
.then(() => fetchReplicationDocs(pageLimit))
.then(docs => {
expect(docs.length).toBe(1);
expect(docs[0]._id).toBe("c94d4839d1897105cb75e1251e0003ea");
Expand Down
63 changes: 63 additions & 0 deletions app/addons/replication/__tests__/replication-footer.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// 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:https://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 React from 'react';
import { mount } from 'enzyme';
import sinon from 'sinon';
import { ReplicationFooter } from '../components/replication-footer';

describe('Replication Footer', () =>{
it('no replications to display', () => {
const footer = mount(<ReplicationFooter
statusDocs={[]}
pageLimit={5}
setPageLimit={() => {}}
/>);

expect(footer.find('.current-replications').text()).toBe('Showing 0 replications.');
});

it('display max # of replications', () => {
const footer = mount(<ReplicationFooter
statusDocs={[1, 2, 3, 4, 5]}
pageLimit={5}
setPageLimit={() => {}}
/>);

expect(footer.find('.current-replications').text()).toBe('Showing replications 1 - 5');
});

it('display replications with less than max #', () => {
const footer = mount(<ReplicationFooter
statusDocs={[1, 2, 3, 4, 5, 6, 7, 8]}
pageLimit={10}
setPageLimit={() => {}}
/>);

expect(footer.find('.current-replications').text()).toBe('Showing replications 1 - 8');
});

it('change max value with dropdown', () => {
const spy = sinon.spy();
const footer = mount(<ReplicationFooter
statusDocs={[1, 2, 3, 4, 5, 6, 7, 8]}
pageLimit={5}
setPageLimit={spy}
/>);

expect(footer.find('.current-replications').text()).toBe('Showing replications 1 - 5');
footer.find('#select-per-page').simulate('change', {
target: {value: 10}
});
sinon.assert.calledOnce(spy);
});
});
25 changes: 15 additions & 10 deletions app/addons/replication/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export const getDatabasesList = () => dispatch => {
});
};

export const replicate = (params) => dispatch => {
export const replicate = (params, pageLimit) => dispatch => {
const replicationDoc = createReplicationDoc(params);
const url = MainHelper.getServerUrl("/_replicator");
const promise = post(url, replicationDoc);
Expand Down Expand Up @@ -85,12 +85,12 @@ export const replicate = (params) => dispatch => {
clear: true
});

dispatch(getReplicationActivity());
dispatch(getReplicationActivity(pageLimit));
FauxtonAPI.navigate('#/replication');
}).catch(json => {
if (json.error && json.error === "not_found") {
return createReplicatorDB().then(() => {
return replicate(params)(dispatch);
return replicate(params, pageLimit)(dispatch);
}).catch(handleError);
}
handleError(json);
Expand All @@ -111,15 +111,12 @@ export const clearReplicationForm = () => {
return { type: ActionTypes.REPLICATION_CLEAR_FORM };
};

export const getReplicationActivity = () => dispatch => {
export const getReplicationActivity = (pageLimit) => (dispatch) => {
dispatch({
type: ActionTypes.REPLICATION_FETCHING_STATUS,
});

supportNewApi()
.then(supportNewApi => {
return fetchReplicationDocs(supportNewApi);
})
fetchReplicationDocs(pageLimit)
.then(docs => {
dispatch({
type: ActionTypes.REPLICATION_STATUS,
Expand Down Expand Up @@ -201,7 +198,7 @@ export const clearSelectedReplicates = () => {
};
};

export const deleteDocs = (docs) => dispatch => {
export const deleteDocs = (docs, pageLimit) => dispatch => {
const bulkDocs = docs.map(({raw: doc}) => {
doc._deleted = true;
return doc;
Expand Down Expand Up @@ -237,7 +234,7 @@ export const deleteDocs = (docs) => dispatch => {
});

dispatch(clearSelectedDocs());
dispatch(getReplicationActivity());
dispatch(getReplicationActivity(pageLimit));
})
.catch(resp => {
resp.json()
Expand Down Expand Up @@ -420,3 +417,11 @@ export const checkForNewApi = () => dispatch => {
});
});
};

export const setPageLimit = (limit) => dispatch => {
dispatch({
type: ActionTypes.REPLICATION_SET_PAGE_LIMIT,
options: limit,
});
getReplicationActivity(limit)(dispatch);
};
3 changes: 2 additions & 1 deletion app/addons/replication/actiontypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,6 @@ export default {
REPLICATION_CLEAR_SELECTED_REPLICATES: 'REPLICATION_CLEAR_SELECTED_REPLICATES',
REPLICATION_FETCHING_FORM_STATE: 'REPLICATION_FETCHING_FORM_STATE',
REPLICATION_HIDE_PASSWORD_MODAL: 'REPLICATION_HIDE_PASSWORD_MODAL',
REPLICATION_SHOW_PASSWORD_MODAL: 'REPLICATION_SHOW_PASSWORD_MODAL'
REPLICATION_SHOW_PASSWORD_MODAL: 'REPLICATION_SHOW_PASSWORD_MODAL',
REPLICATION_SET_PAGE_LIMIT: 'REPLICATION_SET_PAGE_LIMIT'
};
6 changes: 3 additions & 3 deletions app/addons/replication/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import FauxtonAPI from '../../core/api';
import Helpers from '../../helpers';
import {get, post, put} from '../../core/ajax';
import base64 from 'base-64';
import _ from 'lodash';

let newApiPromise = null;
export const supportNewApi = (forceCheck) => {
Expand Down Expand Up @@ -308,10 +307,11 @@ export const combineDocsAndScheduler = (docs, schedulerDocs) => {
});
};

export const fetchReplicationDocs = () => {
export const fetchReplicationDocs = (maxItems) => {
return supportNewApi()
.then(newApi => {
const url = Helpers.getServerUrl('/_replicator/_all_docs?include_docs=true&limit=100');
// Increase limit by 1 to account for the design doc in the DB
const url = Helpers.getServerUrl(`/_replicator/_all_docs?include_docs=true&limit=${maxItems + 1}`);
const docsPromise = get(url)
.then((res) => {
if (res.error) {
Expand Down
4 changes: 2 additions & 2 deletions app/addons/replication/assets/less/replication.less
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
@replication_input_field_width: 400px;

div.replication__page {
padding-top: 25px !important;
padding: 25px 0 40px 0 !important;
display: flex;
flex-direction: column;
align-items: center;
Expand Down Expand Up @@ -179,7 +179,7 @@ div.replication__page {
}

.replication__activity {
padding: 0 10px 0 10px !important;
padding: 0 10px 40px 10px !important;
width:100%;
}

Expand Down
1 change: 0 additions & 1 deletion app/addons/replication/components/activity.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ export default class Activity extends React.Component {
<div className="replication__activity">
<p className="replication__activity-caveat">
Replications must have a replication document to display in the following table.
Up to about 100 replications are displayed.
</p>
<ReplicationHeader
filter={filter}
Expand Down
52 changes: 52 additions & 0 deletions app/addons/replication/components/replication-footer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// 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:https://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 PropTypes from 'prop-types';

import React from 'react';
import PerPageSelector from '../../documents/index-results/components/pagination/PerPageSelector';

export class ReplicationFooter extends React.Component {

getFooterText () {
const { statusDocs, pageLimit } = this.props;

if (statusDocs.length === 0) {
return <span>Showing 0 replications.</span>;
}

//either page limit or total # of replications, whichever is smaller
return <span>Showing replications 1 - {Math.min(pageLimit, statusDocs.length)}</span>;
}

perPageChange (limit) {
this.props.setPageLimit(limit);
}

render() {
const { pageLimit } = this.props;

return (
<footer className="pagination-footer">
<PerPageSelector label="Max replications displayed:" options={[5, 10, 25, 50, 100, 200, 300, 400, 500]} perPageChange={this.perPageChange.bind(this)} perPage={pageLimit} />
<div className="current-replications">
{this.getFooterText()}
</div>
</footer>
);
}
}

ReplicationFooter.PropTypes = {
statusDocs: PropTypes.array.isRequired,
pageLimit: PropTypes.number.isRequired,
setPageLimit: PropTypes.func.isRequired
};
Loading

0 comments on commit c878ceb

Please sign in to comment.