339 lines
14 KiB
C++
339 lines
14 KiB
C++
#include "app_core/document_session.h"
|
|
#include "test_harness.h"
|
|
|
|
namespace {
|
|
|
|
void project_open_clean_document_executes_immediately(pp::tests::Harness& harness)
|
|
{
|
|
PP_EXPECT(harness, pp::app::plan_project_open(false) == pp::app::ProjectOpenDecision::open_now);
|
|
}
|
|
|
|
void project_open_dirty_document_prompts_for_discard(pp::tests::Harness& harness)
|
|
{
|
|
PP_EXPECT(
|
|
harness,
|
|
pp::app::plan_project_open(true) == pp::app::ProjectOpenDecision::prompt_discard_unsaved);
|
|
}
|
|
|
|
void document_open_project_respects_unsaved_state(pp::tests::Harness& harness)
|
|
{
|
|
PP_EXPECT(
|
|
harness,
|
|
pp::app::plan_document_open(pp::app::DocumentOpenKind::open_project, false)
|
|
== pp::app::DocumentOpenPlanAction::open_project_now);
|
|
PP_EXPECT(
|
|
harness,
|
|
pp::app::plan_document_open(pp::app::DocumentOpenKind::open_project, true)
|
|
== pp::app::DocumentOpenPlanAction::prompt_discard_unsaved_project);
|
|
}
|
|
|
|
void document_open_brush_imports_prompt_regardless_of_unsaved_state(pp::tests::Harness& harness)
|
|
{
|
|
PP_EXPECT(
|
|
harness,
|
|
pp::app::plan_document_open(pp::app::DocumentOpenKind::import_abr, false)
|
|
== pp::app::DocumentOpenPlanAction::prompt_import_abr);
|
|
PP_EXPECT(
|
|
harness,
|
|
pp::app::plan_document_open(pp::app::DocumentOpenKind::import_abr, true)
|
|
== pp::app::DocumentOpenPlanAction::prompt_import_abr);
|
|
PP_EXPECT(
|
|
harness,
|
|
pp::app::plan_document_open(pp::app::DocumentOpenKind::import_ppbr, false)
|
|
== pp::app::DocumentOpenPlanAction::prompt_import_ppbr);
|
|
PP_EXPECT(
|
|
harness,
|
|
pp::app::plan_document_open(pp::app::DocumentOpenKind::import_ppbr, true)
|
|
== pp::app::DocumentOpenPlanAction::prompt_import_ppbr);
|
|
}
|
|
|
|
void close_clean_document_executes_immediately(pp::tests::Harness& harness)
|
|
{
|
|
PP_EXPECT(
|
|
harness,
|
|
pp::app::plan_close_request(false, false) == pp::app::CloseRequestDecision::close_now);
|
|
PP_EXPECT(
|
|
harness,
|
|
pp::app::plan_close_request(false, true) == pp::app::CloseRequestDecision::close_now);
|
|
}
|
|
|
|
void close_dirty_document_opens_one_prompt(pp::tests::Harness& harness)
|
|
{
|
|
PP_EXPECT(
|
|
harness,
|
|
pp::app::plan_close_request(true, false) == pp::app::CloseRequestDecision::show_unsaved_prompt);
|
|
PP_EXPECT(
|
|
harness,
|
|
pp::app::plan_close_request(true, true) == pp::app::CloseRequestDecision::wait_for_existing_prompt);
|
|
}
|
|
|
|
void save_clean_existing_document_is_no_op(pp::tests::Harness& harness)
|
|
{
|
|
PP_EXPECT(
|
|
harness,
|
|
pp::app::plan_document_save(false, false, pp::app::DocumentSaveIntent::save)
|
|
== pp::app::DocumentSaveDecision::no_op);
|
|
}
|
|
|
|
void save_new_or_dirty_document_has_user_visible_work(pp::tests::Harness& harness)
|
|
{
|
|
PP_EXPECT(
|
|
harness,
|
|
pp::app::plan_document_save(true, false, pp::app::DocumentSaveIntent::save)
|
|
== pp::app::DocumentSaveDecision::show_save_dialog);
|
|
PP_EXPECT(
|
|
harness,
|
|
pp::app::plan_document_save(false, true, pp::app::DocumentSaveIntent::save)
|
|
== pp::app::DocumentSaveDecision::save_existing);
|
|
}
|
|
|
|
void save_as_always_shows_save_dialog(pp::tests::Harness& harness)
|
|
{
|
|
PP_EXPECT(
|
|
harness,
|
|
pp::app::plan_document_save(false, false, pp::app::DocumentSaveIntent::save_as)
|
|
== pp::app::DocumentSaveDecision::show_save_dialog);
|
|
PP_EXPECT(
|
|
harness,
|
|
pp::app::plan_document_save(false, true, pp::app::DocumentSaveIntent::save_as)
|
|
== pp::app::DocumentSaveDecision::show_save_dialog);
|
|
}
|
|
|
|
void save_version_respects_menu_and_hotkey_behaviors(pp::tests::Harness& harness)
|
|
{
|
|
PP_EXPECT(
|
|
harness,
|
|
pp::app::plan_document_save(false, false, pp::app::DocumentSaveIntent::save_version)
|
|
== pp::app::DocumentSaveDecision::save_version);
|
|
PP_EXPECT(
|
|
harness,
|
|
pp::app::plan_document_save(false, false, pp::app::DocumentSaveIntent::save_dirty_version)
|
|
== pp::app::DocumentSaveDecision::no_op);
|
|
PP_EXPECT(
|
|
harness,
|
|
pp::app::plan_document_save(false, true, pp::app::DocumentSaveIntent::save_dirty_version)
|
|
== pp::app::DocumentSaveDecision::save_version);
|
|
PP_EXPECT(
|
|
harness,
|
|
pp::app::plan_document_save(true, false, pp::app::DocumentSaveIntent::save_version)
|
|
== pp::app::DocumentSaveDecision::show_save_dialog);
|
|
}
|
|
|
|
void workflow_without_canvas_is_unavailable(pp::tests::Harness& harness)
|
|
{
|
|
PP_EXPECT(
|
|
harness,
|
|
pp::app::plan_document_workflow(false, false)
|
|
== pp::app::DocumentWorkflowDecision::unavailable);
|
|
PP_EXPECT(
|
|
harness,
|
|
pp::app::plan_document_workflow(false, true)
|
|
== pp::app::DocumentWorkflowDecision::unavailable);
|
|
}
|
|
|
|
void workflow_with_clean_canvas_continues_now(pp::tests::Harness& harness)
|
|
{
|
|
PP_EXPECT(
|
|
harness,
|
|
pp::app::plan_document_workflow(true, false)
|
|
== pp::app::DocumentWorkflowDecision::continue_now);
|
|
}
|
|
|
|
void workflow_with_dirty_canvas_prompts_for_save(pp::tests::Harness& harness)
|
|
{
|
|
PP_EXPECT(
|
|
harness,
|
|
pp::app::plan_document_workflow(true, true)
|
|
== pp::app::DocumentWorkflowDecision::prompt_save_before_continue);
|
|
}
|
|
|
|
void document_file_target_rejects_empty_name(pp::tests::Harness& harness)
|
|
{
|
|
const auto target = pp::app::make_document_file_target("D:/Paint", "");
|
|
PP_EXPECT(harness, !target);
|
|
PP_EXPECT(harness, target.status().code == pp::foundation::StatusCode::invalid_argument);
|
|
}
|
|
|
|
void document_file_target_builds_legacy_ppi_path(pp::tests::Harness& harness)
|
|
{
|
|
const auto target = pp::app::make_document_file_target("D:/Paint", "demo");
|
|
PP_EXPECT(harness, target);
|
|
PP_EXPECT(harness, target.value().name == "demo");
|
|
PP_EXPECT(harness, target.value().directory == "D:/Paint");
|
|
PP_EXPECT(harness, target.value().path == "D:/Paint/demo.ppi");
|
|
}
|
|
|
|
void document_file_write_prompts_only_for_existing_targets(pp::tests::Harness& harness)
|
|
{
|
|
PP_EXPECT(
|
|
harness,
|
|
pp::app::plan_document_file_write(false)
|
|
== pp::app::DocumentFileWriteDecision::save_now);
|
|
PP_EXPECT(
|
|
harness,
|
|
pp::app::plan_document_file_write(true)
|
|
== pp::app::DocumentFileWriteDecision::prompt_overwrite);
|
|
}
|
|
|
|
void document_resolution_index_maps_legacy_choices(pp::tests::Harness& harness)
|
|
{
|
|
const auto first = pp::app::document_resolution_from_index(0);
|
|
const auto last = pp::app::document_resolution_from_index(5);
|
|
PP_EXPECT(harness, first);
|
|
PP_EXPECT(harness, first.value() == 512);
|
|
PP_EXPECT(harness, last);
|
|
PP_EXPECT(harness, last.value() == 8192);
|
|
}
|
|
|
|
void document_resolution_index_rejects_out_of_range(pp::tests::Harness& harness)
|
|
{
|
|
const auto negative = pp::app::document_resolution_from_index(-1);
|
|
const auto too_large = pp::app::document_resolution_from_index(6);
|
|
PP_EXPECT(harness, !negative);
|
|
PP_EXPECT(harness, negative.status().code == pp::foundation::StatusCode::out_of_range);
|
|
PP_EXPECT(harness, !too_large);
|
|
PP_EXPECT(harness, too_large.status().code == pp::foundation::StatusCode::out_of_range);
|
|
}
|
|
|
|
void new_document_plan_builds_target_resolution_and_write_decision(pp::tests::Harness& harness)
|
|
{
|
|
const auto plan = pp::app::plan_new_document(
|
|
"D:/Paint",
|
|
"demo",
|
|
2,
|
|
[](const std::string&) { return false; });
|
|
PP_EXPECT(harness, plan);
|
|
PP_EXPECT(harness, plan.value().target.name == "demo");
|
|
PP_EXPECT(harness, plan.value().target.path == "D:/Paint/demo.ppi");
|
|
PP_EXPECT(harness, plan.value().resolution == 1536);
|
|
PP_EXPECT(harness, plan.value().write_decision == pp::app::DocumentFileWriteDecision::save_now);
|
|
}
|
|
|
|
void new_document_plan_prompts_for_existing_target(pp::tests::Harness& harness)
|
|
{
|
|
const auto plan = pp::app::plan_new_document(
|
|
"D:/Paint",
|
|
"demo",
|
|
1,
|
|
[](const std::string& path) { return path == "D:/Paint/demo.ppi"; });
|
|
PP_EXPECT(harness, plan);
|
|
PP_EXPECT(harness, plan.value().resolution == 1024);
|
|
PP_EXPECT(
|
|
harness,
|
|
plan.value().write_decision == pp::app::DocumentFileWriteDecision::prompt_overwrite);
|
|
}
|
|
|
|
void new_document_plan_rejects_invalid_inputs(pp::tests::Harness& harness)
|
|
{
|
|
const auto missing_name = pp::app::plan_new_document(
|
|
"D:/Paint",
|
|
"",
|
|
0,
|
|
[](const std::string&) { return false; });
|
|
const auto invalid_resolution = pp::app::plan_new_document(
|
|
"D:/Paint",
|
|
"demo",
|
|
99,
|
|
[](const std::string&) { return false; });
|
|
PP_EXPECT(harness, !missing_name);
|
|
PP_EXPECT(harness, missing_name.status().code == pp::foundation::StatusCode::invalid_argument);
|
|
PP_EXPECT(harness, !invalid_resolution);
|
|
PP_EXPECT(harness, invalid_resolution.status().code == pp::foundation::StatusCode::out_of_range);
|
|
}
|
|
|
|
void document_version_target_starts_at_first_version(pp::tests::Harness& harness)
|
|
{
|
|
const auto target = pp::app::find_next_document_version_target(
|
|
"D:/Paint",
|
|
"demo",
|
|
[](const std::string&) { return false; });
|
|
PP_EXPECT(harness, target);
|
|
PP_EXPECT(harness, target.value().name == "demo.01");
|
|
PP_EXPECT(harness, target.value().path == "D:/Paint/demo.01.ppi");
|
|
}
|
|
|
|
void document_version_target_increments_existing_suffix(pp::tests::Harness& harness)
|
|
{
|
|
const auto target = pp::app::find_next_document_version_target(
|
|
"D:/Paint",
|
|
"demo.07",
|
|
[](const std::string&) { return false; });
|
|
PP_EXPECT(harness, target);
|
|
PP_EXPECT(harness, target.value().name == "demo.08");
|
|
PP_EXPECT(harness, target.value().path == "D:/Paint/demo.08.ppi");
|
|
}
|
|
|
|
void document_version_target_skips_existing_paths(pp::tests::Harness& harness)
|
|
{
|
|
const auto target = pp::app::find_next_document_version_target(
|
|
"D:/Paint",
|
|
"demo",
|
|
[](const std::string& path) {
|
|
return path == "D:/Paint/demo.01.ppi" || path == "D:/Paint/demo.02.ppi";
|
|
});
|
|
PP_EXPECT(harness, target);
|
|
PP_EXPECT(harness, target.value().name == "demo.03");
|
|
PP_EXPECT(harness, target.value().path == "D:/Paint/demo.03.ppi");
|
|
}
|
|
|
|
void document_version_target_preserves_legacy_nonnumeric_suffix_handling(pp::tests::Harness& harness)
|
|
{
|
|
const auto target = pp::app::find_next_document_version_target(
|
|
"D:/Paint",
|
|
"demo.ab",
|
|
[](const std::string&) { return false; });
|
|
PP_EXPECT(harness, target);
|
|
PP_EXPECT(harness, target.value().name == "demo.01");
|
|
PP_EXPECT(harness, target.value().path == "D:/Paint/demo.01.ppi");
|
|
}
|
|
|
|
void document_version_target_reports_when_no_slots_remain(pp::tests::Harness& harness)
|
|
{
|
|
const auto target = pp::app::find_next_document_version_target(
|
|
"D:/Paint",
|
|
"demo.98",
|
|
[](const std::string&) { return false; });
|
|
PP_EXPECT(harness, !target);
|
|
PP_EXPECT(harness, target.status().code == pp::foundation::StatusCode::out_of_range);
|
|
}
|
|
|
|
}
|
|
|
|
int main()
|
|
{
|
|
pp::tests::Harness harness;
|
|
harness.run("project open clean document executes immediately", project_open_clean_document_executes_immediately);
|
|
harness.run("project open dirty document prompts for discard", project_open_dirty_document_prompts_for_discard);
|
|
harness.run("document open project respects unsaved state", document_open_project_respects_unsaved_state);
|
|
harness.run(
|
|
"document open brush imports prompt regardless of unsaved state",
|
|
document_open_brush_imports_prompt_regardless_of_unsaved_state);
|
|
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("save clean existing document is no op", save_clean_existing_document_is_no_op);
|
|
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("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);
|
|
harness.run("document resolution index maps legacy choices", document_resolution_index_maps_legacy_choices);
|
|
harness.run("document resolution index rejects out of range", document_resolution_index_rejects_out_of_range);
|
|
harness.run(
|
|
"new document plan builds target resolution and write decision",
|
|
new_document_plan_builds_target_resolution_and_write_decision);
|
|
harness.run("new document plan prompts for existing target", new_document_plan_prompts_for_existing_target);
|
|
harness.run("new document plan rejects invalid inputs", new_document_plan_rejects_invalid_inputs);
|
|
harness.run("document version target starts at first version", document_version_target_starts_at_first_version);
|
|
harness.run("document version target increments existing suffix", document_version_target_increments_existing_suffix);
|
|
harness.run("document version target skips existing paths", document_version_target_skips_existing_paths);
|
|
harness.run(
|
|
"document version target preserves legacy nonnumeric suffix handling",
|
|
document_version_target_preserves_legacy_nonnumeric_suffix_handling);
|
|
harness.run("document version target reports when no slots remain", document_version_target_reports_when_no_slots_remain);
|
|
return harness.finish();
|
|
}
|