How to use BukkitSchedulerMock class of be.seeseemelk.mockbukkit.scheduler package

Best MockBukkit code snippet using be.seeseemelk.mockbukkit.scheduler.BukkitSchedulerMock

Source:EnchantingTableUtilTest.java Github

copy

Full Screen

...13import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;14import be.seeseemelk.mockbukkit.MockBukkit;15import be.seeseemelk.mockbukkit.enchantments.EnchantmentMock;16import be.seeseemelk.mockbukkit.entity.PlayerMock;17import be.seeseemelk.mockbukkit.scheduler.BukkitSchedulerMock;18import com.github.jikoo.planarenchanting.util.EnchantmentHelper;19import com.github.jikoo.planarenchanting.util.mock.CraftEnchantMock;20import com.github.jikoo.planarenchanting.util.mock.MockHelper;21import java.util.Arrays;22import java.util.EnumMap;23import java.util.List;24import java.util.Map;25import java.util.Random;26import org.bukkit.NamespacedKey;27import org.bukkit.enchantments.Enchantment;28import org.bukkit.enchantments.EnchantmentOffer;29import org.bukkit.inventory.InventoryView;30import org.bukkit.inventory.InventoryView.Property;31import org.jetbrains.annotations.NotNull;32import org.junit.jupiter.api.AfterAll;33import org.junit.jupiter.api.BeforeAll;34import org.junit.jupiter.api.DisplayName;35import org.junit.jupiter.api.Test;36import org.junit.jupiter.api.TestInstance;37import org.junit.jupiter.api.TestInstance.Lifecycle;38import org.junit.jupiter.params.ParameterizedTest;39import org.junit.jupiter.params.provider.CsvSource;40@DisplayName("Enchanting table utility methods")41@TestInstance(Lifecycle.PER_CLASS)42class EnchantingTableUtilTest {43 @BeforeAll44 void beforeAll() {45 MockBukkit.mock();46 EnchantmentHelper.setupToolEnchants();47 }48 @AfterAll49 void afterAll() {50 MockHelper.unmock();51 }52 @DisplayName("Enchanting table button levels should be calculated consistently.")53 @ParameterizedTest54 @CsvSource({"1,0", "10,0", "15,0", "1,12348", "10,98124", "15,23479"})55 void testGetButtonLevels(int shelves, int seed) {56 Random random = new Random(seed);57 int[] buttonLevels1 = EnchantingTable.getButtonLevels(random, shelves);58 random.setSeed(seed);59 int[] buttonLevels2 = EnchantingTable.getButtonLevels(random, shelves);60 assertThat("There are always three buttons", buttonLevels1.length, is(3));61 assertThat("There are always three buttons", buttonLevels2.length, is(3));62 List<Integer> buttonLevelsList1 = Arrays.stream(buttonLevels1).boxed().toList();63 assertThat(64 "Button levels should be generated consistently",65 buttonLevelsList1,66 contains(buttonLevels2[0], buttonLevels2[1], buttonLevels2[2]));67 assertThat(68 "Button levels must be positive integers that do not exceed 30",69 buttonLevelsList1,70 everyItem(is(both(lessThanOrEqualTo(30)).and(greaterThanOrEqualTo(0)))));71 }72 @DisplayName("Button updates send to user as expected.")73 @Test74 void testSendButtonUpdates() {75 var server = MockBukkit.getMock();76 var plugin = MockBukkit.createMockPlugin("SampleText");77 var offerData = new EnumMap<>(InventoryView.Property.class);78 var player = new PlayerMock(server, "sampletext") {79 @Override80 public boolean setWindowProperty(@NotNull InventoryView.Property prop, int value) {81 offerData.put(prop, value);82 return true;83 }84 };85 EnchantmentOffer[] offers = new EnchantmentOffer[] {86 new EnchantmentOffer(Enchantment.DIG_SPEED, 5, 1),87 new EnchantmentOffer(Enchantment.DURABILITY, 20, 2),88 new EnchantmentOffer(Enchantment.SILK_TOUCH, 30, 3)89 };90 assertDoesNotThrow(() -> EnchantingTable.updateButtons(plugin, player, offers));91 assertThat("Offer data is sent next tick", offerData, is(anEmptyMap()));92 BukkitSchedulerMock scheduler = server.getScheduler();93 assertDoesNotThrow(() -> scheduler.performTicks(1));94 assertThat("Offer data is sent", offerData, is(not(anEmptyMap())));95 // Ensure enchantment level requirements are sent correctly.96 assertThat(97 "First offer cost must be set",98 offerData.entrySet(),99 hasItem(Map.entry(Property.ENCHANT_BUTTON1, offers[0].getCost())));100 assertThat(101 "Second offer cost must be set",102 offerData.entrySet(),103 hasItem(Map.entry(Property.ENCHANT_BUTTON2, offers[1].getCost())));104 assertThat(105 "Third offer cost must be set",106 offerData.entrySet(),107 hasItem(Map.entry(Property.ENCHANT_BUTTON3, offers[2].getCost())));108 // Ensure enchantment levels are sent correctly.109 assertThat(110 "First offer level must be set",111 offerData.entrySet(),112 hasItem(Map.entry(Property.ENCHANT_LEVEL1, offers[0].getEnchantmentLevel())));113 assertThat(114 "Second offer level must be set",115 offerData.entrySet(),116 hasItem(Map.entry(Property.ENCHANT_LEVEL2, offers[1].getEnchantmentLevel())));117 assertThat(118 "Third offer level must be set",119 offerData.entrySet(),120 hasItem(Map.entry(Property.ENCHANT_LEVEL3, offers[2].getEnchantmentLevel())));121 // Exact IDs not verified - can't really test this without NMS.122 assertThat(123 "Offer contains enchantment IDs",124 offerData.keySet(),125 hasItems(Property.ENCHANT_ID1, Property.ENCHANT_ID2, Property.ENCHANT_ID3));126 }127 @DisplayName("Fetching Enchantment ID should not cause errors.")128 @Test129 void testInvalidGetEnchantmentId() {130 var server = MockBukkit.getMock();131 var plugin = MockBukkit.createMockPlugin("SampleText");132 var player = new PlayerMock(server, "sampletext") {133 @Override134 public boolean setWindowProperty(@NotNull InventoryView.Property prop, int value) {135 return true;136 }137 };138 String enchantName = "enchant_table_util";139 var unregisteredEnchantment = new EnchantmentMock(NamespacedKey.minecraft(enchantName + 1), enchantName + 1);140 var registeredReflectableEnchant = new CraftEnchantMock(NamespacedKey.minecraft(enchantName + 2), 1, value -> value, value -> value);141 EnchantmentHelper.putEnchant(registeredReflectableEnchant);142 var registeredUnlistedNonReflectableEnchant = new EnchantmentMock(NamespacedKey.minecraft(enchantName + 3), enchantName + 3);143 EnchantmentOffer[] offers = new EnchantmentOffer[] {144 new EnchantmentOffer(unregisteredEnchantment, 5, 1),145 new EnchantmentOffer(registeredReflectableEnchant, 20, 2),146 new EnchantmentOffer(registeredUnlistedNonReflectableEnchant, 30, 3)147 };148 // Schedule button update.149 EnchantingTable.updateButtons(plugin, player, offers);150 BukkitSchedulerMock scheduler = server.getScheduler();151 assertDoesNotThrow(() -> scheduler.performTicks(1));152 }153}...

Full Screen

Full Screen

Source:RabbitTests.java Github

copy

Full Screen

1package me.drepic.proton.common;2import be.seeseemelk.mockbukkit.MockBukkit;3import be.seeseemelk.mockbukkit.MockPlugin;4import be.seeseemelk.mockbukkit.ServerMock;5import be.seeseemelk.mockbukkit.scheduler.BukkitSchedulerMock;6import net.jodah.concurrentunit.Waiter;7import org.junit.jupiter.api.AfterEach;8import org.junit.jupiter.api.BeforeEach;9import java.util.List;10import java.util.Objects;11import java.util.logging.Logger;12/**13 * Tests the ProtonManager. Requires that rabbitmq is running on localhost.14 * <p>15 * Most tests use Waiter to ensure that the message handlers have been called.16 * Waiter.await(timeout, N) will throw an exception if N parties have not called resume.17 * Waiter assertions should be used in any code running in a different thread.18 * <p>19 * Most tests use async = true as this does not require manually progressing through server ticks.20 */21class RabbitTests {22 // ProtonManager Config23 static final String COMMON_GROUP = "commonGroup";24 static final String CLIENT_1_NAME = "client1";25 static final String CLIENT_1_GROUP = "client1Group";26 static final String[] CLIENT_1_GROUPS = {COMMON_GROUP, CLIENT_1_GROUP};27 static final String CLIENT_2_NAME = "client2";28 static final String CLIENT_2_GROUP = "client2Group";29 static final String[] CLIENT_2_GROUPS = {COMMON_GROUP, CLIENT_2_GROUP};30 static final String HOST = System.getenv("RABBIT_HOST");31 static final String VIRTUAL_HOST = System.getenv("RABBIT_VHOST");32 static final int PORT = 5672;33 static final String USERNAME = System.getenv("RABBIT_USER");34 static final String PASSWORD = System.getenv("RABBIT_PASS");35 static final String NAMESPACE = "test-namespace";36 static final String SUBJECT = "test-subject";37 MockPlugin plugin;38 ProtonManager client1ProtonManager;39 ProtonManager client2ProtonManager;40 Logger logger;41 BukkitSchedulerMock scheduler;42 MockBukkitSchedulerAdapter schedulerAdapter;43 Waiter waiter;44 public ProtonManager createManager(String name, String[] groups, String host, String virtualHost, int port, String username, String password) throws Exception {45 return new RabbitMQManager(schedulerAdapter, logger, name, groups, host, virtualHost, port, username, password);46 }47 @BeforeEach48 public void setUp() throws Exception {49 ServerMock server = MockBukkit.mock();50 plugin = MockBukkit.createMockPlugin();51 this.logger = Logger.getLogger("proton");52 scheduler = server.getScheduler();53 schedulerAdapter = new MockBukkitSchedulerAdapter(scheduler, plugin);54 client1ProtonManager = createManager(CLIENT_1_NAME, CLIENT_1_GROUPS, HOST, VIRTUAL_HOST, PORT, USERNAME, PASSWORD);55 client2ProtonManager = createManager(CLIENT_2_NAME, CLIENT_2_GROUPS, HOST, VIRTUAL_HOST, PORT, USERNAME, PASSWORD);...

Full Screen

Full Screen

Source:RedisTests.java Github

copy

Full Screen

1package me.drepic.proton.common;2import be.seeseemelk.mockbukkit.MockBukkit;3import be.seeseemelk.mockbukkit.MockPlugin;4import be.seeseemelk.mockbukkit.ServerMock;5import be.seeseemelk.mockbukkit.scheduler.BukkitSchedulerMock;6import net.jodah.concurrentunit.Waiter;7import org.junit.jupiter.api.AfterEach;8import org.junit.jupiter.api.BeforeEach;9import java.util.List;10import java.util.Objects;11import java.util.logging.Logger;12public class RedisTests {13 static final String COMMON_GROUP = "commonGroup";14 static final String CLIENT_1_NAME = "client1";15 static final String CLIENT_1_GROUP = "client1Group";16 static final String[] CLIENT_1_GROUPS = {COMMON_GROUP, CLIENT_1_GROUP};17 static final String CLIENT_2_NAME = "client2";18 static final String CLIENT_2_GROUP = "client2Group";19 static final String[] CLIENT_2_GROUPS = {COMMON_GROUP, CLIENT_2_GROUP};20 static final String HOST = System.getenv("REDIS_HOST");21 static final int PORT = Integer.parseInt(System.getenv("REDIS_PORT"));22 static final String PASSWORD = System.getenv("REDIS_PASS");23 static final String NAMESPACE = "test-namespace";24 static final String SUBJECT = "test-subject";25 MockPlugin plugin;26 ProtonManager client1ProtonManager;27 ProtonManager client2ProtonManager;28 Logger logger;29 BukkitSchedulerMock scheduler;30 MockBukkitSchedulerAdapter schedulerAdapter;31 Waiter waiter;32 public ProtonManager createManager(String name, String[] groups) throws Exception {33 return new RedisManager(schedulerAdapter, logger, name, groups, HOST, PORT, PASSWORD);34 }35 @BeforeEach36 public void setUp() throws Exception {37 ServerMock server = MockBukkit.mock();38 plugin = MockBukkit.createMockPlugin();39 this.logger = Logger.getLogger("proton");40 scheduler = server.getScheduler();41 schedulerAdapter = new MockBukkitSchedulerAdapter(scheduler, plugin);42 client1ProtonManager = createManager(CLIENT_1_NAME, CLIENT_1_GROUPS);43 client2ProtonManager = createManager(CLIENT_2_NAME, CLIENT_2_GROUPS);...

Full Screen

Full Screen

BukkitSchedulerMock

Using AI Code Generation

copy

Full Screen

1import be.seeseemelk.mockbukkit.scheduler.BukkitSchedulerMock;2import be.seeseemelk.mockbukkit.scheduler.BukkitTaskMock;3import org.bukkit.plugin.Plugin;4import org.bukkit.scheduler.BukkitTask;5public class SchedulerMock extends BukkitSchedulerMock {6 public BukkitTask runTask(Plugin plugin, Runnable task) {7 BukkitTaskMock taskMock = new BukkitTaskMock(plugin, task);8 taskMock.run();9 return taskMock;10 }11}12import org.bukkit.plugin.java.JavaPlugin;13import org.bukkit.scheduler.BukkitTask;14public class SchedulerMockTest extends JavaPlugin {15 private BukkitTask task;16 public void onEnable() {17 task = new SchedulerMock().runTask(this, () -> getLogger().info("Test"));18 }19 public void onDisable() {20 task.cancel();21 }22}23import be.seeseemelk.mockbukkit.MockBukkit;24import be.seeseemelk.mockbukkit.ServerMock;25import org.bukkit.plugin.Plugin;26import org.junit.After;27import org.junit.Before;28import org.junit.Test;29public class SchedulerMockTest {30 private ServerMock server;31 private Plugin plugin;32 public void setUp() {33 server = MockBukkit.mock();34 plugin = MockBukkit.load(SchedulerMockTest.class);35 }36 public void tearDown() {37 MockBukkit.unmock();38 }39 public void testRunTask() {40 }41}

Full Screen

Full Screen

BukkitSchedulerMock

Using AI Code Generation

copy

Full Screen

1import be.seeseemelk.mockbukkit.MockBukkit;2import be.seeseemelk.mockbukkit.scheduler.BukkitSchedulerMock;3public class Main {4 public static void main(String[] args) throws InterruptedException {5 BukkitSchedulerMock scheduler = MockBukkit.getScheduler();6 scheduler.runTaskTimer(new Runnable() {7 public void run() {8 System.out.println("Hello world!");9 }10 }, 0, 20);11 scheduler.advanceTime(20);12 scheduler.advanceTime(20);

Full Screen

Full Screen

BukkitSchedulerMock

Using AI Code Generation

copy

Full Screen

1import java.util.concurrent.TimeUnit;2import be.seeseemelk.mockbukkit.scheduler.BukkitSchedulerMock;3public class TestBukkitScheduler {4 private BukkitSchedulerMock scheduler;5 public void testScheduler() {6 scheduler = new BukkitSchedulerMock();7 scheduler.runTaskLater(() -> {8 System.out.println("Hello World!");9 }, 20L);10 scheduler.tick(20, TimeUnit.SECONDS);11 }12}13import static org.junit.Assert.assertEquals;14import org.junit.jupiter.api.Test;15import be.seeseemelk.mockbukkit.MockBukkit;16import be.seeseemelk.mockbukkit.ServerMock;17public class TestMockBukkit {18 public void testMockBukkit() {19 ServerMock server = MockBukkit.mock();20 assertEquals("MockBukkit", server.getName());21 }22}23import static org.junit.Assert.assertEquals;24import org.junit.jupiter.api.Test;25import be.seeseemelk.mockbukkit.MockBukkit;26import be.seeseemelk.mockbukkit.ServerMock;27public class TestMockBukkit {28 public void testMockBukkit() {29 ServerMock server = MockBukkit.mock();30 assertEquals("MockBukkit", server.getName());31 MockBukkit.unmock();32 }33}34import static org.junit.Assert.assertEquals;35import org.bukkit.Material;36import org.bukkit.block.Block;37import org.bukkit.block.BlockFace;38import org.bukkit.block.BlockState;39import org.bukkit.inventory.ItemStack;40import org.junit.jupiter.api.Test;41import be.seeseemelk.mockbukkit.MockBukkit;42import be.seeseemelk.mockbukkit.ServerMock;43import be.seeseemelk.mockbukkit.block.BlockMock;44import be.seeseemelk.mockbukkit.block.BlockStateMock;45public class TestMockBukkit {46 public void testMockBukkit() {47 ServerMock server = MockBukkit.mock();48 assertEquals("MockBukkit", server.getName());49 BlockMock block = new BlockMock(Material.GRASS);50 BlockState state = block.getState();51 block.setType(Material.DIRT);52 assertEquals(Material.DIRT, block.getType());53 assertEquals(Material.GRASS, state.getType());54 block.setType(Material.GRASS);55 assertEquals(Material.GRASS, block.getType());56 assertEquals(Material.GRASS, state.getType());

Full Screen

Full Screen

BukkitSchedulerMock

Using AI Code Generation

copy

Full Screen

1import static org.junit.Assert.*;2import org.bukkit.plugin.java.JavaPlugin;3import org.junit.Before;4import org.junit.Test;5import be.seeseemelk.mockbukkit.BukkitMock;6import be.seeseemelk.mockbukkit.scheduler.BukkitSchedulerMock;7{8 private BukkitMock bukkit;9 private BukkitSchedulerMock scheduler;10 private JavaPlugin plugin;11 public void setUp()12 {13 bukkit = new BukkitMock();14 scheduler = bukkit.getScheduler();15 plugin = new JavaPlugin();16 }17 public void test()18 {19 scheduler.runTask(plugin, () -> {20 assertEquals(plugin, JavaPlugin.getProvidingPlugin(TestPlugin.class));21 });22 }23}24import static org.junit.Assert.*;25import org.bukkit.plugin.java.JavaPlugin;26import org.junit.Before;27import org.junit.Test;28import be.seeseemelk.mockbukkit.BukkitMock;29import be.seeseemelk.mockbukkit.scheduler.BukkitSchedulerMock;30{31 private BukkitMock bukkit;32 private BukkitSchedulerMock scheduler;33 private JavaPlugin plugin;34 public void setUp()35 {36 bukkit = new BukkitMock();37 scheduler = bukkit.getScheduler();38 plugin = new JavaPlugin();39 }40 public void test()41 {42 scheduler.runTask(plugin, () -> {43 assertEquals(plugin, JavaPlugin.getProvidingPlugin(TestPlugin.class));44 });45 }46}

Full Screen

Full Screen

BukkitSchedulerMock

Using AI Code Generation

copy

Full Screen

1import org.junit.Test;2import org.junit.runner.RunWith;3import org.mockito.junit.MockitoJUnitRunner;4import org.bukkit.plugin.Plugin;5import org.bukkit.scheduler.BukkitScheduler;6import org.bukkit.scheduler.BukkitTask;7import org.junit.Before;8import org.junit.Test;9import org.junit.runner.RunWith;10import org.mockito.junit.MockitoJUnitRunner;11import be.seeseemelk.mockbukkit.MockBukkit;12import be.seeseemelk.mockbukkit.ServerMock;13import be.seeseemelk.mockbukkit.scheduler.BukkitSchedulerMock;14import static org.junit.Assert.*;15import static org.mockito.Mockito.*;16import org.junit.Before;17import org.junit.Test;18import org.junit.runner.RunWith;19import org.mockito.junit.MockitoJUnitRunner;20import be.seeseemelk.mockbukkit.MockBukkit;21import be.seeseemelk.mockbukkit.ServerMock;22import be.seeseemelk.mockbukkit.scheduler.BukkitSchedulerMock;23import static org.junit.Assert.*;24import static org.mockito.Mockito.*;25import org.junit.Before;26import org.junit.Test;27import org.junit.runner.RunWith;28import org.mockito.junit.MockitoJUnitRunner;29import be.seeseemelk.mockbukkit.MockBukkit;30import be.seeseemelk.mockbukkit.ServerMock;31import be.seeseemelk.mockbukkit.scheduler.BukkitSchedulerMock;32import static org.junit.Assert.*;33import static org.mockito.Mockito.*;34import org.junit.Before;35import org.junit.Test;36import org.junit.runner.RunWith;37import org.mockito.junit.MockitoJUnitRunner;38import be.seeseemelk.mockbukkit.MockBukkit;39import be.seeseemelk.mockbukkit.ServerMock;40import be.seeseemelk.mockbukkit.scheduler.BukkitSchedulerMock;41import static org.junit.Assert.*;42import static org.mockito.Mockito.*;43import org.junit.Before;44import org.junit.Test;45import org.junit.runner.RunWith;46import org.mockito.junit.MockitoJUnitRunner;47import be.seeseemelk.mockbukkit.MockBukkit;48import be.seeseemelk.mockbukkit.ServerMock;49import be.seeseemelk.mockbukkit.scheduler.BukkitSchedulerMock;50import static org.junit.Assert.*;51import static org.mockito.Mockito.*;52import org.junit.Before;53import org.junit.Test;54import org.junit.runner.RunWith;55import org.mockito.junit.MockitoJUnitRunner;56import be.seeseemelk.mockbukkit.MockBukkit;57import be.se

Full Screen

Full Screen

BukkitSchedulerMock

Using AI Code Generation

copy

Full Screen

1public void scheduleTask() {2 BukkitSchedulerMock scheduler = new BukkitSchedulerMock();3 scheduler.scheduleSyncRepeatingTask(plugin, () -> {4 }, 0L, 20L);5}6public void scheduleTask() {7 BukkitSchedulerMock scheduler = new BukkitSchedulerMock();8 scheduler.scheduleSyncDelayedTask(plugin, () -> {9 }, 20L);10}11public void scheduleTask() {12 BukkitSchedulerMock scheduler = new BukkitSchedulerMock();13 scheduler.scheduleSyncDelayedTask(plugin, () -> {14 }, 20L);15}16public void scheduleTask() {17 BukkitSchedulerMock scheduler = new BukkitSchedulerMock();18 scheduler.scheduleSyncDelayedTask(plugin, () -> {19 }, 20L);20}21public void scheduleTask() {22 BukkitSchedulerMock scheduler = new BukkitSchedulerMock();23 scheduler.scheduleSyncDelayedTask(plugin, () -> {24 }, 20L);25}26public void scheduleTask() {

Full Screen

Full Screen

BukkitSchedulerMock

Using AI Code Generation

copy

Full Screen

1import static org.junit.jupiter.api.Assertions.assertEquals;2import org.bukkit.plugin.Plugin;3import org.junit.jupiter.api.Test;4import org.junit.jupiter.api.extension.ExtendWith;5import be.seeseemelk.mockbukkit.MockBukkit;6import be.seeseemelk.mockbukkit.ServerMock;7import be.seeseemelk.mockbukkit.scheduler.BukkitSchedulerMock;8@ExtendWith(MockBukkitExtension.class)9{10 private Plugin plugin;11 private BukkitSchedulerMock scheduler;12 public void testScheduler()13 {14 ServerMock server = MockBukkit.mock();15 plugin = MockBukkit.createMockPlugin();16 scheduler = server.getScheduler();17 Runnable runnable = new Runnable()18 {19 public void run()20 {21 System.out.println("test");22 }23 };24 int taskId = 1;25 scheduler.runTask(plugin, runnable);26 scheduler.runTaskLater(plugin, runnable, 20);27 scheduler.runTaskTimer(plugin, runnable, 20, 20);28 scheduler.runTaskTimer(plugin, runnable, taskId, 20, 20);29 scheduler.runTaskLaterAsynchronously(plugin, runnable, 20);30 scheduler.runTaskTimerAsynchronously(plugin, runnable, 20, 20);31 scheduler.runTaskTimerAsynchronously(plugin, runnable, taskId, 20, 20);32 scheduler.cancelTask(taskId);33 scheduler.cancelTasks(plugin);

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful