mirror of
https://github.com/zotero/zotero.git
synced 2026-09-27 01:21:27 +00:00
When resizing the window in list mode to match the height of the content, account for the difference between outerHeight and innerHeight of the window on Linux. outerHeight > innerHeight (perhaps Linux includes chrome, borders, etc. in its outerHeight), so we have to add their difference to the desired height for resizing. Otherwise, the visible dialog ends up receiving only some of the desired height and the last row is cut off. Also, ensure that in tests, we wait for searching triggered by switching dialog mode to finish before running the next search. Fixes: zotero#5502
652 lines
23 KiB
JavaScript
652 lines
23 KiB
JavaScript
describe("Citation Dialog", function () {
|
|
let io = {
|
|
accept() {},
|
|
cancel() {},
|
|
sort() {},
|
|
sortable: false,
|
|
citation: {
|
|
citationItems: [],
|
|
properties: {
|
|
unsorted: false,
|
|
}
|
|
},
|
|
getItems() {
|
|
return [];
|
|
},
|
|
allCitedDataLoadedPromise: Promise.resolve(),
|
|
};
|
|
let dialog, win, IOManager, CitationDataManager, SearchHandler;
|
|
|
|
before(async function () {
|
|
// one of helper functions of searchHandler uses zotero pane
|
|
win = await loadZoteroPane();
|
|
let dialogPromise = waitForWindow("chrome://zotero/content/integration/citationDialog.xhtml");
|
|
Services.ww.openWindow(null, "chrome://zotero/content/integration/citationDialog.xhtml", "", "", io);
|
|
dialog = await dialogPromise;
|
|
IOManager = dialog.IOManager;
|
|
CitationDataManager = dialog.CitationDataManager;
|
|
SearchHandler = dialog.SearchHandler;
|
|
// wait for everything (e.g. itemTree/collectionTree) inside of the dialog to be loaded.
|
|
while (!dialog.loaded) {
|
|
await Zotero.Promise.delay(10);
|
|
}
|
|
});
|
|
|
|
beforeEach(async function () {
|
|
// Many operations (e.g. IOManager.addItemsToCitation) are disabled
|
|
// when search runs. Search can be triggered by a variety of events
|
|
// so before each test, we make sure that search has finished running
|
|
while (SearchHandler.searching) {
|
|
await Zotero.Promise.delay(10);
|
|
}
|
|
});
|
|
|
|
after(function () {
|
|
dialog.close();
|
|
win.close();
|
|
});
|
|
|
|
describe("Manage entries in the citation", function () {
|
|
let citedItemNotInLibrary = {
|
|
id: "o7HzMbH6/6iMXHx6s",
|
|
itemData: {
|
|
id: "o7HzMbH6/6iMXHx6s",
|
|
type: "book",
|
|
title: "cited_not_in_library_test_title",
|
|
author: [
|
|
{
|
|
family: "Last",
|
|
given: "First"
|
|
}
|
|
]
|
|
},
|
|
uris: [
|
|
"http://zotero.org/users/11573780/items/K22KNVZL"
|
|
],
|
|
item: {
|
|
id: "o7HzMbH6/6iMXHx6s",
|
|
type: "book",
|
|
title: "cited_not_in_library_test_title",
|
|
author: [
|
|
{
|
|
family: "Last",
|
|
given: "First"
|
|
}
|
|
],
|
|
"title-main": "cited_not_in_library_test_title",
|
|
"title-sub": "",
|
|
"title-subjoin": ""
|
|
},
|
|
label: undefined,
|
|
locator: undefined,
|
|
prefix: undefined,
|
|
suffix: undefined,
|
|
"suppress-author": undefined
|
|
};
|
|
let citedItemOne = {
|
|
id: null,
|
|
item: {
|
|
id: null,
|
|
type: "book",
|
|
title: "cited_in_library_test_title",
|
|
author: [
|
|
{
|
|
family: "Last",
|
|
given: "First"
|
|
}
|
|
],
|
|
"title-main": "cited_in_library_test_title",
|
|
"title-sub": "",
|
|
"title-subjoin": ""
|
|
},
|
|
label: undefined,
|
|
locator: undefined,
|
|
prefix: undefined,
|
|
suffix: undefined,
|
|
"suppress-author": undefined
|
|
};
|
|
let itemOne, itemTwo, bubbleInput, ZoteroCiteGetItemStub, surrogateCitedItem;
|
|
|
|
before(async function () {
|
|
bubbleInput = dialog.document.querySelector("bubble-input");
|
|
|
|
// Virtual Zotero.Item for a cited item that does not exist in the library.
|
|
// Same logic as in Zotero.Integration.Citation.loadItemData.
|
|
surrogateCitedItem = new Zotero.Item();
|
|
Zotero.Utilities.itemFromCSLJSON(surrogateCitedItem, citedItemNotInLibrary.itemData);
|
|
surrogateCitedItem.cslItemID = citedItemNotInLibrary.id;
|
|
surrogateCitedItem.cslURIs = citedItemNotInLibrary.uris;
|
|
surrogateCitedItem.cslItemData = citedItemNotInLibrary.itemData;
|
|
// Zotero.Cite.getItem called with citedItemNotInLibrary returns virtual Zotero.Item from above
|
|
ZoteroCiteGetItemStub = sinon.stub(Zotero.Cite, 'getItem').callsFake(function (id) {
|
|
if (id === citedItemNotInLibrary.id) {
|
|
return surrogateCitedItem;
|
|
}
|
|
return Zotero.Items.get(id);
|
|
});
|
|
|
|
itemOne = await createDataObject('item', { title: "one" });
|
|
itemOne.setCreators([
|
|
{
|
|
firstName: "First_One",
|
|
lastName: "Last_One",
|
|
creatorType: "author"
|
|
}
|
|
]);
|
|
await itemOne.saveTx();
|
|
// citedItemOne is an earlier cited itemOne
|
|
citedItemOne.id = itemOne.id;
|
|
citedItemOne.item.id = itemOne.id;
|
|
|
|
itemTwo = await createDataObject('item', { title: "two" });
|
|
itemTwo.setCreators([
|
|
{
|
|
firstName: "First_Two",
|
|
lastName: "Last_Two",
|
|
creatorType: "author"
|
|
}
|
|
]);
|
|
await itemTwo.saveTx();
|
|
});
|
|
|
|
after(function () {
|
|
ZoteroCiteGetItemStub.restore();
|
|
});
|
|
|
|
beforeEach(function () {
|
|
io.citation.citationItems = [];
|
|
io.citation.sortable = false;
|
|
dialog.document.getElementById("keepSorted").checked = false;
|
|
io.sort = () => {};
|
|
CitationDataManager.items = [];
|
|
IOManager.updateBubbleInput();
|
|
});
|
|
|
|
it("should add an item to citation", async function () {
|
|
await IOManager.addItemsToCitation([itemOne]);
|
|
|
|
let bubbles = bubbleInput.getAllBubbles();
|
|
assert.equal(CitationDataManager.items.length, 1);
|
|
assert.equal(bubbles.length, 1);
|
|
assert.equal(bubbles[0].textContent, itemOne.getCreator(0).lastName);
|
|
});
|
|
|
|
it("should remove an item from citation", async function () {
|
|
await IOManager.addItemsToCitation([itemOne, itemTwo]);
|
|
let bubbles = bubbleInput.getAllBubbles();
|
|
assert.equal(bubbles.length, 2);
|
|
|
|
let firstBubbleItem = CitationDataManager.items[0];
|
|
IOManager._deleteItem(firstBubbleItem.dialogReferenceID);
|
|
|
|
bubbles = bubbleInput.getAllBubbles();
|
|
assert.equal(CitationDataManager.items.length, 1);
|
|
assert.equal(CitationDataManager.items[0].id, itemTwo.id);
|
|
assert.equal(bubbles.length, 1);
|
|
assert.equal(bubbles[0].textContent, itemTwo.getCreator(0).lastName);
|
|
});
|
|
|
|
it("should build citation with a cited item in library", async function () {
|
|
io.citation.citationItems = [citedItemOne];
|
|
|
|
await CitationDataManager.buildCitation();
|
|
IOManager.updateBubbleInput();
|
|
|
|
let bubbles = bubbleInput.getAllBubbles();
|
|
assert.equal(CitationDataManager.items.length, 1);
|
|
assert.equal(bubbles.length, 1);
|
|
assert.equal(bubbles[0].textContent, itemOne.getCreator(0).lastName);
|
|
});
|
|
|
|
it("should build citation with a cited item not in library", async function () {
|
|
io.citation.citationItems = [citedItemNotInLibrary];
|
|
|
|
await CitationDataManager.buildCitation();
|
|
IOManager.updateBubbleInput();
|
|
|
|
let bubbles = bubbleInput.getAllBubbles();
|
|
assert.equal(CitationDataManager.items.length, 1);
|
|
assert.equal(bubbles.length, 1);
|
|
assert.equal(bubbles[0].textContent, surrogateCitedItem.getCreator(0).lastName);
|
|
});
|
|
|
|
it("should add a locator/suffix/prefix to a bubble", async function () {
|
|
// add two bubbles for the same item
|
|
await IOManager.addItemsToCitation([itemOne, itemOne]);
|
|
assert.equal(CitationDataManager.items.length, 2);
|
|
|
|
// open popup
|
|
let firstBubble = CitationDataManager.items[0];
|
|
IOManager._openItemDetailsPopup(firstBubble.dialogReferenceID);
|
|
let popup = dialog.document.getElementById("itemDetails");
|
|
|
|
// give the popup time to open
|
|
await Zotero.Promise.delay(50);
|
|
assert.equal(popup.state, "open");
|
|
|
|
// set locator/suffix/prefix values
|
|
popup.querySelector("#locator").value = "10";
|
|
popup.querySelector("#suffix").value = "suffix";
|
|
popup.querySelector("#prefix").value = "prefix";
|
|
popup.querySelector("#prefix").dispatchEvent(new Event('input', { bubbles: true }));
|
|
|
|
// make sure they are set on the bubbleItem
|
|
assert.equal(firstBubble.locator, "10");
|
|
assert.equal(firstBubble.suffix, "suffix");
|
|
assert.equal(firstBubble.prefix, "prefix");
|
|
let bubble = dialog.document.querySelector(`.bubble[dialogReferenceID="${firstBubble.dialogReferenceID}"]`);
|
|
assert.equal(bubble.textContent, "prefix Last_One, p. 10 suffix");
|
|
|
|
// make sure the other bubbleItem is not affected
|
|
let secondBubble = CitationDataManager.items[1];
|
|
assert.notOk(secondBubble.locator);
|
|
assert.notOk(secondBubble.suffix);
|
|
assert.notOk(secondBubble.prefix);
|
|
});
|
|
|
|
it("should change the order of bubbles", async function () {
|
|
// add two items
|
|
await IOManager.addItemsToCitation([itemOne, itemTwo]);
|
|
let bubbleItemOne = CitationDataManager.items[0];
|
|
let bubbleItemTwo = CitationDataManager.items[1];
|
|
|
|
// check initial order
|
|
let bubbles = bubbleInput.getAllBubbles();
|
|
assert.equal(bubbles[0].getAttribute("dialogReferenceID"), bubbleItemOne.dialogReferenceID);
|
|
assert.equal(bubbles[1].getAttribute("dialogReferenceID"), bubbleItemTwo.dialogReferenceID);
|
|
|
|
// move the second item to the first position
|
|
IOManager._moveItem(bubbleItemTwo.dialogReferenceID, 0);
|
|
|
|
// ensure the order is correct
|
|
assert.equal(CitationDataManager.items[0].dialogReferenceID, bubbleItemTwo.dialogReferenceID);
|
|
assert.equal(CitationDataManager.items[1].dialogReferenceID, bubbleItemOne.dialogReferenceID);
|
|
bubbles = dialog.document.querySelector("bubble-input").getAllBubbles();
|
|
assert.equal(bubbles[0].getAttribute("dialogReferenceID"), bubbleItemTwo.dialogReferenceID);
|
|
assert.equal(bubbles[1].getAttribute("dialogReferenceID"), bubbleItemOne.dialogReferenceID);
|
|
});
|
|
|
|
it("should sort the citation", async function () {
|
|
// Make dialog sortable
|
|
io.citation.sortable = true;
|
|
dialog.document.getElementById("keepSorted").checked = true;
|
|
// Mock sort.io implementation that sorts itemOne to the first position
|
|
io.sort = () => {
|
|
let items = io.citation.citationItems;
|
|
items.sort((a, b) => {
|
|
if (a.id === itemOne.id) return -1;
|
|
if (b.id === itemOne.id) return 1;
|
|
return 0;
|
|
});
|
|
io.citation.sortedItems = [
|
|
[null, items[0]],
|
|
[null, items[1]]
|
|
];
|
|
};
|
|
|
|
// Add items to citation in wrong order
|
|
await IOManager.addItemsToCitation([itemTwo, itemOne]);
|
|
|
|
// Make sure the bubbleItems are sorted with itemOne being first
|
|
let firstBubbleItem = CitationDataManager.items[0];
|
|
let secondBubbleItem = CitationDataManager.items[1];
|
|
assert.equal(firstBubbleItem.id, itemOne.id);
|
|
assert.equal(secondBubbleItem.id, itemTwo.id);
|
|
let bubbles = bubbleInput.getAllBubbles();
|
|
assert.equal(bubbles[0].getAttribute("dialogReferenceID"), firstBubbleItem.dialogReferenceID);
|
|
assert.equal(bubbles[1].getAttribute("dialogReferenceID"), secondBubbleItem.dialogReferenceID);
|
|
});
|
|
|
|
it("should update io.citation.items from bubbles", async function () {
|
|
let bubbleItems = CitationDataManager.items;
|
|
// Build citation with several cited items
|
|
io.citation.citationItems = [citedItemOne, citedItemNotInLibrary];
|
|
await CitationDataManager.buildCitation();
|
|
|
|
// Add another item
|
|
await IOManager.addItemsToCitation([itemTwo], { index: 2 });
|
|
|
|
// Add modifications
|
|
bubbleItems[0].label = "page";
|
|
bubbleItems[0].locator = "10";
|
|
|
|
bubbleItems[1].prefix = "prefix";
|
|
bubbleItems[1].suffix = "suffix";
|
|
|
|
bubbleItems[2].suppressAuthor = true;
|
|
|
|
// Update io.citation.items and make sure it looks right
|
|
CitationDataManager.updateCitationObject(true);
|
|
let expected = [
|
|
{
|
|
id: itemOne.id,
|
|
locator: "10",
|
|
label: "page"
|
|
},
|
|
{
|
|
id: citedItemNotInLibrary.id,
|
|
suffix: "suffix",
|
|
prefix: "prefix",
|
|
itemData: citedItemNotInLibrary.itemData,
|
|
uris: citedItemNotInLibrary.uris,
|
|
},
|
|
{
|
|
id: itemTwo.id,
|
|
"suppress-author": true
|
|
}
|
|
];
|
|
assert.deepEqual(io.citation.citationItems, expected);
|
|
});
|
|
});
|
|
|
|
describe("UI", function () {
|
|
beforeEach(function () {
|
|
CitationDataManager.items = [];
|
|
IOManager.updateBubbleInput();
|
|
});
|
|
|
|
it("should switch dialog mode", async function () {
|
|
IOManager.toggleDialogMode("list");
|
|
assert.isFalse(dialog.document.getElementById("list-layout").hidden);
|
|
assert.isTrue(dialog.document.getElementById("library-layout").hidden);
|
|
IOManager.toggleDialogMode("library");
|
|
assert.isFalse(dialog.document.getElementById("library-layout").hidden);
|
|
assert.isTrue(dialog.document.getElementById("list-layout").hidden);
|
|
});
|
|
|
|
it("should highlight bubbles whose items are selected", async function () {
|
|
let itemOne = await createDataObject('item');
|
|
let itemTwo = await createDataObject('item');
|
|
|
|
IOManager.toggleDialogMode("library");
|
|
await IOManager.addItemsToCitation([itemOne, itemTwo]);
|
|
|
|
// Select row of the first bubble
|
|
await dialog.libraryLayout.itemsView.selectItem(itemOne.id);
|
|
// Check that the bubble is highlighted
|
|
let bubbleOne = dialog.document.querySelector(`.bubble[dialogReferenceID="${CitationDataManager.items[0].dialogReferenceID}"]`);
|
|
assert.isTrue(bubbleOne.classList.contains("has-item-selected"));
|
|
// Check the other bubble is unaffected
|
|
let bubbleTwo = dialog.document.querySelector(`.bubble[dialogReferenceID="${CitationDataManager.items[1].dialogReferenceID}"]`);
|
|
assert.isFalse(bubbleTwo.classList.contains("has-item-selected"));
|
|
});
|
|
|
|
it("should highlight rows of items in the citation", async function () {
|
|
let itemOne = await createDataObject('item');
|
|
IOManager.toggleDialogMode("library");
|
|
|
|
// Add the item to citation
|
|
await IOManager.addItemsToCitation([itemOne]);
|
|
// Select the row in itemTree, so it is visible
|
|
await dialog.libraryLayout.itemsView.selectItem(itemOne.id);
|
|
// Make sure the row node is highlighted
|
|
let rowIndex = dialog.libraryLayout.itemsView.getRowIndexByID(itemOne.id);
|
|
let rowID = "item-tree-citationDialog-row-" + rowIndex;
|
|
let rowNode = dialog.document.getElementById(rowID);
|
|
assert.isTrue(rowNode.classList.contains("highlighted"));
|
|
});
|
|
});
|
|
|
|
describe("Search", function () {
|
|
let selectedOne, selectedTwo, openOne, openTwo, selectedAndOpenOne, citedOne, citedAndOpenOne, libraryOne, libraryTwo;
|
|
|
|
before(async function () {
|
|
selectedOne = await createDataObject('item', { title: "one_selected" });
|
|
selectedTwo = await createDataObject('item', { title: "two_selected" });
|
|
openOne = await createDataObject('item', { title: "one_open" });
|
|
openTwo = await createDataObject('item', { title: "two_open" });
|
|
selectedAndOpenOne = await createDataObject('item', { title: "one_selected_open" });
|
|
libraryOne = await createDataObject('item', { title: "one_library" });
|
|
libraryTwo = await createDataObject('item', { title: "two_library" });
|
|
citedOne = await createDataObject('item', { title: "one_cited" });
|
|
citedAndOpenOne = await createDataObject('item', { title: "one_open_cited" });
|
|
|
|
// Present these items are selected/open/cited
|
|
SearchHandler.selectedItems = [selectedOne, selectedTwo, selectedAndOpenOne];
|
|
SearchHandler.openItems = [openOne, openTwo, selectedAndOpenOne, citedAndOpenOne];
|
|
SearchHandler.citedItems = [citedOne, citedAndOpenOne];
|
|
});
|
|
|
|
after(function () {
|
|
SearchHandler.openItems = [];
|
|
SearchHandler.selectedItems = [];
|
|
});
|
|
|
|
it("should perform search in list mode", async function () {
|
|
IOManager.toggleDialogMode("list");
|
|
|
|
// Wait for search triggered after switching dialog modes to finish
|
|
while (SearchHandler.searching) {
|
|
await Zotero.Promise.delay(10);
|
|
}
|
|
// Search for "one"
|
|
await dialog.currentLayout.search("one", { skipDebounce: true });
|
|
// Selected items should have both "one_selected" and "one_selected_open"
|
|
let selectedIDs = SearchHandler.results.selected.map(item => item.id);
|
|
assert.sameMembers(selectedIDs, [selectedOne.id, selectedAndOpenOne.id]);
|
|
// Open items should have "one_open" and "one_open_cited" but not "one_selected_open", since it is selected
|
|
let openIDs = SearchHandler.results.open.map(item => item.id);
|
|
assert.sameMembers(openIDs, [openOne.id, citedAndOpenOne.id]);
|
|
// Cited items should have "one_cited"
|
|
let citedIDs = SearchHandler.results.cited.map(item => item.id);
|
|
assert.sameMembers(citedIDs, [citedOne.id]);
|
|
// Library items should have "one_library" but not "two_library", "one_cited", or "one_open_cited"
|
|
let libraryIDs = SearchHandler.results.found.map(item => item.id);
|
|
assert.include(libraryIDs, libraryOne.id);
|
|
assert.notInclude(libraryIDs, libraryTwo.id);
|
|
assert.notInclude(libraryIDs, citedOne.id);
|
|
// Make sure actual nodes for search matches are rendered
|
|
let expectedItemCardIDs = [...selectedIDs, ...openIDs, ...citedIDs, ...libraryIDs];
|
|
for (let itemID of expectedItemCardIDs) {
|
|
let node = dialog.document.querySelector(`.item[id="${itemID}"]`);
|
|
assert.isOk(node);
|
|
}
|
|
});
|
|
|
|
it("should perform search in library mode", async function () {
|
|
IOManager.toggleDialogMode("library");
|
|
|
|
// Wait for search triggered after switching dialog modes to finish
|
|
while (SearchHandler.searching) {
|
|
await Zotero.Promise.delay(10);
|
|
}
|
|
// Search for "one"
|
|
await dialog.currentLayout.search("one", { skipDebounce: true });
|
|
// Selected items should have both "one_selected" and "one_selected_open"
|
|
let selectedIDs = SearchHandler.results.selected.map(item => item.id);
|
|
assert.sameMembers(selectedIDs, [selectedOne.id, selectedAndOpenOne.id]);
|
|
// Open items should have "one_open" and "one_open_cited" but not "one_selected_open", since it is selected
|
|
let openIDs = SearchHandler.results.open.map(item => item.id);
|
|
assert.sameMembers(openIDs, [openOne.id, citedAndOpenOne.id]);
|
|
// Cited items should have "one_cited"
|
|
let citedIDs = SearchHandler.results.cited.map(item => item.id);
|
|
assert.sameMembers(citedIDs, [citedOne.id]);
|
|
// In library mode, library is searched via itemTree, so this should be empty
|
|
assert.equal(SearchHandler.results.found.length, 0);
|
|
// Make sure actual nodes for search matches are rendered
|
|
let expectedItemCardIDs = [...selectedIDs, ...openIDs, ...citedIDs];
|
|
for (let itemID of expectedItemCardIDs) {
|
|
let node = dialog.document.querySelector(`.item[id="${itemID}"]`);
|
|
assert.isOk(node);
|
|
}
|
|
});
|
|
});
|
|
|
|
describe("Dialog loading", function () {
|
|
let newDialog;
|
|
|
|
after(() => {
|
|
newDialog.close();
|
|
});
|
|
|
|
it("the dialog should be interactable even if io functions are not loaded", async function () {
|
|
let io = {
|
|
accept() {},
|
|
cancel() {},
|
|
sortable: true,
|
|
citation: {
|
|
citationItems: [],
|
|
properties: {
|
|
unsorted: false,
|
|
}
|
|
},
|
|
// allCitedDataLoadedPromise is what citation dialog checks
|
|
// but make all functions unresolved promises just to be sure
|
|
sort() {
|
|
return new Zotero.Promise(() => {});
|
|
},
|
|
getItems() {
|
|
return new Zotero.Promise(() => {});
|
|
},
|
|
allCitedDataLoadedPromise: new Zotero.Promise(() => {}),
|
|
};
|
|
|
|
let newDialogPromise = waitForWindow("chrome://zotero/content/integration/citationDialog.xhtml");
|
|
Services.ww.openWindow(null, "chrome://zotero/content/integration/citationDialog.xhtml", "", "", io);
|
|
newDialog = await newDialogPromise;
|
|
|
|
while (!newDialog.loaded || newDialog.SearchHandler.searching) {
|
|
await Zotero.Promise.delay(10);
|
|
}
|
|
let item = await createDataObject('item', { title: "test" });
|
|
await newDialog.IOManager.addItemsToCitation([item]);
|
|
// verify that the new bubbles was added
|
|
let addedBubble = newDialog.document.querySelector(".bubble");
|
|
assert.isOk(addedBubble);
|
|
});
|
|
});
|
|
|
|
describe("Helpers.extractLocator", function () {
|
|
let locator;
|
|
describe("Invalid locators", function () {
|
|
it("has no locator label with numeric locator value", function () {
|
|
locator = dialog.Helpers.extractLocator('history of the US 10-15');
|
|
assert.isNull(locator);
|
|
locator = dialog.Helpers.extractLocator('10-15');
|
|
assert.isNull(locator);
|
|
});
|
|
|
|
it("has no locator label with textual locator value", function () {
|
|
locator = dialog.Helpers.extractLocator('history of the US "test"');
|
|
assert.isNull(locator);
|
|
locator = dialog.Helpers.extractLocator('"test"');
|
|
assert.isNull(locator);
|
|
});
|
|
|
|
it("has no quotes around textual locator value", function () {
|
|
locator = dialog.Helpers.extractLocator('history of the US chapter something');
|
|
assert.isNull(locator);
|
|
locator = dialog.Helpers.extractLocator('chapter search query');
|
|
assert.isNull(locator);
|
|
});
|
|
|
|
it("has no locator value", function () {
|
|
locator = dialog.Helpers.extractLocator('history of the US p');
|
|
assert.isNull(locator);
|
|
locator = dialog.Helpers.extractLocator('page');
|
|
assert.isNull(locator);
|
|
});
|
|
|
|
it("has textual locator value that does not follow locator label", function () {
|
|
locator = dialog.Helpers.extractLocator('history of the US note blank "testing"');
|
|
assert.isNull(locator);
|
|
});
|
|
|
|
it("has numeric locator value that does not follow locator label", function () {
|
|
locator = dialog.Helpers.extractLocator('history of the US p blank 11-12');
|
|
assert.isNull(locator);
|
|
});
|
|
|
|
it("has textual locator value not in the end of the string", function () {
|
|
locator = dialog.Helpers.extractLocator('history of the US chapter "some quotations" some more text');
|
|
assert.isNull(locator);
|
|
});
|
|
|
|
it("has numeric locator value not in the end of the string", function () {
|
|
locator = dialog.Helpers.extractLocator('history of the US page 10-15 some more text');
|
|
assert.isNull(locator);
|
|
});
|
|
});
|
|
|
|
describe("Valid locator labels", function () {
|
|
it("is a valid numeric locator by itself", function () {
|
|
let locators = [
|
|
'line 10-15',
|
|
'line10-15',
|
|
'l. 10-15',
|
|
'l.10-15',
|
|
'l 10-15',
|
|
' l10-15'
|
|
];
|
|
for (let locatorString of locators) {
|
|
let locator = dialog.Helpers.extractLocator(locatorString);
|
|
assert.isOk(locator);
|
|
assert.equal(locator.label, 'line');
|
|
assert.equal(locator.locator, '10-15');
|
|
assert.equal(locator.onlyLocator, true);
|
|
assert.equal(locator.fullLocatorString, locatorString.trim());
|
|
}
|
|
});
|
|
|
|
it("is a valid textual locator by itself", function () {
|
|
let locators = [
|
|
'note "this is a note"',
|
|
'note"this is a note"',
|
|
'n. "this is a note"',
|
|
'n."this is a note"',
|
|
'n "this is a note"',
|
|
' n"this is a note"'
|
|
];
|
|
|
|
for (let locatorString of locators) {
|
|
let locator = dialog.Helpers.extractLocator(locatorString);
|
|
assert.isOk(locator);
|
|
assert.equal(locator.label, 'note');
|
|
assert.equal(locator.locator, 'this is a note');
|
|
assert.equal(locator.onlyLocator, true);
|
|
assert.equal(locator.fullLocatorString, locatorString.trim());
|
|
}
|
|
});
|
|
|
|
it("is a valid numeric locator with other text", function () {
|
|
let locators = [
|
|
{ str: 'history of the US page 10-15', locatorStr: 'page 10-15' },
|
|
{ str: 'history of the US page10-15', locatorStr: 'page10-15' },
|
|
{ str: 'history of the US p. 10-15', locatorStr: 'p. 10-15' },
|
|
{ str: 'history of the US p.10-15', locatorStr: 'p.10-15' },
|
|
{ str: 'history of the US p 10-15', locatorStr: 'p 10-15' },
|
|
{ str: 'history of the US p10-15', locatorStr: 'p10-15' }
|
|
];
|
|
|
|
for (let locatorObj of locators) {
|
|
let locator = dialog.Helpers.extractLocator(locatorObj.str);
|
|
assert.isOk(locator);
|
|
assert.equal(locator.label, 'page');
|
|
assert.equal(locator.locator, '10-15');
|
|
assert.equal(locator.onlyLocator, false);
|
|
assert.equal(locator.fullLocatorString, locatorObj.locatorStr);
|
|
}
|
|
});
|
|
|
|
it("is a valid textual locator with other text", function () {
|
|
let locators = [
|
|
{ str: 'history of the US chapter "one and two"', locatorStr: 'chapter "one and two"' },
|
|
{ str: 'history of the US chapter"one and two"', locatorStr: 'chapter"one and two"' },
|
|
{ str: 'history of the US chap. "one and two"', locatorStr: 'chap. "one and two"' },
|
|
{ str: 'history of the US chap."one and two"', locatorStr: 'chap."one and two"' },
|
|
{ str: 'history of the US chap "one and two"', locatorStr: 'chap "one and two"' },
|
|
{ str: 'history of the US chap"one and two"', locatorStr: 'chap"one and two"' }
|
|
];
|
|
|
|
for (let locatorObj of locators) {
|
|
let locator = dialog.Helpers.extractLocator(locatorObj.str);
|
|
assert.isOk(locator);
|
|
assert.equal(locator.label, 'chapter');
|
|
assert.equal(locator.locator, 'one and two');
|
|
assert.equal(locator.onlyLocator, false);
|
|
assert.equal(locator.fullLocatorString, locatorObj.locatorStr);
|
|
}
|
|
});
|
|
});
|
|
});
|
|
});
|