Repository: pajlads/DinkPlugin
Pull request #75 (2022-11-24 06:32:12)

chore: add more mock notifier tests
* For each notifier, ensure no message is sent if the notifier is disabled in config
* Add more interesting test cases for death notifier



Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 95cb0f9..a1308e3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,6 @@
 ## Unreleased
 
-- Dev: Add mockito test suite for notifiers. (#74)
+- Dev: Add mockito test suite for notifiers. (#74, #75)
 - Dev: Utilize more dependency injection. (#73)
 
 ## 1.1.0
diff --git a/src/main/java/dinkplugin/Utils.java b/src/main/java/dinkplugin/Utils.java
index 5444c84..2029e48 100644
--- a/src/main/java/dinkplugin/Utils.java
+++ b/src/main/java/dinkplugin/Utils.java
@@ -16,6 +16,7 @@ import net.runelite.api.widgets.WidgetInfo;
 import net.runelite.client.game.ItemManager;
 import net.runelite.client.game.ItemStack;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.VisibleForTesting;
 
 import javax.imageio.ImageIO;
 import java.awt.image.BufferedImage;
@@ -49,7 +50,8 @@ public class Utils {
     private static final BinaryOperator<ItemStack> SUM_ITEM_STACK_QUANTITIES = (a, b) -> new ItemStack(a.getId(), a.getQuantity() + b.getQuantity(), a.getLocation());
 
     @Varbit
-    private static final int CASTLE_WARS_COUNTDOWN = 380;
+    @VisibleForTesting
+    public static final int CASTLE_WARS_COUNTDOWN = 380;
     @Varbit
     private static final int CASTLE_WARS_CATAPULT_X_AXIS_OFFSET = 156;
     @Varbit
diff --git a/src/main/java/dinkplugin/notifiers/LootNotifier.java b/src/main/java/dinkplugin/notifiers/LootNotifier.java
index c777a42..e031964 100644
--- a/src/main/java/dinkplugin/notifiers/LootNotifier.java
+++ b/src/main/java/dinkplugin/notifiers/LootNotifier.java
@@ -37,8 +37,8 @@ public class LootNotifier extends BaseNotifier {
     }
 
     public void onPlayerLootReceived(PlayerLootReceived event) {
-        // intentional super call until PK gets its own toggle
-        if (super.isEnabled())
+        // TODO: player loot should be a configurable toggle
+        if (isEnabled())
             this.handleNotify(event.getItems(), event.getPlayer().getName());
     }
 


Test patch:
diff --git a/src/test/java/dinkplugin/notifiers/ClueNotifierTest.java b/src/test/java/dinkplugin/notifiers/ClueNotifierTest.java
index 912abaf..66cc14f 100644
--- a/src/test/java/dinkplugin/notifiers/ClueNotifierTest.java
+++ b/src/test/java/dinkplugin/notifiers/ClueNotifierTest.java
@@ -5,7 +5,6 @@ import dinkplugin.message.NotificationBody;
 import dinkplugin.message.NotificationType;
 import dinkplugin.notifiers.data.ClueNotificationData;
 import dinkplugin.notifiers.data.SerializedItemStack;
-import net.runelite.api.ItemComposition;
 import net.runelite.api.ItemID;
 import net.runelite.api.events.WidgetLoaded;
 import net.runelite.api.widgets.Widget;
@@ -51,15 +50,8 @@ class ClueNotifierTest extends MockedNotifierTest {
         when(config.clueNotifyMessage()).thenReturn("%USERNAME% has completed a %CLUE% clue, for a total of %COUNT%. They obtained: %LOOT%");
 
         // init item mocks
-        when(itemManager.getItemPrice(ItemID.RUBY)).thenReturn(RUBY_PRICE);
-        ItemComposition ruby = mock(ItemComposition.class);
-        when(ruby.getName()).thenReturn("Ruby");
-        when(itemManager.getItemComposition(ItemID.RUBY)).thenReturn(ruby);
-
-        when(itemManager.getItemPrice(ItemID.TUNA)).thenReturn(TUNA_PRICE);
-        ItemComposition tuna = mock(ItemComposition.class);
-        when(tuna.getName()).thenReturn("Tuna");
-        when(itemManager.getItemComposition(ItemID.TUNA)).thenReturn(tuna);
+        mockItem(itemManager, ItemID.RUBY, RUBY_PRICE, "Ruby");
+        mockItem(itemManager, ItemID.TUNA, TUNA_PRICE, "Tuna");
     }
 
     @Test
@@ -119,4 +111,32 @@ class ClueNotifierTest extends MockedNotifierTest {
         verify(messageHandler, never()).createMessage(anyBoolean(), any());
     }
 
+    @Test
+    void testDisabled() {
+        // disable notifier
+        when(config.notifyClue()).thenReturn(false);
+
+        // fire chat event
+        notifier.onChatMessage("You have completed 1312 medium Treasure Trails.");
+
+        // mock widgets
+        Widget widget = mock(Widget.class);
+        when(client.getWidget(WidgetInfo.CLUE_SCROLL_REWARD_ITEM_CONTAINER)).thenReturn(widget);
+
+        Widget child = mock(Widget.class);
+        when(child.getItemQuantity()).thenReturn(1);
+        when(child.getItemId()).thenReturn(ItemID.RUBY);
+
+        Widget[] children = { child };
+        when(widget.getChildren()).thenReturn(children);
+
+        // fire widget event
+        WidgetLoaded event = new WidgetLoaded();
+        event.setGroupId(WidgetID.CLUE_SCROLL_REWARD_GROUP_ID);
+        notifier.onWidgetLoaded(event);
+
+        // ensure no notification was fired
+        verify(messageHandler, never()).createMessage(anyBoolean(), any());
+    }
+
 }
diff --git a/src/test/java/dinkplugin/notifiers/CollectionNotifierTest.java b/src/test/java/dinkplugin/notifiers/CollectionNotifierTest.java
index af7ba94..141682d 100644
--- a/src/test/java/dinkplugin/notifiers/CollectionNotifierTest.java
+++ b/src/test/java/dinkplugin/notifiers/CollectionNotifierTest.java
@@ -56,4 +56,17 @@ class CollectionNotifierTest extends MockedNotifierTest {
         verify(messageHandler, never()).createMessage(anyBoolean(), any());
     }
 
+    @Test
+    void testDisabled() {
+        // disable notifier
+        when(config.notifyCollectionLog()).thenReturn(false);
+
+        // send fake message
+        String item = "Seercull";
+        notifier.onChatMessage("New item added to your collection log: " + item);
+
+        // ensure no notification occurred
+        verify(messageHandler, never()).createMessage(anyBoolean(), any());
+    }
+
 }
diff --git a/src/test/java/dinkplugin/notifiers/CombatTaskNotifierTest.java b/src/test/java/dinkplugin/notifiers/CombatTaskNotifierTest.java
index 504953e..ce11752 100644
--- a/src/test/java/dinkplugin/notifiers/CombatTaskNotifierTest.java
+++ b/src/test/java/dinkplugin/notifiers/CombatTaskNotifierTest.java
@@ -67,4 +67,16 @@ class CombatTaskNotifierTest extends MockedNotifierTest {
         verify(messageHandler, never()).createMessage(anyBoolean(), any());
     }
 
+    @Test
+    void testDisabled() {
+        // disable notifier
+        when(config.notifyCombatTask()).thenReturn(false);
+
+        // send fake message
+        notifier.onGameMessage("Congratulations, you've completed a hard combat task: Whack-a-Mole.");
+
+        // ensure no notification occurred
+        verify(messageHandler, never()).createMessage(anyBoolean(), any());
+    }
+
 }
diff --git a/src/test/java/dinkplugin/notifiers/DeathNotifierTest.java b/src/test/java/dinkplugin/notifiers/DeathNotifierTest.java
index fa5b5b4..5e7ab89 100644
--- a/src/test/java/dinkplugin/notifiers/DeathNotifierTest.java
+++ b/src/test/java/dinkplugin/notifiers/DeathNotifierTest.java
@@ -1,17 +1,30 @@
 package dinkplugin.notifiers;
 
+import com.google.inject.testing.fieldbinder.Bind;
+import dinkplugin.Utils;
 import dinkplugin.message.NotificationBody;
 import dinkplugin.message.NotificationType;
 import dinkplugin.notifiers.data.DeathNotificationData;
+import dinkplugin.notifiers.data.SerializedItemStack;
+import net.runelite.api.InventoryID;
+import net.runelite.api.Item;
+import net.runelite.api.ItemContainer;
+import net.runelite.api.ItemID;
 import net.runelite.api.Player;
+import net.runelite.api.Prayer;
 import net.runelite.api.Varbits;
 import net.runelite.api.coords.WorldPoint;
 import net.runelite.api.events.ActorDeath;
+import net.runelite.api.events.InteractingChanged;
+import net.runelite.client.game.ItemManager;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.mockito.InjectMocks;
+import org.mockito.Mock;
 
+import java.util.Arrays;
 import java.util.Collections;
+import java.util.List;
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -22,6 +35,16 @@ import static org.mockito.Mockito.when;
 
 class DeathNotifierTest extends MockedNotifierTest {
 
+    private static final int RUBY_PRICE = 900;
+    private static final int SHARK_PRICE = 700;
+    private static final int OPAL_PRICE = 600;
+    private static final int COAL_PRICE = 200;
+    private static final int TUNA_PRICE = 100;
+
+    @Bind
+    @Mock
+    ItemManager itemManager;
+
     @InjectMocks
     DeathNotifier notifier;
 
@@ -35,13 +58,20 @@ class DeathNotifierTest extends MockedNotifierTest {
         when(config.deathNotifPvpEnabled()).thenReturn(true);
         when(config.deathSendImage()).thenReturn(false);
         when(config.deathNotifyMessage()).thenReturn("%USERNAME% has died, losing %VALUELOST% gp");
-        when(config.deathNotifPvpMessage()).thenReturn("%USERNAME% has just been PKed by %PKER% for %VALUELOST% gp...");
+        when(config.deathNotifPvpMessage()).thenReturn("%USERNAME% has been PKed by %PKER% for %VALUELOST% gp");
 
         // init client mocks
         when(client.getVarbitValue(Varbits.IN_WILDERNESS)).thenReturn(1);
         when(client.getPlayers()).thenReturn(Collections.emptyList());
         WorldPoint location = new WorldPoint(0, 0, 0);
         when(localPlayer.getWorldLocation()).thenReturn(location);
+
+        // init item mocks
+        mockItem(itemManager, ItemID.RUBY, RUBY_PRICE, "Ruby");
+        mockItem(itemManager, ItemID.SHARK, SHARK_PRICE, "Shark");
+        mockItem(itemManager, ItemID.OPAL, OPAL_PRICE, "Opal");
+        mockItem(itemManager, ItemID.COAL, COAL_PRICE, "Coal");
+        mockItem(itemManager, ItemID.TUNA, TUNA_PRICE, "Tuna");
     }
 
     @Test
@@ -60,6 +90,120 @@ class DeathNotifierTest extends MockedNotifierTest {
         );
     }
 
+    @Test
+    void testNotify() {
+        // prepare mocks
+        when(client.isPrayerActive(Prayer.PROTECT_ITEM)).thenReturn(true);
+        Item[] items = {
+            new Item(ItemID.RUBY, 1),
+            new Item(ItemID.TUNA, 1),
+            new Item(ItemID.COAL, 1),
+            new Item(ItemID.SHARK, 1),
+            new Item(ItemID.OPAL, 1),
+        };
+        ItemContainer inv = mock(ItemContainer.class);
+        when(client.getItemContainer(InventoryID.INVENTORY)).thenReturn(inv);
+        when(inv.getItems()).thenReturn(items);
+
+        // fire event
+        notifier.onActorDeath(new ActorDeath(localPlayer));
+
+        // verify notification
+        List<SerializedItemStack> kept = Arrays.asList(
+            new SerializedItemStack(ItemID.RUBY, 1, RUBY_PRICE, "Ruby"),
+            new SerializedItemStack(ItemID.SHARK, 1, SHARK_PRICE, "Shark"),
+            new SerializedItemStack(ItemID.OPAL, 1, OPAL_PRICE, "Opal"),
+            new SerializedItemStack(ItemID.COAL, 1, COAL_PRICE, "Coal")
+        );
+        List<SerializedItemStack> lost = Collections.singletonList(
+            new SerializedItemStack(ItemID.TUNA, 1, TUNA_PRICE, "Tuna")
+        );
+        List<NotificationBody.Embed> embeds = Collections.singletonList(
+            new NotificationBody.Embed(new NotificationBody.UrlEmbed("https://static.runelite.net/cache/item/icon/" + ItemID.TUNA + ".png"))
+        );
+        verify(messageHandler).createMessage(
+            false,
+            NotificationBody.builder()
+                .content(String.format("%s has died, losing %d gp", PLAYER_NAME, TUNA_PRICE))
+                .extra(new DeathNotificationData((long) TUNA_PRICE, false, null, kept, lost))
+                .type(NotificationType.DEATH)
+                .embeds(embeds)
+                .build()
+        );
+    }
+
+    @Test
+    void testNotifyPk() {
+        // prepare mocks
+        String pker = "Rasmus";
+        Player other = mock(Player.class);
+        when(other.getName()).thenReturn(pker);
+        when(other.getInteracting()).thenReturn(localPlayer);
+        when(client.getPlayers()).thenReturn(Arrays.asList(mock(Player.class), mock(Player.class), other, mock(Player.class)));
+
+        // fire event
+        notifier.onActorDeath(new ActorDeath(localPlayer));
+
+        // verify notification
+        verify(messageHandler).createMessage(
+            false,
+            NotificationBody.builder()
+                .content(String.format("%s has been PKed by %s for %d gp", PLAYER_NAME, pker, 0))
+                .extra(new DeathNotificationData(0L, true, pker, Collections.emptyList(), Collections.emptyList()))
+                .type(NotificationType.DEATH)
+                .build()
+        );
+    }
+
+    @Test
+    void testNotifyPkInteraction() {
+        // prepare mocks
+        String pker = "Rasmus";
+        Player other = mock(Player.class);
+        when(other.getName()).thenReturn(pker);
+        when(other.getInteracting()).thenReturn(localPlayer);
+        when(other.getCombatLevel()).thenReturn(50);
+        when(localPlayer.getCombatLevel()).thenReturn(50);
+
+        // fire events
+        notifier.onInteraction(new InteractingChanged(other, localPlayer));
+        notifier.onInteraction(new InteractingChanged(localPlayer, other));
+        notifier.onActorDeath(new ActorDeath(localPlayer));
+
+        // verify notification
+        verify(messageHandler).createMessage(
+            false,
+            NotificationBody.builder()
+                .content(String.format("%s has been PKed by %s for %d gp", PLAYER_NAME, pker, 0))
+                .extra(new DeathNotificationData(0L, true, pker, Collections.emptyList(), Collections.emptyList()))
+                .type(NotificationType.DEATH)
+                .build()
+        );
+    }
+
+    @Test
+    void testNotifyNotPk() {
+        // prepare mocks: look like PK, but not in wilderness
+        Player other = mock(Player.class);
+        when(other.getName()).thenReturn("Rasmus");
+        when(other.getInteracting()).thenReturn(localPlayer);
+        when(client.getPlayers()).thenReturn(Collections.singletonList(other));
+        when(client.getVarbitValue(Varbits.IN_WILDERNESS)).thenReturn(0);
+
+        // fire event
+        notifier.onActorDeath(new ActorDeath(localPlayer));
+
+        // verify non-PK notification
+        verify(messageHandler).createMessage(
+            false,
+            NotificationBody.builder()
+                .content(String.format("%s has died, losing %d gp", PLAYER_NAME, 0))
+                .extra(new DeathNotificationData(0L, false, null, Collections.emptyList(), Collections.emptyList()))
+                .type(NotificationType.DEATH)
+                .build()
+        );
+    }
+
     @Test
     void testIgnore() {
         // prepare mock
@@ -72,4 +216,28 @@ class DeathNotifierTest extends MockedNotifierTest {
         verify(messageHandler, never()).createMessage(anyBoolean(), any());
     }
 
+    @Test
+    void testIgnoreSafe() {
+        // mock castle wars
+        when(client.getVarbitValue(Utils.CASTLE_WARS_COUNTDOWN)).thenReturn(10);
+
+        // fire event
+        notifier.onActorDeath(new ActorDeath(localPlayer));
+
+        // ensure no notification occurred
+        verify(messageHandler, never()).createMessage(anyBoolean(), any());
+    }
+
+    @Test
+    void testDisabled() {
+        // disable notifier
+        when(config.notifyDeath()).thenReturn(false);
+
+        // fire event
+        notifier.onActorDeath(new ActorDeath(localPlayer));
+
+        // ensure no notification occurred
+        verify(messageHandler, never()).createMessage(anyBoolean(), any());
+    }
+
 }
diff --git a/src/test/java/dinkplugin/notifiers/DiaryNotifierTest.java b/src/test/java/dinkplugin/notifiers/DiaryNotifierTest.java
index 339f460..5b4de08 100644
--- a/src/test/java/dinkplugin/notifiers/DiaryNotifierTest.java
+++ b/src/test/java/dinkplugin/notifiers/DiaryNotifierTest.java
@@ -148,6 +148,25 @@ class DiaryNotifierTest extends MockedNotifierTest {
         verify(messageHandler, never()).createMessage(anyBoolean(), any());
     }
 
+    @Test
+    void testDisabled() {
+        // disable notifier
+        when(config.notifyAchievementDiary()).thenReturn(false);
+
+        // initially 0 diary completions
+        when(client.getVarbitValue(anyInt())).thenReturn(0);
+
+        // perform enough ticks to trigger diary initialization
+        IntStream.range(0, 16).forEach(i -> notifier.onTick());
+
+        // trigger diary completion
+        int id = Varbits.DIARY_DESERT_ELITE;
+        notifier.onVarbitChanged(event(id, 1));
+
+        // ensure no notification
+        verify(messageHandler, never()).createMessage(anyBoolean(), any());
+    }
+
     private static VarbitChanged event(int id, int value) {
         VarbitChanged event = new VarbitChanged();
         event.setVarbitId(id);
diff --git a/src/test/java/dinkplugin/notifiers/KillCountNotifierTest.java b/src/test/java/dinkplugin/notifiers/KillCountNotifierTest.java
index 3c82a4d..e427537 100644
--- a/src/test/java/dinkplugin/notifiers/KillCountNotifierTest.java
+++ b/src/test/java/dinkplugin/notifiers/KillCountNotifierTest.java
@@ -87,4 +87,19 @@ class KillCountNotifierTest extends MockedNotifierTest {
         verify(messageHandler, never()).createMessage(anyBoolean(), any());
     }
 
+    @Test
+    void testDisabled() {
+        // more config
+        when(config.notifyKillCount()).thenReturn(false);
+        when(config.killCountNotifyInitial()).thenReturn(true);
+        when(config.killCountInterval()).thenReturn(1);
+
+        // fire event
+        String gameMessage = "Your King Black Dragon kill count is: 1.";
+        notifier.onGameMessage(gameMessage);
+
+        // ensure no message
+        verify(messageHandler, never()).createMessage(anyBoolean(), any());
+    }
+
 }
diff --git a/src/test/java/dinkplugin/notifiers/LevelNotifierTest.java b/src/test/java/dinkplugin/notifiers/LevelNotifierTest.java
index 6e3e186..656d36a 100644
--- a/src/test/java/dinkplugin/notifiers/LevelNotifierTest.java
+++ b/src/test/java/dinkplugin/notifiers/LevelNotifierTest.java
@@ -131,4 +131,19 @@ class LevelNotifierTest extends MockedNotifierTest {
         verify(messageHandler, never()).createMessage(anyBoolean(), any());
     }
 
+    @Test
+    void testDisabled() {
+        // disable notifier
+        when(config.notifyLevel()).thenReturn(false);
+
+        // fire skill event
+        notifier.onStatChanged(new StatChanged(Skill.AGILITY, 400, 5, 5));
+
+        // let ticks pass
+        IntStream.range(0, 4).forEach(i -> notifier.onTick());
+
+        // ensure no notification occurred
+        verify(messageHandler, never()).createMessage(anyBoolean(), any());
+    }
+
 }
diff --git a/src/test/java/dinkplugin/notifiers/LootNotifierTest.java b/src/test/java/dinkplugin/notifiers/LootNotifierTest.java
index 8e9c899..deab078 100644
--- a/src/test/java/dinkplugin/notifiers/LootNotifierTest.java
+++ b/src/test/java/dinkplugin/notifiers/LootNotifierTest.java
@@ -5,7 +5,6 @@ import dinkplugin.message.NotificationBody;
 import dinkplugin.message.NotificationType;
 import dinkplugin.notifiers.data.LootNotificationData;
 import dinkplugin.notifiers.data.SerializedItemStack;
-import net.runelite.api.ItemComposition;
 import net.runelite.api.ItemID;
 import net.runelite.api.NPC;
 import net.runelite.api.Player;
@@ -58,20 +57,9 @@ class LootNotifierTest extends MockedNotifierTest {
         when(config.lootNotifyMessage()).thenReturn("%USERNAME% has looted: %LOOT% from %SOURCE% for %TOTAL_VALUE% gp");
 
         // init item mocks
-        when(itemManager.getItemPrice(ItemID.RUBY)).thenReturn(RUBY_PRICE);
-        ItemComposition ruby = mock(ItemComposition.class);
-        when(ruby.getName()).thenReturn("Ruby");
-        when(itemManager.getItemComposition(ItemID.RUBY)).thenReturn(ruby);
-
-        when(itemManager.getItemPrice(ItemID.OPAL)).thenReturn(OPAL_PRICE);
-        ItemComposition opal = mock(ItemComposition.class);
-        when(opal.getName()).thenReturn("Opal");
-        when(itemManager.getItemComposition(ItemID.OPAL)).thenReturn(opal);
-
-        when(itemManager.getItemPrice(ItemID.TUNA)).thenReturn(TUNA_PRICE);
-        ItemComposition tuna = mock(ItemComposition.class);
-        when(tuna.getName()).thenReturn("Tuna");
-        when(itemManager.getItemComposition(ItemID.TUNA)).thenReturn(tuna);
+        mockItem(itemManager, ItemID.RUBY, RUBY_PRICE, "Ruby");
+        mockItem(itemManager, ItemID.OPAL, OPAL_PRICE, "Opal");
+        mockItem(itemManager, ItemID.TUNA, TUNA_PRICE, "Tuna");
     }
 
     @Test
@@ -240,4 +228,17 @@ class LootNotifierTest extends MockedNotifierTest {
         verify(messageHandler, never()).createMessage(anyBoolean(), any());
     }
 
+    @Test
+    void testDisabled() {
+        // disable notifier
+        when(config.notifyLoot()).thenReturn(false);
+
+        // fire event
+        LootReceived event = new LootReceived(LOOTED_NAME, 99, LootRecordType.PICKPOCKET, Collections.singletonList(new ItemStack(ItemID.RUBY, 1, null)), RUBY_PRICE);
+        notifier.onLootReceived(event);
+
+        // ensure no notification
+        verify(messageHandler, never()).createMessage(anyBoolean(), any());
+    }
+
 }
diff --git a/src/test/java/dinkplugin/notifiers/MockedNotifierTest.java b/src/test/java/dinkplugin/notifiers/MockedNotifierTest.java
index 8b2d293..87c414d 100644
--- a/src/test/java/dinkplugin/notifiers/MockedNotifierTest.java
+++ b/src/test/java/dinkplugin/notifiers/MockedNotifierTest.java
@@ -5,12 +5,17 @@ import dinkplugin.DinkPluginConfig;
 import dinkplugin.MockedTestBase;
 import dinkplugin.message.DiscordMessageHandler;
 import net.runelite.api.Client;
+import net.runelite.api.ItemComposition;
 import net.runelite.api.Player;
 import net.runelite.api.WorldType;
+import net.runelite.api.vars.AccountType;
+import net.runelite.client.game.ItemManager;
 import org.mockito.Mock;
 
 import java.util.EnumSet;
 
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 class MockedNotifierTest extends MockedTestBase {
@@ -38,8 +43,17 @@ class MockedNotifierTest extends MockedTestBase {
 
         // init client mocks
         when(client.getWorldType()).thenReturn(EnumSet.noneOf(WorldType.class));
+        when(client.getAccountType()).thenReturn(AccountType.NORMAL);
+        when(client.isPrayerActive(any())).thenReturn(false);
         when(client.getLocalPlayer()).thenReturn(localPlayer);
         when(localPlayer.getName()).thenReturn(PLAYER_NAME);
     }
 
+    protected void mockItem(ItemManager manager, int id, int price, String name) {
+        when(manager.getItemPrice(id)).thenReturn(price);
+        ItemComposition item = mock(ItemComposition.class);
+        when(item.getName()).thenReturn(name);
+        when(manager.getItemComposition(id)).thenReturn(item);
+    }
+
 }
diff --git a/src/test/java/dinkplugin/notifiers/PetNotifierTest.java b/src/test/java/dinkplugin/notifiers/PetNotifierTest.java
index 173daa8..eb78469 100644
--- a/src/test/java/dinkplugin/notifiers/PetNotifierTest.java
+++ b/src/test/java/dinkplugin/notifiers/PetNotifierTest.java
@@ -52,4 +52,16 @@ class PetNotifierTest extends MockedNotifierTest {
         verify(messageHandler, never()).createMessage(anyBoolean(), any());
     }
 
+    @Test
+    void testDisabled() {
+        // disable notifier
+        when(config.notifyPet()).thenReturn(false);
+
+        // send fake message
+        notifier.onChatMessage("You feel something weird sneaking into your backpack.");
+
+        // ensure no notification occurred
+        verify(messageHandler, never()).createMessage(anyBoolean(), any());
+    }
+
 }
diff --git a/src/test/java/dinkplugin/notifiers/QuestNotifierTest.java b/src/test/java/dinkplugin/notifiers/QuestNotifierTest.java
index 24a458c..ee0015b 100644
--- a/src/test/java/dinkplugin/notifiers/QuestNotifierTest.java
+++ b/src/test/java/dinkplugin/notifiers/QuestNotifierTest.java
@@ -64,6 +64,23 @@ class QuestNotifierTest extends MockedNotifierTest {
         verify(messageHandler, never()).createMessage(anyBoolean(), any());
     }
 
+    @Test
+    void testDisabled() {
+        // disable notifier
+        when(config.notifyQuest()).thenReturn(false);
+
+        // mock widget
+        Widget questWidget = mock(Widget.class);
+        when(client.getWidget(QUEST_COMPLETED_NAME_TEXT)).thenReturn(questWidget);
+        when(questWidget.getText()).thenReturn("You have completed the Dragon Slayer quest!");
+
+        // send event
+        notifier.onWidgetLoaded(event(QUEST_COMPLETED_GROUP_ID));
+
+        // verify no message
+        verify(messageHandler, never()).createMessage(anyBoolean(), any());
+    }
+
     private static WidgetLoaded event(int id) {
         WidgetLoaded event = new WidgetLoaded();
         event.setGroupId(id);
diff --git a/src/test/java/dinkplugin/notifiers/SlayerNotifierTest.java b/src/test/java/dinkplugin/notifiers/SlayerNotifierTest.java
index 18cd368..bd46e88 100644
--- a/src/test/java/dinkplugin/notifiers/SlayerNotifierTest.java
+++ b/src/test/java/dinkplugin/notifiers/SlayerNotifierTest.java
@@ -57,4 +57,17 @@ class SlayerNotifierTest extends MockedNotifierTest {
         verify(messageHandler, never()).createMessage(anyBoolean(), any());
     }
 
+    @Test
+    void testDisabled() {
+        // disable notifier
+        when(config.notifySlayer()).thenReturn(false);
+
+        // fire chat messages
+        notifier.onChatMessage("You have completed your task! You killed 1 TzTok-Jad. You gained 69,420 xp.");
+        notifier.onChatMessage("You've completed 100 tasks and received 10 points, giving you a total of 200; return to a Slayer master.");
+
+        // ensure no notification
+        verify(messageHandler, never()).createMessage(anyBoolean(), any());
+    }
+
 }
diff --git a/src/test/java/dinkplugin/notifiers/SpeedrunNotifierTest.java b/src/test/java/dinkplugin/notifiers/SpeedrunNotifierTest.java
index 243407e..515c6b7 100644
--- a/src/test/java/dinkplugin/notifiers/SpeedrunNotifierTest.java
+++ b/src/test/java/dinkplugin/notifiers/SpeedrunNotifierTest.java
@@ -89,6 +89,23 @@ class SpeedrunNotifierTest extends MockedNotifierTest {
         verify(messageHandler, never()).createMessage(anyBoolean(), any());
     }
 
+    @Test
+    void testDisabled() {
+        // disable notifier
+        when(config.notifySpeedrun()).thenReturn(false);
+
+        // mock widget
+        Widget time = mock(Widget.class);
+        when(client.getWidget(SPEEDRUN_COMPLETED_GROUP_ID, SPEEDRUN_COMPLETED_DURATION_CHILD_ID)).thenReturn(time);
+        when(time.getText()).thenReturn("1:15.30");
+
+        // fire fake event
+        notifier.onWidgetLoaded(event());
+
+        // ensure no notification
+        verify(messageHandler, never()).createMessage(anyBoolean(), any());
+    }
+
     private WidgetLoaded event() {
         WidgetLoaded event = new WidgetLoaded();
         event.setGroupId(SPEEDRUN_COMPLETED_GROUP_ID);