워크스페이스 브라우저 상태 복원 경로를 추가하고 설정 및 검증을 정리한다
변경 목적: ~ 워크스페이스 복원 시 창 배치뿐 아니라 브라우저 탭/URL 상태까지 가능한 범위에서 함께 재현하도록 저장/복원 경로를 확장한다. 핵심 수정사항: BrowserWorkspaceStateHelper를 추가해 Chromium/Firefox 계열 창의 프로필 인자, 탭 URL, 활성 탭 인덱스를 수집하고, ContextManager가 브라우저 상태가 저장된 창은 부분 제목 매칭으로 기존 창을 재사용하지 않고 새 브라우저 창을 띄워 동일한 URL 세트를 복원한 뒤 위치와 활성 탭을 맞추도록 변경했다. Launcher 설정에 브라우저 상태 복원 토글을 추가하고 SettingsViewModel 및 설정 UI와 연결했으며, ContextManagerTests와 SettingsServiceTests를 확장했다. README와 DEVELOPMENT 문서에도 2026-04-15 17:26 (KST) 기준 작업 이력과 검증 명령을 반영했다. 검증 결과: dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\verify_browser_restore\ -p:IntermediateOutputPath=obj\verify_browser_restore\ 에서 경고 0/오류 0을 확인했고, dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj -c Release -v minimal --filter WorkspaceHandlerTests|ContextManagerTests|SettingsServiceTests -p:OutputPath=bin\verify_browser_restore_workspace_tests\ -p:IntermediateOutputPath=obj\verify_browser_restore_workspace_tests\ 에서 44개 테스트 통과를 확인했다.
This commit is contained in:
@@ -62,4 +62,96 @@ public class ContextManagerTests
|
||||
|
||||
selected.Should().Be(IntPtr.Zero);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BrowserLaunchPlan_CreatesChromiumWindowWithProfileAndTabs()
|
||||
{
|
||||
var state = new BrowserWindowState
|
||||
{
|
||||
Kind = "edge",
|
||||
UserDataDir = @"C:\Users\tester\AppData\Local\Microsoft\Edge\User Data",
|
||||
ProfileDirectory = "Profile 2",
|
||||
TabUrls = ["https://example.com", "edge://settings/profiles"]
|
||||
};
|
||||
|
||||
var plan = BrowserWorkspaceStateHelper.CreateLaunchPlan(
|
||||
@"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe",
|
||||
state);
|
||||
|
||||
plan.Should().NotBeNull();
|
||||
plan!.Arguments.Should().ContainInOrder(
|
||||
"--new-window",
|
||||
"--user-data-dir=C:\\Users\\tester\\AppData\\Local\\Microsoft\\Edge\\User Data",
|
||||
"--profile-directory=Profile 2",
|
||||
"https://example.com",
|
||||
"edge://settings/profiles");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BrowserLaunchPlan_CreatesFirefoxWindowWithTabs()
|
||||
{
|
||||
var state = new BrowserWindowState
|
||||
{
|
||||
Kind = "firefox",
|
||||
ProfileDirectory = "work-profile",
|
||||
TabUrls = ["https://www.mozilla.org", "about:newtab"]
|
||||
};
|
||||
|
||||
var plan = BrowserWorkspaceStateHelper.CreateLaunchPlan(
|
||||
@"C:\Program Files\Mozilla Firefox\firefox.exe",
|
||||
state);
|
||||
|
||||
plan.Should().NotBeNull();
|
||||
plan!.Arguments.Should().ContainInOrder(
|
||||
"-P",
|
||||
"work-profile",
|
||||
"-new-window",
|
||||
"https://www.mozilla.org",
|
||||
"-new-tab",
|
||||
"about:newtab");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShouldLaunchNewWindow_WithBrowserStateAndPartialTitleMatch_ReturnsTrue()
|
||||
{
|
||||
var snapshot = new WindowSnapshot
|
||||
{
|
||||
Exe = @"C:\Program Files\Google\Chrome\Application\chrome.exe",
|
||||
Title = "Inbox - Google Chrome",
|
||||
Browser = new BrowserWindowState
|
||||
{
|
||||
Kind = "chrome",
|
||||
TabUrls = ["https://mail.google.com"]
|
||||
}
|
||||
};
|
||||
|
||||
var candidate = new ContextManager.WindowCandidate(
|
||||
new IntPtr(5),
|
||||
snapshot.Exe,
|
||||
"Docs - Google Chrome");
|
||||
|
||||
BrowserWorkspaceStateHelper.ShouldLaunchNewWindow(snapshot, candidate).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShouldLaunchNewWindow_WithBrowserStateAndExactTitleMatch_ReturnsFalse()
|
||||
{
|
||||
var snapshot = new WindowSnapshot
|
||||
{
|
||||
Exe = @"C:\Program Files\Google\Chrome\Application\chrome.exe",
|
||||
Title = "Inbox - Google Chrome",
|
||||
Browser = new BrowserWindowState
|
||||
{
|
||||
Kind = "chrome",
|
||||
TabUrls = ["https://mail.google.com"]
|
||||
}
|
||||
};
|
||||
|
||||
var candidate = new ContextManager.WindowCandidate(
|
||||
new IntPtr(5),
|
||||
snapshot.Exe,
|
||||
"Inbox - Google Chrome");
|
||||
|
||||
BrowserWorkspaceStateHelper.ShouldLaunchNewWindow(snapshot, candidate).Should().BeFalse();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,12 @@ public class SettingsServiceTests
|
||||
opacity.Should().BeInRange(0.0, 1.0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LauncherSettings_DefaultBrowserSessionRestore_IsEnabled()
|
||||
{
|
||||
new LauncherSettings().EnableBrowserSessionRestore.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AppSettings_DefaultMonitorMismatch_IsWarn()
|
||||
{
|
||||
@@ -200,6 +206,44 @@ public class SettingsServiceTests
|
||||
restored.Windows[0].Monitor.Should().Be(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WorkspaceProfile_Serialization_PreservesBrowserState()
|
||||
{
|
||||
var profile = new WorkspaceProfile
|
||||
{
|
||||
Name = "브라우저 프로필",
|
||||
Windows =
|
||||
[
|
||||
new()
|
||||
{
|
||||
Exe = "msedge.exe",
|
||||
Title = "업무 포털 - Microsoft Edge",
|
||||
Browser = new BrowserWindowState
|
||||
{
|
||||
Kind = "edge",
|
||||
UserDataDir = @"C:\Users\tester\AppData\Local\Microsoft\Edge\User Data",
|
||||
ProfileDirectory = "Profile 3",
|
||||
ActiveUrl = "https://portal.example.com",
|
||||
ActiveTabIndex = 1,
|
||||
TabUrls = ["https://mail.example.com", "https://portal.example.com"]
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
var json = JsonSerializer.Serialize(profile, JsonOptions);
|
||||
var restored = JsonSerializer.Deserialize<WorkspaceProfile>(json, JsonOptions)!;
|
||||
|
||||
restored.Windows.Should().HaveCount(1);
|
||||
restored.Windows[0].Browser.Should().NotBeNull();
|
||||
restored.Windows[0].Browser!.Kind.Should().Be("edge");
|
||||
restored.Windows[0].Browser!.ProfileDirectory.Should().Be("Profile 3");
|
||||
restored.Windows[0].Browser!.ActiveTabIndex.Should().Be(1);
|
||||
restored.Windows[0].Browser!.TabUrls.Should().ContainInOrder(
|
||||
"https://mail.example.com",
|
||||
"https://portal.example.com");
|
||||
}
|
||||
|
||||
// ─── ClipboardTransformer ────────────────────────────────────────────────
|
||||
|
||||
[Fact]
|
||||
|
||||
Reference in New Issue
Block a user