summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authormatiboy <mathieu.chauvinc@gmail.com>2023-11-16 21:48:36 +0100
committerGitHub <noreply@github.com>2023-11-16 13:48:36 -0700
commitc454ea4eee43ca7e6449f7ccce86dac05fa284cf (patch)
treec2c93647e3f9056012c8dfd54a4025caf1ad228d
parent68661753bd96b4b6d9cc82b4f9f36d52d609244e (diff)
downloadhtmx-c454ea4eee43ca7e6449f7ccce86dac05fa284cf.tar.gz
htmx-c454ea4eee43ca7e6449f7ccce86dac05fa284cf.zip
Fix WS sendImmediately (#1949)
* Tests at current state of the code * Currently failing case (actual issue) * Fix issue --------- Co-authored-by: mat <matt@techspace.asia>
-rw-r--r--src/ext/ws.js2
-rw-r--r--test/ext/ws.js201
2 files changed, 202 insertions, 1 deletions
diff --git a/src/ext/ws.js b/src/ext/ws.js
index 3366e9e5..05be1eca 100644
--- a/src/ext/ws.js
+++ b/src/ext/ws.js
@@ -200,7 +200,7 @@ This extension adds support for WebSockets to htmx. See /www/extensions/ws.md f
if (!this.socket) {
api.triggerErrorEvent()
}
- if (sendElt && api.triggerEvent(sendElt, 'htmx:wsBeforeSend', {
+ if (!sendElt || api.triggerEvent(sendElt, 'htmx:wsBeforeSend', {
message: message,
socketWrapper: this.publicInterface
})) {
diff --git a/test/ext/ws.js b/test/ext/ws.js
index 7e6f140d..ce17782d 100644
--- a/test/ext/ws.js
+++ b/test/ext/ws.js
@@ -614,4 +614,205 @@ describe("web-sockets extension", function () {
this.messages[1].should.contains('"foo":"bar"')
this.messages[1].should.contains('"action":"B"')
})
+
+ describe("Send immediately", function() {
+ function checkCallForWsBeforeSend(spy, wrapper, message, target) {
+ // Utility function to always check the same for htmx:wsBeforeSend caught by a spy
+ spy.calledOnce.should.be.true;
+ var call = spy.getCall(0);
+ call.args.length.should.equal(1);
+ var arg = call.args[0];
+ arg.target.should.equal(target);
+ arg.detail.socketWrapper.should.equal(wrapper);
+ arg.detail.message.should.equal(message);
+ }
+ it('triggers wsBeforeSend on body if provided to sendImmediately', function (done) {
+ var myEventCalled = sinon.spy();
+ var message = '{"foo":"bar"}';
+ var handler = function(e){
+ var socketWrapper = e.detail.socketWrapper;
+ window.document.body.addEventListener("htmx:wsBeforeSend", myEventCalled)
+ try {
+ socketWrapper.sendImmediately(message, window.document.body)
+ checkCallForWsBeforeSend(myEventCalled, socketWrapper, message, window.document.body)
+ } finally {
+ window.document.body.removeEventListener("htmx:wsBeforeSend", myEventCalled)
+ }
+ done()
+ }
+ try {
+ window.document.addEventListener("htmx:wsOpen", handler)
+
+ var div = make('<div hx-ext="ws" ws-connect="ws://localhost:8080"><div id="d1">div1</div></div>');
+ this.tickMock();
+ } finally {
+ window.document.removeEventListener("htmx:wsOpen", handler)
+ }
+
+ })
+ it('triggers wsBeforeSend on any send element provided to sendImmediately', function (done) {
+ var myEventCalled = sinon.spy();
+ var message = '{"a":"b"}';
+ var handler = function(e){
+ var socketWrapper = e.detail.socketWrapper;
+ var id1 = byId("d1");
+ id1.addEventListener("htmx:wsBeforeSend", myEventCalled)
+ try {
+ socketWrapper.sendImmediately(message, d1)
+ checkCallForWsBeforeSend(myEventCalled, socketWrapper, message, d1)
+ } finally {
+ id1.removeEventListener("htmx:wsBeforeSend", myEventCalled)
+ }
+ done()
+ }
+
+ window.document.addEventListener("htmx:wsOpen", handler)
+ try {
+ var div = make('<div hx-ext="ws" ws-connect="ws://localhost:8080"><div id="d1">div1</div></div>');
+ this.tickMock();
+ } finally {
+ window.document.removeEventListener("htmx:wsOpen", handler)
+ }
+
+ })
+ it('triggers wsAfterSend on body if provided to sendImmediately', function (done) {
+ var myEventCalled = sinon.spy();
+ var message = '{"foo":"bar"}';
+ var handler = function(e){
+ var socketWrapper = e.detail.socketWrapper;
+ window.document.body.addEventListener("htmx:wsAfterSend", myEventCalled)
+ try {
+ socketWrapper.sendImmediately(message, window.document.body)
+ checkCallForWsBeforeSend(myEventCalled, socketWrapper, message, window.document.body)
+ } finally {
+ window.document.body.removeEventListener("htmx:wsAfterSend", myEventCalled)
+ }
+ done()
+ }
+ try {
+ window.document.addEventListener("htmx:wsOpen", handler)
+
+ var div = make('<div hx-ext="ws" ws-connect="ws://localhost:8080"><div id="d1">div1</div></div>');
+ this.tickMock();
+ } finally {
+ window.document.removeEventListener("htmx:wsOpen", handler)
+ }
+
+ })
+ it('triggers wsAfterSend on any send element provided to sendImmediately', function (done) {
+ var myEventCalled = sinon.spy();
+ var message = '{"a":"b"}';
+ var handler = function(e){
+ var socketWrapper = e.detail.socketWrapper;
+ var id1 = byId("d1");
+ id1.addEventListener("htmx:wsAfterSend", myEventCalled)
+ try {
+ socketWrapper.sendImmediately(message, d1)
+ checkCallForWsBeforeSend(myEventCalled, socketWrapper, message, d1)
+ } finally {
+ id1.removeEventListener("htmx:wsAfterSend", myEventCalled)
+ }
+ done()
+ }
+
+ window.document.addEventListener("htmx:wsOpen", handler)
+ try {
+ var div = make('<div hx-ext="ws" ws-connect="ws://localhost:8080"><div id="d1">div1</div></div>');
+ this.tickMock();
+ } finally {
+ window.document.removeEventListener("htmx:wsOpen", handler)
+ }
+
+ })
+ it('sends message if event is not prevented', function (done) {
+ var message = '{"a":"b"}';
+ var noop = function() {}
+ var handler = function(e){
+ var socketWrapper = e.detail.socketWrapper;
+ var id1 = byId("d1");
+ id1.addEventListener("htmx:wsBeforeSend", noop)
+ try {
+ socketWrapper.sendImmediately(message, d1)
+ this.tickMock();
+ this.messages.should.eql([message])
+ } finally {
+ id1.removeEventListener("htmx:wsBeforeSend", noop)
+ }
+ done()
+ }.bind(this)
+
+ window.document.addEventListener("htmx:wsOpen", handler)
+ try {
+ var div = make('<div hx-ext="ws" ws-connect="ws://localhost:8080"><div id="d1">div1</div></div>');
+ this.tickMock();
+ } finally {
+ window.document.removeEventListener("htmx:wsOpen", handler)
+ }
+ })
+ it('sends message if no sending element is provided', function (done) {
+ var message = '{"a":"b"}';
+ var handler = function(e){
+ var socketWrapper = e.detail.socketWrapper;
+ socketWrapper.sendImmediately(message)
+ this.tickMock();
+ this.messages.should.eql([message])
+ done()
+ }.bind(this)
+
+ window.document.addEventListener("htmx:wsOpen", handler)
+ try {
+ var div = make('<div hx-ext="ws" ws-connect="ws://localhost:8080"><div id="d1">div1</div></div>');
+ this.tickMock();
+ } finally {
+ window.document.removeEventListener("htmx:wsOpen", handler)
+ }
+ })
+ it('sends message if sending element has no event listener for beforeSend', function (done) {
+ var message = '{"a":"b"}';
+ var handler = function(e){
+ var socketWrapper = e.detail.socketWrapper;
+ var d1 = byId("d1");
+ socketWrapper.sendImmediately(message, d1)
+ this.tickMock();
+ this.messages.should.eql([message])
+ done()
+ }.bind(this)
+
+ window.document.addEventListener("htmx:wsOpen", handler)
+ try {
+ var div = make('<div hx-ext="ws" ws-connect="ws://localhost:8080"><div id="d1">div1</div></div>');
+ this.tickMock();
+ } finally {
+ window.document.removeEventListener("htmx:wsOpen", handler)
+ }
+ })
+ it('does not send message if beforeSend is prevented', function (done) {
+ var message = '{"a":"b"}';
+ var eventPrevented = function(e) {e.preventDefault()}
+ var handler = function(e){
+ var socketWrapper = e.detail.socketWrapper;
+ var id1 = byId("d1");
+ id1.addEventListener("htmx:wsBeforeSend", eventPrevented)
+ try {
+ socketWrapper.sendImmediately(message, d1)
+ this.tickMock();
+ this.messages.should.eql([])
+ } finally {
+ id1.removeEventListener("htmx:wsBeforeSend", eventPrevented)
+ }
+ done()
+ }.bind(this)
+
+ window.document.addEventListener("htmx:wsOpen", handler)
+ try {
+ var div = make('<div hx-ext="ws" ws-connect="ws://localhost:8080"><div id="d1">div1</div></div>');
+ this.tickMock();
+ } finally {
+ window.document.removeEventListener("htmx:wsOpen", handler)
+ }
+
+ })
+ })
+
+
});