**Improve event handling with new music and queue updates**
Added new `MusicEvent` types, including `TRACK_ERROR`, `TRACK_STUCK`, and `PLAYER_POSITION`, providing enhanced diagnostics and feedback. Improved queue mutation notifications by introducing granular events like `added`, `removed`, `moved`, `cleared`, and `shuffled`. Updated tests and documentation to reflect the changes, ensuring consistency and clarity across the event system.
This commit is contained in:
1 parent
75b495b08c
commit
87ba09b001
9 files changed
+336
-20
No files matched your search
@@ -27,7 +27,11 @@ public record MusicEvent(Type type, String guildId, long timestamp, long seq, Ob
|
||||
PLAYER_SEEKED,
|
||||
VOTE_SKIP_UPDATED,
|
||||
VOICE_CONNECTED,
|
||||
VOICE_DISCONNECTED
|
||||
VOICE_DISCONNECTED,
|
||||
QUEUE_SHUFFLED,
|
||||
TRACK_ERROR,
|
||||
TRACK_STUCK,
|
||||
PLAYER_POSITION
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -171,6 +171,8 @@ public class EventsHandler implements EventListener {
|
||||
return Map.of(
|
||||
"channelId", channelId,
|
||||
"userId", event.getEntity().getId(),
|
||||
"username", event.getEntity().getUser().getName(),
|
||||
"nickname", event.getEntity().getEffectiveName(),
|
||||
"bot", event.getEntity().getUser().isBot(),
|
||||
"self", self);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import dev.arbjerg.lavalink.client.Helpers;
|
||||
import dev.arbjerg.lavalink.client.LavalinkClient;
|
||||
import dev.arbjerg.lavalink.client.LavalinkNode;
|
||||
import dev.arbjerg.lavalink.client.NodeOptions;
|
||||
import dev.arbjerg.lavalink.client.event.PlayerUpdateEvent;
|
||||
import dev.arbjerg.lavalink.client.event.ReadyEvent;
|
||||
import dev.arbjerg.lavalink.client.event.TrackEndEvent;
|
||||
import dev.arbjerg.lavalink.client.event.TrackExceptionEvent;
|
||||
@@ -209,6 +210,11 @@ public class MusicServiceImpl implements MusicService {
|
||||
subscriptions.add(client.on(TrackStuckEvent.class)
|
||||
.subscribe(event -> dispatch(event.getGuildId(), scheduler -> scheduler.onTrackStuck(event.getTrack(), event.getThresholdMs()))));
|
||||
|
||||
subscriptions.add(client.on(PlayerUpdateEvent.class)
|
||||
.subscribe(event -> dispatch(event.getGuildId(), scheduler -> scheduler.onPlayerUpdate(
|
||||
event.getState().getTime(), event.getState().getPosition(),
|
||||
event.getState().getConnected(), event.getState().getPing()))));
|
||||
|
||||
subscriptions.add(client.on(WebSocketClosedEvent.class)
|
||||
.subscribe(event -> dispatch(event.getGuildId(), scheduler -> scheduler.onWebSocketClosed(event.getCode(), event.getReason(), event.getByRemote()))));
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import org.apache.logging.log4j.Logger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Deque;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
@@ -63,18 +64,31 @@ public class QueueManager {
|
||||
|
||||
public void removeHeadOfQueue() {
|
||||
synchronized (queue) {
|
||||
queue.poll();
|
||||
notifyQueueUpdated();
|
||||
TrackInfo head = queue.poll();
|
||||
notifyQueueUpdated("removed", head == null ? List.of() : List.of(item(0, head)));
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyQueueUpdated() {
|
||||
private static Map<String, Object> item(int index, TrackInfo info) {
|
||||
Map<String, Object> item = new HashMap<>();
|
||||
item.put("index", index);
|
||||
item.put("identifier", info.getTrack().getInfo().getIdentifier());
|
||||
item.put("title", info.getTrack().getInfo().getTitle());
|
||||
item.put("uri", info.getTrack().getInfo().getUri());
|
||||
item.put("requesterId", info.getRequester() == null ? null : info.getRequester().getId());
|
||||
return item;
|
||||
}
|
||||
|
||||
private void notifyQueueUpdated(String change, List<Map<String, Object>> items) {
|
||||
MusicManager musicManager = scheduler.getMusicManager();
|
||||
if (musicManager == null || musicManager.getEvents() == null) {
|
||||
return;
|
||||
}
|
||||
musicManager.getEvents().publish(MusicEvent.of(MusicEvent.Type.QUEUE_UPDATED, guild.getId(),
|
||||
Map.of("size", queue.size())));
|
||||
Map<String, Object> payload = new HashMap<>();
|
||||
payload.put("size", queue.size());
|
||||
payload.put("change", change);
|
||||
payload.put("items", items);
|
||||
musicManager.getEvents().publish(MusicEvent.of(MusicEvent.Type.QUEUE_UPDATED, guild.getId(), payload));
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
@@ -91,7 +105,7 @@ public class QueueManager {
|
||||
}
|
||||
|
||||
queue.clear();
|
||||
notifyQueueUpdated();
|
||||
notifyQueueUpdated("cleared", List.of());
|
||||
scheduler.getCallback().onQueueEmpty();
|
||||
return QueueActionResult.success(String.format("Removed %d track%s from the queue", queueSize, (queueSize > 1 ? "s" : "")));
|
||||
}
|
||||
@@ -109,8 +123,16 @@ public class QueueManager {
|
||||
}
|
||||
|
||||
TrackInfo first = queue.peek();
|
||||
List<Map<String, Object>> removed = new ArrayList<>();
|
||||
int position = 0;
|
||||
for (TrackInfo trackInfo : queue) {
|
||||
if (member.equals(trackInfo.getRequester())) {
|
||||
removed.add(item(position, trackInfo));
|
||||
}
|
||||
position++;
|
||||
}
|
||||
queue.removeIf(trackInfo -> member.equals(trackInfo.getRequester()));
|
||||
notifyQueueUpdated();
|
||||
notifyQueueUpdated("removed", removed);
|
||||
|
||||
if (first != null && member.equals(first.getRequester())) {
|
||||
skip(1);
|
||||
@@ -148,7 +170,7 @@ public class QueueManager {
|
||||
} else {
|
||||
queue.add(info);
|
||||
}
|
||||
notifyQueueUpdated();
|
||||
notifyQueueUpdated("added", List.of(item(queue.peekFirst() == info ? 0 : queue.size() - 1, info)));
|
||||
|
||||
if (idle) {
|
||||
TrackInfo head = queue.peek();
|
||||
@@ -196,8 +218,8 @@ public class QueueManager {
|
||||
|
||||
public void startNextTrack() {
|
||||
synchronized (queue) {
|
||||
queue.poll();
|
||||
notifyQueueUpdated();
|
||||
TrackInfo polled = queue.poll();
|
||||
notifyQueueUpdated("removed", polled == null ? List.of() : List.of(item(0, polled)));
|
||||
TrackInfo next = queue.peek();
|
||||
|
||||
if (next != null) {
|
||||
@@ -259,7 +281,12 @@ public class QueueManager {
|
||||
queue.clear();
|
||||
queue.add(current);
|
||||
queue.addAll(newQueue);
|
||||
notifyQueueUpdated();
|
||||
notifyQueueUpdated("shuffled", List.of());
|
||||
MusicManager musicManager = scheduler.getMusicManager();
|
||||
if (musicManager != null && musicManager.getEvents() != null) {
|
||||
musicManager.getEvents().publish(MusicEvent.of(MusicEvent.Type.QUEUE_SHUFFLED, guild.getId(),
|
||||
Map.of("size", queue.size())));
|
||||
}
|
||||
|
||||
return QueueActionResult.success("The queue is now shuffled.");
|
||||
}
|
||||
@@ -279,11 +306,11 @@ public class QueueManager {
|
||||
|
||||
if (index > 1) {
|
||||
List<TrackInfo> newQueue = new ArrayList<>(queue);
|
||||
newQueue.remove(index - 1);
|
||||
TrackInfo removedInfo = newQueue.remove(index - 1);
|
||||
|
||||
queue.clear();
|
||||
queue.addAll(newQueue);
|
||||
notifyQueueUpdated();
|
||||
notifyQueueUpdated("removed", List.of(item(index - 1, removedInfo)));
|
||||
|
||||
return QueueActionResult.success(String.format("Removed track #%d from the queue", index));
|
||||
}
|
||||
@@ -327,7 +354,10 @@ public class QueueManager {
|
||||
|
||||
queue.clear();
|
||||
queue.addAll(newQueue);
|
||||
notifyQueueUpdated();
|
||||
Map<String, Object> movedItem = item(toIndex - 1, moved);
|
||||
movedItem.put("fromIndex", fromIndex - 1);
|
||||
movedItem.put("toIndex", toIndex - 1);
|
||||
notifyQueueUpdated("moved", List.of(movedItem));
|
||||
|
||||
return QueueActionResult.success(String.format("Moved track #%d to position #%d", fromIndex, toIndex));
|
||||
}
|
||||
|
||||
@@ -33,6 +33,8 @@ public class TrackScheduler {
|
||||
private volatile Context context;
|
||||
private volatile Track currentTrack;
|
||||
private final StuckTrackRecoveryHandler stuckTrackRecoveryHandler;
|
||||
private static final long POSITION_THROTTLE_MS = 5000;
|
||||
private volatile long lastPositionSent = Long.MIN_VALUE;
|
||||
|
||||
public TrackScheduler(MusicManager manager) {
|
||||
this.manager = manager;
|
||||
@@ -137,10 +139,7 @@ public class TrackScheduler {
|
||||
// clone of this back to your queue
|
||||
}
|
||||
|
||||
private void publish(MusicEvent.Type type, Track track, String reason) {
|
||||
if (manager.getEvents() == null) {
|
||||
return;
|
||||
}
|
||||
private static java.util.Map<String, Object> trackPayload(Track track) {
|
||||
java.util.Map<String, Object> payload = new java.util.HashMap<>();
|
||||
payload.put("identifier", track.getInfo().getIdentifier());
|
||||
payload.put("title", track.getInfo().getTitle());
|
||||
@@ -148,6 +147,14 @@ public class TrackScheduler {
|
||||
payload.put("length", track.getInfo().getLength());
|
||||
payload.put("uri", track.getInfo().getUri());
|
||||
payload.put("artworkUrl", track.getInfo().getArtworkUrl());
|
||||
return payload;
|
||||
}
|
||||
|
||||
private void publish(MusicEvent.Type type, Track track, String reason) {
|
||||
if (manager.getEvents() == null) {
|
||||
return;
|
||||
}
|
||||
java.util.Map<String, Object> payload = trackPayload(track);
|
||||
if (reason != null) {
|
||||
payload.put("reason", reason);
|
||||
}
|
||||
@@ -157,6 +164,14 @@ public class TrackScheduler {
|
||||
public void onTrackException(Track track, TrackException exception) {
|
||||
logger.error("Guild {}: exception while playing track: {}", guild.getId(), track.getInfo().getIdentifier());
|
||||
|
||||
if (manager.getEvents() != null) {
|
||||
java.util.Map<String, Object> payload = new java.util.HashMap<>();
|
||||
payload.put("track", trackPayload(track));
|
||||
payload.put("message", exception.getMessage());
|
||||
payload.put("severity", exception.getSeverity() == null ? null : exception.getSeverity().name());
|
||||
manager.getEvents().publish(MusicEvent.of(MusicEvent.Type.TRACK_ERROR, guild.getId(), payload));
|
||||
}
|
||||
|
||||
LogHandler.log(new ContextException(
|
||||
String.format("Error while playing track: %s", track.getInfo().getTitle()),
|
||||
getContext(),
|
||||
@@ -166,9 +181,36 @@ public class TrackScheduler {
|
||||
|
||||
public void onTrackStuck(Track track, long thresholdMs) {
|
||||
logger.error("Guild {}: currently playing track is stuck: {} (threshold {}ms)", guild.getId(), track.getInfo().getIdentifier(), thresholdMs);
|
||||
if (manager.getEvents() != null) {
|
||||
java.util.Map<String, Object> payload = new java.util.HashMap<>();
|
||||
payload.put("track", trackPayload(track));
|
||||
payload.put("thresholdMs", thresholdMs);
|
||||
manager.getEvents().publish(MusicEvent.of(MusicEvent.Type.TRACK_STUCK, guild.getId(), payload));
|
||||
}
|
||||
stuckTrackRecoveryHandler.handle(track, context);
|
||||
}
|
||||
|
||||
public void onPlayerUpdate(long timestamp, long position, boolean connected, long ping) {
|
||||
onPlayerUpdate(timestamp, position, connected, ping, System.currentTimeMillis());
|
||||
}
|
||||
|
||||
void onPlayerUpdate(long timestamp, long position, boolean connected, long ping, long now) {
|
||||
if (manager.getEvents() == null || currentTrack == null) {
|
||||
return;
|
||||
}
|
||||
if (lastPositionSent != Long.MIN_VALUE && now - lastPositionSent < POSITION_THROTTLE_MS) {
|
||||
return;
|
||||
}
|
||||
lastPositionSent = now;
|
||||
|
||||
java.util.Map<String, Object> payload = new java.util.HashMap<>();
|
||||
payload.put("position", position);
|
||||
payload.put("timestamp", timestamp);
|
||||
payload.put("connected", connected);
|
||||
payload.put("ping", ping);
|
||||
manager.getEvents().publish(MusicEvent.of(MusicEvent.Type.PLAYER_POSITION, guild.getId(), payload));
|
||||
}
|
||||
|
||||
public void onWebSocketClosed(int code, String reason, boolean byRemote) {
|
||||
logger.warn("Guild {}: voice websocket closed with code {} ({}), by remote: {}", guild.getId(), code, reason, byRemote);
|
||||
currentTrack = null;
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
package me.bobert.netneutrality.music;
|
||||
/*
|
||||
* Copyright (c) anthorob
|
||||
*
|
||||
* https://discord.gg/qUa6zNFZsd
|
||||
*/
|
||||
|
||||
import dev.arbjerg.lavalink.client.player.Track;
|
||||
import me.bobert.netneutrality.events.EventPublisher;
|
||||
import me.bobert.netneutrality.events.MusicEvent;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
public class QueueManagerEventsTest {
|
||||
|
||||
private final List<MusicEvent> events = new ArrayList<>();
|
||||
private TrackScheduler scheduler;
|
||||
private QueueManager queueManager;
|
||||
private Member member;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
Guild guild = mock(Guild.class);
|
||||
when(guild.getId()).thenReturn("guild1");
|
||||
|
||||
scheduler = mock(TrackScheduler.class);
|
||||
MusicManager musicManager = mock(MusicManager.class);
|
||||
EventPublisher publisher = events::add;
|
||||
|
||||
when(scheduler.getGuild()).thenReturn(guild);
|
||||
when(scheduler.getMusicManager()).thenReturn(musicManager);
|
||||
when(scheduler.getCallback()).thenReturn(mock(MusicManagerCallback.class));
|
||||
when(musicManager.getEvents()).thenReturn(publisher);
|
||||
when(scheduler.getCurrentTrack()).thenReturn(null).thenReturn(QueueManagerTest.mockTrack("t1"));
|
||||
|
||||
member = mock(Member.class);
|
||||
when(member.getId()).thenReturn("u1");
|
||||
|
||||
queueManager = new QueueManager(scheduler);
|
||||
}
|
||||
|
||||
private void fill(int count) {
|
||||
for (int i = 1; i <= count; i++) {
|
||||
Track track = QueueManagerTest.mockTrack("t" + i);
|
||||
queueManager.queue(track, member);
|
||||
}
|
||||
events.clear();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<String, Object> payload(MusicEvent event) {
|
||||
return (Map<String, Object>) event.payload();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private List<Map<String, Object>> items(MusicEvent event) {
|
||||
return (List<Map<String, Object>>) payload(event).get("items");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addPublishesAddedWithIndex() {
|
||||
queueManager.queue(QueueManagerTest.mockTrack("t1"), member);
|
||||
|
||||
assertEquals(1, events.size());
|
||||
MusicEvent event = events.get(0);
|
||||
assertEquals(MusicEvent.Type.QUEUE_UPDATED, event.type());
|
||||
assertEquals("guild1", event.guildId());
|
||||
assertEquals(1, payload(event).get("size"));
|
||||
assertEquals("added", payload(event).get("change"));
|
||||
assertEquals(0, items(event).get(0).get("index"));
|
||||
assertEquals("t1", items(event).get(0).get("identifier"));
|
||||
assertEquals("u1", items(event).get(0).get("requesterId"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removePublishesRemovedWithOriginalIndex() {
|
||||
fill(3);
|
||||
|
||||
queueManager.removeFromQueue(3);
|
||||
|
||||
assertEquals(1, events.size());
|
||||
assertEquals("removed", payload(events.get(0)).get("change"));
|
||||
assertEquals(2, payload(events.get(0)).get("size"));
|
||||
assertEquals(2, items(events.get(0)).get(0).get("index"));
|
||||
assertEquals("t3", items(events.get(0)).get(0).get("identifier"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void movePublishesFromAndTo() {
|
||||
fill(4);
|
||||
|
||||
queueManager.reorder(4, 2);
|
||||
|
||||
assertEquals(1, events.size());
|
||||
assertEquals("moved", payload(events.get(0)).get("change"));
|
||||
Map<String, Object> item = items(events.get(0)).get(0);
|
||||
assertEquals(3, item.get("fromIndex"));
|
||||
assertEquals(1, item.get("toIndex"));
|
||||
assertEquals("t4", item.get("identifier"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clearPublishesCleared() {
|
||||
fill(2);
|
||||
|
||||
queueManager.clearQueue();
|
||||
|
||||
assertEquals(1, events.size());
|
||||
assertEquals("cleared", payload(events.get(0)).get("change"));
|
||||
assertEquals(0, payload(events.get(0)).get("size"));
|
||||
assertTrue(items(events.get(0)).isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shufflePublishesShuffledAndQueueShuffled() {
|
||||
fill(4);
|
||||
|
||||
queueManager.shuffle();
|
||||
|
||||
assertEquals(2, events.size());
|
||||
assertEquals(MusicEvent.Type.QUEUE_UPDATED, events.get(0).type());
|
||||
assertEquals("shuffled", payload(events.get(0)).get("change"));
|
||||
assertEquals(4, payload(events.get(0)).get("size"));
|
||||
assertEquals(MusicEvent.Type.QUEUE_SHUFFLED, events.get(1).type());
|
||||
assertEquals("guild1", events.get(1).guildId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeHeadPublishesRemovedAtIndexZero() {
|
||||
fill(2);
|
||||
|
||||
queueManager.removeHeadOfQueue();
|
||||
|
||||
assertEquals("removed", payload(events.get(0)).get("change"));
|
||||
assertEquals(0, items(events.get(0)).get(0).get("index"));
|
||||
assertEquals(1, payload(events.get(0)).get("size"));
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import net.dv8tion.jda.api.entities.Guild;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.mockito.Mockito.*;
|
||||
@@ -76,6 +77,75 @@ public class TrackSchedulerTest {
|
||||
assertNull(scheduler.getCurrentTrack());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void onTrackExceptionPublishesTrackError() {
|
||||
java.util.List<me.bobert.netneutrality.events.MusicEvent> events = new java.util.ArrayList<>();
|
||||
when(musicManager.getEvents()).thenReturn(events::add);
|
||||
dev.arbjerg.lavalink.client.player.TrackException exception = mock(dev.arbjerg.lavalink.client.player.TrackException.class);
|
||||
when(exception.getMessage()).thenReturn("boom");
|
||||
scheduler.attachContext(mock(me.bobert.netneutrality.context.MusicChannelContext.class));
|
||||
|
||||
scheduler.onTrackException(QueueManagerTest.mockTrack("t1"), exception);
|
||||
|
||||
assertEquals(1, events.size());
|
||||
assertEquals(me.bobert.netneutrality.events.MusicEvent.Type.TRACK_ERROR, events.get(0).type());
|
||||
assertEquals("guild1", events.get(0).guildId());
|
||||
java.util.Map<String, Object> payload = (java.util.Map<String, Object>) events.get(0).payload();
|
||||
assertEquals("boom", payload.get("message"));
|
||||
assertEquals("t1", ((java.util.Map<String, Object>) payload.get("track")).get("identifier"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void onTrackStuckPublishesTrackStuck() {
|
||||
java.util.List<me.bobert.netneutrality.events.MusicEvent> events = new java.util.ArrayList<>();
|
||||
when(musicManager.getEvents()).thenReturn(events::add);
|
||||
|
||||
scheduler.attachContext(mock(me.bobert.netneutrality.context.MusicChannelContext.class));
|
||||
|
||||
scheduler.onTrackStuck(QueueManagerTest.mockTrack("t1"), 10000L);
|
||||
|
||||
me.bobert.netneutrality.events.MusicEvent event = events.stream()
|
||||
.filter(e -> e.type() == me.bobert.netneutrality.events.MusicEvent.Type.TRACK_STUCK)
|
||||
.findFirst().orElseThrow();
|
||||
assertEquals("guild1", event.guildId());
|
||||
java.util.Map<String, Object> payload = (java.util.Map<String, Object>) event.payload();
|
||||
assertEquals(10000L, payload.get("thresholdMs"));
|
||||
assertEquals("t1", ((java.util.Map<String, Object>) payload.get("track")).get("identifier"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void onPlayerUpdateIsThrottledPerGuild() {
|
||||
java.util.List<me.bobert.netneutrality.events.MusicEvent> events = new java.util.ArrayList<>();
|
||||
when(musicManager.getEvents()).thenReturn(events::add);
|
||||
scheduler.onTrackStart(QueueManagerTest.mockTrack("t1"));
|
||||
events.clear();
|
||||
|
||||
scheduler.onPlayerUpdate(100L, 1500L, true, 20L, 1000L);
|
||||
scheduler.onPlayerUpdate(101L, 1600L, true, 20L, 3000L);
|
||||
scheduler.onPlayerUpdate(102L, 6500L, true, 20L, 6000L);
|
||||
|
||||
assertEquals(2, events.size());
|
||||
assertEquals(me.bobert.netneutrality.events.MusicEvent.Type.PLAYER_POSITION, events.get(0).type());
|
||||
java.util.Map<String, Object> payload = (java.util.Map<String, Object>) events.get(0).payload();
|
||||
assertEquals(1500L, payload.get("position"));
|
||||
assertEquals(100L, payload.get("timestamp"));
|
||||
assertEquals(true, payload.get("connected"));
|
||||
assertEquals(20L, payload.get("ping"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPlayerUpdateSkippedWhenNothingPlaying() {
|
||||
java.util.List<me.bobert.netneutrality.events.MusicEvent> events = new java.util.ArrayList<>();
|
||||
when(musicManager.getEvents()).thenReturn(events::add);
|
||||
|
||||
scheduler.onPlayerUpdate(100L, 1500L, true, 20L, 1000L);
|
||||
|
||||
assertEquals(0, events.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDjReturnsNullWhenNoContext() {
|
||||
assertNull(scheduler.getDj());
|
||||
|
||||
Reference in new issue
Block a user