Centralize legacy document session bridge

This commit is contained in:
2026-06-04 13:30:22 +02:00
parent d980b81bd7
commit 4528edfb2c
10 changed files with 437 additions and 64 deletions

View File

@@ -43,6 +43,70 @@ public:
std::string call_order;
};
class FakeCloseRequestServices final : public pp::app::CloseRequestServices {
public:
void request_close_now() override
{
close_now += 1;
call_order += "close;";
}
void show_unsaved_close_prompt() override
{
close_prompts += 1;
call_order += "prompt;";
}
int close_now = 0;
int close_prompts = 0;
std::string call_order;
};
class FakeDocumentSaveServices final : public pp::app::DocumentSaveServices {
public:
void show_save_dialog() override
{
dialogs += 1;
call_order += "dialog;";
}
void save_existing_document() override
{
saves += 1;
call_order += "save;";
}
void save_document_version() override
{
versions += 1;
call_order += "version;";
}
int dialogs = 0;
int saves = 0;
int versions = 0;
std::string call_order;
};
class FakeDocumentWorkflowServices final : public pp::app::DocumentWorkflowServices {
public:
void continue_workflow_now() override
{
continues += 1;
call_order += "continue;";
}
void prompt_save_before_continue() override
{
prompts += 1;
call_order += "prompt-save;";
}
int continues = 0;
int prompts = 0;
std::string call_order;
};
[[nodiscard]] pp::app::DocumentOpenRoute project_route()
{
return {
@@ -212,6 +276,25 @@ void close_dirty_document_opens_one_prompt(pp::tests::Harness& harness)
pp::app::plan_close_request(true, true) == pp::app::CloseRequestDecision::wait_for_existing_prompt);
}
void close_request_executor_dispatches_and_preserves_wait(pp::tests::Harness& harness)
{
FakeCloseRequestServices services;
PP_EXPECT(
harness,
pp::app::execute_close_request_decision(pp::app::CloseRequestDecision::close_now, services).ok());
PP_EXPECT(
harness,
pp::app::execute_close_request_decision(pp::app::CloseRequestDecision::show_unsaved_prompt, services).ok());
PP_EXPECT(
harness,
pp::app::execute_close_request_decision(pp::app::CloseRequestDecision::wait_for_existing_prompt, services).ok());
PP_EXPECT(harness, services.close_now == 1);
PP_EXPECT(harness, services.close_prompts == 1);
PP_EXPECT(harness, services.call_order == "close;prompt;");
}
void save_clean_existing_document_is_no_op(pp::tests::Harness& harness)
{
PP_EXPECT(
@@ -220,6 +303,29 @@ void save_clean_existing_document_is_no_op(pp::tests::Harness& harness)
== pp::app::DocumentSaveDecision::no_op);
}
void save_executor_dispatches_visible_work_and_no_ops_cleanly(pp::tests::Harness& harness)
{
FakeDocumentSaveServices services;
PP_EXPECT(
harness,
pp::app::execute_document_save_decision(pp::app::DocumentSaveDecision::show_save_dialog, services).ok());
PP_EXPECT(
harness,
pp::app::execute_document_save_decision(pp::app::DocumentSaveDecision::save_existing, services).ok());
PP_EXPECT(
harness,
pp::app::execute_document_save_decision(pp::app::DocumentSaveDecision::save_version, services).ok());
PP_EXPECT(
harness,
pp::app::execute_document_save_decision(pp::app::DocumentSaveDecision::no_op, services).ok());
PP_EXPECT(harness, services.dialogs == 1);
PP_EXPECT(harness, services.saves == 1);
PP_EXPECT(harness, services.versions == 1);
PP_EXPECT(harness, services.call_order == "dialog;save;version;");
}
void save_new_or_dirty_document_has_user_visible_work(pp::tests::Harness& harness)
{
PP_EXPECT(
@@ -292,6 +398,34 @@ void workflow_with_dirty_canvas_prompts_for_save(pp::tests::Harness& harness)
== pp::app::DocumentWorkflowDecision::prompt_save_before_continue);
}
void workflow_executor_dispatches_continue_prompt_and_unavailable(pp::tests::Harness& harness)
{
FakeDocumentWorkflowServices services;
PP_EXPECT(
harness,
pp::app::execute_document_workflow_decision(
pp::app::DocumentWorkflowDecision::continue_now,
services)
.ok());
PP_EXPECT(
harness,
pp::app::execute_document_workflow_decision(
pp::app::DocumentWorkflowDecision::prompt_save_before_continue,
services)
.ok());
PP_EXPECT(
harness,
pp::app::execute_document_workflow_decision(
pp::app::DocumentWorkflowDecision::unavailable,
services)
.ok());
PP_EXPECT(harness, services.continues == 1);
PP_EXPECT(harness, services.prompts == 1);
PP_EXPECT(harness, services.call_order == "continue;prompt-save;");
}
void document_file_target_rejects_empty_name(pp::tests::Harness& harness)
{
const auto target = pp::app::make_document_file_target("D:/Paint", "");
@@ -484,13 +618,16 @@ int main()
harness.run("document open executor rejects mismatched routes", document_open_executor_rejects_mismatched_routes);
harness.run("close clean document executes immediately", close_clean_document_executes_immediately);
harness.run("close dirty document opens one prompt", close_dirty_document_opens_one_prompt);
harness.run("close request executor dispatches and preserves wait", close_request_executor_dispatches_and_preserves_wait);
harness.run("save clean existing document is no op", save_clean_existing_document_is_no_op);
harness.run("save executor dispatches visible work and no ops cleanly", save_executor_dispatches_visible_work_and_no_ops_cleanly);
harness.run("save new or dirty document has user visible work", save_new_or_dirty_document_has_user_visible_work);
harness.run("save as always shows save dialog", save_as_always_shows_save_dialog);
harness.run("save version respects menu and hotkey behaviors", save_version_respects_menu_and_hotkey_behaviors);
harness.run("workflow without canvas is unavailable", workflow_without_canvas_is_unavailable);
harness.run("workflow with clean canvas continues now", workflow_with_clean_canvas_continues_now);
harness.run("workflow with dirty canvas prompts for save", workflow_with_dirty_canvas_prompts_for_save);
harness.run("workflow executor dispatches continue prompt and unavailable", workflow_executor_dispatches_continue_prompt_and_unavailable);
harness.run("document file target rejects empty name", document_file_target_rejects_empty_name);
harness.run("document file target builds legacy ppi path", document_file_target_builds_legacy_ppi_path);
harness.run("document file write prompts only for existing targets", document_file_write_prompts_only_for_existing_targets);