Fix race conditions in tag selector tests

And take an optional second parameter in waitForTagSelector() to
indicate how many updates to wait for, since certain operations trigger
two updates, one from notify() and the other from onItemViewChanged().
This commit is contained in:
Dan Stillman 2019-03-18 04:53:30 -04:00
parent 67febb2f45
commit a92b29cebf
2 changed files with 30 additions and 17 deletions

View file

@ -209,15 +209,26 @@ var waitForItemsLoad = Zotero.Promise.coroutine(function* (win, collectionRowToS
yield zp.itemsView.waitForLoad(); yield zp.itemsView.waitForLoad();
}); });
var waitForTagSelector = function (win) { /**
* Return a promise that resolves once the tag selector has updated
*
* Some operations result in two tag selector updates, one from the notify() and another from
* onItemViewChanged(). Pass 2 for numUpdates to wait for both.
*/
var waitForTagSelector = function (win, numUpdates = 1) {
var updates = 0;
var zp = win.ZoteroPane; var zp = win.ZoteroPane;
var deferred = Zotero.Promise.defer(); var deferred = Zotero.Promise.defer();
if (zp.tagSelectorShown()) { if (zp.tagSelectorShown()) {
let tagSelector = zp.tagSelector; let tagSelector = zp.tagSelector;
let componentDidUpdate = tagSelector.componentDidUpdate; let componentDidUpdate = tagSelector.componentDidUpdate;
tagSelector.componentDidUpdate = function() { tagSelector.componentDidUpdate = function() {
deferred.resolve(); updates++;
tagSelector.componentDidUpdate = componentDidUpdate; if (updates == numUpdates) {
deferred.resolve();
tagSelector.componentDidUpdate = componentDidUpdate;
}
if (typeof componentDidUpdate == 'function') { if (typeof componentDidUpdate == 'function') {
componentDidUpdate.call(this, arguments); componentDidUpdate.call(this, arguments);
} }

View file

@ -419,9 +419,13 @@ describe("Tag Selector", function () {
var tag1 = Zotero.Utilities.randomString(); var tag1 = Zotero.Utilities.randomString();
var tag2 = Zotero.Utilities.randomString(); var tag2 = Zotero.Utilities.randomString();
var promise = waitForTagSelector(win); var item1 = createUnsavedDataObject('item', { tags: [{ tag: tag1 }] });
var item1 = await createDataObject('item', { tags: [{ tag: tag1 }] }); var item2 = createUnsavedDataObject('item', { tags: [{ tag: tag2 }] });
var item2 = await createDataObject('item', { tags: [{ tag: tag2 }] }); var promise = waitForTagSelector(win, 2);
await Zotero.DB.executeTransaction(async function () {
await item1.save();
await item2.save();
});
await promise; await promise;
tagSelector.handleTagSelected(tag1); tagSelector.handleTagSelected(tag1);
@ -433,12 +437,10 @@ describe("Tag Selector", function () {
assert.notInclude(getRegularTags(), tag2); assert.notInclude(getRegularTags(), tag2);
// Remove tag from item // Remove tag from item
promise = waitForTagSelector(win); promise = waitForTagSelector(win, 2);
item1.removeTag(tag1); item1.removeTag(tag1);
await item1.saveTx(); await item1.saveTx();
await promise; await promise;
// Notifier item-tag remove triggers #onSelected, which eventually triggers #onItemViewChanged
await waitForTagSelector(win);
// Removed tag should no longer be shown or selected // Removed tag should no longer be shown or selected
assert.notInclude(getRegularTags(), tag1); assert.notInclude(getRegularTags(), tag1);
@ -451,12 +453,15 @@ describe("Tag Selector", function () {
var libraryID = Zotero.Libraries.userLibraryID; var libraryID = Zotero.Libraries.userLibraryID;
await selectLibrary(win); await selectLibrary(win);
var promise = waitForTagSelector(win); var promise = waitForTagSelector(win, 2);
var tag1 = Zotero.Utilities.randomString(); var tag1 = Zotero.Utilities.randomString();
var tag2 = Zotero.Utilities.randomString(); var tag2 = Zotero.Utilities.randomString();
await createDataObject('item', { tags: [{ tag: tag1 }] }); var item1 = await createDataObject('item', { tags: [{ tag: tag1 }] });
await createDataObject('item', { tags: [{ tag: tag2 }] }); var item2 = await createDataObject('item', { tags: [{ tag: tag2 }] });
await Zotero.DB.executeTransaction(async function () {
await item1.save();
await item2.save();
});
await promise; await promise;
tagSelector.handleTagSelected(tag1); tagSelector.handleTagSelected(tag1);
@ -468,12 +473,9 @@ describe("Tag Selector", function () {
assert.notInclude(getRegularTags(), tag2); assert.notInclude(getRegularTags(), tag2);
// Remove tag from library // Remove tag from library
promise = waitForTagSelector(win); promise = waitForTagSelector(win, 2);
await Zotero.Tags.removeFromLibrary(libraryID, Zotero.Tags.getID(tag1)); await Zotero.Tags.removeFromLibrary(libraryID, Zotero.Tags.getID(tag1));
// Notifier item-tag remove
await promise; await promise;
// Notifier tag delete triggers #onSelected, which eventually triggers #onItemViewChanged
await waitForTagSelector(win);
// Deleted tag should no longer be shown or selected // Deleted tag should no longer be shown or selected
assert.notInclude(getRegularTags(), tag1); assert.notInclude(getRegularTags(), tag1);