namespace XFESystem.Browser.Tests;
public sealed class MonacoInitializationTests
{
[Theory]
[InlineData("Code.cs", "csharp")]
[InlineData("Script.js", "javascript")]
[InlineData("Notes.txt", "plaintext")]
public void FileCreatesExactlyOneModelWithFinalTextAndLanguageBeforeEditing(string path, string language)
{
const string source = "// 中文 </script><script>globalThis.injected=true</script>\nconst text = '\\\"&';";
var browser = new BrowserService();
try
{
browser.ResizeViewport(796, 404);
browser.NavigateEditor(source, path);
Assert.Equal(source, browser.ReadEditorText());
Assert.Equal(language, browser.ExecuteJavaScript("xfeMonacoEditor.getModel().getLanguageId()"));
Assert.Equal("1,1,undefined,undefined,undefined,true", browser.ExecuteJavaScript("[monaco.editor.getModels().length,xfeMonacoEditor.getModel().getVersionId(),typeof __xfeMonacoInitialSource,typeof __xfeMonacoInitialLanguage,typeof injected,xfeMonacoEditor.hasTextFocus()].join(',')"));
browser.ExecuteJavaScript("xfeMonacoSetLanguage('javascript')");
Assert.Equal(source, browser.ReadEditorText());
browser.Key(new("keydown", "x", "KeyX", "x")); browser.Key(new("keyup", "x", "KeyX"));
Assert.Equal("x" + source, browser.ReadEditorText());
browser.Navigate("about:Monaco");
Assert.Equal("undefined", browser.ExecuteJavaScript("typeof xfeMonacoFileMode"));
Assert.Contains("const answer", browser.ReadEditorText());
}
finally { browser.Release(); }
}
[Fact]
public void DirectCSharpNavigationUsesItsRealSampleAndWebsiteTokensAtInitialCreation()
{
var browser = new BrowserService();
try
{
browser.ResizeViewport(796, 404);
browser.Navigate(PackagedBrowserResources.MonacoPageAddress + "?language=csharp");
for (int time = 20; time <= 160; time += 20) browser.AdvanceTime(time);
Assert.Contains("namespace XFEstudio", browser.ReadEditorText());
Assert.Equal("csharp,1,1", browser.ExecuteJavaScript("[xfeMonacoEditor.getModel().getLanguageId(),monaco.editor.getModels().length,xfeMonacoEditor.getModel().getVersionId()].join(',')"));
Assert.Contains("ActualMonacoWebsiteCSharpDomReadback", browser.ReadMonacoProof());
Assert.DoesNotContain("Monaco failed:", browser.CurrentPage.Text);
Assert.True(browser.Document!.QuerySelectorAll(".view-lines .view-line span[class]").Length > 20);
}
finally { browser.Release(); }
}
[Fact]
public void LongCSharpModelReusesOneVersionAcrossAllLinesAndRetokenizesAfterEditing()
{
string source = "using System;\nclass Example {\n" + string.Concat(Enumerable.Range(0, 256).Select(i => $" public int Value{i} => 42;\n")) + "}";
var browser = new BrowserService();
try
{
browser.ResizeViewport(796, 404); browser.NavigateEditor(source, "Long.cs");
string result = browser.ExecuteJavaScript("""
(function(){
const model=xfeMonacoEditor.getModel(), source=model.getValue();
const original=model.getValue, highlight=hljs.highlight;
let reads=0, highlights=0;
model.getValue=function(){reads++;return original.apply(this,arguments);};
hljs.highlight=function(){highlights++;return highlight.apply(this,arguments);};
try {
const lines=monaco.editor.tokenize(source,'csharp');
if(lines.length!==259 || reads>1 || highlights>1)throw new Error('Repeated full-model work '+[lines.length,reads,highlights]);
const changed=source+'\n// changed';
model.setValue(changed);reads=0;highlights=0;
const updated=monaco.editor.tokenize(changed,'csharp');
if(updated.length!==260 || reads>1 || highlights>1)throw new Error('Repeated changed-model work '+[updated.length,reads,highlights]);
const proof=xfeWebsiteHighlight.getProof(xfeMonacoEditor);
if(proof.ModelValue!==changed || proof.TokenLines.length!==260 || highlights>1)throw new Error('Stale model or repeated proof highlighting');
const fresh=xfeWebsiteHighlight.tokenizeSource(changed);
if(JSON.stringify(fresh.lines)!==JSON.stringify(proof.TokenLines))throw new Error('Grammar/context changed');
return 'PASS';
} finally {model.getValue=original;hljs.highlight=highlight;}
})()
""");
Assert.Equal("PASS", result);
Assert.EndsWith("// changed", browser.ReadEditorText());
}
finally { browser.Release(); }
}
}
namespace XFESystem.Browser.Tests;
public sealed class MonacoInitializationTests
{
[Theory]
[InlineData("Code.cs", "csharp")]
[InlineData("Script.js", "javascript")]
[InlineData("Notes.txt", "plaintext")]
public void FileCreatesExactlyOneModelWithFinalTextAndLanguageBeforeEditing(string path, string language)
{
const string source = "// 中文 </script><script>globalThis.injected=true</script>\nconst text = '\\\"&';";
var browser = new BrowserService();
try
{
browser.ResizeViewport(796, 404);
browser.NavigateEditor(source, path);
Assert.Equal(source, browser.ReadEditorText());
Assert.Equal(language, browser.ExecuteJavaScript("xfeMonacoEditor.getModel().getLanguageId()"));
Assert.Equal("1,1,undefined,undefined,undefined,true", browser.ExecuteJavaScript("[monaco.editor.getModels().length,xfeMonacoEditor.getModel().getVersionId(),typeof __xfeMonacoInitialSource,typeof __xfeMonacoInitialLanguage,typeof injected,xfeMonacoEditor.hasTextFocus()].join(',')"));
browser.ExecuteJavaScript("xfeMonacoSetLanguage('javascript')");
Assert.Equal(source, browser.ReadEditorText());
browser.Key(new("keydown", "x", "KeyX", "x")); browser.Key(new("keyup", "x", "KeyX"));
Assert.Equal("x" + source, browser.ReadEditorText());
browser.Navigate("about:Monaco");
Assert.Equal("undefined", browser.ExecuteJavaScript("typeof xfeMonacoFileMode"));
Assert.Contains("const answer", browser.ReadEditorText());
}
finally { browser.Release(); }
}
[Fact]
public void DirectCSharpNavigationUsesItsRealSampleAndWebsiteTokensAtInitialCreation()
{
var browser = new BrowserService();
try
{
browser.ResizeViewport(796, 404);
browser.Navigate(PackagedBrowserResources.MonacoPageAddress + "?language=csharp");
for (int time = 20; time <= 160; time += 20) browser.AdvanceTime(time);
Assert.Contains("namespace XFEstudio", browser.ReadEditorText());
Assert.Equal("csharp,1,1", browser.ExecuteJavaScript("[xfeMonacoEditor.getModel().getLanguageId(),monaco.editor.getModels().length,xfeMonacoEditor.getModel().getVersionId()].join(',')"));
Assert.Contains("ActualMonacoWebsiteCSharpDomReadback", browser.ReadMonacoProof());
Assert.DoesNotContain("Monaco failed:", browser.CurrentPage.Text);
Assert.True(browser.Document!.QuerySelectorAll(".view-lines .view-line span[class]").Length > 20);
}
finally { browser.Release(); }
}
[Fact]
public void LongCSharpModelReusesOneVersionAcrossAllLinesAndRetokenizesAfterEditing()
{
string source = "using System;\nclass Example {\n" + string.Concat(Enumerable.Range(0, 256).Select(i => $" public int Value{i} => 42;\n")) + "}";
var browser = new BrowserService();
try
{
browser.ResizeViewport(796, 404); browser.NavigateEditor(source, "Long.cs");
string result = browser.ExecuteJavaScript("""
(function(){
const model=xfeMonacoEditor.getModel(), source=model.getValue();
const original=model.getValue, highlight=hljs.highlight;
let reads=0, highlights=0;
model.getValue=function(){reads++;return original.apply(this,arguments);};
hljs.highlight=function(){highlights++;return highlight.apply(this,arguments);};
try {
const lines=monaco.editor.tokenize(source,'csharp');
if(lines.length!==259 || reads>1 || highlights>1)throw new Error('Repeated full-model work '+[lines.length,reads,highlights]);
const changed=source+'\n// changed';
model.setValue(changed);reads=0;highlights=0;
const updated=monaco.editor.tokenize(changed,'csharp');
if(updated.length!==260 || reads>1 || highlights>1)throw new Error('Repeated changed-model work '+[updated.length,reads,highlights]);
const proof=xfeWebsiteHighlight.getProof(xfeMonacoEditor);
if(proof.ModelValue!==changed || proof.TokenLines.length!==260 || highlights>1)throw new Error('Stale model or repeated proof highlighting');
const fresh=xfeWebsiteHighlight.tokenizeSource(changed);
if(JSON.stringify(fresh.lines)!==JSON.stringify(proof.TokenLines))throw new Error('Grammar/context changed');
return 'PASS';
} finally {model.getValue=original;hljs.highlight=highlight;}
})()
""");
Assert.Equal("PASS", result);
Assert.EndsWith("// changed", browser.ReadEditorText());
}
finally { browser.Release(); }
}
}