using NUnit.Framework;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
using Unity.Tutorials.Core.Editor;
using static Unity.Tutorials.Core.Editor.RichTextParser;
namespace Unity.Tutorials.Core.Editor.Tests
{
public class RichTextParserTests
{
TutorialWindow m_Window;
string k_LoremIpsum = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. " +
"Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown" +
" printer took a galley of type and scrambled it to make a type specimen book. It has survived" +
" not only five centuries, but also the leap into electronic typesetting, remaining essentially" +
" unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem" +
" Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including" +
" versions of Lorem Ipsum.";
int m_BoldUsed;
int m_ItalicUsed;
int m_LinksUsed;
int m_NumParagraphs;
int m_StyledUsed;
string Bold(string toBold)
{
m_BoldUsed++;
return " " + toBold + " ";
}
string Italic(string toBold)
{
m_ItalicUsed++;
return " " + toBold + " ";
}
string Link(string URL, string Text)
{
m_LinksUsed++;
return " " + Text + " ";
}
string EmptyParagraph()
{
m_NumParagraphs++;
return "\n\n";
}
string Styled(string toStyled, string className)
{
m_StyledUsed++;
return " ";
}
void Reset()
{
m_BoldUsed = 0;
m_ItalicUsed = 0;
m_LinksUsed = 0;
m_NumParagraphs = 0;
}
[SetUp]
public void SetUp()
{
Reset();
m_Window = EditorWindow.GetWindow();
TutorialWindow.ShowTutorialsClosedDialog.SetValue(false);
m_Window.rootVisualElement.style.flexDirection = FlexDirection.Row;
m_Window.rootVisualElement.style.flexWrap = Wrap.Wrap;
}
[TearDown]
public void TearDown()
{
m_Window.Close();
}
[Test]
public void CanCreateWrappingTextLabels()
{
Reset();
RichTextToVisualElements(CreateRichText(50, 0, 0, 0), m_Window.rootVisualElement);
Assert.IsTrue(DoStylesMatch());
}
[Test]
[TestCase("There are five words here", "teststyle", 5)]
[TestCase("There are now six words here", "anotherteststyle", 6)]
[TestCase("There are now eleven words here and it should be enough", "anotherteststyle", 11)]
public void CanUseCustomStyleClasses(string testText, string styleClassName, int styledWords)
{
Reset();
string testRichText = Styled(testText, styleClassName) + " " + testText;
var visualElements = RichTextToVisualElements(testRichText, m_Window.rootVisualElement);
Assert.AreEqual(visualElements.FindAll(elem => elem.ClassListContains(styleClassName)).Count, styledWords);
}
[Test]
public void CanCreateRichText()
{
Reset();
RichTextToVisualElements(CreateRichText(50, 10, 10, 5), m_Window.rootVisualElement);
Assert.IsTrue(DoStylesMatch());
}
[Test]
[TestCase("asdfasdf and some non bold words. These are italic", 1, 3, 6)]
[TestCase("bold words and some non bold words. These are italic", 2, 3, 5)]
[TestCase("bold wordsand some non bold words. These are italic", 2, 3, 5)]
// [TestCase("bold wordsand some non bold words.These are italic", 2, 3, 5)] This fails. Todo: split anything from before from the italic tag
public void CanRenderRichTextPrecisely(string testRichText, int boldWords, int italicWords, int normalWords)
{
Reset();
var visualElements = RichTextToVisualElements(testRichText, m_Window.rootVisualElement);
Assert.AreEqual(visualElements.FindAll(elem => elem is BoldLabel).Count, boldWords);
Assert.AreEqual(visualElements.FindAll(elem => elem is ItalicLabel).Count, italicWords);
Assert.AreEqual(visualElements.FindAll(elem => !(elem is ItalicLabel) && !(elem is BoldLabel)).Count, normalWords);
}
[Test]
[TestCase("asdfasdf", 1, 1, "asdf")]
[TestCase("asdfasdfasdf", 1, 2, "asdf")]
public void TestForTagParsingError(string testRichText, int boldWords, int normalWords, string wordToLookFor)
{
Reset();
var visualElements = RichTextToVisualElements(testRichText, m_Window.rootVisualElement);
foreach (VisualElement elem in visualElements)
{
Label label = (Label)elem;
Assert.AreEqual(wordToLookFor, label.text);
}
Assert.AreEqual(boldWords + normalWords, visualElements.Count);
Assert.AreEqual(boldWords, visualElements.FindAll(elem => elem is BoldLabel).Count);
Assert.AreEqual(normalWords, visualElements.FindAll(elem => elem is TextLabel).Count);
}
[Test]
[TestCase(" bold wordsand some non bold words. These are italic", 2, 3, 5, 6)]
[TestCase(" Here are five normal words And the next six are italic", 0, 6, 5, 3)]
public void LeadingWhiteSpaceIsPreserved(string testRichText, int boldWords, int italicWords, int normalWords, int whiteSpaceAmount)
{
Reset();
var visualElements = RichTextToVisualElements(testRichText, m_Window.rootVisualElement);
Assert.AreEqual(boldWords, visualElements.FindAll(elem => elem is BoldLabel).Count);
Assert.AreEqual(italicWords, visualElements.FindAll(elem => elem is ItalicLabel).Count);
Assert.AreEqual(normalWords, visualElements.FindAll(elem => elem is TextLabel).Count);
WhiteSpaceLabel whitespacelabel = (WhiteSpaceLabel)visualElements.Find(elem => elem is WhiteSpaceLabel);
Assert.AreEqual(whiteSpaceAmount, whitespacelabel.text.Length);
}
[Test]
[TestCase(" bold wordsand some non bold words.These are italic \n a aaa ", 3, 3, 7, 6)]
[TestCase(" bold wordsand some non bold words.These are italic \n a aaa", 3, 3, 7, 6)]
public void TrailingWhiteSpaceIsRemoved(string testRichText, int boldWords, int italicWords, int normalWords, int whiteSpaceAmount)
{
Reset();
var visualElements = RichTextToVisualElements(testRichText, m_Window.rootVisualElement);
Assert.AreEqual(boldWords, visualElements.FindAll(elem => elem is BoldLabel).Count);
Assert.AreEqual(italicWords, visualElements.FindAll(elem => elem is ItalicLabel).Count);
Assert.AreEqual(normalWords, visualElements.FindAll(elem => elem is TextLabel).Count);
WhiteSpaceLabel whitespacelabel = (WhiteSpaceLabel)visualElements.Find(elem => elem is WhiteSpaceLabel);
Assert.AreEqual(whiteSpaceAmount, whitespacelabel.text.Length);
}
[Test]
[TestCase("&",1)]
[TestCase("& <>", 3)]
[TestCase("Test&Result", 11)]
[TestCase("Test&Result", 11)]
[TestCase("Test & Result", 11)]
public void HTMLCharacterSupport (string testRichText, int totalCharacterCount)
{
Reset();
var visualElements = RichTextToVisualElements(testRichText, m_Window.rootVisualElement);
int totalCharacters = 0;
foreach (Label label in visualElements)
{
totalCharacters += label.text.Length;
}
Assert.AreEqual(totalCharacterCount, totalCharacters);
}
[Test]
public void CanCreateParagraphsOfRichText()
{
Reset();
string richText = "";
for (int i = 0; i < 10; i++)
{
richText += CreateRichText(i * 10, i * 2, i, i) + EmptyParagraph();
}
RichTextToVisualElements(richText, m_Window.rootVisualElement);
Assert.IsTrue(DoStylesMatch());
}
bool DoStylesMatch()
{
int boldFound = CountStyles(typeof(BoldLabel));
int italicFound = CountStyles(typeof(ItalicLabel));
if (boldFound != m_BoldUsed)
{
Debug.LogError("Invalid amount of bold words. Entered: " + m_BoldUsed + " - Found: " + boldFound);
return false;
}
if (italicFound != m_ItalicUsed)
{
Debug.LogError("Invalid amount of italic words. Entered: " + m_ItalicUsed + " - Found: " + italicFound);
return false;
}
return true;
}
int CountWordLabels()
{
return m_Window.rootVisualElement.childCount;
}
int CountStyles(System.Type styleType)
{
var root = m_Window.rootVisualElement;
int styledWords = 0;
for (int i = 0; i < root.childCount; i++)
{
VisualElement element = root.ElementAt(i);
if (element.GetType() == styleType)
{
styledWords++;
}
}
return styledWords;
}
string CreateRichText(int normalWords, int boldedWords, int italicWords, int links)
{
string richText = "";
int wordNumber = 0;
string[] loremIpsums = k_LoremIpsum.Split(' ');
while (normalWords > 0 || boldedWords > 0 || italicWords > 0 || links > 0)
{
if (normalWords > 0)
{
richText += loremIpsums[wordNumber] + " ";
normalWords--;
wordNumber = (wordNumber + 1) % loremIpsums.Length;
}
if (boldedWords > 0)
{
richText += Bold(loremIpsums[wordNumber]);
boldedWords--;
wordNumber = (wordNumber + 1) % loremIpsums.Length;
}
if (italicWords > 0)
{
richText += Italic(loremIpsums[wordNumber]);
italicWords--;
wordNumber = (wordNumber + 1) % loremIpsums.Length;
}
if (links > 0)
{
richText += Link("http://www.google.fi", loremIpsums[wordNumber]);
links--;
wordNumber = (wordNumber + 1) % loremIpsums.Length;
}
}
return richText;
}
}
}