2026-11-08 19:49:46 +01:00
using AIStudio.Assistants.BeyondFactsLab ;
namespace AIStudio.Tests.BeyondFactsLab ;
/// <summary>
/// Checks the steps and the fields of the forms "Your details" in the BeyondFacts Lab.
/// </summary>
/// <remarks>
/// The forms store their values under the IDs of the fields and options, and the folders of the steps carry their
/// names, so all of them are pinned here: changing one would lose what people entered before.
/// </remarks>
[TestFixture]
public sealed class BflFieldCatalogTests
{
[Test]
public void TheStepsKeepTheirNamesAndOrder ()
{
Assert . That ( BflStep . All . Select ( step => step . ToString ()), Is . EqualTo ( new []
{
"FRAMEWORK" , "KNOWLEDGE" , "GOALS_AND_ROLE" , "VALUES_AND_PERSPECTIVES" , "STRATEGY" , "TEST_SITUATION" , "RESULTS" ,
}));
}
[Test]
public void TheFoldersOfTheStepsKeepTheirNames ()
{
Assert . That ( BflStep . All . Select ( step => step . FolderName ), Is . EqualTo ( new []
{
"01-framework" , "02-knowledge" , "03-goals" , "04-values" , "05-strategy" , "06-test" , "07-results" ,
}));
}
[Test]
public void TheFieldsKeepTheirIds ()
{
Assert . That ( BflFieldCatalog . FIELDS . Select ( field => field . Id ), Is . EqualTo ( new []
{
2026-11-10 18:17:44 +01:00
"format" , "event_topic" , "audience" , "event_visibility" , "contribution_topic" , "event_date" , "event_location" , "event_duration" , "contribution_duration" , "other_participants" , "event_link" ,
2026-11-08 19:49:46 +01:00
"contribution_summary" , "core_theses" , "uncertainties" , "material_notes" ,
"goals" , "goal_directions" ,
"values_and_concerns" , "personal_concern" , "other_perspectives" ,
"communication_worries" ,
"question_type" , "difficulty" , "test_notes" ,
"position_changes" ,
}));
}
[Test]
public void TheOptionsKeepTheirIds ()
{
Assert . That ( BflFieldCatalog . FIELDS . SelectMany ( field => field . Options ). Select ( option => option . Id ), Is . EqualTo ( new []
{
2026-11-10 18:17:44 +01:00
"event_public" , "event_not_public" ,
2026-11-08 19:49:46 +01:00
"goal_inform" , "goal_moderate" , "goal_take_position" , "goal_raise_awareness" , "goal_show_options" , "goal_influence_policy" ,
"questions_mixed" , "questions_scientific_criticism" , "questions_emotional_criticism" , "questions_manipulative" , "questions_political_instrumentalization" ,
"difficulty_moderate" , "difficulty_demanding" , "difficulty_very_demanding" ,
}));
}
[Test]
public void EveryIdIsUnique ()
{
var ids = BflFieldCatalog . FIELDS . Select ( field => field . Id ). Concat ( BflFieldCatalog . FIELDS . SelectMany ( field => field . Options ). Select ( option => option . Id )). ToList ();
Assert . That ( ids , Is . Unique );
}
[Test]
public void TheFieldsOfAStepFollowEachOther ()
{
var stepsInOrder = BflFieldCatalog . FIELDS . Select ( field => field . Step ). Distinct ();
Assert . That ( stepsInOrder , Is . EqualTo ( BflStep . All ));
}
2026-11-15 13:06:06 +01:00
[Test]
public void TheValuesStepShowsTheThreeSectionsOfLarasDialogueLogicInTheirOrder ()
{
var sections = BflFieldCatalog . ForStep ( BflStep . VALUES_AND_PERSPECTIVES ). Select ( field => field . Section ). Distinct ();
Assert . That ( sections , Is . EqualTo ( new [] { BflFormSection . WHAT_MATTERS_TO_ME , BflFormSection . WHAT_TOUCHES_ME , BflFormSection . WHAT_MOVES_OTHERS }));
}
[Test]
public void TheFieldsOfASectionFollowEachOtherAndHaveAHeading ()
{
using ( Assert . EnterMultipleScope ())
{
foreach ( var step in BflStep . All )
{
var sections = BflFieldCatalog . ForStep ( step ). Select ( field => field . Section ). ToList ();
var runs = sections . Where (( section , index ) => index == 0 || sections [ index - 1 ] != section ). ToList ();
Assert . That ( runs , Is . Unique , $"The fields of a section of {step} do not follow each other." );
Assert . That ( runs . Where ( section => section is not BflFormSection . NONE ). Select ( section => section . Title ), Has . None . Empty , $"A section of {step} has no heading." );
}
}
}
[Test]
public void OnlyTheSectionAboutWhatMattersHoldsTheCardSort ()
{
Assert . That ( Enum . GetValues < BflFormSection >(). Where ( section => section . HasCardSort ), Is . EqualTo ( new [] { BflFormSection . WHAT_MATTERS_TO_ME }));
}
2026-11-08 19:49:46 +01:00
[Test]
public void EveryStepHasAFormWithATitleAndADescription ()
{
using ( Assert . EnterMultipleScope ())
{
foreach ( var step in BflStep . All )
{
Assert . That ( BflFieldCatalog . ForStep ( step ), Is . Not . Empty , $"{step} has no fields." );
Assert . That ( step . Title , Is . Not . Empty , $"{step} has no title." );
Assert . That ( step . Description , Is . Not . Empty , $"{step} has no description." );
}
}
}
[Test]
public void OnlyFieldsWithAChoiceHaveOptions ()
{
using ( Assert . EnterMultipleScope ())
{
foreach ( var field in BflFieldCatalog . FIELDS )
{
if ( field . Kind . HasOptions )
Assert . That ( field . Options , Has . Count . GreaterThanOrEqualTo ( 2 ), $"{field.Id} offers too few options." );
else
Assert . That ( field . Options , Is . Empty , $"{field.Id} has options, but nothing shows them." );
}
}
}
[Test]
public void EveryKindHasALimit ()
{
Assert . That ( Enum . GetValues < BflFieldKind >(). Select ( kind => kind . MaxLength ), Has . All . GreaterThan ( 0 ));
}
[Test]
public void EveryFieldAndOptionHasALabel ()
{
using ( Assert . EnterMultipleScope ())
{
foreach ( var field in BflFieldCatalog . FIELDS )
{
Assert . That ( field . Label , Is . Not . Empty , $"{field.Id} has no label." );
foreach ( var option in field . Options )
Assert . That ( option . Label , Is . Not . Empty , $"{option.Id} has no label." );
}
}
}
[Test]
public void EveryFieldAndOptionHasALabelOfItsOwn ()
{
// Equal English texts share one key of the localization, so another language could not tell them apart:
var labels = BflFieldCatalog . FIELDS . SelectMany ( field => field . Options . Select ( option => option . Label ). Prepend ( field . Label ));
Assert . That ( labels , Is . Unique );
}
[Test]
public void OnlyPublicDetailsAboutTheEventReachTheResearch ()
{
var shared = BflFieldCatalog . FIELDS . Where ( field => field . IsSharedWithResearch ). Select ( field => field . Id );
Assert . That ( shared , Is . EquivalentTo ( new []
{
BflFieldCatalog . FORMAT , BflFieldCatalog . EVENT_TOPIC , BflFieldCatalog . EVENT_DATE , BflFieldCatalog . EVENT_LOCATION , BflFieldCatalog . OTHER_PARTICIPANTS , BflFieldCatalog . EVENT_LINK ,
}), "The topic of a contribution may be unpublished, and nothing personal belongs on the web." );
}
[Test]
public void OnlyThePersonalInvolvementIsPersonal ()
{
var personal = BflFieldCatalog . FIELDS . Where ( field => field . IsPersonalDisclosure ). Select ( field => field . Id );
Assert . That ( personal , Is . EquivalentTo ( new [] { BflFieldCatalog . PERSONAL_CONCERN }));
}
[Test]
public void OnlyTheOtherParticipantsHoldNames ()
{
var withNames = BflFieldCatalog . FIELDS . Where ( field => field . NameRole is not BflNameRole . NONE ). Select ( field => field . Id );
Assert . That ( withNames , Is . EquivalentTo ( new [] { BflFieldCatalog . OTHER_PARTICIPANTS }));
}
[Test]
public void TheKeyDetailsAreThoseOfTheEventAndTheContribution ()
{
var keyDetails = BflFieldCatalog . FIELDS . Where ( field => field . IsKeyDetail ). Select ( field => field . Id );
Assert . That ( keyDetails , Is . EquivalentTo ( new []
{
2026-11-10 18:17:44 +01:00
BflFieldCatalog . FORMAT , BflFieldCatalog . EVENT_TOPIC , BflFieldCatalog . AUDIENCE , BflFieldCatalog . EVENT_VISIBILITY , BflFieldCatalog . CONTRIBUTION_TOPIC , BflFieldCatalog . CONTRIBUTION_SUMMARY ,
2026-11-08 19:49:46 +01:00
}));
}
2026-11-10 18:17:44 +01:00
[Test]
public void WhetherTheEventIsPublicIsASingleChoiceWhichNeverReachesTheResearch ()
{
var visibility = BflFieldCatalog . FIELDS . Single ( field => field . Id == BflFieldCatalog . EVENT_VISIBILITY );
using ( Assert . EnterMultipleScope ())
{
Assert . That ( visibility . Step , Is . EqualTo ( BflStep . FRAMEWORK ));
Assert . That ( visibility . Kind , Is . EqualTo ( BflFieldKind . CHOICE ));
Assert . That ( visibility . Options . Select ( option => option . Id ), Is . EqualTo ( new [] { BflFieldCatalog . EVENT_PUBLIC , BflFieldCatalog . EVENT_NOT_PUBLIC }));
Assert . That ( visibility . IsSharedWithResearch , Is . False , "The field decides about the research; it is no detail about the event." );
}
}
2026-11-08 19:49:46 +01:00
}