using Nonemm.Contests; using Nonemm.Contests.Rules; using Nonemm.Core; using Nonemm.Storage; namespace Nonemm.Session.Tests; public class MessagePlanTests { private static OperatingPosition Session() { FakeLogStore store = new(); ContestInstance instance = store.AddContest(new ContestInstance { ContestNumber = 0, ContestName = "CQWW", SentExchange = "14", }); return new OperatingPosition(new ContestSession( store, new CqWorldWide(ModeCategory.Cw), instance, new StationInfo { Callsign = "DL1ABC", CqZone = 14 }, null)); } [Fact] public void AMessageWithNoMacrosIsJustText() { MessagePlan plan = MessagePlan.Read("TEST DE DL1ABC", Session()); Assert.Equal("TEST DE DL1ABC", plan.Text); Assert.Empty(plan.Before); Assert.Empty(plan.After); } [Fact] public void AnActionMacroRunsBeforeTheMessageAndDoesNotGoOnTheAir() { MessagePlan plan = MessagePlan.Read("{RUN}CQ TEST *", Session()); Assert.Equal("CQ TEST DL1ABC", plan.Text); Assert.Equal([new MessageAction(MessageCommand.Run)], plan.Before); } [Fact] public void WhatFollowsEndRunsAfterTheMessage() { MessagePlan plan = MessagePlan.Read("TU {LOG}{END}{WIPE}", Session()); Assert.Equal("TU ", plan.Text); Assert.Equal([new MessageAction(MessageCommand.Log)], plan.Before); Assert.Equal([new MessageAction(MessageCommand.Wipe)], plan.After); } [Fact] public void TextAfterEndIsDropped() { MessagePlan plan = MessagePlan.Read("TU{END} 5NN {MYCALL}", Session()); Assert.Equal("TU", plan.Text); } [Fact] public void AMacroWithACommandAfterItKeepsTheCommandAsTyped() { MessagePlan plan = MessagePlan.Read("{Telnet sh/dx 20}{OTRSP TX2}", Session()); Assert.Equal( [ new MessageAction(MessageCommand.Telnet, "sh/dx 20"), new MessageAction(MessageCommand.Otrsp, "TX2"), ], plan.Before); Assert.Equal("", plan.Text); } [Fact] public void CtrlFSendsThatKeyOnTheOtherRadio() { MessagePlan plan = MessagePlan.Read("TU {CTRLF9}", Session()); Assert.Equal([new MessageAction(MessageCommand.SendOnOtherRadio, "9")], plan.Before); } [Fact] public void TheCallStackingMacrosAreRead() { MessagePlan plan = MessagePlan.Read( "{STACKANOTHER}{SOCALLSTACK}{LOGTHENPOP}{LOGTHENNEXT}{CLRSTACK}", Session()); Assert.Equal( [ new MessageAction(MessageCommand.StackAnother), new MessageAction(MessageCommand.SwapWithStack), new MessageAction(MessageCommand.LogThenPop), new MessageAction(MessageCommand.LogThenPop), new MessageAction(MessageCommand.ClearStack), ], plan.Before); Assert.Equal("", plan.Text); } [Fact] public void AMacroThisProgramDoesNotActOnIsPassedOver() { MessagePlan plan = MessagePlan.Read("CQ {STEREOOFF}TEST", Session()); Assert.Equal("CQ TEST", plan.Text); Assert.Empty(plan.Before); } /// The digital window's transmit macros, and the carriage return that /// starts a new line on the other station's screen. [Fact] public void TheDigitalMacrosAreReadAsActionsAndText() { MessagePlan plan = MessagePlan.Read("{TX}CQ DE {MYCALL}{ENTER}{RX}", Session()); Assert.Equal([MessageCommand.StartTransmit], plan.Before.Select(a => a.Command)); Assert.Equal("CQ DE DL1ABC\r", plan.Text); Assert.Equal([MessageCommand.ReturnToReceive], plan.After.Select(a => a.Command)); } /// `{RX}` waits for the message even when it stands in front of it, because /// the transmitter cannot drop before the text has gone out. Everything /// else in front of the text still runs first. [Fact] public void ReturnToReceiveRunsAfterTheMessageWhereverItStands() { MessagePlan plan = MessagePlan.Read("{TX}{RX}CQ TEST{WIPE}", Session()); Assert.Equal([MessageCommand.StartTransmit, MessageCommand.Wipe], plan.Before.Select(a => a.Command)); Assert.Equal([MessageCommand.ReturnToReceive], plan.After.Select(a => a.Command)); } }