commit 0de22b132efd92d4660e26f24f1772f2ec57106d
parent e1c183b59719a35eb8554ed30da0108452698074
Author: Adomas VenĨkauskas <adomas.ven@gmail.com>
Date: Fri, 14 Apr 2017 12:43:21 +0300
Move document plugin interface description into integrationTests
Diffstat:
2 files changed, 143 insertions(+), 24 deletions(-)
diff --git a/chrome/content/zotero/xpcom/integration.js b/chrome/content/zotero/xpcom/integration.js
@@ -41,7 +41,7 @@ const FORCE_CITATIONS_RESET_TEXT = 2;
const INTEGRATION_PLUGINS = ["zoteroMacWordIntegration@zotero.org",
"zoteroOpenOfficeIntegration@zotero.org", "zoteroWinWordIntegration@zotero.org"];
-// These must match the constants defined in zoteroIntegration.idl
+// These must match the constants in corresponding word plugins
const DIALOG_ICON_STOP = 0;
const DIALOG_ICON_WARNING = 1;
const DIALOG_ICON_CAUTION = 2;
diff --git a/test/tests/integrationTests.js b/test/tests/integrationTests.js
@@ -2,10 +2,14 @@
describe("Zotero.Integration", function () {
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
- // Fully functional document plugin dummy based on word-for-windows-integration
- // Functions should be stubbed when testing as needed
+ /**
+ * To be used as a reference for Zotero-Word Integration plugins
+ */
var DocumentPluginDummy = {};
-
+
+ /**
+ * The Application class corresponds to a word processing application.
+ */
DocumentPluginDummy.Application = function() {
this.doc = new DocumentPluginDummy.Document();
this.primaryFieldType = "Field";
@@ -13,36 +17,112 @@ describe("Zotero.Integration", function () {
this.fields = [];
};
DocumentPluginDummy.Application.prototype = {
+ /**
+ * Gets the active document.
+ * @returns {DocumentPluginDummy.Document}
+ */
getActiveDocument: function() {return this.doc},
- getDocument: function() {return this.doc},
+ /**
+ * Gets the document by some app-specific identifier.
+ * @param {String|Number} docID
+ */
+ getDocument: function(docID) {return this.doc},
QueryInterface: function() {return this},
};
-
+
+ /**
+ * The Document class corresponds to a single word processing document.
+ */
DocumentPluginDummy.Document = function() {this.fields = []};
DocumentPluginDummy.Document.prototype = {
- // Needs to be stubbed for expected return values depending on prompt type
- // - Yes: 2, No: 1, Cancel: 0
- // - Yes: 1, No: 0
- // - Ok: 1, Cancel: 0
- // - Ok: 0
- displayAlert: () => 0,
+ /**
+ * Displays a dialog in the word processing application
+ * @param {String} dialogText
+ * @param {Number} icon - one of the constants defined in integration.js for dialog icons
+ * @param {Number} buttons - one of the constants defined in integration.js for dialog buttons
+ * @returns {Number}
+ * - Yes: 2, No: 1, Cancel: 0
+ * - Yes: 1, No: 0
+ * - Ok: 1, Cancel: 0
+ * - Ok: 0
+ */
+ displayAlert: (dialogText, icon, buttons) => 0,
+ /**
+ * Brings this document to the foreground (if necessary to return after displaying a dialog)
+ */
activate: () => 0,
- canInsertField: () => true,
- cursorInField: () => false,
+ /**
+ * Determines whether a field can be inserted at the current position.
+ * @param {String} fieldType
+ * @returns {Boolean}
+ */
+ canInsertField: (fieldType) => true,
+ /**
+ * Returns the field in which the cursor resides, or NULL if none.
+ * @param {String} fieldType
+ * @returns {Boolean}
+ */
+ cursorInField: (fieldType) => false,
+ /**
+ * Get document data property from the current document
+ * @returns {String}
+ */
getDocumentData: function() {return this.data},
+ /**
+ * Set document data property
+ * @param {String} data
+ */
setDocumentData: function(data) {this.data = data},
- insertField: function() { var field = new DocumentPluginDummy.Field(this); this.fields.push(field); return field },
- getFields: function() {return new DocumentPluginDummy.FieldEnumerator(this)},
+ /**
+ * Inserts a field at the given position and initializes the field object.
+ * @param {String} fieldType
+ * @param {String} noteType
+ * @returns {DocumentPluginDummy.Field}
+ */
+ insertField: function(fieldType, noteType) {
+ var field = new DocumentPluginDummy.Field(this);
+ this.fields.push(field);
+ return field
+ },
+ /**
+ * Gets all fields present in the document.
+ * @param {String} fieldType
+ * @returns {DocumentPluginDummy.FieldEnumerator}
+ */
+ getFields: function(fieldType) {return new DocumentPluginDummy.FieldEnumerator(this)},
+ /**
+ * Gets all fields present in the document. The observer will receive notifications for two
+ * topics: "fields-progress", with the document as the subject and percent progress as data, and
+ * "fields-available", with an nsISimpleEnumerator of fields as the subject and the length as
+ * data
+ * @param {String} fieldType
+ * @param {nsIObserver} observer
+ */
getFieldsAsync: function(fieldType, observer) {
observer.observe(this.getFields(fieldType), 'fields-available', null)
},
- setBibliographyStyle: () => 0,
- convert: () => 0,
- cleanup: () => 0,
+ /**
+ * Sets the bibliography style, overwriting the current values for this document
+ */
+ setBibliographyStyle: (firstLineIndent, bodyIndent, lineSpacing, entrySpacing,
+ tabStops, tabStopsCount) => 0,
+ /**
+ * Converts all fields in a document to a different fieldType or noteType
+ * @params {DocumentPluginDummy.FieldEnumerator} fields
+ */
+ convert: (fields, toFieldType, toNoteType, count) => 0,
+ /**
+ * Cleans up the document state and resumes processor for editing
+ */
+ cleanup: () => 0,
+
+ /**
+ * Informs the document processor that the operation is complete
+ */
complete: () => 0,
QueryInterface: function() {return this},
};
-
+
DocumentPluginDummy.FieldEnumerator = function(doc) {this.doc = doc; this.idx = 0};
DocumentPluginDummy.FieldEnumerator.prototype = {
hasMoreElements: function() {return this.idx < this.doc.fields.length;},
@@ -51,26 +131,65 @@ describe("Zotero.Integration", function () {
Components.interfaces.nsISimpleEnumerator])
};
+ /**
+ * The Field class corresponds to a field containing an individual citation
+ * or bibliography
+ */
DocumentPluginDummy.Field = function(doc) {
this.doc = doc;
this.code = '';
// This is actually required and current integration code depends on text being non-empty upon insertion.
// insertBibliography will fail if there is no placeholder text.
this.text = '{Placeholder}';
- this.noteIndex = DocumentPluginDummy.Field.noteIndex++;
this.wrappedJSObject = this;
};
DocumentPluginDummy.Field.noteIndex = 0;
DocumentPluginDummy.Field.prototype = {
- delete: function() {this.doc.fields.filter((field) => field != this)},
+ /**
+ * Deletes this field and its contents.
+ */
+ delete: function() {this.doc.fields.filter((field) => field !== this)},
+ /**
+ * Removes this field, but maintains the field's contents.
+ */
removeCode: function() {this.code = ""},
+ /**
+ * Selects this field.
+ */
select: () => 0,
- setText: function(text) {this.text = text},
+ /**
+ * Sets the text inside this field to a specified plain text string or pseudo-RTF formatted text
+ * string.
+ * @param {String} text
+ * @param {Boolean} isRich
+ */
+ setText: function(text, isRich) {this.text = text},
+ /**
+ * Gets the text inside this field, preferably with formatting, but potentially without
+ * @returns {String}
+ */
getText: function() {return this.text},
+ /**
+ * Sets field's code
+ * @param {String} code
+ */
setCode: function(code) {this.code = code},
+ /**
+ * Gets field's code.
+ * @returns {String}
+ */
getCode: function() {return this.code},
+ /**
+ * Returns true if this field and the passed field are actually references to the same field.
+ * @param {DocumentPluginDummy.Field} field
+ * @returns {Boolean}
+ */
equals: function(field) {return this == field},
- getNoteIndex: function() {return this.noteIndex},
+ /**
+ * This field's note index, if it is in a footnote or endnote; otherwise zero.
+ * @returns {Number}
+ */
+ getNoteIndex: () => 0,
QueryInterface: function() {return this},
};