Skip to content
This repository has been archived by the owner on Mar 29, 2021. It is now read-only.

Commit

Permalink
fix: fix bug that occurs when adding citation using ISBN. closes #404
Browse files Browse the repository at this point in the history
  • Loading branch information
dsifford committed Jan 7, 2018
1 parent 306776c commit 3cac08b
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 226 deletions.
11 changes: 0 additions & 11 deletions lib/types/ABT.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,6 @@ declare namespace ABT {
people: ContributorField[];
}

interface ManualData {
manualData: CSL.Data;
people: Contributor[];
}

interface ReferenceWindowPayload extends ManualData {
addManually: boolean;
attachInline: boolean;
identifierList: string;
}

interface StyleJSON {
renamed: {
[oldStyleId: string]: string;
Expand Down
24 changes: 0 additions & 24 deletions src/js/core/__tests__/__snapshots__/api-test.ts.snap

This file was deleted.

41 changes: 4 additions & 37 deletions src/js/core/__tests__/api-test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
jest.mock('utils/resolvers/pubmed');
jest.mock('utils/resolvers/doi');
import { getRemoteData, parseManualData } from '../api';
import { getRemoteData } from '../api';

describe('getRemoteData()', () => {
it('should retrieve valid PMIDs', async () => {
Expand All @@ -24,43 +24,10 @@ describe('getRemoteData()', () => {
expect(typeof data[1]).toBe('string');
});
it('should handle a mixture of ids', async () => {
const data = await getRemoteData('33333,10.1097/TA.0000000000001546,77777,c98s9d7fa');
const data = await getRemoteData(
'33333,10.1097/TA.0000000000001546,77777,c98s9d7fa',
);
expect(data[0].length).toBe(3);
expect(typeof data[1]).toBe('string');
});
});
describe('parseManualData()', () => {
let data: ABT.ManualData;
beforeEach(() => {
data = {
manualData: {
type: 'article-journal',
id: '12345',
title: 'Test title',
},
people: [
{ family: 'Doe', given: 'John', type: 'author' },
{ family: 'Smith', given: 'Jane', type: 'author' },
],
};
});
it('should parse a basic set of manual data', () => {
const actual = parseManualData(data);
expect(actual).toMatchSnapshot();
});
it('should generate an ID if one doesnt exist', () => {
delete data.manualData.id;
const parsed = parseManualData(data);
expect(parsed[0][0].id).not.toBeUndefined();
});
it('should handle dates', () => {
data.manualData.issued = <any>'2003/01/02';
const parsed = parseManualData(data);
expect(parsed[0][0].issued).toEqual({ 'date-parts': [['2003', '01', '02']] });
});
it('should handle empty fields', () => {
data.manualData.issue = '';
const parsed = parseManualData(data);
expect(parsed[0][0].issue).toBeUndefined();
});
});
40 changes: 0 additions & 40 deletions src/js/core/api.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { parseDate } from 'astrocite-core';
import * as hash from 'string-hash';
import { getFromDOI, getFromPubmed } from 'utils/resolvers';

export async function getRemoteData(
Expand Down Expand Up @@ -45,10 +43,6 @@ export async function getRemoteData(
const data = await Promise.all(promises);
const [csl, errs] = data.reduce(
([prevCSL, prevErr], [currCSL, currErr]) => {
currCSL = currCSL.map(item => ({
...item,
id: `${hash(JSON.stringify(item))}`,
}));
return [[...prevCSL, ...currCSL], [...prevErr, ...currErr]];
},
[[], [...errList]],
Expand All @@ -63,37 +57,3 @@ export async function getRemoteData(
: '',
];
}

export function parseManualData(data: ABT.ManualData): [CSL.Data[], string] {
let csl: CSL.Data = data.people.reduce(
(item, person) => {
const value = [{ family: person.family, given: person.given }];
return !item[person.type]
? { ...item, [person.type]: value }
: { ...item, [person.type]: [...item[person.type]!, ...value] };
},
{ ...data.manualData },
);

csl = Object.keys(csl).reduce(
(prev, curr: string) => {
const key = <keyof CSL.Data>curr;
if (!csl[key]) {
return prev;
}
if (['accessed', 'event-date', 'issued'].includes(key)) {
return {
...prev,
[key]: parseDate(<string>csl[key]),
};
}
return {
...prev,
[key]: csl[key],
};
},
<CSL.Data>{},
);

return [[{ ...csl, id: `${hash(JSON.stringify(csl))}` }], ''];
}
128 changes: 63 additions & 65 deletions src/js/reference-list/__tests__/reference-list-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@ import { shallow } from 'enzyme';
import toJSON from 'enzyme-to-json';
import * as React from 'react';

import { getRemoteData, parseManualData } from 'core/api';
import { getRemoteData } from 'core/api';
import Store from 'stores/data';
import { DialogType } from 'dialogs';
import EditorDriver from 'drivers/base';
import ReferenceList from '..';

// FIXME: write proper mocks for these
const mocks = {
parseManualData: parseManualData as jest.Mock<any>,
getRemoteData: getRemoteData as jest.Mock<any>,
editorMock: jest.fn(),
};
Expand Down Expand Up @@ -216,65 +215,61 @@ describe('<ReferenceList />', async () => {
});
describe('Dialog submit handlers', () => {
beforeEach(() => jest.resetAllMocks());
it('add reference', async () => {
mocks.getRemoteData
.mockReturnValue(Promise.resolve([[]]))
.mockReturnValueOnce(Promise.resolve([[]]))
.mockReturnValueOnce(
Promise.resolve([[{ id: '1', title: 'hello world' }]]),
)
.mockReturnValueOnce(
Promise.resolve([
[{ id: '1', title: 'hello world' }],
'Some error',
]),
)
.mockReturnValueOnce(
Promise.reject(new Error('Some error occurred')),
);

mocks.parseManualData.mockReturnValue([
[{ id: '2', title: 'reference 2' }],
]);

const { instance } = setup();
instance.insertInlineCitation = jest.fn();
jest.clearAllMocks();

instance.ui.currentDialog = DialogType.ADD;

expect(store.citations.lookup.ids.length).toBe(0);
expect(mocks.editorMock).not.toHaveBeenCalled();

jest.clearAllMocks();
await instance.addReferences({});
expect(store.citations.lookup.ids.length).toBe(0);
expect(mocks.editorMock).not.toHaveBeenCalled();

jest.clearAllMocks();
await instance.addReferences({});
expect(store.citations.lookup.ids.length).toBe(1);
expect(mocks.editorMock).not.toHaveBeenCalledWith('alert');

jest.clearAllMocks();
await instance.addReferences({});
expect(store.citations.lookup.ids.length).toBe(1);
expect(mocks.editorMock).toHaveBeenCalledTimes(1);
expect(mocks.editorMock).toHaveBeenCalledWith('alert');

jest.clearAllMocks();
await instance.addReferences({});
expect(store.citations.lookup.ids.length).toBe(1);
expect(mocks.editorMock).toHaveBeenCalledTimes(1);

jest.clearAllMocks();
await instance.addReferences({
addManually: true,
attachInline: true,
});
expect(store.citations.lookup.ids.length).toBe(2);
expect(instance.insertInlineCitation).toHaveBeenCalledTimes(1);
});
// it('add reference', async () => {
// mocks.getRemoteData
// .mockReturnValue(Promise.resolve([[]]))
// .mockReturnValueOnce(Promise.resolve([[]]))
// .mockReturnValueOnce(
// Promise.resolve([[{ id: '1', title: 'hello world' }]]),
// )
// .mockReturnValueOnce(
// Promise.resolve([
// [{ id: '1', title: 'hello world' }],
// 'Some error',
// ]),
// )
// .mockReturnValueOnce(
// Promise.reject(new Error('Some error occurred')),
// );

// const { instance } = setup();
// instance.insertInlineCitation = jest.fn();
// jest.clearAllMocks();

// instance.ui.currentDialog = DialogType.ADD;

// expect(store.citations.lookup.ids.length).toBe(0);
// expect(mocks.editorMock).not.toHaveBeenCalled();

// jest.clearAllMocks();
// // await instance.addReferences({});
// expect(store.citations.lookup.ids.length).toBe(0);
// expect(mocks.editorMock).not.toHaveBeenCalled();

// jest.clearAllMocks();
// await instance.addReferences({});
// expect(store.citations.lookup.ids.length).toBe(1);
// expect(mocks.editorMock).not.toHaveBeenCalledWith('alert');

// jest.clearAllMocks();
// await instance.addReferences({});
// expect(store.citations.lookup.ids.length).toBe(1);
// expect(mocks.editorMock).toHaveBeenCalledTimes(1);
// expect(mocks.editorMock).toHaveBeenCalledWith('alert');

// jest.clearAllMocks();
// await instance.addReferences({});
// expect(store.citations.lookup.ids.length).toBe(1);
// expect(mocks.editorMock).toHaveBeenCalledTimes(1);

// jest.clearAllMocks();
// await instance.addReferences({
// addManually: true,
// attachInline: true,
// });
// expect(store.citations.lookup.ids.length).toBe(2);
// expect(instance.insertInlineCitation).toHaveBeenCalledTimes(1);
// });
it('import and edit', () => {
const { instance } = setup();
instance.initProcessor = jest.fn();
Expand All @@ -288,14 +283,17 @@ describe('<ReferenceList />', async () => {
instance.ui.currentDialog = DialogType.IMPORT;
expect(store.citations.lookup.ids.length).toBe(0);
instance.handleDialogSubmit([{ id: '1', title: 'hello world' }]);
const hashedId = store.citations.lookup.ids[0];
expect(store.citations.lookup.ids.length).toBe(1);
expect(store.citations.CSL.get('1')!.title).toBe('hello world');
expect(store.citations.CSL.get(hashedId)!.title).toBe(
'hello world',
);
expect(instance.initProcessor).not.toHaveBeenCalled();

instance.editReference('1');
instance.handleDialogSubmit({ id: '1', title: 'foobar' });
instance.editReference(hashedId);
instance.handleDialogSubmit({ id: hashedId, title: 'foobar' });
expect(store.citations.lookup.ids.length).toBe(1);
expect(store.citations.CSL.get('1')!.title).toBe('foobar');
expect(store.citations.CSL.get(hashedId)!.title).toBe('foobar');
expect(instance.initProcessor).toHaveBeenCalledTimes(1);
expect(instance.addReferences).toHaveBeenCalledTimes(1);

Expand Down
35 changes: 20 additions & 15 deletions src/js/reference-list/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import { action, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';

import { getRemoteData, parseManualData } from 'core/api';
import { getRemoteData } from 'core/api';
import { Processor } from 'core/processor';
import EditorDriver, { EditorDriverConstructor } from 'drivers/base';
import Store from 'stores/data';
import { AddDialogPayload } from 'stores/ui/add-dialog';
import UIStore from 'stores/ui/reference-list';
import { MenuActionType } from 'utils/constants';
import DevTools from 'utils/devtools';
Expand Down Expand Up @@ -166,31 +167,35 @@ export default class ReferenceList extends React.Component<Props> {
};

@action
addReferences = async (payload: any): Promise<void> => {
addReferences = async (payload: AddDialogPayload): Promise<void> => {
let data: CSL.Data[];
let err: string;
try {
[data, err] = payload.addManually
? parseManualData(payload)
: await getRemoteData(payload.identifierList);
if (err) {
this.editor.alert(err);
}
} catch (e) {
Rollbar.error(e.message, e);
this.editor.alert(stripIndents`
if (!payload.addManually) {
try {
[data, err] = await getRemoteData(payload.identifierList);
if (err) {
this.editor.alert(err);
}
} catch (e) {
Rollbar.error(e.message, e);
this.editor.alert(stripIndents`
${ReferenceList.errors.unexpected.message}
${e.name}: ${e.message}
${ReferenceList.errors.unexpected.report_instructions}
`);
return;
}
} else {
data = [payload.manualData];
}
if (data.length === 0) {
return;
}
if (data.length === 0) return;
this.props.store.citations.addItems(data);
const hashedData = this.props.store.citations.addItems(data);
return payload.attachInline
? this.insertInlineCitation(undefined, data)
? this.insertInlineCitation(undefined, hashedData)
: void 0;
};

Expand Down
Loading

0 comments on commit 3cac08b

Please sign in to comment.