Skip to content

Commit 6ab73b5

Browse files
authored
Fixed the .off() function from removing all bindings (#9)
1 parent da01865 commit 6ab73b5

File tree

4 files changed

+137
-8
lines changed

4 files changed

+137
-8
lines changed

build.gradle

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ dependencies {
2424

2525
testCompile group: 'junit', name: 'junit', version: '4.12'
2626
testCompile group: 'com.google.truth', name: 'truth', version: '0.42'
27+
testCompile group: 'org.mockito', name: 'mockito-core', version: '2.19.1'
2728

2829
}
2930

src/main/kotlin/org/phoenixframework/PhxChannel.kt

+4-4
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import java.lang.IllegalStateException
55

66
class PhxChannel(
77
val topic: String,
8-
var params: Payload,
8+
val params: Payload,
99
val socket: PhxSocket
1010
) {
1111

@@ -60,7 +60,7 @@ class PhxChannel(
6060
this.state = PhxChannel.PhxState.CLOSED
6161
this.bindings = ArrayList()
6262
this.bindingRef = 0
63-
this.timeout = DEFAULT_TIMEOUT
63+
this.timeout = socket.timeout
6464
this.joinedOnce = false
6565
this.pushBuffer = ArrayList()
6666
this.joinPush = PhxPush(this,
@@ -220,7 +220,7 @@ class PhxChannel(
220220
// Remove any subscriptions that match the given event and ref ID. If no ref
221221
// ID is given, then remove all subscriptions for an event.
222222
this.bindings = bindings
223-
.filter { it.first == event && (ref == null || ref == it.second) }
223+
.filterNot { it.first == event && (ref == null || ref == it.second) }
224224
.toMutableList()
225225
}
226226

@@ -300,7 +300,7 @@ class PhxChannel(
300300
// Internal
301301
//------------------------------------------------------------------------------
302302
/** Checks if an event received by the socket belongs to the Channel */
303-
fun isMemeber(message: PhxMessage): Boolean {
303+
fun isMember(message: PhxMessage): Boolean {
304304
if (message.topic != this.topic) { return false }
305305

306306
val isLifecycleEvent = PhxEvent.isLifecycleEvent(message.event)

src/main/kotlin/org/phoenixframework/PhxSocket.kt

+4-4
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const val DEFAULT_TIMEOUT: Long = 10000
2323
/** Default heartbeat interval set to 30s */
2424
const val DEFAULT_HEARTBEAT: Long = 30000
2525

26-
class PhxSocket(
26+
open class PhxSocket(
2727
url: String,
2828
params: Payload? = null
2929
) : WebSocketListener() {
@@ -259,7 +259,7 @@ class PhxSocket(
259259
/**
260260
* Sends data through the Socket
261261
*/
262-
public fun push(topic: String,
262+
public open fun push(topic: String,
263263
event: String,
264264
payload: Payload,
265265
ref: String? = null,
@@ -295,7 +295,7 @@ class PhxSocket(
295295
/**
296296
* @return the next message ref, accounting for overflows
297297
*/
298-
public fun makeRef(): String {
298+
public open fun makeRef(): String {
299299
val newRef = this.ref + 1
300300
this.ref = if (newRef == Int.MAX_VALUE) 0 else newRef
301301

@@ -363,7 +363,7 @@ class PhxSocket(
363363

364364
// Dispatch the message to all channels that belong to the topic
365365
this.channels
366-
.filter { it.isMemeber(message) }
366+
.filter { it.isMember(message) }
367367
.forEach { it.trigger(message) }
368368

369369
// Inform all onMessage callbacks of the message
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
package org.phoenixframework
2+
3+
import com.google.common.truth.Truth.assertThat
4+
import org.junit.Before
5+
import org.junit.Test
6+
import org.mockito.Mockito
7+
import org.mockito.MockitoAnnotations
8+
import org.mockito.Spy
9+
10+
class PhxChannelTest {
11+
12+
private val defaultRef = "1"
13+
14+
@Spy
15+
var socket: PhxSocket = PhxSocket("http://localhost:4000/socket/websocket")
16+
lateinit var channel: PhxChannel
17+
18+
@Before
19+
fun setUp() {
20+
MockitoAnnotations.initMocks(this)
21+
Mockito.doReturn(defaultRef).`when`(socket).makeRef()
22+
23+
socket.timeout = 1234
24+
channel = PhxChannel("topic", hashMapOf("one" to "two"), socket)
25+
}
26+
27+
28+
//------------------------------------------------------------------------------
29+
// Constructor
30+
//------------------------------------------------------------------------------
31+
@Test
32+
fun `constructor sets defaults`() {
33+
assertThat(channel.isClosed).isTrue()
34+
assertThat(channel.topic).isEqualTo("topic")
35+
assertThat(channel.params["one"]).isEqualTo("two")
36+
assertThat(channel.socket).isEqualTo(socket)
37+
assertThat(channel.timeout).isEqualTo(1234)
38+
assertThat(channel.joinedOnce).isFalse()
39+
assertThat(channel.pushBuffer).isEmpty()
40+
}
41+
42+
@Test
43+
fun `constructor sets up joinPush with params`() {
44+
val joinPush = channel.joinPush
45+
46+
assertThat(joinPush.channel).isEqualTo(channel)
47+
assertThat(joinPush.payload["one"]).isEqualTo("two")
48+
assertThat(joinPush.event).isEqualTo(PhxChannel.PhxEvent.JOIN.value)
49+
assertThat(joinPush.timeout).isEqualTo(1234)
50+
}
51+
52+
53+
//------------------------------------------------------------------------------
54+
// Join
55+
//------------------------------------------------------------------------------
56+
@Test
57+
fun `it sets the state to joining`() {
58+
channel.join()
59+
assertThat(channel.isJoining).isTrue()
60+
}
61+
62+
@Test
63+
fun `it updates the join parameters`() {
64+
channel.join(hashMapOf("one" to "three"))
65+
66+
val joinPush = channel.joinPush
67+
assertThat(joinPush.payload["one"]).isEqualTo("three")
68+
}
69+
70+
@Test
71+
fun `it sets joinedOnce to true`() {
72+
assertThat(channel.joinedOnce).isFalse()
73+
74+
channel.join()
75+
assertThat(channel.joinedOnce).isTrue()
76+
}
77+
78+
@Test(expected = IllegalStateException::class)
79+
fun `it throws if attempting to join multiple times`() {
80+
channel.join()
81+
channel.join()
82+
}
83+
84+
85+
86+
//------------------------------------------------------------------------------
87+
// .off()
88+
//------------------------------------------------------------------------------
89+
@Test
90+
fun `it removes all callbacks for events`() {
91+
Mockito.doReturn(defaultRef).`when`(socket).makeRef()
92+
93+
var aCalled = false
94+
var bCalled = false
95+
var cCalled = false
96+
97+
channel.on("event") { aCalled = true }
98+
channel.on("event") { bCalled = true }
99+
channel.on("other") { cCalled = true }
100+
101+
channel.off("event")
102+
103+
channel.trigger(PhxMessage(event = "event", ref = defaultRef))
104+
channel.trigger(PhxMessage(event = "other", ref = defaultRef))
105+
106+
assertThat(aCalled).isFalse()
107+
assertThat(bCalled).isFalse()
108+
assertThat(cCalled).isTrue()
109+
}
110+
111+
@Test
112+
fun `it removes callbacks by its ref`() {
113+
var aCalled = false
114+
var bCalled = false
115+
116+
val aRef = channel.on("event") { aCalled = true }
117+
channel.on("event") { bCalled = true }
118+
119+
120+
channel.off("event", aRef)
121+
122+
channel.trigger(PhxMessage(event = "event", ref = defaultRef))
123+
124+
assertThat(aCalled).isFalse()
125+
assertThat(bCalled).isTrue()
126+
}
127+
}
128+

0 commit comments

Comments
 (0)