The entry window had a fixed set of boxes with a Name and Comment box beside the exchange. N1MM lays out one row of boxes per contest and nothing else, so this does the same: general logging keeps Name and Comment, and a contest gets the boxes it exchanges. Two new members on `Contest` carry the cases where the boxes and the log columns are not the same list: - `FromExchange1` spreads what was typed in one box across the log columns. Where the other station sends a serial or a district code depending on where it is, N1MM gives it one box and sorts the value into the number, section or zone column from there, so the score and the Cabrillo file read it from the same column N1MM does. - `LogFieldsFor` gives the log window its own column list. Sweepstakes takes the whole exchange in one box and logs it in four columns; `SweepstakesExchange` parses `72 A 74 SCV` in any order, reading from the last word back as N1MM does. The sent serial is now marked as not required and space steps over it along with the two report boxes, because nobody types the number going out. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015NZkFxHde1iifAQemFTHxf
602 lines
19 KiB
C#
602 lines
19 KiB
C#
using Nonemm.Contests;
|
|
using Nonemm.Contests.Rules;
|
|
using Nonemm.Core;
|
|
using Nonemm.Core.Calls;
|
|
using Nonemm.Core.Country;
|
|
using Nonemm.Storage;
|
|
|
|
namespace Nonemm.Session.Tests;
|
|
|
|
public class OperatingPositionTests
|
|
{
|
|
private const string Countries = """
|
|
Germany: 14: 28: EU: 51.00: -10.00: -1.0: DL:
|
|
DL,DK,DJ;
|
|
Japan: 25: 45: AS: 36.40: -138.38: -9.0: JA:
|
|
JA,JH,JR;
|
|
""";
|
|
|
|
private static readonly StationInfo Me = new()
|
|
{
|
|
Callsign = "DL1ABC",
|
|
CqZone = 14,
|
|
ItuZone = 28,
|
|
Continent = "EU",
|
|
CountryPrefix = "DL",
|
|
};
|
|
|
|
private static OperatingPosition Session(Contest? contest = null) =>
|
|
new(Shared(new FakeLogStore(), contest));
|
|
|
|
private static ContestSession Shared(FakeLogStore store, Contest? contest = null)
|
|
{
|
|
ContestInstance instance = store.AddContest(new ContestInstance
|
|
{
|
|
ContestNumber = 0,
|
|
ContestName = "CQWW",
|
|
});
|
|
return new ContestSession(
|
|
store,
|
|
contest ?? new CqWorldWide(ModeCategory.Cw),
|
|
instance,
|
|
Me,
|
|
CountryFile.Parse(Countries));
|
|
}
|
|
|
|
private static void Type(OperatingPosition session, string call, string zone)
|
|
{
|
|
session.Entry.Call = call;
|
|
session.Entry.Set(ExchangeSlot.ReceivedReport, "599");
|
|
session.Entry.Set(ExchangeSlot.Zone, zone);
|
|
}
|
|
|
|
/// N1MM shows what this station sends beside what it copies, keeps both
|
|
/// filled in and steps over them.
|
|
[Fact]
|
|
public void TheSentBoxesAreFilledInAndSteppedOver()
|
|
{
|
|
OperatingPosition session = Session(new CqWpx(ModeCategory.Cw));
|
|
|
|
Assert.Equal("599", session.Entry.ValueOf(ExchangeSlot.SentReport));
|
|
Assert.Equal("1", session.Entry.ValueOf(ExchangeSlot.SentNumber));
|
|
|
|
// the boxes are the call, the two reports, the sent serial and the
|
|
// serial being copied
|
|
session.Entry.Advance();
|
|
Assert.Equal(4, session.Entry.Focus);
|
|
}
|
|
|
|
[Fact]
|
|
public void TheSentSerialGoesUpWhenAContactIsLogged()
|
|
{
|
|
OperatingPosition session = Session(new CqWpx(ModeCategory.Cw));
|
|
session.Entry.Call = "JA1XYZ";
|
|
session.Entry.Set(ExchangeSlot.ReceivedReport, "599");
|
|
session.Entry.Set(ExchangeSlot.SerialNumber, "12");
|
|
|
|
Assert.Equal(1, session.LogContact().SentNumber);
|
|
Assert.Equal("2", session.Entry.ValueOf(ExchangeSlot.SentNumber));
|
|
}
|
|
|
|
/// The BARTG contest sends the time of the exchange, and logs the time it
|
|
/// sent rather than the time the contact was logged.
|
|
[Fact]
|
|
public void TheTimeTheExchangeWentOutIsLoggedForBartg()
|
|
{
|
|
OperatingPosition session = Session(new BartgSprint());
|
|
session.Entry.Call = "JA1XYZ";
|
|
session.Entry.Set(ExchangeSlot.ReceivedReport, "599");
|
|
session.Entry.Set(ExchangeSlot.SerialNumber, "12");
|
|
session.Entry.Set(ExchangeSlot.Exchange1, "1646");
|
|
session.StampSentTime();
|
|
string stamped = session.SentTime;
|
|
|
|
Qso logged = session.LogContact();
|
|
|
|
Assert.Equal(4, stamped.Length);
|
|
Assert.Equal(stamped, logged.MiscText);
|
|
Assert.Equal("", session.SentTime);
|
|
}
|
|
|
|
/// A contest that does not exchange a time keeps the column empty.
|
|
[Fact]
|
|
public void NothingIsStampedForAContestThatSendsNoTime()
|
|
{
|
|
OperatingPosition session = Session();
|
|
Type(session, "JA1XYZ", "25");
|
|
session.StampSentTime();
|
|
|
|
Assert.Equal("", session.SentTime);
|
|
Assert.Equal("", session.LogContact().MiscText);
|
|
}
|
|
|
|
[Fact]
|
|
public void LoggingAContactPutsItInTheLogAndClearsTheEntry()
|
|
{
|
|
OperatingPosition session = Session();
|
|
Type(session, "JA1XYZ", "25");
|
|
Qso logged = session.LogContact();
|
|
|
|
Assert.Equal("JA1XYZ", logged.Call.Text);
|
|
Assert.Equal(25, logged.Zone);
|
|
Assert.Equal(3, logged.Points);
|
|
Assert.Equal("", session.Entry.Call);
|
|
Assert.Single(session.Log.Qsos);
|
|
}
|
|
|
|
[Fact]
|
|
public void CountryAndPrefixAreFilledInFromTheCountryFile()
|
|
{
|
|
OperatingPosition session = Session();
|
|
Type(session, "JA1XYZ", "25");
|
|
Qso logged = session.LogContact();
|
|
|
|
Assert.Equal("JA", logged.CountryPrefix);
|
|
Assert.Equal("AS", logged.Continent);
|
|
Assert.Equal("JA1", logged.WpxPrefix);
|
|
}
|
|
|
|
[Fact]
|
|
public void AnIncompleteExchangeIsNotLogged()
|
|
{
|
|
OperatingPosition session = Session();
|
|
session.Entry.Call = "JA1XYZ";
|
|
Assert.Throws<InvalidOperationException>(() => session.LogContact());
|
|
}
|
|
|
|
[Fact]
|
|
public void TheSameStationOnTheSameBandReadsAsADupe()
|
|
{
|
|
OperatingPosition session = Session();
|
|
Type(session, "JA1XYZ", "25");
|
|
session.LogContact();
|
|
Type(session, "JA1XYZ", "25");
|
|
Assert.True(session.Verdict()?.IsDupe);
|
|
}
|
|
|
|
[Fact]
|
|
public void MovingBandClearsTheDupe()
|
|
{
|
|
OperatingPosition session = Session();
|
|
Type(session, "JA1XYZ", "25");
|
|
session.LogContact();
|
|
session.Tune(Frequency.FromKilohertz(7_025));
|
|
Type(session, "JA1XYZ", "25");
|
|
Assert.False(session.Verdict()?.IsDupe);
|
|
}
|
|
|
|
[Fact]
|
|
public void SerialNumbersCountUp()
|
|
{
|
|
OperatingPosition session = Session(new CqWpx(ModeCategory.Cw));
|
|
Assert.Equal(1, session.SentNumber);
|
|
session.Entry.Call = "JA1XYZ";
|
|
session.Entry.Set(ExchangeSlot.ReceivedReport, "599");
|
|
session.Entry.Set(ExchangeSlot.SerialNumber, "12");
|
|
session.LogContact();
|
|
Assert.Equal(2, session.SentNumber);
|
|
}
|
|
|
|
[Fact]
|
|
public void SpaceStepsOverTheReportAndComesBackToTheCall()
|
|
{
|
|
// CQ WW's boxes are the call, the two reports and the zone
|
|
OperatingPosition session = Session();
|
|
|
|
Assert.Equal(0, session.Entry.Focus);
|
|
session.Entry.Advance();
|
|
Assert.Equal(3, session.Entry.Focus);
|
|
session.Entry.Advance();
|
|
Assert.Equal(0, session.Entry.Focus);
|
|
}
|
|
|
|
[Fact]
|
|
public void GoingBackStepsOverTheReportToo()
|
|
{
|
|
OperatingPosition session = Session();
|
|
session.Entry.FocusOn(3);
|
|
|
|
session.Entry.Retreat();
|
|
|
|
Assert.Equal(0, session.Entry.Focus);
|
|
}
|
|
|
|
[Fact]
|
|
public void TheReportBoxesAreFilledInWithWhatWouldBeSentAnyway()
|
|
{
|
|
OperatingPosition session = Session();
|
|
|
|
Assert.True(session.FillReports());
|
|
|
|
Assert.Equal("599", session.Entry.ValueOf(ExchangeSlot.ReceivedReport));
|
|
Assert.False(session.FillReports());
|
|
}
|
|
|
|
[Fact]
|
|
public void AReportTheOperatorTypedIsLeftAlone()
|
|
{
|
|
OperatingPosition session = Session();
|
|
session.Entry.Set(ExchangeSlot.ReceivedReport, "559");
|
|
|
|
Assert.False(session.FillReports());
|
|
Assert.Equal("559", session.Entry.ValueOf(ExchangeSlot.ReceivedReport));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData("14025", 14_025_000)]
|
|
[InlineData("14.025", 14_025_000)]
|
|
[InlineData("7025.5", 7_025_500)]
|
|
public void AFrequencyTypedIntoTheCallBoxIsRecognised(string typed, long hertz)
|
|
{
|
|
OperatingPosition session = Session();
|
|
session.Entry.Call = typed;
|
|
Assert.Equal(hertz, session.PendingQsy()?.Hertz);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData("JA1XYZ")]
|
|
[InlineData("12000")]
|
|
public void ACallOrAnOutOfBandNumberIsNotAQsy(string typed)
|
|
{
|
|
OperatingPosition session = Session();
|
|
session.Entry.Call = typed;
|
|
Assert.Null(session.PendingQsy());
|
|
}
|
|
|
|
[Fact]
|
|
public void AContactDeletedFromTheLogGivesItsMultiplierBack()
|
|
{
|
|
OperatingPosition session = Session();
|
|
Type(session, "JA1XYZ", "25");
|
|
Qso first = session.LogContact();
|
|
Type(session, "JA2XYZ", "25");
|
|
session.LogContact();
|
|
Assert.Equal(2, session.Log.Tally.TotalMultipliers);
|
|
|
|
session.Session.Delete(first.Id);
|
|
Assert.Single(session.Log.Qsos);
|
|
Assert.Equal(2, session.Log.Tally.TotalMultipliers);
|
|
Assert.True(session.Log.Qsos.Single().IsMultiplier1);
|
|
}
|
|
|
|
[Fact]
|
|
public void AContactWorkedSplitRecordsWhereWeTransmitted()
|
|
{
|
|
OperatingPosition session = Session();
|
|
session.Tune(
|
|
Frequency.FromKilohertz(14_025),
|
|
Modes.Cw,
|
|
Frequency.FromKilohertz(14_200));
|
|
Type(session, "JA1XYZ", "25");
|
|
|
|
Qso logged = session.LogContact();
|
|
|
|
Assert.Equal(14_025_000, logged.Frequency.Hertz);
|
|
Assert.Equal(14_200_000, logged.QsxFrequency.Hertz);
|
|
}
|
|
|
|
[Fact]
|
|
public void AContactRecordsWhichRadioMadeIt()
|
|
{
|
|
OperatingPosition session = new(Shared(new FakeLogStore()), 2);
|
|
Type(session, "JA1XYZ", "25");
|
|
|
|
Assert.Equal(2, session.LogContact().RadioNumber);
|
|
}
|
|
|
|
/// Tuning without saying anything about split leaves it where it was, so a
|
|
/// frequency typed by hand does not clear what the radio reported.
|
|
[Fact]
|
|
public void TuningWithoutASplitLeavesTheOneAlreadySet()
|
|
{
|
|
OperatingPosition session = Session();
|
|
session.Tune(Frequency.FromKilohertz(14_025), null, Frequency.FromKilohertz(14_200));
|
|
|
|
session.Tune(Frequency.FromKilohertz(14_030));
|
|
|
|
Assert.Equal(14_200_000, session.TransmitFrequency.Hertz);
|
|
}
|
|
|
|
[Fact]
|
|
public void EditingAContactRescoresTheLog()
|
|
{
|
|
OperatingPosition session = Session();
|
|
Type(session, "JA1XYZ", "25");
|
|
Qso logged = session.LogContact();
|
|
Assert.Equal(3, session.Log.Tally.Points);
|
|
|
|
QsoEdit edit = session.Session.Edit(logged.Id, QsoField.Call, "DL2XYZ");
|
|
|
|
Assert.True(edit.IsAccepted);
|
|
Assert.Equal("DL2XYZ", session.Log.Qsos.Single().Call.Text);
|
|
Assert.Equal(0, session.Log.Tally.Points);
|
|
}
|
|
|
|
[Fact]
|
|
public void ARefusedEditLeavesTheLogAlone()
|
|
{
|
|
OperatingPosition session = Session();
|
|
Type(session, "JA1XYZ", "25");
|
|
Qso logged = session.LogContact();
|
|
|
|
QsoEdit edit = session.Session.Edit(logged.Id, QsoField.Zone, "41");
|
|
|
|
Assert.False(edit.IsAccepted);
|
|
Assert.Equal(25, session.Log.Qsos.Single().Zone);
|
|
}
|
|
|
|
/// The other stations need the call and time the contact had before, because
|
|
/// that is how they find their own copy of it.
|
|
[Fact]
|
|
public void AnEditReportsWhatTheContactUsedToBe()
|
|
{
|
|
OperatingPosition session = Session();
|
|
Type(session, "JA1XYZ", "25");
|
|
Qso logged = session.LogContact();
|
|
QsoChange? change = null;
|
|
session.Session.Edited += (_, c) => change = c;
|
|
|
|
session.Session.Edit(logged.Id, QsoField.Call, "JA2XYZ");
|
|
|
|
Assert.Equal("JA1XYZ", change?.OldCall);
|
|
Assert.Equal(logged.TimestampUtc, change?.OldTimestampUtc);
|
|
Assert.Equal("JA2XYZ", change?.Qso.Call.Text);
|
|
}
|
|
|
|
/// The country file gets a call wrong now and then. Correcting the country
|
|
/// by hand has to change the score, or the correction is decoration.
|
|
[Fact]
|
|
public void CorrectingTheCountryChangesTheScore()
|
|
{
|
|
OperatingPosition session = Session();
|
|
Type(session, "JA1XYZ", "25");
|
|
Qso logged = session.LogContact();
|
|
Assert.Equal(3, session.Log.Tally.Points);
|
|
|
|
session.Session.Edit(logged.Id, QsoField.CountryPrefix, "DL");
|
|
|
|
Assert.Equal(0, session.Log.Tally.Points);
|
|
}
|
|
|
|
[Fact]
|
|
public void ADeleteReportsTheContactThatWent()
|
|
{
|
|
OperatingPosition session = Session();
|
|
Type(session, "JA1XYZ", "25");
|
|
Qso logged = session.LogContact();
|
|
Qso? gone = null;
|
|
session.Session.Deleted += (_, q) => gone = q;
|
|
|
|
session.Session.Delete(logged.Id);
|
|
|
|
Assert.Equal("JA1XYZ", gone?.Call.Text);
|
|
}
|
|
|
|
[Fact]
|
|
public void StoredContactsAreReadBackWhenTheSessionStarts()
|
|
{
|
|
FakeLogStore store = new();
|
|
OperatingPosition first = new(Shared(store));
|
|
Type(first, "JA1XYZ", "25");
|
|
first.LogContact();
|
|
|
|
OperatingPosition second = new(new ContestSession(
|
|
store,
|
|
new CqWorldWide(ModeCategory.Cw),
|
|
first.Instance,
|
|
Me,
|
|
CountryFile.Parse(Countries)));
|
|
Assert.Single(second.Log.Qsos);
|
|
Assert.Equal(3, second.Log.Tally.Points);
|
|
}
|
|
|
|
private static OperatingPosition WithHistory(Contest contest, string file)
|
|
{
|
|
FakeLogStore store = new();
|
|
ContestInstance instance = store.AddContest(new ContestInstance
|
|
{
|
|
ContestNumber = 0,
|
|
ContestName = contest.Name,
|
|
});
|
|
return new OperatingPosition(new ContestSession(
|
|
store,
|
|
contest,
|
|
instance,
|
|
Me,
|
|
CountryFile.Parse(Countries),
|
|
CallHistory.Parse(file)));
|
|
}
|
|
|
|
[Fact]
|
|
public void TheCallHistoryFillsTheExchangeIn()
|
|
{
|
|
OperatingPosition session = WithHistory(
|
|
new Sweepstakes(ModeCategory.Cw),
|
|
"!!Order!!,Call,Sect,CK\nW3LPL,MDC,56");
|
|
session.Entry.Call = "W3LPL";
|
|
|
|
Assert.True(session.FillFromHistory());
|
|
Assert.Equal("56MDC", session.Entry.ValueOf(ExchangeSlot.Exchange1));
|
|
}
|
|
|
|
/// What the other station actually sends beats what was published, so a box
|
|
/// with something in it is left alone.
|
|
[Fact]
|
|
public void WhatIsAlreadyTypedIsNotOverwritten()
|
|
{
|
|
OperatingPosition session = WithHistory(
|
|
new Sweepstakes(ModeCategory.Cw),
|
|
"!!Order!!,Call,Sect\nW3LPL,MDC");
|
|
session.Entry.Call = "W3LPL";
|
|
session.Entry.Set(ExchangeSlot.Exchange1, "72A 74EPA");
|
|
|
|
session.FillFromHistory();
|
|
|
|
Assert.Equal("72A 74EPA", session.Entry.ValueOf(ExchangeSlot.Exchange1));
|
|
}
|
|
|
|
[Fact]
|
|
public void ACallTheHistoryDoesNotHoldFillsNothing()
|
|
{
|
|
OperatingPosition session = WithHistory(
|
|
new Sweepstakes(ModeCategory.Cw),
|
|
"!!Order!!,Call,Sect\nW3LPL,MDC");
|
|
session.Entry.Call = "JA1XYZ";
|
|
|
|
Assert.False(session.FillFromHistory());
|
|
Assert.Equal("", session.Entry.ValueOf(ExchangeSlot.Exchange1));
|
|
}
|
|
|
|
/// CQ WW exchanges the CQ zone, so the CQ zone column is the one to use.
|
|
[Fact]
|
|
public void TheZoneComesFromTheColumnTheContestAsksFor()
|
|
{
|
|
OperatingPosition session = WithHistory(
|
|
new CqWorldWide(ModeCategory.Cw),
|
|
"!!Order!!,Call,CqZone,ITUZone\nJA1XYZ,25,45");
|
|
session.Entry.Call = "JA1XYZ";
|
|
|
|
session.FillFromHistory();
|
|
|
|
Assert.Equal("25", session.Entry.ValueOf(ExchangeSlot.Zone));
|
|
}
|
|
|
|
/// A file for a section contest often carries the state instead.
|
|
[Fact]
|
|
public void TheStateFillsASectionWhenTheFileHasNoSection()
|
|
{
|
|
OperatingPosition session = WithHistory(
|
|
new Sweepstakes(ModeCategory.Cw),
|
|
"!!Order!!,Call,Sect,State\nK1TTT,,CT");
|
|
session.Entry.Call = "K1TTT";
|
|
|
|
session.FillFromHistory();
|
|
|
|
Assert.Equal("00CT", session.Entry.ValueOf(ExchangeSlot.Exchange1));
|
|
}
|
|
|
|
[Fact]
|
|
public void TheNameAndCommentBoxesReachTheLog()
|
|
{
|
|
OperatingPosition session = Session();
|
|
session.Entry.Call = "JA1XYZ";
|
|
session.Entry.Set(ExchangeSlot.ReceivedReport, "599");
|
|
session.Entry.Set(ExchangeSlot.Zone, "25");
|
|
session.OtherName = "Ken";
|
|
session.Comment = "up 2";
|
|
|
|
Qso logged = session.LogContact();
|
|
|
|
Assert.Equal("Ken", logged.Name);
|
|
Assert.Equal("up 2", logged.Comment);
|
|
Assert.Equal("", session.OtherName);
|
|
Assert.Equal("", session.Comment);
|
|
}
|
|
|
|
[Fact]
|
|
public void WipingClearsTheNameAndTheComment()
|
|
{
|
|
OperatingPosition session = Session();
|
|
session.OtherName = "Ken";
|
|
session.Comment = "up 2";
|
|
|
|
session.Wipe();
|
|
|
|
Assert.Equal("", session.OtherName);
|
|
Assert.Equal("", session.Comment);
|
|
}
|
|
|
|
[Fact]
|
|
public void CqWwRttyStepsOverTheStateBoxForAStationOutsideTheUsAndCanada()
|
|
{
|
|
OperatingPosition session = Session(new CqWorldWide(ModeCategory.Digital));
|
|
session.Entry.Call = "JA1XYZ";
|
|
|
|
// the boxes are the call, the two reports, the zone and the state
|
|
session.MoveFocus(forward: true);
|
|
Assert.Equal(3, session.Entry.Focus);
|
|
session.MoveFocus(forward: true);
|
|
Assert.Equal(0, session.Entry.Focus);
|
|
}
|
|
|
|
[Fact]
|
|
public void CqWwRttyStopsOnTheStateBoxForAUsStation()
|
|
{
|
|
OperatingPosition session = Session(new CqWorldWide(ModeCategory.Digital));
|
|
session.Entry.Call = "K1ABC";
|
|
|
|
session.MoveFocus(forward: true);
|
|
Assert.Equal(3, session.Entry.Focus);
|
|
session.MoveFocus(forward: true);
|
|
Assert.Equal(4, session.Entry.Focus);
|
|
}
|
|
|
|
[Fact]
|
|
public void QuickEditLoadsTheLastContactAndSavesTheChangeBack()
|
|
{
|
|
OperatingPosition session = Session();
|
|
Type(session, "JA1XYZ", "25");
|
|
Qso logged = session.LogContact();
|
|
Type(session, "DL9ZZZ", "14");
|
|
|
|
Assert.True(session.QuickEdit(forward: false));
|
|
Assert.Equal(logged.Id, session.Editing?.Id);
|
|
Assert.Equal("JA1XYZ", session.Entry.Call);
|
|
Assert.Equal("25", session.Entry.ValueOf(ExchangeSlot.Zone));
|
|
|
|
session.Entry.Set(ExchangeSlot.Zone, "24");
|
|
Qso? saved = session.SaveQuickEdit();
|
|
|
|
Assert.Equal(24, saved?.Zone);
|
|
Assert.Equal(24, session.Log.Qsos[0].Zone);
|
|
Assert.Null(session.Editing);
|
|
}
|
|
|
|
[Fact]
|
|
public void LeavingQuickEditPutsBackWhatWasBeingTyped()
|
|
{
|
|
OperatingPosition session = Session();
|
|
Type(session, "JA1XYZ", "25");
|
|
session.LogContact();
|
|
Type(session, "DL9ZZZ", "14");
|
|
|
|
session.QuickEdit(forward: false);
|
|
session.LeaveQuickEdit();
|
|
|
|
Assert.Null(session.Editing);
|
|
Assert.Equal("DL9ZZZ", session.Entry.Call);
|
|
Assert.Equal("14", session.Entry.ValueOf(ExchangeSlot.Zone));
|
|
}
|
|
|
|
[Fact]
|
|
public void QuickEditForwardPastTheNewestContactLeavesQuickEdit()
|
|
{
|
|
OperatingPosition session = Session();
|
|
Type(session, "JA1XYZ", "25");
|
|
session.LogContact();
|
|
Type(session, "DL9ZZZ", "14");
|
|
|
|
session.QuickEdit(forward: false);
|
|
Assert.True(session.QuickEdit(forward: true));
|
|
|
|
Assert.Null(session.Editing);
|
|
Assert.Equal("DL9ZZZ", session.Entry.Call);
|
|
}
|
|
|
|
[Fact]
|
|
public void QuickEditStepsBackThroughTheLog()
|
|
{
|
|
OperatingPosition session = Session();
|
|
Type(session, "JA1XYZ", "25");
|
|
session.LogContact();
|
|
Type(session, "DL9ZZZ", "14");
|
|
session.LogContact();
|
|
|
|
session.QuickEdit(forward: false);
|
|
Assert.Equal("DL9ZZZ", session.Entry.Call);
|
|
session.QuickEdit(forward: false);
|
|
Assert.Equal("JA1XYZ", session.Entry.Call);
|
|
Assert.False(session.QuickEdit(forward: false));
|
|
}
|
|
}
|