using Sandbox.UI;
namespace UITests.Controls;
[TestClass]
[DoNotParallelize] // Modifies UI System Global
public class LabelTextTest
{
bool previousRenderText;
///
/// Label layout finalization rebuilds the text texture (TextBlock.RebuildTexture), which needs
/// the native render system that this tier never boots. Turn the convar off for the duration of
/// each test - text measurement is pure RichTextKit (CPU) and is unaffected.
///
[TestInitialize]
public void DisableTextTextures()
{
previousRenderText = TextBlock.ui_rendertext;
TextBlock.ui_rendertext = false;
}
///
/// Restores the text texture convar so this class doesn't leak state into other tests.
///
[TestCleanup]
public void RestoreTextTextures()
{
TextBlock.ui_rendertext = previousRenderText;
}
///
/// Creates a root sized 1000x1000 whose children are content-sized in both axes - the default
/// align-items: stretch would otherwise stretch label boxes to fill the cross axis.
///
static RootPanel CreateRoot()
{
var root = new RootPanel();
root.PanelBounds = new Rect( 0, 0, 1000, 1000 );
root.Style.Set( "flex-direction: row; align-items: flex-start;" );
return root;
}
///
/// Text starts null, round-trips through the setter, and assigning null is coalesced to an
/// empty string rather than stored as null. The constructor also adds the "label" class.
///
[TestMethod]
public void TextGetSetRoundTrip()
{
var label = new Label();
Assert.IsTrue( label.Class.Contains( "label" ) );
Assert.IsNull( label.Text );
label.Text = "Hello";
Assert.AreEqual( "Hello", label.Text );
label.Text = null;
Assert.AreEqual( "", label.Text );
}
///
/// The text+classname constructor sets the text and adds the extra class on top of the
/// built-in "label" class.
///
[TestMethod]
public void ConstructorSetsTextAndClass()
{
var label = new Label( "Hi", "greeting" );
Assert.AreEqual( "Hi", label.Text );
Assert.IsTrue( label.Class.Contains( "label" ) );
Assert.IsTrue( label.Class.Contains( "greeting" ) );
}
///
/// SetContent (markup inner text) and SetProperty( "text", ... ) (markup attribute) are both
/// equivalent to assigning the Text property directly.
///
[TestMethod]
public void SetContentAndSetPropertyMatchTextProperty()
{
var viaProperty = new Label();
viaProperty.Text = "Hello";
var viaContent = new Label();
viaContent.SetContent( "Hello" );
var viaSetProperty = new Label();
viaSetProperty.SetProperty( "text", "Hello" );
Assert.AreEqual( viaProperty.Text, viaContent.Text );
Assert.AreEqual( viaProperty.Text, viaSetProperty.Text );
}
///
/// With Tokenize disabled, text starting with '#' is stored verbatim instead of being run
/// through the language phrase lookup.
///
[TestMethod]
public void TokenizeDisabledKeepsHashPrefixedText()
{
var label = new Label { Tokenize = false, Text = "#some.token" };
Assert.AreEqual( "#some.token", label.Text );
}
///
/// TextLength counts text elements (graphemes), not chars - a surrogate-pair emoji is one
/// element even though it is two chars.
///
[TestMethod]
public void TextLengthCountsGraphemes()
{
var label = new Label();
label.Text = "a\U0001F44Db";
Assert.AreEqual( 4, label.Text.Length );
Assert.AreEqual( 3, label.TextLength );
}
///
/// A label with text and a fixed font size measures to a non-zero, content-sized box after
/// layout - the measure function runs through RichTextKit on the CPU.
///
[TestMethod]
public void MeasuredBoxIsNonZeroAfterLayout()
{
var root = CreateRoot();
var label = root.AddChild