Updates #1896: Properly identify archived one-on-one messages
Also, rename attribute from `is_receipt_request` to `is_valid_receipt_request` to avoid confusion.
This commit is contained in:
parent
78bf07ecff
commit
09371712b0
|
@ -46,6 +46,7 @@ module.exports = function(config) {
|
|||
{ pattern: "spec/chatbox.js", type: 'module' },
|
||||
{ pattern: "spec/user-details-modal.js", type: 'module' },
|
||||
{ pattern: "spec/messages.js", type: 'module' },
|
||||
{ pattern: "spec/receipts.js", type: 'module' },
|
||||
{ pattern: "spec/muc_messages.js", type: 'module' },
|
||||
{ pattern: "spec/mentions.js", type: 'module' },
|
||||
{ pattern: "spec/retractions.js", type: 'module' },
|
||||
|
|
136
package-lock.json
generated
136
package-lock.json
generated
|
@ -5069,9 +5069,9 @@
|
|||
}
|
||||
},
|
||||
"@octokit/types": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-5.1.2.tgz",
|
||||
"integrity": "sha512-+zuMnja97vuZmWa+HdUY+0KB9MLwcEHueSSyKu0G/HqZaFYCVdLpBkavb0xyDlH7eoBdvAvSX/+Y8+4FOEZkrQ==",
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-5.4.0.tgz",
|
||||
"integrity": "sha512-D/uotqF69M50OIlwMqgyIg9PuLT2daOiBAYF0P40I2ekFA2ESwwBY5dxZe/UhXdPvIbNKDzuZmQrO7rMpuFbcg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": ">= 8"
|
||||
|
@ -5532,9 +5532,9 @@
|
|||
}
|
||||
},
|
||||
"abab": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.3.tgz",
|
||||
"integrity": "sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg=="
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.4.tgz",
|
||||
"integrity": "sha512-Eu9ELJWCz/c1e9gTiCY+FceWxcqzjYEbqMgtndnuSqZSUCOL73TWNK2mHfIj4Cw2E/ongOp+JISVNCmovt2KYQ=="
|
||||
},
|
||||
"abbrev": {
|
||||
"version": "1.1.1",
|
||||
|
@ -7297,23 +7297,29 @@
|
|||
"dev": true
|
||||
},
|
||||
"compare-func": {
|
||||
"version": "1.3.4",
|
||||
"resolved": "https://registry.npmjs.org/compare-func/-/compare-func-1.3.4.tgz",
|
||||
"integrity": "sha512-sq2sWtrqKPkEXAC8tEJA1+BqAH9GbFkGBtUOqrUX57VSfwp8xyktctk+uLoRy5eccTdxzDcVIztlYDpKs3Jv1Q==",
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz",
|
||||
"integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"array-ify": "^1.0.0",
|
||||
"dot-prop": "^3.0.0"
|
||||
"dot-prop": "^5.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"dot-prop": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-3.0.0.tgz",
|
||||
"integrity": "sha1-G3CK8JSknJoOfbyteQq6U52sEXc=",
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz",
|
||||
"integrity": "sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-obj": "^1.0.0"
|
||||
"is-obj": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"is-obj": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
|
||||
"integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -7483,12 +7489,12 @@
|
|||
"dev": true
|
||||
},
|
||||
"conventional-changelog-angular": {
|
||||
"version": "5.0.10",
|
||||
"resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.10.tgz",
|
||||
"integrity": "sha512-k7RPPRs0vp8+BtPsM9uDxRl6KcgqtCJmzRD1wRtgqmhQ96g8ifBGo9O/TZBG23jqlXS/rg8BKRDELxfnQQGiaA==",
|
||||
"version": "5.0.11",
|
||||
"resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.11.tgz",
|
||||
"integrity": "sha512-nSLypht/1yEflhuTogC03i7DX7sOrXGsRn14g131Potqi6cbGbGEE9PSDEHKldabB6N76HiSyw9Ph+kLmC04Qw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"compare-func": "^1.3.1",
|
||||
"compare-func": "^2.0.0",
|
||||
"q": "^1.5.1"
|
||||
}
|
||||
},
|
||||
|
@ -7538,12 +7544,12 @@
|
|||
"dev": true
|
||||
},
|
||||
"conventional-changelog-writer": {
|
||||
"version": "4.0.16",
|
||||
"resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-4.0.16.tgz",
|
||||
"integrity": "sha512-jmU1sDJDZpm/dkuFxBeRXvyNcJQeKhGtVcFFkwTphUAzyYWcwz2j36Wcv+Mv2hU3tpvLMkysOPXJTLO55AUrYQ==",
|
||||
"version": "4.0.17",
|
||||
"resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-4.0.17.tgz",
|
||||
"integrity": "sha512-IKQuK3bib/n032KWaSb8YlBFds+aLmzENtnKtxJy3+HqDq5kohu3g/UdNbIHeJWygfnEbZjnCKFxAW0y7ArZAw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"compare-func": "^1.3.1",
|
||||
"compare-func": "^2.0.0",
|
||||
"conventional-commits-filter": "^2.0.6",
|
||||
"dateformat": "^3.0.0",
|
||||
"handlebars": "^4.7.6",
|
||||
|
@ -8883,9 +8889,9 @@
|
|||
}
|
||||
},
|
||||
"duplexer": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
|
||||
"integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz",
|
||||
"integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==",
|
||||
"dev": true
|
||||
},
|
||||
"duplexify": {
|
||||
|
@ -11635,9 +11641,9 @@
|
|||
}
|
||||
},
|
||||
"git-up": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/git-up/-/git-up-4.0.1.tgz",
|
||||
"integrity": "sha512-LFTZZrBlrCrGCG07/dm1aCjjpL1z9L3+5aEeI9SBhAqSc+kiA9Or1bgZhQFNppJX6h/f5McrvJt1mQXTFm6Qrw==",
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/git-up/-/git-up-4.0.2.tgz",
|
||||
"integrity": "sha512-kbuvus1dWQB2sSW4cbfTeGpCMd8ge9jx9RKnhXhuJ7tnvT+NIrTVfYZxjtflZddQYcmdOTlkAcjmx7bor+15AQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-ssh": "^1.3.0",
|
||||
|
@ -11645,9 +11651,9 @@
|
|||
}
|
||||
},
|
||||
"git-url-parse": {
|
||||
"version": "11.1.2",
|
||||
"resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-11.1.2.tgz",
|
||||
"integrity": "sha512-gZeLVGY8QVKMIkckncX+iCq2/L8PlwncvDFKiWkBn9EtCfYDbliRTTp6qzyQ1VMdITUfq7293zDzfpjdiGASSQ==",
|
||||
"version": "11.1.3",
|
||||
"resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-11.1.3.tgz",
|
||||
"integrity": "sha512-GPsfwticcu52WQ+eHp0IYkAyaOASgYdtsQDIt4rUp6GbiNt1P9ddrh3O0kQB0eD4UJZszVqNT3+9Zwcg40fywA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"git-up": "^4.0.0"
|
||||
|
@ -12873,9 +12879,9 @@
|
|||
}
|
||||
},
|
||||
"is-ssh": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.1.tgz",
|
||||
"integrity": "sha512-0eRIASHZt1E68/ixClI8bp2YK2wmBPVWEismTs6M+M099jKgrzl/3E976zIbImSIob48N2/XGe9y7ZiYdImSlg==",
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.2.tgz",
|
||||
"integrity": "sha512-elEw0/0c2UscLrNG+OAorbP539E3rhliKPg+hDMWN9VwrDXfYK+4PBEykDPfxlYYtQvl84TascnQyobfQLHEhQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"protocols": "^1.1.0"
|
||||
|
@ -13735,9 +13741,9 @@
|
|||
}
|
||||
},
|
||||
"localforage": {
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/localforage/-/localforage-1.8.1.tgz",
|
||||
"integrity": "sha512-azSSJJfc7h4bVpi0PGi+SmLQKJl2/8NErI+LhJsrORNikMZnhaQ7rv9fHj+ofwgSHrKRlsDCL/639a6nECIKuQ==",
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/localforage/-/localforage-1.9.0.tgz",
|
||||
"integrity": "sha512-rR1oyNrKulpe+VM9cYmcFn6tsHuokyVHFaCM3+osEmxaHTbEk8oQu6eGDfS6DQLWi/N67XRmB8ECG37OES368g==",
|
||||
"requires": {
|
||||
"lie": "3.1.1"
|
||||
}
|
||||
|
@ -14112,18 +14118,16 @@
|
|||
}
|
||||
},
|
||||
"meow": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/meow/-/meow-7.0.1.tgz",
|
||||
"integrity": "sha512-tBKIQqVrAHqwit0vfuFPY3LlzJYkEOFyKa3bPgxzNl6q/RtN8KQ+ALYEASYuFayzSAsjlhXj/JZ10rH85Q6TUw==",
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/meow/-/meow-7.1.0.tgz",
|
||||
"integrity": "sha512-kq5F0KVteskZ3JdfyQFivJEj2RaA8NFsS4+r9DaMKLcUHpk5OcHS3Q0XkCXONB1mZRPsu/Y/qImKri0nwSEZog==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/minimist": "^1.2.0",
|
||||
"arrify": "^2.0.1",
|
||||
"camelcase": "^6.0.0",
|
||||
"camelcase-keys": "^6.2.2",
|
||||
"decamelize-keys": "^1.1.0",
|
||||
"hard-rejection": "^2.1.0",
|
||||
"minimist-options": "^4.0.2",
|
||||
"minimist-options": "4.1.0",
|
||||
"normalize-package-data": "^2.5.0",
|
||||
"read-pkg-up": "^7.0.1",
|
||||
"redent": "^3.0.0",
|
||||
|
@ -14132,18 +14136,6 @@
|
|||
"yargs-parser": "^18.1.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"arrify": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz",
|
||||
"integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==",
|
||||
"dev": true
|
||||
},
|
||||
"camelcase": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.0.0.tgz",
|
||||
"integrity": "sha512-8KMDF1Vz2gzOq54ONPJS65IvTUaB1cHJ2DMM7MbPmLZljDH1qpzzLsWdiN9pHh6qvkRVDTi/07+eNGch/oLU4w==",
|
||||
"dev": true
|
||||
},
|
||||
"find-up": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
|
||||
|
@ -19385,9 +19377,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"parse-path": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/parse-path/-/parse-path-4.0.1.tgz",
|
||||
"integrity": "sha512-d7yhga0Oc+PwNXDvQ0Jv1BuWkLVPXcAoQ/WREgd6vNNoKYaW52KI+RdOFjI63wjkmps9yUE8VS4veP+AgpQ/hA==",
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/parse-path/-/parse-path-4.0.2.tgz",
|
||||
"integrity": "sha512-HSqVz6iuXSiL8C1ku5Gl1Z5cwDd9Wo0q8CoffdAghP6bz8pJa1tcMC+m4N+z6VAS8QdksnIGq1TB6EgR4vPR6w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-ssh": "^1.3.0",
|
||||
|
@ -19401,9 +19393,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"parse-url": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/parse-url/-/parse-url-5.0.1.tgz",
|
||||
"integrity": "sha512-flNUPP27r3vJpROi0/R3/2efgKkyXqnXwyP1KQ2U0SfFRgdizOdWfvrrvJg1LuOoxs7GQhmxJlq23IpQ/BkByg==",
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/parse-url/-/parse-url-5.0.2.tgz",
|
||||
"integrity": "sha512-Czj+GIit4cdWtxo3ISZCvLiUjErSo0iI3wJ+q9Oi3QuMYTI6OZu+7cewMWZ+C1YAnKhYTk6/TLuhIgCypLthPA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-ssh": "^1.3.0",
|
||||
|
@ -20435,9 +20427,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"protocols": {
|
||||
"version": "1.4.7",
|
||||
"resolved": "https://registry.npmjs.org/protocols/-/protocols-1.4.7.tgz",
|
||||
"integrity": "sha512-Fx65lf9/YDn3hUX08XUc0J8rSux36rEsyiv21ZGUC1mOyeM3lTRpZLcrm8aAolzS4itwVfm7TAPyxC2E5zd6xg==",
|
||||
"version": "1.4.8",
|
||||
"resolved": "https://registry.npmjs.org/protocols/-/protocols-1.4.8.tgz",
|
||||
"integrity": "sha512-IgjKyaUSjsROSO8/D49Ab7hP8mJgTYcqApOqdPhLoPxAplXmkp+zRvsrSQjFn5by0rhm4VH0GAUELIPpx7B1yg==",
|
||||
"dev": true
|
||||
},
|
||||
"protoduck": {
|
||||
|
@ -21281,9 +21273,9 @@
|
|||
}
|
||||
},
|
||||
"rxjs": {
|
||||
"version": "6.6.0",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.0.tgz",
|
||||
"integrity": "sha512-3HMA8z/Oz61DUHe+SdOiQyzIf4tOx5oQHmMir7IZEu6TMqCLHT4LRcmNaUS0NwOz8VLvmmBduMsoaUvMaIiqzg==",
|
||||
"version": "6.6.2",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.2.tgz",
|
||||
"integrity": "sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"tslib": "^1.9.0"
|
||||
|
@ -22852,8 +22844,8 @@
|
|||
}
|
||||
},
|
||||
"strophe.js": {
|
||||
"version": "github:strophe/strophejs#c4a94e59877c06dc2395f4ccbd26f3fee67a4c9f",
|
||||
"from": "github:strophe/strophejs#c4a94e59877c06dc2395f4ccbd26f3fee67a4c9f",
|
||||
"version": "github:strophe/strophejs#ceb5640786dc60de4a13b18c9a263f2ef112874c",
|
||||
"from": "github:strophe/strophejs#ceb5640786dc60de4a13b18c9a263f2ef112874c",
|
||||
"requires": {
|
||||
"abab": "^2.0.3",
|
||||
"ws": "^7.0.0",
|
||||
|
@ -24351,9 +24343,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"windows-release": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/windows-release/-/windows-release-3.3.1.tgz",
|
||||
"integrity": "sha512-Pngk/RDCaI/DkuHPlGTdIkDiTAnAkyMjoQMZqRsxydNl1qGXNIoZrB7RK8g53F2tEgQBMqQJHQdYZuQEEAu54A==",
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/windows-release/-/windows-release-3.3.3.tgz",
|
||||
"integrity": "sha512-OSOGH1QYiW5yVor9TtmXKQvt2vjQqbYS+DqmsZw+r7xDwLXEeT3JGW0ZppFmHx4diyXmxt238KFR3N9jzevBRg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"execa": "^1.0.0"
|
||||
|
|
108
spec/messages.js
108
spec/messages.js
|
@ -1188,117 +1188,9 @@ describe("A Chat Message", function () {
|
|||
done();
|
||||
}));
|
||||
|
||||
it("received may emit a message delivery receipt",
|
||||
mock.initConverse(
|
||||
['rosterGroupsFetched', 'chatBoxesFetched'], {},
|
||||
async function (done, _converse) {
|
||||
|
||||
await mock.waitForRoster(_converse, 'current');
|
||||
const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
|
||||
const msg_id = u.getUniqueId();
|
||||
const sent_stanzas = [];
|
||||
spyOn(_converse.connection, 'send').and.callFake(stanza => sent_stanzas.push(stanza));
|
||||
const msg = $msg({
|
||||
'from': sender_jid,
|
||||
'to': _converse.connection.jid,
|
||||
'type': 'chat',
|
||||
'id': msg_id,
|
||||
}).c('body').t('Message!').up()
|
||||
.c('request', {'xmlns': Strophe.NS.RECEIPTS}).tree();
|
||||
await _converse.handleMessageStanza(msg);
|
||||
const sent_messages = sent_stanzas.map(s => _.isElement(s) ? s : s.nodeTree).filter(s => s.nodeName === 'message');
|
||||
// A chat state message is also included
|
||||
expect(sent_messages.length).toBe(2);
|
||||
const receipt = sizzle(`received[xmlns="${Strophe.NS.RECEIPTS}"]`, sent_messages[1]).pop();
|
||||
expect(Strophe.serialize(receipt)).toBe(`<received id="${msg_id}" xmlns="${Strophe.NS.RECEIPTS}"/>`);
|
||||
done();
|
||||
}));
|
||||
|
||||
it("carbon received does not emit a message delivery receipt",
|
||||
mock.initConverse(
|
||||
['rosterGroupsFetched', 'chatBoxesFetched'], {},
|
||||
async function (done, _converse) {
|
||||
await mock.waitForRoster(_converse, 'current', 1);
|
||||
const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
|
||||
const msg_id = u.getUniqueId();
|
||||
const view = await mock.openChatBoxFor(_converse, sender_jid);
|
||||
spyOn(view.model, 'sendReceiptStanza').and.callThrough();
|
||||
const msg = $msg({
|
||||
'from': sender_jid,
|
||||
'to': _converse.connection.jid,
|
||||
'type': 'chat',
|
||||
'id': u.getUniqueId(),
|
||||
}).c('received', {'xmlns': 'urn:xmpp:carbons:2'})
|
||||
.c('forwarded', {'xmlns': 'urn:xmpp:forward:0'})
|
||||
.c('message', {
|
||||
'xmlns': 'jabber:client',
|
||||
'from': sender_jid,
|
||||
'to': _converse.bare_jid+'/another-resource',
|
||||
'type': 'chat',
|
||||
'id': msg_id
|
||||
}).c('body').t('Message!').up()
|
||||
.c('request', {'xmlns': Strophe.NS.RECEIPTS}).tree();
|
||||
await _converse.handleMessageStanza(msg);
|
||||
expect(view.model.sendReceiptStanza).not.toHaveBeenCalled();
|
||||
done();
|
||||
}));
|
||||
|
||||
describe("when sent", function () {
|
||||
|
||||
it("can have its delivery acknowledged by a receipt",
|
||||
mock.initConverse(
|
||||
['rosterGroupsFetched', 'chatBoxesFetched'], {},
|
||||
async function (done, _converse) {
|
||||
|
||||
await mock.waitForRoster(_converse, 'current', 1);
|
||||
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
|
||||
await mock.openChatBoxFor(_converse, contact_jid);
|
||||
const view = _converse.chatboxviews.get(contact_jid);
|
||||
const textarea = view.el.querySelector('textarea.chat-textarea');
|
||||
textarea.value = 'But soft, what light through yonder airlock breaks?';
|
||||
view.onKeyDown({
|
||||
target: textarea,
|
||||
preventDefault: function preventDefault () {},
|
||||
keyCode: 13 // Enter
|
||||
});
|
||||
const chatbox = _converse.chatboxes.get(contact_jid);
|
||||
expect(chatbox).toBeDefined();
|
||||
await new Promise(resolve => view.model.messages.once('rendered', resolve));
|
||||
let msg_obj = chatbox.messages.models[0];
|
||||
let msg_id = msg_obj.get('msgid');
|
||||
let msg = $msg({
|
||||
'from': contact_jid,
|
||||
'to': _converse.connection.jid,
|
||||
'id': u.getUniqueId(),
|
||||
}).c('received', {'id': msg_id, xmlns: Strophe.NS.RECEIPTS}).up().tree();
|
||||
_converse.connection._dataRecv(mock.createRequest(msg));
|
||||
await u.waitUntil(() => view.el.querySelectorAll('.chat-msg__receipt').length === 1);
|
||||
|
||||
// Also handle receipts with type 'chat'. See #1353
|
||||
spyOn(_converse, 'handleMessageStanza').and.callThrough();
|
||||
textarea.value = 'Another message';
|
||||
view.onKeyDown({
|
||||
target: textarea,
|
||||
preventDefault: function preventDefault () {},
|
||||
keyCode: 13 // Enter
|
||||
});
|
||||
await new Promise(resolve => view.model.messages.once('rendered', resolve));
|
||||
|
||||
msg_obj = chatbox.messages.models[1];
|
||||
msg_id = msg_obj.get('msgid');
|
||||
msg = $msg({
|
||||
'from': contact_jid,
|
||||
'type': 'chat',
|
||||
'to': _converse.connection.jid,
|
||||
'id': u.getUniqueId(),
|
||||
}).c('received', {'id': msg_id, xmlns: Strophe.NS.RECEIPTS}).up().tree();
|
||||
_converse.connection._dataRecv(mock.createRequest(msg));
|
||||
await u.waitUntil(() => view.el.querySelectorAll('.chat-msg__receipt').length === 2);
|
||||
expect(_converse.handleMessageStanza.calls.count()).toBe(1);
|
||||
done();
|
||||
}));
|
||||
|
||||
|
||||
it("will appear inside the chatbox it was sent from",
|
||||
mock.initConverse(
|
||||
['rosterGroupsFetched', 'chatBoxesFetched'], {},
|
||||
|
|
154
spec/receipts.js
Normal file
154
spec/receipts.js
Normal file
|
@ -0,0 +1,154 @@
|
|||
/*global mock, converse */
|
||||
|
||||
const { Promise, Strophe, $msg, sizzle, _ } = converse.env;
|
||||
const u = converse.env.utils;
|
||||
|
||||
|
||||
describe("A delivery receipt", function () {
|
||||
|
||||
it("is emitted for a received message which requests it",
|
||||
mock.initConverse(
|
||||
['rosterGroupsFetched', 'chatBoxesFetched'], {},
|
||||
async function (done, _converse) {
|
||||
|
||||
await mock.waitForRoster(_converse, 'current');
|
||||
const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
|
||||
const msg_id = u.getUniqueId();
|
||||
const sent_stanzas = [];
|
||||
spyOn(_converse.connection, 'send').and.callFake(stanza => sent_stanzas.push(stanza));
|
||||
const msg = $msg({
|
||||
'from': sender_jid,
|
||||
'to': _converse.connection.jid,
|
||||
'type': 'chat',
|
||||
'id': msg_id,
|
||||
}).c('body').t('Message!').up()
|
||||
.c('request', {'xmlns': Strophe.NS.RECEIPTS}).tree();
|
||||
await _converse.handleMessageStanza(msg);
|
||||
const sent_messages = sent_stanzas.map(s => _.isElement(s) ? s : s.nodeTree).filter(s => s.nodeName === 'message');
|
||||
// A chat state message is also included
|
||||
expect(sent_messages.length).toBe(2);
|
||||
const receipt = sizzle(`received[xmlns="${Strophe.NS.RECEIPTS}"]`, sent_messages[1]).pop();
|
||||
expect(Strophe.serialize(receipt)).toBe(`<received id="${msg_id}" xmlns="${Strophe.NS.RECEIPTS}"/>`);
|
||||
done();
|
||||
}));
|
||||
|
||||
it("is not emitted for a carbon message",
|
||||
mock.initConverse(
|
||||
['rosterGroupsFetched', 'chatBoxesFetched'], {},
|
||||
async function (done, _converse) {
|
||||
|
||||
await mock.waitForRoster(_converse, 'current', 1);
|
||||
const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
|
||||
const msg_id = u.getUniqueId();
|
||||
const view = await mock.openChatBoxFor(_converse, sender_jid);
|
||||
spyOn(view.model, 'sendReceiptStanza').and.callThrough();
|
||||
const msg = $msg({
|
||||
'from': sender_jid,
|
||||
'to': _converse.connection.jid,
|
||||
'type': 'chat',
|
||||
'id': u.getUniqueId(),
|
||||
}).c('received', {'xmlns': 'urn:xmpp:carbons:2'})
|
||||
.c('forwarded', {'xmlns': 'urn:xmpp:forward:0'})
|
||||
.c('message', {
|
||||
'xmlns': 'jabber:client',
|
||||
'from': sender_jid,
|
||||
'to': _converse.bare_jid+'/another-resource',
|
||||
'type': 'chat',
|
||||
'id': msg_id
|
||||
}).c('body').t('Message!').up()
|
||||
.c('request', {'xmlns': Strophe.NS.RECEIPTS}).tree();
|
||||
await _converse.handleMessageStanza(msg);
|
||||
expect(view.model.sendReceiptStanza).not.toHaveBeenCalled();
|
||||
done();
|
||||
}));
|
||||
|
||||
it("is not emitted for an archived message",
|
||||
mock.initConverse(
|
||||
['rosterGroupsFetched', 'chatBoxesFetched'], {},
|
||||
async function (done, _converse) {
|
||||
|
||||
await mock.waitForRoster(_converse, 'current', 1);
|
||||
const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
|
||||
const view = await mock.openChatBoxFor(_converse, sender_jid);
|
||||
spyOn(view.model, 'sendReceiptStanza').and.callThrough();
|
||||
|
||||
const stanza = u.toStanza(
|
||||
`<message xmlns="jabber:client" to="${_converse.jid}">
|
||||
<result xmlns="urn:xmpp:mam:2" id="9ZWxmXMR8SVor-tC" queryid="f543c5f9-55e7-400e-860a-56baac121e6a">
|
||||
<forwarded xmlns="urn:xmpp:forward:0">
|
||||
<delay xmlns="urn:xmpp:delay" stamp="2020-01-10T22:19:30Z"/>
|
||||
<message xmlns="jabber:client" type="chat" to="${_converse.jid}" from="${sender_jid}" id="id8b6426b4-40fe-4151-941e-4c64e380acb9">
|
||||
<body>Please confirm receipt</body>
|
||||
<request xmlns="urn:xmpp:receipts"/>
|
||||
<origin-id xmlns="urn:xmpp:sid:0" id="id8b6426b4-40fe-4151-941e-4c64e380acb9"/>
|
||||
</message>
|
||||
</forwarded>
|
||||
</result>
|
||||
</message>`);
|
||||
|
||||
spyOn(view.model, 'getDuplicateMessage').and.callThrough();
|
||||
view.model.handleMAMResult({ 'messages': [stanza] });
|
||||
let message_attrs;
|
||||
_converse.api.listen.on('MAMResult', async data => {
|
||||
message_attrs = await data.messages[0];
|
||||
});
|
||||
await u.waitUntil(() => view.model.getDuplicateMessage.calls.count());
|
||||
expect(message_attrs.is_archived).toBe(true);
|
||||
expect(message_attrs.is_valid_receipt_request).toBe(false);
|
||||
expect(view.model.sendReceiptStanza).not.toHaveBeenCalled();
|
||||
done();
|
||||
}));
|
||||
|
||||
it("can be received for a sent message",
|
||||
mock.initConverse(
|
||||
['rosterGroupsFetched', 'chatBoxesFetched'], {},
|
||||
async function (done, _converse) {
|
||||
|
||||
await mock.waitForRoster(_converse, 'current', 1);
|
||||
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
|
||||
await mock.openChatBoxFor(_converse, contact_jid);
|
||||
const view = _converse.chatboxviews.get(contact_jid);
|
||||
const textarea = view.el.querySelector('textarea.chat-textarea');
|
||||
textarea.value = 'But soft, what light through yonder airlock breaks?';
|
||||
view.onKeyDown({
|
||||
target: textarea,
|
||||
preventDefault: function preventDefault () {},
|
||||
keyCode: 13 // Enter
|
||||
});
|
||||
const chatbox = _converse.chatboxes.get(contact_jid);
|
||||
expect(chatbox).toBeDefined();
|
||||
await new Promise(resolve => view.model.messages.once('rendered', resolve));
|
||||
let msg_obj = chatbox.messages.models[0];
|
||||
let msg_id = msg_obj.get('msgid');
|
||||
let msg = $msg({
|
||||
'from': contact_jid,
|
||||
'to': _converse.connection.jid,
|
||||
'id': u.getUniqueId(),
|
||||
}).c('received', {'id': msg_id, xmlns: Strophe.NS.RECEIPTS}).up().tree();
|
||||
_converse.connection._dataRecv(mock.createRequest(msg));
|
||||
await u.waitUntil(() => view.el.querySelectorAll('.chat-msg__receipt').length === 1);
|
||||
|
||||
// Also handle receipts with type 'chat'. See #1353
|
||||
spyOn(_converse, 'handleMessageStanza').and.callThrough();
|
||||
textarea.value = 'Another message';
|
||||
view.onKeyDown({
|
||||
target: textarea,
|
||||
preventDefault: function preventDefault () {},
|
||||
keyCode: 13 // Enter
|
||||
});
|
||||
await new Promise(resolve => view.model.messages.once('rendered', resolve));
|
||||
|
||||
msg_obj = chatbox.messages.models[1];
|
||||
msg_id = msg_obj.get('msgid');
|
||||
msg = $msg({
|
||||
'from': contact_jid,
|
||||
'type': 'chat',
|
||||
'to': _converse.connection.jid,
|
||||
'id': u.getUniqueId(),
|
||||
}).c('received', {'id': msg_id, xmlns: Strophe.NS.RECEIPTS}).up().tree();
|
||||
_converse.connection._dataRecv(mock.createRequest(msg));
|
||||
await u.waitUntil(() => view.el.querySelectorAll('.chat-msg__receipt').length === 2);
|
||||
expect(_converse.handleMessageStanza.calls.count()).toBe(1);
|
||||
done();
|
||||
}));
|
||||
});
|
|
@ -889,7 +889,7 @@ converse.plugins.add('converse-chat', {
|
|||
|
||||
handleReceipt (attrs) {
|
||||
if (attrs.sender === 'them') {
|
||||
if (attrs.is_receipt_request) {
|
||||
if (attrs.is_valid_receipt_request) {
|
||||
this.sendReceiptStanza(attrs.from, attrs.msgid);
|
||||
} else if (attrs.receipt_id) {
|
||||
const message = this.messages.findWhere({'msgid': attrs.receipt_id});
|
||||
|
|
|
@ -1998,7 +1998,7 @@ converse.plugins.add('converse-muc', {
|
|||
const message = this.getDuplicateMessage(attrs);
|
||||
if (message) {
|
||||
return this.updateMessage(message, attrs);
|
||||
} else if (attrs.is_receipt_request || attrs.is_marker || this.ignorableCSN(attrs)) {
|
||||
} else if (attrs.is_valid_receipt_request || attrs.is_marker || this.ignorableCSN(attrs)) {
|
||||
return;
|
||||
}
|
||||
if (await this.handleRetraction(attrs) ||
|
||||
|
|
10
src/headless/package-lock.json
generated
10
src/headless/package-lock.json
generated
|
@ -14,9 +14,9 @@
|
|||
}
|
||||
},
|
||||
"abab": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.3.tgz",
|
||||
"integrity": "sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg==",
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.4.tgz",
|
||||
"integrity": "sha512-Eu9ELJWCz/c1e9gTiCY+FceWxcqzjYEbqMgtndnuSqZSUCOL73TWNK2mHfIj4Cw2E/ongOp+JISVNCmovt2KYQ==",
|
||||
"dev": true
|
||||
},
|
||||
"filesize": {
|
||||
|
@ -83,8 +83,8 @@
|
|||
}
|
||||
},
|
||||
"strophe.js": {
|
||||
"version": "github:strophe/strophejs#c4a94e59877c06dc2395f4ccbd26f3fee67a4c9f",
|
||||
"from": "github:strophe/strophejs#c4a94e59877c06dc2395f4ccbd26f3fee67a4c9f",
|
||||
"version": "github:strophe/strophejs#ceb5640786dc60de4a13b18c9a263f2ef112874c",
|
||||
"from": "github:strophe/strophejs#ceb5640786dc60de4a13b18c9a263f2ef112874c",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"abab": "^2.0.3",
|
||||
|
|
|
@ -42,6 +42,6 @@
|
|||
"localforage": "^1.7.3",
|
||||
"lodash-es": "^4.17.15",
|
||||
"pluggable.js": "2.0.1",
|
||||
"strophe.js": "strophe/strophejs#c4a94e59877c06dc2395f4ccbd26f3fee67a4c9f"
|
||||
"strophe.js": "strophe/strophejs#ceb5640786dc60de4a13b18c9a263f2ef112874c"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ function getEncryptionAttributes (stanza, _converse) {
|
|||
}
|
||||
|
||||
|
||||
function isReceiptRequest (stanza, attrs) {
|
||||
function isValidReceiptRequest (stanza, attrs) {
|
||||
return (
|
||||
attrs.sender !== 'me' &&
|
||||
!attrs.is_carbon &&
|
||||
|
@ -382,6 +382,7 @@ const st = {
|
|||
return new StanzaParseError(`Ignoring incoming message intended for a different resource: ${to_jid}`, stanza);
|
||||
}
|
||||
|
||||
const original_stanza = stanza;
|
||||
let from_jid = stanza.getAttribute('from') || _converse.bare_jid;
|
||||
if (isCarbon(stanza)) {
|
||||
if (from_jid === _converse.bare_jid) {
|
||||
|
@ -396,7 +397,8 @@ const st = {
|
|||
}
|
||||
}
|
||||
|
||||
if (st.isArchived(stanza)) {
|
||||
const is_archived = st.isArchived(stanza);
|
||||
if (is_archived) {
|
||||
if (from_jid === _converse.bare_jid) {
|
||||
const selector = `[xmlns="${Strophe.NS.MAM}"] > forwarded[xmlns="${Strophe.NS.FORWARD}"] > message`;
|
||||
stanza = sizzle(selector, stanza).pop();
|
||||
|
@ -446,7 +448,7 @@ const st = {
|
|||
* @property { Boolean } is_markable - Can this message be marked with a XEP-0333 chat marker?
|
||||
* @property { Boolean } is_marker - Is this message a XEP-0333 Chat Marker?
|
||||
* @property { Boolean } is_only_emojis - Does the message body contain only emojis?
|
||||
* @property { Boolean } is_receipt_request - Does this message request a XEP-0184 receipt?
|
||||
* @property { Boolean } is_valid_receipt_request - Does this message request a XEP-0184 receipt (and is not from us or a carbon or archived message)
|
||||
* @property { Boolean } is_spoiler - Is this a XEP-0382 spoiler message?
|
||||
* @property { Boolean } is_tombstone - Is this a XEP-0424 tombstone?
|
||||
* @property { Object } encrypted - XEP-0384 encryption payload attributes
|
||||
|
@ -479,18 +481,17 @@ const st = {
|
|||
* @property { String } to - The recipient JID
|
||||
* @property { String } type - The type of message
|
||||
*/
|
||||
const original_stanza = stanza;
|
||||
const delay = sizzle(`delay[xmlns="${Strophe.NS.DELAY}"]`, original_stanza).pop();
|
||||
const marker = st.getChatMarker(stanza);
|
||||
const now = (new Date()).toISOString();
|
||||
let attrs = Object.assign({
|
||||
contact_jid,
|
||||
is_archived,
|
||||
is_headline,
|
||||
is_server_message,
|
||||
'body': stanza.querySelector('body')?.textContent?.trim(),
|
||||
'chat_state': getChatState(stanza),
|
||||
'from': Strophe.getBareJidFromJid(stanza.getAttribute('from')),
|
||||
'is_archived': st.isArchived(original_stanza),
|
||||
'is_carbon': isCarbon(original_stanza),
|
||||
'is_delayed': !!delay,
|
||||
'is_markable': !!sizzle(`markable[xmlns="${Strophe.NS.MARKERS}"]`, stanza).length,
|
||||
|
@ -527,7 +528,7 @@ const st = {
|
|||
attrs = Object.assign({
|
||||
'message': attrs.body || attrs.error, // TODO: Remove and use body and error attributes instead
|
||||
'is_only_emojis': attrs.body ? u.isOnlyEmojis(attrs.body) : false,
|
||||
'is_receipt_request': isReceiptRequest(stanza, attrs)
|
||||
'is_valid_receipt_request': isValidReceiptRequest(stanza, attrs)
|
||||
}, attrs);
|
||||
|
||||
// We prefer to use one of the XEP-0359 unique and stable stanza IDs
|
||||
|
@ -581,7 +582,7 @@ const st = {
|
|||
* @property { Boolean } is_markable - Can this message be marked with a XEP-0333 chat marker?
|
||||
* @property { Boolean } is_marker - Is this message a XEP-0333 Chat Marker?
|
||||
* @property { Boolean } is_only_emojis - Does the message body contain only emojis?
|
||||
* @property { Boolean } is_receipt_request - Does this message request a XEP-0184 receipt?
|
||||
* @property { Boolean } is_valid_receipt_request - Does this message request a XEP-0184 receipt (and is not from us or a carbon or archived message)
|
||||
* @property { Boolean } is_spoiler - Is this a XEP-0382 spoiler message?
|
||||
* @property { Boolean } is_tombstone - Is this a XEP-0424 tombstone?
|
||||
* @property { Object } encrypted - XEP-0384 encryption payload attributes
|
||||
|
@ -654,7 +655,7 @@ const st = {
|
|||
await api.emojis.initialize();
|
||||
attrs = Object.assign({
|
||||
'is_only_emojis': attrs.body ? u.isOnlyEmojis(attrs.body) : false,
|
||||
'is_receipt_request': isReceiptRequest(stanza, attrs),
|
||||
'is_valid_receipt_request': isValidReceiptRequest(stanza, attrs),
|
||||
'message': attrs.body || attrs.error, // TODO: Remove and use body and error attributes instead
|
||||
'sender': attrs.nick === chatbox.get('nick') ? 'me': 'them',
|
||||
}, attrs);
|
||||
|
|
Loading…
Reference in New Issue
Block a user