public void YarnProjectUtility_OnGeneratingLinesFile_CreatesFile()
        {
            // Arrange:
            // Set up a project with a Yarn file filled with tagged lines.
            var project  = SetUpProject(TestYarnScriptSource);
            var importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(project)) as YarnProjectImporter;

            var destinationStringsFilePath = "Assets/" + Path.GetRandomFileName() + ".csv";

            // Act:
            // Create a .CSV File, and add it to the Yarn project.
            YarnProjectUtility.WriteStringsFile(destinationStringsFilePath, importer);
            createdFilePaths.Add(destinationStringsFilePath);
            AssetDatabase.Refresh();

            var stringsAsset = AssetDatabase.LoadAssetAtPath <TextAsset>(destinationStringsFilePath);

            importer.languagesToSourceAssets.Add(new YarnProjectImporter.LanguageToSourceAsset {
                languageID = "test", stringsFile = stringsAsset
            });
            EditorUtility.SetDirty(importer);
            importer.SaveAndReimport();

            // Assert:
            // A new localization, based on the .csv file we just created,
            // should be present.
            Assert.IsNotNull(project.baseLocalization);
            Assert.IsNotEmpty(project.localizations);
            Assert.AreEqual("test", project.localizations[0].LocaleCode);
            CollectionAssert.AreEquivalent(project.localizations[0].GetLineIDs(), ExpectedStrings.Select(l => l.ID));
        }
        public void YarnImporterUtility_CanUpdateLocalizedCSVs_WhenBaseScriptChanges()
        {
            // Arrange:
            // Set up a project with a Yarn file filled with tagged lines.
            var project    = SetUpProject(TestYarnScriptSource);
            var importer   = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(project)) as YarnProjectImporter;
            var scriptPath = AssetDatabase.GetAssetPath(importer.sourceScripts[0]);

            var destinationStringsFilePath = "Assets/" + Path.GetRandomFileName() + ".csv";

            // Act:
            // Create a .CSV File, and add it to the Yarn project.
            YarnProjectUtility.WriteStringsFile(destinationStringsFilePath, importer);
            createdFilePaths.Add(destinationStringsFilePath);

            AssetDatabase.Refresh();

            var stringsAsset = AssetDatabase.LoadAssetAtPath <TextAsset>(destinationStringsFilePath);

            importer.languagesToSourceAssets.Add(new YarnProjectImporter.LanguageToSourceAsset {
                languageID = "test", stringsFile = stringsAsset
            });
            EditorUtility.SetDirty(importer);
            importer.SaveAndReimport();

            // Capture the strings tables. We'll use them later.
            var unmodifiedBaseStringsTable      = importer.GenerateStringsTable();
            var unmodifiedLocalizedStringsTable = StringTableEntry.ParseFromCSV(File.ReadAllText(destinationStringsFilePath));

            // Next, modify the original source script.
            File.WriteAllText(scriptPath, TestYarnScriptSourceModified);

            AssetDatabase.Refresh();

            // Finally, update the CSV.
            LogAssert.Expect(LogType.Log, $"Updated the following files: {destinationStringsFilePath}");
            YarnProjectUtility.UpdateLocalizationCSVs(importer);

            AssetDatabase.Refresh();

            // Doing it again should result in a no-op.
            LogAssert.Expect(LogType.Log, "No files needed updating.");
            YarnProjectUtility.UpdateLocalizationCSVs(importer);

            // Capture the updated strings tables, so we can compare them.
            var modifiedBaseStringsTable      = importer.GenerateStringsTable();
            var modifiedLocalizedStringsTable = StringTableEntry.ParseFromCSV(File.ReadAllText(destinationStringsFilePath));

            // Assert: verify the base language string table contains the
            // string table entries we expect, verify the localized string
            // table contains the string table entries we expect

            System.Func <StringTableEntry, string> CompareIDs   = t => t.ID;
            System.Func <StringTableEntry, string> CompareLocks = t => t.Lock;

            var tests = new[] {