diff --git a/chrome/content/zotero/xpcom/connector/server_connector.js b/chrome/content/zotero/xpcom/connector/server_connector.js
index b2b33778b4..dd891125ed 100644
--- a/chrome/content/zotero/xpcom/connector/server_connector.js
+++ b/chrome/content/zotero/xpcom/connector/server_connector.js
@@ -265,8 +265,13 @@ Zotero.Server.Connector.SaveSession.prototype.update = async function (targetID,
await item.eraseTx();
}
let actionUC = Zotero.Utilities.capitalize(this._action);
- let newItems = await Zotero.Server.Connector[actionUC].prototype[this._action](
- targetID, this._requestData
+ // saveItems has a different signature with the session as the first argument
+ let params = [targetID, this._requestData];
+ if (this._action == 'saveItems') {
+ params.unshift(this);
+ }
+ let newItems = await Zotero.Server.Connector[actionUC].prototype[this._action].apply(
+ Zotero.Server.Connector[actionUC], params
);
// saveSnapshot only returns a single item
if (this._action == 'saveSnapshot') {
diff --git a/test/tests/server_connectorTest.js b/test/tests/server_connectorTest.js
index 41992da77c..d90f9ddf8d 100644
--- a/test/tests/server_connectorTest.js
+++ b/test/tests/server_connectorTest.js
@@ -1132,6 +1132,191 @@ describe("Connector Server", function () {
assert.isTrue(item.hasTag("A"));
assert.isTrue(item.hasTag("B"));
});
+
+ it("should move item saved via /saveItems to another library", async function () {
+ var group = await createGroup({ editable: true, filesEditable: false });
+ await selectLibrary(win);
+ await waitForItemsLoad(win);
+
+ var sessionID = Zotero.Utilities.randomString();
+ var body = {
+ sessionID,
+ items: [
+ {
+ itemType: "newspaperArticle",
+ title: "Title",
+ attachments: [
+ {
+ title: "Attachment",
+ url: `${testServerPath}/attachment`,
+ mimeType: "text/html"
+ }
+ ]
+ }
+ ],
+ uri: "http://example.com"
+ };
+
+ httpd.registerPathHandler(
+ "/attachment",
+ {
+ handle: function (request, response) {
+ response.setStatusLine(null, 200, "OK");
+ response.write("
TitleBody");
+ }
+ }
+ );
+
+ var reqPromise = Zotero.HTTP.request(
+ 'POST',
+ connectorServerPath + "/connector/saveItems",
+ {
+ headers: {
+ "Content-Type": "application/json"
+ },
+ body: JSON.stringify(body)
+ }
+ );
+
+ var ids1 = await waitForItemEvent('add');
+ var item1 = Zotero.Items.get(ids1[0]);
+ await waitForItemEvent('add');
+
+ var req = await reqPromise;
+ assert.equal(req.status, 201);
+
+ // Move item to group without file attachment
+ reqPromise = Zotero.HTTP.request(
+ 'POST',
+ connectorServerPath + "/connector/updateSession",
+ {
+ headers: {
+ "Content-Type": "application/json"
+ },
+ body: JSON.stringify({
+ sessionID,
+ target: group.treeViewID
+ })
+ }
+ );
+
+ var ids2 = await waitForItemEvent('add');
+ var item2 = Zotero.Items.get(ids2[0]);
+
+ req = await reqPromise;
+ assert.equal(req.status, 200);
+ assert.isFalse(Zotero.Items.exists(item1.id));
+ assert.equal(item2.libraryID, group.libraryID);
+ assert.equal(item2.numAttachments(), 0);
+
+ // Move back to My Library and resave attachment
+ reqPromise = Zotero.HTTP.request(
+ 'POST',
+ connectorServerPath + "/connector/updateSession",
+ {
+ headers: {
+ "Content-Type": "application/json"
+ },
+ body: JSON.stringify({
+ sessionID,
+ target: Zotero.Libraries.userLibrary.treeViewID
+ })
+ }
+ );
+
+ var ids3 = await waitForItemEvent('add');
+ var item3 = Zotero.Items.get(ids3[0]);
+ await waitForItemEvent('add');
+
+ req = await reqPromise;
+ assert.equal(req.status, 200);
+ assert.isFalse(Zotero.Items.exists(item2.id));
+ assert.equal(item3.libraryID, Zotero.Libraries.userLibraryID);
+ assert.equal(item3.numAttachments(), 1);
+ });
+
+ it("should move item saved via /saveSnapshot to another library", async function () {
+ var group = await createGroup({ editable: true, filesEditable: false });
+ await selectLibrary(win);
+ await waitForItemsLoad(win);
+ var sessionID = Zotero.Utilities.randomString();
+
+ // saveSnapshot saves parent and child before returning
+ var ids1;
+ var promise = waitForItemEvent('add').then(function (ids) {
+ ids1 = ids;
+ return waitForItemEvent('add').then(function (ids) {
+ ids1 = ids1.concat(ids);
+ });
+ });
+ await Zotero.HTTP.request(
+ 'POST',
+ connectorServerPath + "/connector/saveSnapshot",
+ {
+ headers: {
+ "Content-Type": "application/json"
+ },
+ body: JSON.stringify({
+ sessionID,
+ url: "http://example.com",
+ html: "TitleBody"
+ })
+ }
+ );
+
+ assert.isTrue(promise.isFulfilled());
+
+ var item1 = Zotero.Items.get(ids1[0]);
+
+ // Move item to group without file attachment
+ var reqPromise = Zotero.HTTP.request(
+ 'POST',
+ connectorServerPath + "/connector/updateSession",
+ {
+ headers: {
+ "Content-Type": "application/json"
+ },
+ body: JSON.stringify({
+ sessionID,
+ target: group.treeViewID
+ })
+ }
+ );
+
+ var ids2 = await waitForItemEvent('add');
+ var item2 = Zotero.Items.get(ids2[0]);
+
+ var req = await reqPromise;
+ assert.equal(req.status, 200);
+ assert.isFalse(Zotero.Items.exists(item1.id));
+ assert.equal(item2.libraryID, group.libraryID);
+ assert.equal(item2.numAttachments(), 0);
+
+ // Move back to My Library and resave attachment
+ reqPromise = Zotero.HTTP.request(
+ 'POST',
+ connectorServerPath + "/connector/updateSession",
+ {
+ headers: {
+ "Content-Type": "application/json"
+ },
+ body: JSON.stringify({
+ sessionID,
+ target: Zotero.Libraries.userLibrary.treeViewID
+ })
+ }
+ );
+
+ var ids3 = await waitForItemEvent('add');
+ var item3 = Zotero.Items.get(ids3[0]);
+ await waitForItemEvent('add');
+
+ req = await reqPromise;
+ assert.equal(req.status, 200);
+ assert.isFalse(Zotero.Items.exists(item2.id));
+ assert.equal(item3.libraryID, Zotero.Libraries.userLibraryID);
+ assert.equal(item3.numAttachments(), 1);
+ });
});
describe('/connector/installStyle', function() {