public void TestTopParentSerialization(string appName, string topParentName)
        {
            var root = Path.Combine(Environment.CurrentDirectory, "Apps", appName);

            Assert.IsTrue(File.Exists(root));

            (var msapp, var errors) = CanvasDocument.LoadFromMsapp(root);
            errors.ThrowOnErrors();

            using (var tempDir = new TempDir())
            {
                string outSrcDir = tempDir.Dir;

                // Save to sources
                msapp.SaveToSources(outSrcDir);

                // Go find the source file for the editor state
                string filename     = $"{topParentName}{EditorStateFileExtension}";
                string fullFilePath = Path.Combine(outSrcDir, "Src", "EditorState", filename);
                if (File.Exists(fullFilePath))
                {
                    // Get the file for the specific control we're looking for
                    DirectoryReader.Entry file        = new DirectoryReader.Entry(fullFilePath);
                    ControlTreeState      editorState = file.ToObject <ControlTreeState>();

                    // Check that the IsTopParent was set correctly
                    Assert.AreEqual(topParentName, editorState.TopParentName);
                }
                else
                {
                    Assert.Fail($"Could not find expected file {fullFilePath}.");
                }
            }
        }
        public void TestTopParentNameFallback(string appName, string topParentName)
        {
            var root = Path.Combine(Environment.CurrentDirectory, "Apps", appName);

            Assert.IsTrue(File.Exists(root));

            (var msapp, var errors) = CanvasDocument.LoadFromMsapp(root);
            errors.ThrowOnErrors();

            using (var tempDir = new TempDir())
            {
                string outSrcDir = tempDir.Dir;

                // Save to sources
                msapp.SaveToSources(outSrcDir);

                // Go find the source file for the editor state
                string filename     = $"{topParentName}.editorstate.json";
                string fullFilePath = Path.Combine(outSrcDir, "Src", "EditorState", filename);
                if (File.Exists(fullFilePath))
                {
                    // Get the file for the specific control we're looking for
                    DirectoryReader.Entry file        = new DirectoryReader.Entry(fullFilePath);
                    ControlTreeState      editorState = file.ToObject <ControlTreeState>();

                    // Rename the file so we know that the file name itself is used.
                    string newFileName = Guid.NewGuid().ToString();
                    string newFilePath = Path.Combine(outSrcDir, "Src", "EditorState");

                    // Write out only the dictionary to the file, which is the older format.
                    DirectoryWriter dir = new DirectoryWriter(newFilePath);
                    dir.WriteAllJson(newFilePath, $"{newFileName}{EditorStateFileExtension}", editorState.ControlStates);

                    // Remove the old file, we only want the re-written and re-named file
                    File.Delete(fullFilePath);

                    // Load app from the source folder
                    var app = SourceSerializer.LoadFromSource(outSrcDir, new ErrorContainer());

                    // Find the relevant controls and check their top parent name
                    foreach (var control in editorState.ControlStates)
                    {
                        app._editorStateStore.TryGetControlState(control.Value.Name, out ControlState state);
                        Assert.AreEqual(newFileName, state.TopParentName);
                    }
                }
                else
                {
                    Assert.Fail($"Could not find expected file {fullFilePath}.");
                }
            }
        }