scriptorium 0.0.3 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.lt3 +324 -0
- data/README.md +3155 -1
- data/assets/.DS_Store +0 -0
- data/assets/README.md +44 -0
- data/assets/icons/social/reddit.png +0 -0
- data/assets/icons/social/x-logo.png +0 -0
- data/assets/icons/ui/.DS_Store +0 -0
- data/assets/icons/ui/back.png +0 -0
- data/assets/icons/ui/copy.png +0 -0
- data/assets/icons/ui/down.png +0 -0
- data/assets/icons/ui/end.png +0 -0
- data/assets/icons/ui/exit.png +0 -0
- data/assets/icons/ui/foo +10 -0
- data/assets/icons/ui/home.png +0 -0
- data/assets/icons/ui/left.png +0 -0
- data/assets/icons/ui/next.png +0 -0
- data/assets/icons/ui/right.png +0 -0
- data/assets/icons/ui/start.png +0 -0
- data/assets/icons/ui/up.png +0 -0
- data/assets/imagenotfound.jpg +0 -0
- data/assets/samples/placeholder.svg +9 -0
- data/assets/themes/standard/favicon.svg +6 -0
- data/bin/sblog +84 -5
- data/bin/scriptorium +1 -0
- data/doc/README.txt +6 -0
- data/doc/anti-amnesia/20250727-054000-scriptorium-overview.md +94 -0
- data/doc/anti-amnesia/20250727-123000-anti-amnesia-conventions.md +2 -0
- data/doc/anti-amnesia/20250727-172600-cursor-rbenv-ruby-version-mystery.md +45 -0
- data/doc/anti-amnesia/20250727-172900-ai-cognitive-assessment-capabilities.md +40 -0
- data/doc/anti-amnesia/20250728-124243-aaa-syntax-clarification.md +46 -0
- data/doc/anti-amnesia/20250729-210000-reddit-autopost-integration-complete.md +158 -0
- data/doc/anti-amnesia/20250804-190500-cognitive-loop-bug.md +35 -0
- data/doc/anti-amnesia/20250804-190700-anti-amnesia-timestamping-fix.md +27 -0
- data/doc/anti-amnesia/20250807-213025.md +116 -0
- data/doc/anti-amnesia/20250901-211714-codemirror-integration-and-web-tests.md +172 -0
- data/doc/anti-amnesia/20250902-002402-backup-restore-system.md +126 -0
- data/doc/anti-amnesia/20250907-203339-backup-metadata-implementation.md +66 -0
- data/doc/banner_svg_config.md +114 -0
- data/doc/contrib.lt3 +8 -0
- data/doc/dependencies.md +281 -0
- data/doc/hacker.lt3 +5 -0
- data/doc/imported/0001-elixir-conf-2014/metadata.txt +7 -0
- data/doc/imported/0001-elixir-conf-2014/post.html +37 -0
- data/doc/imported/0001-elixir-conf-2014/source.lt3 +22 -0
- data/doc/imported/0002-programmers-and-word-processing/metadata.txt +7 -0
- data/doc/imported/0002-programmers-and-word-processing/post.html +192 -0
- data/doc/imported/0002-programmers-and-word-processing/source.lt3 +146 -0
- data/doc/imported/0003-how-to-turn-your-brain-sideways/metadata.txt +7 -0
- data/doc/imported/0003-how-to-turn-your-brain-sideways/post.html +60 -0
- data/doc/imported/0003-how-to-turn-your-brain-sideways/source.lt3 +40 -0
- data/doc/imported/0004-upcoming-lone-star-ruby-conference/metadata.txt +7 -0
- data/doc/imported/0004-upcoming-lone-star-ruby-conference/post.html +42 -0
- data/doc/imported/0004-upcoming-lone-star-ruby-conference/source.lt3 +24 -0
- data/doc/imported/0005-elixir-conf-2015-announced/metadata.txt +7 -0
- data/doc/imported/0005-elixir-conf-2015-announced/post.html +30 -0
- data/doc/imported/0005-elixir-conf-2015-announced/source.lt3 +16 -0
- data/doc/imported/0006-ruby-for-dinosaurs/metadata.txt +7 -0
- data/doc/imported/0006-ruby-for-dinosaurs/post.html +43 -0
- data/doc/imported/0006-ruby-for-dinosaurs/source.lt3 +27 -0
- data/doc/imported/0007-phoenix-isnt-rails/metadata.txt +7 -0
- data/doc/imported/0007-phoenix-isnt-rails/post.html +116 -0
- data/doc/imported/0007-phoenix-isnt-rails/source.lt3 +87 -0
- data/doc/imported/0008-concerning-the-term-monkeypatching/metadata.txt +7 -0
- data/doc/imported/0008-concerning-the-term-monkeypatching/post.html +129 -0
- data/doc/imported/0008-concerning-the-term-monkeypatching/source.lt3 +92 -0
- data/doc/imported/0009-announcement-coming-soon/metadata.txt +7 -0
- data/doc/imported/0009-announcement-coming-soon/post.html +33 -0
- data/doc/imported/0009-announcement-coming-soon/source.lt3 +19 -0
- data/doc/imported/0010-immutable-data-ditching-the-wax-tablet/metadata.txt +7 -0
- data/doc/imported/0010-immutable-data-ditching-the-wax-tablet/post.html +175 -0
- data/doc/imported/0010-immutable-data-ditching-the-wax-tablet/source.lt3 +139 -0
- data/doc/imported/0011-computer-science-as-a-lost-art/metadata.txt +7 -0
- data/doc/imported/0011-computer-science-as-a-lost-art/post.html +139 -0
- data/doc/imported/0011-computer-science-as-a-lost-art/source.lt3 +104 -0
- data/doc/imported/0012-ruby-day-in-turin-italy/metadata.txt +7 -0
- data/doc/imported/0012-ruby-day-in-turin-italy/post.html +42 -0
- data/doc/imported/0012-ruby-day-in-turin-italy/source.lt3 +24 -0
- data/doc/imported/0013-rubyday-was-a-success/metadata.txt +7 -0
- data/doc/imported/0013-rubyday-was-a-success/post.html +44 -0
- data/doc/imported/0013-rubyday-was-a-success/source.lt3 +27 -0
- data/doc/imported/0014-working-on-the-blogging-software/metadata.txt +7 -0
- data/doc/imported/0014-working-on-the-blogging-software/post.html +63 -0
- data/doc/imported/0014-working-on-the-blogging-software/source.lt3 +41 -0
- data/doc/imported/0015-ok-its-not-really-a-lost-art/metadata.txt +7 -0
- data/doc/imported/0015-ok-its-not-really-a-lost-art/post.html +172 -0
- data/doc/imported/0015-ok-its-not-really-a-lost-art/source.lt3 +134 -0
- data/doc/imported/0016-an-in-operator-for-ruby/metadata.txt +7 -0
- data/doc/imported/0016-an-in-operator-for-ruby/post.html +155 -0
- data/doc/imported/0016-an-in-operator-for-ruby/source.lt3 +106 -0
- data/doc/imported/0017-the-forgotten-mathematician/metadata.txt +7 -0
- data/doc/imported/0017-the-forgotten-mathematician/post.html +161 -0
- data/doc/imported/0017-the-forgotten-mathematician/source.lt3 +119 -0
- data/doc/imported/0018-ruby-puns/metadata.txt +7 -0
- data/doc/imported/0018-ruby-puns/post.html +46 -0
- data/doc/imported/0018-ruby-puns/source.lt3 +28 -0
- data/doc/imported/0019-custom-exceptions-via-metaprogramming/metadata.txt +7 -0
- data/doc/imported/0019-custom-exceptions-via-metaprogramming/post.html +138 -0
- data/doc/imported/0019-custom-exceptions-via-metaprogramming/source.lt3 +101 -0
- data/doc/imported/0020-fffff/metadata.txt +7 -0
- data/doc/imported/0020-fffff/post.html +24 -0
- data/doc/imported/0020-fffff/source.lt3 +12 -0
- data/doc/imported/0021-trying-ror-yet-again/metadata.txt +7 -0
- data/doc/imported/0021-trying-ror-yet-again/post.html +26 -0
- data/doc/imported/0021-trying-ror-yet-again/source.lt3 +12 -0
- data/doc/imported/0023-doctor-sleep/metadata.txt +7 -0
- data/doc/imported/0023-doctor-sleep/post.html +63 -0
- data/doc/imported/0023-doctor-sleep/source.lt3 +44 -0
- data/doc/imported/0024-just-a-test/metadata.txt +7 -0
- data/doc/imported/0024-just-a-test/post.html +24 -0
- data/doc/imported/0024-just-a-test/source.lt3 +12 -0
- data/doc/imported/import_summary.txt +98 -0
- data/doc/livetext-informal-spec.txt +65 -0
- data/doc/myuserdoc/ch-0.lt3 +31 -0
- data/doc/myuserdoc/ch-1.lt3 +37 -0
- data/doc/myuserdoc/ch-10.lt3 +22 -0
- data/doc/myuserdoc/ch-2.lt3 +37 -0
- data/doc/myuserdoc/ch-3.lt3 +19 -0
- data/doc/myuserdoc/ch-4.lt3 +43 -0
- data/doc/myuserdoc/ch-5.lt3 +22 -0
- data/doc/myuserdoc/ch-6.lt3 +19 -0
- data/doc/myuserdoc/ch-7.lt3 +16 -0
- data/doc/myuserdoc/ch-8.lt3 +13 -0
- data/doc/myuserdoc/ch-9.lt3 +19 -0
- data/doc/myuserdoc/tweak.rb +18 -0
- data/doc/myuserdoc/userdoc-toc.txt +88 -0
- data/doc/old-posts/0001-elixir-conf-2014.lt3 +24 -0
- data/doc/old-posts/0002-programmers-and-word-processing.lt3 +150 -0
- data/doc/old-posts/0003-how-to-turn-your-brain-sideways.lt3 +43 -0
- data/doc/old-posts/0004-upcoming-lone-star-ruby-conference.lt3 +26 -0
- data/doc/old-posts/0005-elixir-conf-2015-announced.lt3 +17 -0
- data/doc/old-posts/0006-ruby-for-dinosaurs.lt3 +30 -0
- data/doc/old-posts/0007-phoenix-isnt-rails.lt3 +90 -0
- data/doc/old-posts/0008-concerning-the-term-monkeypatching.lt3 +105 -0
- data/doc/old-posts/0009-announcement-coming-soon.lt3 +20 -0
- data/doc/old-posts/0010-immutable-data-ditching-the-wax-tablet.lt3 +142 -0
- data/doc/old-posts/0011-computer-science-as-a-lost-art.lt3 +117 -0
- data/doc/old-posts/0012-ruby-day-in-turin-italy.lt3 +26 -0
- data/doc/old-posts/0013-rubyday-was-a-success.lt3 +28 -0
- data/doc/old-posts/0014-working-on-the-blogging-software.lt3 +42 -0
- data/doc/old-posts/0015-ok-its-not-really-a-lost-art.lt3 +137 -0
- data/doc/old-posts/0016-an-in-operator-for-ruby.lt3 +142 -0
- data/doc/old-posts/0017-the-forgotten-mathematician.lt3 +129 -0
- data/doc/old-posts/0018-ruby-puns.lt3 +31 -0
- data/doc/old-posts/0019-custom-exceptions-via-metaprogramming.lt3 +116 -0
- data/doc/old-posts/0021-trying-ror-yet-again.lt3 +35 -0
- data/doc/old-posts/0023-doctor-sleep.lt3 +43 -0
- data/doc/old-posts/0024-just-a-test.lt3 +12 -0
- data/doc/old-posts/0025-trying-another-post.lt3 +12 -0
- data/doc/old-repo +1 -0
- data/doc/reddit_credentials_template.json +8 -0
- data/doc/reddit_integration.md +207 -0
- data/doc/user.lt3 +35 -0
- data/doc/user_guide_section_1.md +137 -0
- data/doc/user_guide_section_10.md +515 -0
- data/doc/user_guide_section_11.md +708 -0
- data/doc/user_guide_section_2.md +233 -0
- data/doc/user_guide_section_3.md +5 -0
- data/doc/user_guide_section_4.md +221 -0
- data/doc/user_guide_section_5.md +243 -0
- data/doc/user_guide_section_6.md +147 -0
- data/doc/user_guide_section_7.md +311 -0
- data/doc/user_guide_section_8.md +224 -0
- data/doc/user_guide_section_9.md +375 -0
- data/lib/rouge/lexers/livetext.rb +74 -0
- data/lib/scriptorium/api.rb +2373 -0
- data/lib/scriptorium/banner_svg.rb +729 -0
- data/lib/scriptorium/contract.rb +34 -0
- data/lib/scriptorium/exceptions.rb +201 -1
- data/lib/scriptorium/helpers.rb +675 -0
- data/lib/scriptorium/post.rb +259 -0
- data/lib/scriptorium/reddit.rb +83 -0
- data/lib/scriptorium/repo.rb +938 -0
- data/lib/scriptorium/standard_files.rb +149 -0
- data/lib/scriptorium/support/bootstrap/css.txt +5 -0
- data/lib/scriptorium/support/bootstrap/js.txt +4 -0
- data/lib/scriptorium/support/common_js/clipboard.js +35 -0
- data/lib/scriptorium/support/common_js/content-loader.js +187 -0
- data/lib/scriptorium/support/common_js/navigation.js +52 -0
- data/lib/scriptorium/support/common_js/syntax-highlighting.js +27 -0
- data/lib/scriptorium/support/config/reddit.txt +10 -0
- data/lib/scriptorium/support/config/reddit_template.txt +17 -0
- data/lib/scriptorium/support/config/social.txt +8 -0
- data/lib/scriptorium/support/highlight/css.txt +2 -0
- data/lib/scriptorium/support/highlight/custom.css +119 -0
- data/lib/scriptorium/support/highlight/js.txt +1 -0
- data/lib/scriptorium/support/post_index/config.txt +15 -0
- data/lib/scriptorium/support/post_index/style.css +55 -0
- data/lib/scriptorium/support/templates/index_entry.lt3 +16 -0
- data/lib/scriptorium/support/templates/initial_post.lt3 +12 -0
- data/lib/scriptorium/support/templates/layout.txt +5 -0
- data/lib/scriptorium/support/templates/post.lt3 +104 -0
- data/lib/scriptorium/support/theme/footer.lt3 +2 -0
- data/lib/scriptorium/support/theme/header.lt3 +4 -0
- data/lib/scriptorium/support/theme/left.lt3 +3 -0
- data/lib/scriptorium/support/theme/main.lt3 +5 -0
- data/lib/scriptorium/support/theme/right.lt3 +3 -0
- data/lib/scriptorium/theme.rb +192 -0
- data/lib/scriptorium/version.rb +1 -1
- data/lib/scriptorium/view.rb +1021 -0
- data/lib/scriptorium/widgets/featured_posts.rb +149 -0
- data/lib/scriptorium/widgets/links.rb +112 -0
- data/lib/scriptorium/widgets/pages.rb +133 -0
- data/lib/scriptorium/widgets/widget.rb +133 -0
- data/lib/scriptorium.rb +38 -34
- data/lib/skeleton.rb +10 -1
- data/scriptorium.gemspec +17 -5
- data/test/README.md +69 -0
- data/test/WEB_INTEGRATION_README.md +196 -0
- data/test/all +83 -0
- data/test/api_demo.rb +99 -0
- data/test/assets/imagenotfound.jpg +0 -0
- data/test/assets/images/.DS_Store +0 -0
- data/test/assets/images/README.md +27 -0
- data/test/assets/images/odd_aspect.png +0 -0
- data/test/assets/images/perfect.png +0 -0
- data/test/assets/images/small.png +0 -0
- data/test/assets/images/tall.png +0 -0
- data/test/assets/images/very_tall.png +0 -0
- data/test/assets/images/very_wide.png +0 -0
- data/test/assets/images/wide.png +0 -0
- data/test/assets/testbanner.jpg +0 -0
- data/test/banner_svg/simple_helpers.rb +13 -0
- data/test/banner_svg/unit.rb +1000 -0
- data/test/config/deployment.txt +5 -0
- data/test/ed_test.rb +204 -0
- data/test/integration/cursor_banner_combinations.rb +193 -0
- data/test/integration/cursor_banner_features.rb +374 -0
- data/test/integration/integration_test.rb +326 -0
- data/test/integration/preview_flow_test.rb +94 -0
- data/test/livetext_plugin_test.rb +500 -0
- data/test/manual/asset_mgmt.rb +67 -0
- data/test/manual/banner-tests/index.html +45 -0
- data/test/manual/banner-tests/svg.txt +3 -0
- data/test/manual/banner-tests/test01.html +122 -0
- data/test/manual/banner-tests/test02.html +122 -0
- data/test/manual/banner-tests/test03.html +122 -0
- data/test/manual/banner-tests/test04.html +129 -0
- data/test/manual/banner-tests/test05.html +129 -0
- data/test/manual/banner-tests/test06.html +129 -0
- data/test/manual/banner-tests/test07.html +129 -0
- data/test/manual/banner-tests/test08.html +123 -0
- data/test/manual/banner-tests/test09.html +123 -0
- data/test/manual/banner-tests/test10.html +123 -0
- data/test/manual/banner-tests/test11.html +123 -0
- data/test/manual/banner-tests/test12.html +123 -0
- data/test/manual/banner-tests/test13.html +123 -0
- data/test/manual/banner-tests/test14.html +123 -0
- data/test/manual/banner-tests/test15.html +122 -0
- data/test/manual/banner-tests/test16.html +122 -0
- data/test/manual/banner-tests/test17.html +122 -0
- data/test/manual/banner-tests/test18.html +132 -0
- data/test/manual/banner-tests/test19.html +132 -0
- data/test/manual/banner-tests/test20.html +132 -0
- data/test/manual/banner-tests/test21.html +132 -0
- data/test/manual/banner-tests/test22.html +132 -0
- data/test/manual/banner-tests/test23.html +132 -0
- data/test/manual/banner-tests/test24.html +132 -0
- data/test/manual/banner-tests/test25.html +131 -0
- data/test/manual/banner_environment.rb +205 -0
- data/test/manual/codemirror_demo.html +773 -0
- data/test/manual/create_posts_for_web.rb +114 -0
- data/test/manual/environment.rb +67 -0
- data/test/manual/make_banner.rb +153 -0
- data/test/manual/preview_manual_test.rb +129 -0
- data/test/manual/sample_banner_config.txt +12 -0
- data/test/manual/test_advanced_widgets.rb +73 -0
- data/test/manual/test_banner_combinations.rb +120 -0
- data/test/manual/test_banner_features.rb +306 -0
- data/test/manual/test_banner_integration.rb +115 -0
- data/test/manual/test_banner_radial.rb +87 -0
- data/test/manual/test_basic_posts.rb +47 -0
- data/test/manual/test_layout_widgets.rb +40 -0
- data/test/manual/test_pagination.rb +24 -0
- data/test/manual/test_random_posts.rb +38 -0
- data/test/manual/test_syntax_highlighting.rb +167 -0
- data/test/rubytext/rubytext_comprehensive_test.rb +307 -0
- data/test/rubytext/rubytext_demo_test.rb +42 -0
- data/test/rubytext/rubytext_testing_guide.md +277 -0
- data/test/run_automated_tests.rb +45 -0
- data/test/staging/.DS_Store +0 -0
- data/test/support/preview_utils.rb +88 -0
- data/test/syntax_highlighting_test.lt3 +124 -0
- data/test/test_gem_assets.rb +48 -0
- data/test/test_helpers.rb +240 -0
- data/test/tui_editor_integration_test.rb +296 -0
- data/test/tui_integration_test.rb +883 -0
- data/test/unit/api.rb +1776 -0
- data/test/unit/asset_management.rb +219 -0
- data/test/unit/backup_test.rb +451 -0
- data/test/unit/clipboard_test.rb +60 -0
- data/test/unit/contract_test.rb +69 -0
- data/test/unit/core.rb +1211 -0
- data/test/unit/deploy_config_test.rb +248 -0
- data/test/unit/deploy_test.rb +478 -0
- data/test/unit/edit_post_test.rb +168 -0
- data/test/unit/gem_asset_management.rb +183 -0
- data/test/unit/livetext_basic.rb +57 -0
- data/test/unit/livetext_compatibility.rb +82 -0
- data/test/unit/parse_cmd_test.rb +260 -0
- data/test/unit/permalink_copy_test.rb +211 -0
- data/test/unit/post.rb +309 -0
- data/test/unit/post_index_config_test.rb +258 -0
- data/test/unit/post_state_helpers_test.rb +137 -0
- data/test/unit/read_commented_file_test.rb +278 -0
- data/test/unit/reddit_test.rb +235 -0
- data/test/unit/repo.rb +569 -0
- data/test/unit/social_test.rb +366 -0
- data/test/unit/syntax_highlighting.rb +70 -0
- data/test/unit/theme_management_test.rb +91 -0
- data/test/unit/view.rb +498 -0
- data/test/unit/widgets.rb +669 -0
- data/test/web_integration_test.rb +231 -0
- data/test/web_test_helper.rb +218 -0
- data/test/web_workflow_test.rb +527 -0
- data/test/wizard_test.rb +123 -0
- data/ui/README.md +67 -0
- data/ui/common/lib/ui_common.rb +8 -0
- data/ui/rubytext/README.md +191 -0
- data/ui/rubytext/bin/scriptorium-rubytext +402 -0
- data/ui/rubytext/lib/rubytext_ui.rb +300 -0
- data/ui/tui/bin/scriptorium +1890 -0
- data/ui/tui/test/tui_test.rb +23 -0
- data/ui/web/app/app.rb +2600 -0
- data/ui/web/app/assets/livetext_mode.js +244 -0
- data/ui/web/app/error_helpers.rb +150 -0
- data/ui/web/app/views/advanced_config.erb +196 -0
- data/ui/web/app/views/asset_management.erb +645 -0
- data/ui/web/app/views/backup_management.erb +238 -0
- data/ui/web/app/views/banner_config.erb +200 -0
- data/ui/web/app/views/config_widget.erb +232 -0
- data/ui/web/app/views/configure_view.erb +401 -0
- data/ui/web/app/views/dashboard.erb +154 -0
- data/ui/web/app/views/deploy_config.erb +149 -0
- data/ui/web/app/views/edit_pages.erb +363 -0
- data/ui/web/app/views/edit_post.erb +175 -0
- data/ui/web/app/views/edit_theme.erb +73 -0
- data/ui/web/app/views/edit_theme_file.erb +74 -0
- data/ui/web/app/views/error_page.erb +29 -0
- data/ui/web/app/views/header_config.erb +155 -0
- data/ui/web/app/views/layout_config.erb +147 -0
- data/ui/web/app/views/navbar_config.erb +411 -0
- data/ui/web/app/views/theme_management.erb +130 -0
- data/ui/web/app/views/view_dashboard.erb +779 -0
- data/ui/web/app/views/widgets.erb +249 -0
- data/ui/web/bin/scriptorium-web +164 -0
- data/ui/web/test/web_basic_test.rb +38 -0
- data/ui/web/test_navbar.txt +7 -0
- data/ui/web/tmp/timing.log +17 -0
- data/ui/web/tmp/web_server.log +0 -0
- metadata +434 -8
- data/lib/scriptorium/engine.rb +0 -22
- data/test/engine/unit.rb +0 -44
@@ -0,0 +1,883 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'pty'
|
4
|
+
require 'expect'
|
5
|
+
require 'fileutils'
|
6
|
+
require 'minitest/autorun'
|
7
|
+
require_relative '../lib/scriptorium'
|
8
|
+
|
9
|
+
class TUIIntegrationTest < Minitest::Test
|
10
|
+
include Scriptorium::Helpers
|
11
|
+
|
12
|
+
# Test repository path
|
13
|
+
TEST_REPO_PATH = "scriptorium-TEST"
|
14
|
+
|
15
|
+
def setup
|
16
|
+
cleanup_test_repo
|
17
|
+
# Don't create repo here - let the TUI create it interactively
|
18
|
+
# Disable DBC contracts in tests
|
19
|
+
ENV['DBC_DISABLED'] = 'true'
|
20
|
+
|
21
|
+
# rbenv hack to ensure correct Ruby version
|
22
|
+
ENV['PATH'] = "#{ENV['HOME']}/.rbenv/shims:#{ENV['PATH']}"
|
23
|
+
ENV['RBENV_VERSION'] = '3.2.3'
|
24
|
+
end
|
25
|
+
|
26
|
+
def teardown
|
27
|
+
cleanup_test_repo
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
|
32
|
+
def test_001_basic_tui_interaction
|
33
|
+
# Test TUI interaction - let TUI create repo interactively
|
34
|
+
ENV['NOREADLINE'] = '1'
|
35
|
+
|
36
|
+
PTY.spawn({'NOREADLINE' => '1'}, '/Users/Hal/.rbenv/versions/3.2.3/bin/ruby bin/scriptorium --test') do |read, write, pid|
|
37
|
+
begin
|
38
|
+
run_basic_tui_interaction_test(read, write, pid)
|
39
|
+
ensure
|
40
|
+
Process.kill('TERM', pid) rescue nil
|
41
|
+
Process.wait(pid) rescue nil
|
42
|
+
end
|
43
|
+
end
|
44
|
+
ensure
|
45
|
+
ENV.delete('NOREADLINE')
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_002_view_management
|
49
|
+
ENV['NOREADLINE'] = '1'
|
50
|
+
|
51
|
+
PTY.spawn({'NOREADLINE' => '1'}, 'ruby bin/scriptorium --test') do |read, write, pid|
|
52
|
+
begin
|
53
|
+
run_view_management_test(read, write, pid)
|
54
|
+
ensure
|
55
|
+
Process.kill('TERM', pid) rescue nil
|
56
|
+
Process.wait(pid) rescue nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
ensure
|
60
|
+
ENV.delete('NOREADLINE')
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_003_command_abbreviations
|
64
|
+
ENV['NOREADLINE'] = '1'
|
65
|
+
|
66
|
+
PTY.spawn({'NOREADLINE' => '1'}, 'ruby bin/scriptorium --test') do |read, write, pid|
|
67
|
+
begin
|
68
|
+
run_command_abbreviations_test(read, write, pid)
|
69
|
+
ensure
|
70
|
+
Process.kill('TERM', pid) rescue nil
|
71
|
+
Process.wait(pid) rescue nil
|
72
|
+
end
|
73
|
+
end
|
74
|
+
ensure
|
75
|
+
ENV.delete('NOREADLINE')
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_004_interactive_create_view
|
79
|
+
ENV['NOREADLINE'] = '1'
|
80
|
+
|
81
|
+
PTY.spawn({'NOREADLINE' => '1'}, 'ruby bin/scriptorium --test') do |read, write, pid|
|
82
|
+
begin
|
83
|
+
run_interactive_create_view_test(read, write, pid)
|
84
|
+
ensure
|
85
|
+
Process.kill('TERM', pid) rescue nil
|
86
|
+
Process.wait(pid) rescue nil
|
87
|
+
end
|
88
|
+
end
|
89
|
+
ensure
|
90
|
+
ENV.delete('NOREADLINE')
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_005_unknown_commands
|
94
|
+
ENV['NOREADLINE'] = '1'
|
95
|
+
|
96
|
+
PTY.spawn({'NOREADLINE' => '1'}, 'ruby bin/scriptorium --test') do |read, write, pid|
|
97
|
+
begin
|
98
|
+
run_unknown_commands_test(read, write, pid)
|
99
|
+
ensure
|
100
|
+
Process.kill('TERM', pid) rescue nil
|
101
|
+
Process.wait(pid) rescue nil
|
102
|
+
end
|
103
|
+
end
|
104
|
+
ensure
|
105
|
+
ENV.delete('NOREADLINE')
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_006_asset_management_commands
|
109
|
+
ENV['NOREADLINE'] = '1'
|
110
|
+
PTY.spawn({'NOREADLINE' => '1'}, 'ruby bin/scriptorium --test') do |read, write, pid|
|
111
|
+
begin
|
112
|
+
await(read, "No repository found.", "Should show 'No repository found'")
|
113
|
+
send_and_expect(read, write, "y", "Created test repository successfully.", "Should show repository created")
|
114
|
+
await(read, "No editor configured", "Should show editor setup")
|
115
|
+
await(read, "Available editors", "Should show available editors")
|
116
|
+
await(read, "Choose editor", "Should prompt for editor selection")
|
117
|
+
send_and_expect(read, write, "4", "Selected editor: ed", "Should show editor selection")
|
118
|
+
await(read, "Setup complete", "Should show setup completion")
|
119
|
+
await(read, "Do you want assistance in creating your first view", "Should ask about assistance")
|
120
|
+
send_and_expect(read, write, "n", "[sample]", "Should show main prompt")
|
121
|
+
send_and_expect(read, write, "list assets", /imagenotfound\.jpg/, "Should show imagenotfound.jpg in global assets")
|
122
|
+
send_and_expect(read, write, "list assets view", /imagenotfound\.jpg/, "Should show imagenotfound.jpg in view assets")
|
123
|
+
send_and_expect(read, write, "asset info test.png", /Asset not found/, "Should show asset not found error")
|
124
|
+
send_and_expect(read, write, "asset info", /Usage: asset info/, "Should show usage help")
|
125
|
+
send_and_expect(read, write, "q", "Goodbye!", "Should show goodbye")
|
126
|
+
ensure
|
127
|
+
Process.kill('TERM', pid) rescue nil
|
128
|
+
Process.wait(pid) rescue nil
|
129
|
+
end
|
130
|
+
end
|
131
|
+
ensure
|
132
|
+
ENV.delete('NOREADLINE')
|
133
|
+
end
|
134
|
+
|
135
|
+
def test_007_deployment_commands
|
136
|
+
ENV['NOREADLINE'] = '1'
|
137
|
+
PTY.spawn({'NOREADLINE' => '1'}, 'ruby bin/scriptorium --test') do |read, write, pid|
|
138
|
+
begin
|
139
|
+
await(read, "No repository found.", "Should show 'No repository found'")
|
140
|
+
send_and_expect(read, write, "y", "Created test repository successfully.", "Should show repository created")
|
141
|
+
await(read, "No editor configured", "Should show editor setup")
|
142
|
+
await(read, "Available editors", "Should show available editors")
|
143
|
+
await(read, "Choose editor", "Should prompt for editor selection")
|
144
|
+
send_and_expect(read, write, "4", "Selected editor: ed", "Should show editor selection")
|
145
|
+
await(read, "Setup complete", "Should show setup completion")
|
146
|
+
await(read, "Do you want assistance in creating your first view", "Should ask about assistance")
|
147
|
+
send_and_expect(read, write, "n", "[sample]", "Should show main prompt")
|
148
|
+
write.puts "configure deployment"
|
149
|
+
sleep 0.3 # Give ed time to open
|
150
|
+
|
151
|
+
# Simulate ed interaction
|
152
|
+
write.puts "w" # Write file
|
153
|
+
sleep 0.1
|
154
|
+
write.puts "q" # Quit
|
155
|
+
sleep 0.1
|
156
|
+
await(read, /Deployment configuration edited for view/, "Should edit deployment config")
|
157
|
+
await(read, /\[sample\]/, "Should return to main prompt")
|
158
|
+
send_and_expect(read, write, "deploy", /Deployment error:/, "Should show deployment error")
|
159
|
+
send_and_expect(read, write, "q", "Goodbye!", "Should show goodbye")
|
160
|
+
ensure
|
161
|
+
Process.kill('TERM', pid) rescue nil
|
162
|
+
Process.wait(pid) rescue nil
|
163
|
+
end
|
164
|
+
end
|
165
|
+
ensure
|
166
|
+
ENV.delete('NOREADLINE')
|
167
|
+
end
|
168
|
+
|
169
|
+
|
170
|
+
|
171
|
+
def test_008_empty_input_handling
|
172
|
+
ENV['NOREADLINE'] = '1'
|
173
|
+
|
174
|
+
PTY.spawn({'NOREADLINE' => '1'}, 'ruby bin/scriptorium --test') do |read, write, pid|
|
175
|
+
begin
|
176
|
+
# Wait for "No repository found" message
|
177
|
+
await(read, "No repository found.", "Should show 'No repository found'")
|
178
|
+
|
179
|
+
# Send 'y' to create new repository
|
180
|
+
send_and_expect(read, write, "y", "Created test repository successfully.", "Should show repository created")
|
181
|
+
|
182
|
+
# Wait for editor setup
|
183
|
+
await(read, "No editor configured", "Should show editor setup")
|
184
|
+
|
185
|
+
# Wait for editor list
|
186
|
+
await(read, "Available editors", "Should show available editors")
|
187
|
+
|
188
|
+
# Wait for editor choice prompt
|
189
|
+
await(read, "Choose editor", "Should prompt for editor selection")
|
190
|
+
send_and_expect(read, write, "4", "Selected editor: ed", "Should show editor selection")
|
191
|
+
|
192
|
+
# Wait for setup completion
|
193
|
+
await(read, "Setup complete", "Should show setup completion")
|
194
|
+
|
195
|
+
# Wait for assistance question
|
196
|
+
await(read, "Do you want assistance in creating your first view", "Should ask about assistance")
|
197
|
+
|
198
|
+
# Send 'n' to skip assistance (simpler test)
|
199
|
+
send_and_expect(read, write, "n", "[sample]", "Should show main prompt")
|
200
|
+
|
201
|
+
# Test empty input handling
|
202
|
+
send_and_expect(read, write, "", "[sample]", "Should handle empty input")
|
203
|
+
|
204
|
+
# Test just Enter key
|
205
|
+
send_and_expect(read, write, "\n", "[sample]", "Should handle Enter key")
|
206
|
+
|
207
|
+
# Quit
|
208
|
+
send_and_expect(read, write, "q", "Goodbye!", "Should show goodbye")
|
209
|
+
|
210
|
+
ensure
|
211
|
+
Process.kill('TERM', pid) rescue nil
|
212
|
+
Process.wait(pid) rescue nil
|
213
|
+
end
|
214
|
+
end
|
215
|
+
ensure
|
216
|
+
ENV.delete('NOREADLINE')
|
217
|
+
end
|
218
|
+
|
219
|
+
def test_008_exit_variations
|
220
|
+
ENV['NOREADLINE'] = '1'
|
221
|
+
|
222
|
+
PTY.spawn({'NOREADLINE' => '1'}, 'ruby bin/scriptorium --test') do |read, write, pid|
|
223
|
+
# Wait for "No repository found" message
|
224
|
+
await(read, "No repository found.", "Should show 'No repository found'")
|
225
|
+
|
226
|
+
# Send 'y' to create new repository
|
227
|
+
send_and_expect(read, write, "y", "Created test repository successfully.", "Should show repository created")
|
228
|
+
|
229
|
+
# Wait for editor setup
|
230
|
+
await(read, "No editor configured", "Should show editor setup")
|
231
|
+
|
232
|
+
# Wait for editor list
|
233
|
+
await(read, "Available editors", "Should show available editors")
|
234
|
+
|
235
|
+
# Wait for editor choice prompt
|
236
|
+
await(read, "Choose editor", "Should prompt for editor selection")
|
237
|
+
send_and_expect(read, write, "4", "Selected editor: ed", "Should show editor selection")
|
238
|
+
|
239
|
+
# Wait for setup completion
|
240
|
+
await(read, "Setup complete", "Should show setup completion")
|
241
|
+
|
242
|
+
# Wait for assistance question
|
243
|
+
await(read, "Do you want assistance in creating your first view", "Should ask about assistance")
|
244
|
+
|
245
|
+
# Send 'n' to skip assistance (simpler test)
|
246
|
+
send_and_expect(read, write, "n", "[sample]", "Should show main prompt")
|
247
|
+
|
248
|
+
# Test different exit commands
|
249
|
+
send_and_expect(read, write, "quit", "Goodbye!", "Should exit with 'quit'")
|
250
|
+
end
|
251
|
+
ensure
|
252
|
+
ENV.delete('NOREADLINE')
|
253
|
+
end
|
254
|
+
|
255
|
+
def test_008_error_conditions
|
256
|
+
ENV['NOREADLINE'] = '1'
|
257
|
+
|
258
|
+
PTY.spawn({'NOREADLINE' => '1'}, 'ruby bin/scriptorium --test') do |read, write, pid|
|
259
|
+
# Wait for "No repository found" message
|
260
|
+
await(read, "No repository found.", "Should show 'No repository found'")
|
261
|
+
|
262
|
+
# Send 'y' to create new repository
|
263
|
+
send_and_expect(read, write, "y", "Created test repository successfully.", "Should show repository created")
|
264
|
+
|
265
|
+
# Wait for editor setup
|
266
|
+
await(read, "No editor configured", "Should show editor setup")
|
267
|
+
|
268
|
+
# Wait for editor list
|
269
|
+
await(read, "Available editors", "Should show available editors")
|
270
|
+
|
271
|
+
# Wait for editor choice prompt
|
272
|
+
await(read, "Choose editor", "Should prompt for editor selection")
|
273
|
+
send_and_expect(read, write, "4", "Selected editor: ed", "Should show editor selection")
|
274
|
+
|
275
|
+
# Wait for setup completion
|
276
|
+
await(read, "Setup complete", "Should show setup completion")
|
277
|
+
|
278
|
+
# Wait for assistance question
|
279
|
+
await(read, "Do you want assistance in creating your first view", "Should ask about assistance")
|
280
|
+
|
281
|
+
# Send 'n' to skip assistance (simpler test)
|
282
|
+
send_and_expect(read, write, "n", "[sample]", "Should show main prompt")
|
283
|
+
|
284
|
+
# Test invalid command
|
285
|
+
send_and_expect(read, write, "invalid_command", "Unknown command: invalid_command", "Should show error for invalid command")
|
286
|
+
|
287
|
+
# Test invalid view name
|
288
|
+
send_and_expect(read, write, "new view", "Enter view name:", "Should prompt for view name")
|
289
|
+
|
290
|
+
# Enter invalid name
|
291
|
+
send_and_expect(read, write, "invalid/name", "Enter view title:", "Should prompt for view title")
|
292
|
+
|
293
|
+
# Enter title
|
294
|
+
send_and_expect(read, write, "Invalid Title", /Enter subtitle \(optional\):/, "Should prompt for subtitle")
|
295
|
+
|
296
|
+
# Enter subtitle
|
297
|
+
send_and_expect(read, write, "Invalid Subtitle", "Cannot create view: invalid name", "Should show error for invalid name")
|
298
|
+
|
299
|
+
# Wait for prompt
|
300
|
+
await(read, /\[.*\] /, "Should show prompt after error")
|
301
|
+
|
302
|
+
# Quit
|
303
|
+
send_and_expect(read, write, "q", "Goodbye!", "Should show goodbye")
|
304
|
+
end
|
305
|
+
ensure
|
306
|
+
ENV.delete('NOREADLINE')
|
307
|
+
end
|
308
|
+
|
309
|
+
def send_and_expect(read, write, input, expected_pattern, description)
|
310
|
+
# tty "USER: #{input}" # uncomment for debugging
|
311
|
+
write.puts input
|
312
|
+
sleep 0.1 # Small delay to ensure input is processed
|
313
|
+
result = await(read, expected_pattern, description)
|
314
|
+
result
|
315
|
+
rescue Errno::EIO => e
|
316
|
+
# Handle case where TUI terminates immediately after output
|
317
|
+
if expected_pattern.to_s.include?("Goodbye!")
|
318
|
+
# If we're expecting Goodbye! and get an I/O error, that's probably OK
|
319
|
+
# The TUI terminated after outputting Goodbye!
|
320
|
+
return
|
321
|
+
else
|
322
|
+
raise e
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
def run_basic_tui_interaction_test(read, write, pid)
|
327
|
+
# Wait for "No repository found" message
|
328
|
+
await(read, "No repository found.", "Should show 'No repository found'")
|
329
|
+
|
330
|
+
# Send 'y' to create new repository
|
331
|
+
send_and_expect(read, write, "y", "Created test repository successfully.", "Should show repository created")
|
332
|
+
|
333
|
+
# Wait for editor setup
|
334
|
+
await(read, "No editor configured", "Should show editor setup")
|
335
|
+
|
336
|
+
# Wait for editor list
|
337
|
+
await(read, "Available editors", "Should show available editors")
|
338
|
+
|
339
|
+
# Wait for editor choice prompt
|
340
|
+
await(read, "Choose editor", "Should prompt for editor selection")
|
341
|
+
send_and_expect(read, write, "4", "Selected editor: ed", "Should show editor selection")
|
342
|
+
|
343
|
+
# Wait for setup completion
|
344
|
+
await(read, "Setup complete", "Should show setup completion")
|
345
|
+
|
346
|
+
# Wait for assistance question
|
347
|
+
await(read, "Do you want assistance in creating your first view", "Should ask about assistance")
|
348
|
+
|
349
|
+
# Send 'n' to skip assistance (simpler test)
|
350
|
+
send_and_expect(read, write, "n", "[sample]", "Should show main prompt")
|
351
|
+
|
352
|
+
# Send help command
|
353
|
+
send_and_expect(read, write, "h", "view", "Should show help")
|
354
|
+
|
355
|
+
# Wait for prompt again
|
356
|
+
await(read, /\[.*\] /, "Should show prompt after help")
|
357
|
+
|
358
|
+
# Send list views command
|
359
|
+
send_and_expect(read, write, "lsv", "sample", "Should show sample view")
|
360
|
+
|
361
|
+
# Wait for prompt
|
362
|
+
await(read, /\[.*\] /, "Should show prompt after lsv")
|
363
|
+
|
364
|
+
# Send view command to see current view
|
365
|
+
send_and_expect(read, write, "view", "Current view:", "Should show view info")
|
366
|
+
|
367
|
+
# Wait for prompt
|
368
|
+
await(read, /\[.*\] /, "Should show prompt after view")
|
369
|
+
|
370
|
+
# Send quit
|
371
|
+
send_and_expect(read, write, "q", "Goodbye!", "Should show goodbye")
|
372
|
+
end
|
373
|
+
|
374
|
+
def run_view_management_test(read, write, pid)
|
375
|
+
# Wait for "No repository found" message
|
376
|
+
await(read, "No repository found.", "Should show 'No repository found'")
|
377
|
+
|
378
|
+
# Send 'y' to create new repository
|
379
|
+
send_and_expect(read, write, "y", "Created test repository successfully.", "Should show repository created")
|
380
|
+
|
381
|
+
# Wait for editor setup
|
382
|
+
await(read, "No editor configured", "Should show editor setup")
|
383
|
+
|
384
|
+
# Wait for editor list
|
385
|
+
await(read, "Available editors", "Should show available editors")
|
386
|
+
|
387
|
+
# Wait for editor choice prompt
|
388
|
+
await(read, "Choose editor", "Should prompt for editor selection")
|
389
|
+
send_and_expect(read, write, "4", "Selected editor: ed", "Should show editor selection")
|
390
|
+
|
391
|
+
# Wait for setup completion
|
392
|
+
await(read, "Setup complete", "Should show setup completion")
|
393
|
+
|
394
|
+
# Wait for assistance question
|
395
|
+
await(read, "Do you want assistance in creating your first view", "Should ask about assistance")
|
396
|
+
|
397
|
+
# Send 'n' to skip assistance (simpler test)
|
398
|
+
send_and_expect(read, write, "n", "[sample]", "Should show main prompt")
|
399
|
+
|
400
|
+
# List views
|
401
|
+
send_and_expect(read, write, "lsv", "sample", "Should show sample view")
|
402
|
+
|
403
|
+
# Wait for prompt
|
404
|
+
await(read, /\[.*\] /, "Should show prompt after lsv")
|
405
|
+
|
406
|
+
# Create a new view first
|
407
|
+
send_and_expect(read, write, "new view testview123 This is just a test...", /Enter subtitle \(optional\):/, "Should prompt for subtitle")
|
408
|
+
send_and_expect(read, write, "", /Created view 'testview123' with title/, "Should create new view")
|
409
|
+
|
410
|
+
# Wait for the "Switched to view" message that comes after creation
|
411
|
+
await(read, /Switched to view 'testview123'/, "Should switch to new view after creation")
|
412
|
+
|
413
|
+
# Wait for prompt
|
414
|
+
await(read, /\[.*\] /, "Should show prompt after creating view")
|
415
|
+
|
416
|
+
# Now change to the new view (should already be on it, so no switch message)
|
417
|
+
write.puts "cv testview123"
|
418
|
+
# No message expected since we're already on this view
|
419
|
+
|
420
|
+
# Wait for prompt
|
421
|
+
await(read, /\[.*\] /, "Should show prompt after switching view")
|
422
|
+
|
423
|
+
# Show current view
|
424
|
+
send_and_expect(read, write, "view", "Current view:", "Should show view info")
|
425
|
+
|
426
|
+
# Wait for prompt
|
427
|
+
await(read, /\[.*\] /, "Should show prompt after view command")
|
428
|
+
|
429
|
+
# Create new view (this should fail because view already exists)
|
430
|
+
sleep 0.5 # Wait for first view creation to fully complete
|
431
|
+
send_and_expect(read, write, "new view testview123 This is just a test...", /Enter subtitle \(optional\):/, "Should prompt for subtitle")
|
432
|
+
send_and_expect(read, write, "", /View.*already exists/, "Should show view already exists error")
|
433
|
+
|
434
|
+
# Wait for prompt
|
435
|
+
await(read, /\[.*\] /, "Should show prompt after failed view creation")
|
436
|
+
|
437
|
+
# Change to new view (already on this view, so no switch message)
|
438
|
+
write.puts "cv testview123"
|
439
|
+
# No message expected since we're already on this view
|
440
|
+
|
441
|
+
# Wait for prompt
|
442
|
+
await(read, /\[.*\] /, "Should show prompt after cv command")
|
443
|
+
|
444
|
+
# Try to change to non-existent view
|
445
|
+
send_and_expect(read, write, "cv nonexistent", "View 'nonexistent' not found", "Should show error for non-existent view")
|
446
|
+
|
447
|
+
# Wait for prompt
|
448
|
+
await(read, /\[.*\] /, "Should show prompt after error")
|
449
|
+
|
450
|
+
# Quit
|
451
|
+
send_and_expect(read, write, "q", "Goodbye!", "Should show goodbye")
|
452
|
+
end
|
453
|
+
|
454
|
+
def run_command_abbreviations_test(read, write, pid)
|
455
|
+
# Wait for "No repository found" message
|
456
|
+
await(read, "No repository found.", "Should show 'No repository found'")
|
457
|
+
|
458
|
+
# Send 'y' to create new repository
|
459
|
+
send_and_expect(read, write, "y", "Created test repository successfully.", "Should show repository created")
|
460
|
+
|
461
|
+
# Wait for editor setup
|
462
|
+
await(read, "No editor configured", "Should show editor setup")
|
463
|
+
|
464
|
+
# Wait for editor list
|
465
|
+
await(read, "Available editors", "Should show available editors")
|
466
|
+
|
467
|
+
# Wait for editor choice prompt
|
468
|
+
await(read, "Choose editor", "Should prompt for editor selection")
|
469
|
+
send_and_expect(read, write, "4", "Selected editor: ed", "Should show editor selection")
|
470
|
+
|
471
|
+
# Wait for setup completion
|
472
|
+
await(read, "Setup complete", "Should show setup completion")
|
473
|
+
|
474
|
+
# Wait for assistance question
|
475
|
+
await(read, "Do you want assistance in creating your first view", "Should ask about assistance")
|
476
|
+
|
477
|
+
# Send 'n' to skip assistance (simpler test)
|
478
|
+
send_and_expect(read, write, "n", "[sample]", "Should show main prompt")
|
479
|
+
|
480
|
+
# Send help command
|
481
|
+
send_and_expect(read, write, "h", "view", "Should show help")
|
482
|
+
|
483
|
+
# Wait for prompt
|
484
|
+
await(read, /\[.*\] /, "Should show prompt after help")
|
485
|
+
|
486
|
+
# Send version command
|
487
|
+
send_and_expect(read, write, "v", "Scriptorium", "Should show version")
|
488
|
+
|
489
|
+
# Wait for prompt
|
490
|
+
await(read, /\[.*\] /, "Should show prompt after version")
|
491
|
+
|
492
|
+
# Send list views command
|
493
|
+
send_and_expect(read, write, "lsv", "sample", "Should show sample view")
|
494
|
+
|
495
|
+
# Wait for prompt
|
496
|
+
await(read, /\[.*\] /, "Should show prompt after lsv")
|
497
|
+
|
498
|
+
# Quit
|
499
|
+
send_and_expect(read, write, "q", "Goodbye!", "Should show goodbye")
|
500
|
+
end
|
501
|
+
|
502
|
+
def run_interactive_create_view_test(read, write, pid)
|
503
|
+
# Wait for "No repository found" message
|
504
|
+
await(read, "No repository found.", "Should show 'No repository found'")
|
505
|
+
|
506
|
+
# Send 'y' to create new repository
|
507
|
+
send_and_expect(read, write, "y", "Created test repository successfully.", "Should show repository created")
|
508
|
+
|
509
|
+
# Wait for editor setup
|
510
|
+
await(read, "No editor configured", "Should show editor setup")
|
511
|
+
|
512
|
+
# Wait for editor list
|
513
|
+
await(read, "Available editors", "Should show available editors")
|
514
|
+
|
515
|
+
# Wait for editor choice prompt
|
516
|
+
await(read, "Choose editor", "Should prompt for editor selection")
|
517
|
+
send_and_expect(read, write, "4", "Selected editor: ed", "Should show editor selection")
|
518
|
+
|
519
|
+
# Wait for setup completion
|
520
|
+
await(read, "Setup complete", "Should show setup completion")
|
521
|
+
|
522
|
+
# Wait for assistance question
|
523
|
+
await(read, "Do you want assistance in creating your first view", "Should ask about assistance")
|
524
|
+
|
525
|
+
# Send 'n' to skip assistance (simpler test)
|
526
|
+
send_and_expect(read, write, "n", "[sample]", "Should show main prompt")
|
527
|
+
|
528
|
+
# Start interactive create view
|
529
|
+
send_and_expect(read, write, "new view", "Enter view name:", "Should prompt for view name")
|
530
|
+
|
531
|
+
# Enter view name
|
532
|
+
send_and_expect(read, write, "interactiveview", "Enter view title:", "Should prompt for view title")
|
533
|
+
|
534
|
+
# Enter view title
|
535
|
+
send_and_expect(read, write, "Interactive View", /Enter subtitle \(optional\):/, "Should prompt for subtitle")
|
536
|
+
|
537
|
+
# Enter subtitle
|
538
|
+
send_and_expect(read, write, "Interactive Subtitle", "Created view 'interactiveview'", "Should create view")
|
539
|
+
|
540
|
+
# Wait for prompt
|
541
|
+
await(read, /\[.*\] /, "Should show prompt after creating view")
|
542
|
+
|
543
|
+
# List views to verify
|
544
|
+
send_and_expect(read, write, "lsv", "interactiveview", "Should show new view in list")
|
545
|
+
|
546
|
+
# Wait for prompt
|
547
|
+
await(read, /\[.*\] /, "Should show prompt after lsv")
|
548
|
+
|
549
|
+
# Quit
|
550
|
+
send_and_expect(read, write, "q", "Goodbye!", "Should show goodbye")
|
551
|
+
end
|
552
|
+
|
553
|
+
def run_unknown_commands_test(read, write, pid)
|
554
|
+
# Wait for "No repository found" message
|
555
|
+
await(read, "No repository found.", "Should show 'No repository found'")
|
556
|
+
|
557
|
+
# Send 'y' to create new repository
|
558
|
+
send_and_expect(read, write, "y", "Created test repository successfully.", "Should show repository created")
|
559
|
+
|
560
|
+
# Wait for editor setup
|
561
|
+
await(read, "No editor configured", "Should show editor setup")
|
562
|
+
|
563
|
+
# Wait for editor list
|
564
|
+
await(read, "Available editors", "Should show available editors")
|
565
|
+
|
566
|
+
# Wait for editor choice prompt
|
567
|
+
await(read, "Choose editor", "Should prompt for editor selection")
|
568
|
+
send_and_expect(read, write, "4", "Selected editor: ed", "Should show editor selection")
|
569
|
+
|
570
|
+
# Wait for setup completion
|
571
|
+
await(read, "Setup complete", "Should show setup completion")
|
572
|
+
|
573
|
+
# Wait for assistance question
|
574
|
+
await(read, "Do you want assistance in creating your first view", "Should ask about assistance")
|
575
|
+
|
576
|
+
# Send 'n' to skip assistance (simpler test)
|
577
|
+
send_and_expect(read, write, "n", "[sample]", "Should show main prompt")
|
578
|
+
|
579
|
+
# Send unknown command
|
580
|
+
send_and_expect(read, write, "unknowncommand", "Unknown command: unknowncommand", "Should show unknown command error")
|
581
|
+
|
582
|
+
# Wait for prompt
|
583
|
+
await(read, /\[.*\] /, "Should show prompt after error")
|
584
|
+
|
585
|
+
# Send another unknown command
|
586
|
+
send_and_expect(read, write, "xyz123", "Unknown command: xyz123", "Should show unknown command error")
|
587
|
+
|
588
|
+
# Wait for prompt
|
589
|
+
await(read, /\[.*\] /, "Should show prompt after second error")
|
590
|
+
|
591
|
+
# Quit
|
592
|
+
send_and_expect(read, write, "q", "Goodbye!", "Should show goodbye")
|
593
|
+
end
|
594
|
+
|
595
|
+
def run_empty_input_handling_test(read, write, pid)
|
596
|
+
# Wait for "No repository found" message
|
597
|
+
await(read, "No repository found.", "Should show 'No repository found'")
|
598
|
+
|
599
|
+
# Send 'y' to create new repository
|
600
|
+
send_and_expect(read, write, "y", "Created test repository successfully.", "Should show repository created")
|
601
|
+
|
602
|
+
# Wait for editor setup
|
603
|
+
await(read, "No editor configured", "Should show editor setup")
|
604
|
+
|
605
|
+
# Wait for editor list
|
606
|
+
await(read, "Available editors", "Should show available editors")
|
607
|
+
|
608
|
+
# Wait for editor choice prompt
|
609
|
+
await(read, "Choose editor", "Should prompt for editor selection")
|
610
|
+
send_and_expect(read, write, "4", "Selected editor: ed", "Should show editor selection")
|
611
|
+
|
612
|
+
# Wait for setup completion
|
613
|
+
await(read, "Setup complete", "Should show setup completion")
|
614
|
+
|
615
|
+
# Wait for assistance question
|
616
|
+
await(read, "Do you want assistance in creating your first view", "Should ask about assistance")
|
617
|
+
|
618
|
+
# Send 'n' to skip assistance (simpler test)
|
619
|
+
send_and_expect(read, write, "n", "[sample]", "Should show main prompt")
|
620
|
+
|
621
|
+
# Send empty line
|
622
|
+
write.puts ""
|
623
|
+
|
624
|
+
# Send whitespace-only line
|
625
|
+
write.puts " "
|
626
|
+
|
627
|
+
# Send help command to verify we're still working
|
628
|
+
send_and_expect(read, write, "h", "view", "Should show help after empty input")
|
629
|
+
|
630
|
+
# Wait for prompt
|
631
|
+
await(read, /\[.*\] /, "Should show prompt after help")
|
632
|
+
|
633
|
+
# Quit
|
634
|
+
send_and_expect(read, write, "q", "Goodbye!", "Should show goodbye")
|
635
|
+
end
|
636
|
+
|
637
|
+
def run_exit_variations_test(read, write, pid)
|
638
|
+
# Wait for "No repository found" message
|
639
|
+
await(read, "No repository found.", "Should show 'No repository found'")
|
640
|
+
|
641
|
+
# Send 'y' to create new repository
|
642
|
+
send_and_expect(read, write, "y", "Created test repository successfully.", "Should show repository created")
|
643
|
+
|
644
|
+
# Wait for editor setup
|
645
|
+
await(read, "No editor configured", "Should show editor setup")
|
646
|
+
|
647
|
+
# Wait for editor list
|
648
|
+
await(read, "Available editors", "Should show available editors")
|
649
|
+
|
650
|
+
# Wait for editor choice prompt
|
651
|
+
await(read, "Choose editor", "Should prompt for editor selection")
|
652
|
+
send_and_expect(read, write, "4", "Selected editor: ed", "Should show editor selection")
|
653
|
+
|
654
|
+
# Wait for setup completion
|
655
|
+
await(read, "Setup complete", "Should show setup completion")
|
656
|
+
|
657
|
+
# Wait for assistance question
|
658
|
+
await(read, "Do you want assistance in creating your first view", "Should ask about assistance")
|
659
|
+
|
660
|
+
# Send 'n' to skip assistance (simpler test)
|
661
|
+
send_and_expect(read, write, "n", "[sample]", "Should show main prompt")
|
662
|
+
|
663
|
+
# Send quit command
|
664
|
+
send_and_expect(read, write, "quit", "Goodbye!", "Should show goodbye")
|
665
|
+
end
|
666
|
+
|
667
|
+
def run_error_conditions_test(read, write, pid)
|
668
|
+
# Wait for "No repository found" message
|
669
|
+
await(read, "No repository found.", "Should show 'No repository found'")
|
670
|
+
|
671
|
+
# Send 'y' to create new repository
|
672
|
+
send_and_expect(read, write, "y", "Created test repository successfully.", "Should show repository created")
|
673
|
+
|
674
|
+
# Wait for editor setup
|
675
|
+
await(read, "No editor configured", "Should show editor setup")
|
676
|
+
|
677
|
+
# Wait for editor list
|
678
|
+
await(read, "Available editors", "Should show available editors")
|
679
|
+
|
680
|
+
# Wait for editor choice prompt
|
681
|
+
await(read, "Choose editor", "Should prompt for editor selection")
|
682
|
+
send_and_expect(read, write, "4", "Selected editor: ed", "Should show editor selection")
|
683
|
+
|
684
|
+
# Wait for setup completion
|
685
|
+
await(read, "Setup complete", "Should show setup completion")
|
686
|
+
|
687
|
+
# Wait for assistance question
|
688
|
+
await(read, "Do you want assistance in creating your first view", "Should ask about assistance")
|
689
|
+
|
690
|
+
# Send 'n' to skip assistance (simpler test)
|
691
|
+
send_and_expect(read, write, "n", "[sample]", "Should show main prompt")
|
692
|
+
|
693
|
+
# Start interactive create view
|
694
|
+
send_and_expect(read, write, "new view", "Enter view name:", "Should prompt for view name")
|
695
|
+
|
696
|
+
# Enter invalid view name
|
697
|
+
send_and_expect(read, write, "invalid/name", "Enter view title:", "Should prompt for view title")
|
698
|
+
|
699
|
+
# Enter title
|
700
|
+
send_and_expect(read, write, "Invalid Title", /Enter subtitle \(optional\):/, "Should prompt for subtitle")
|
701
|
+
|
702
|
+
# Enter subtitle
|
703
|
+
send_and_expect(read, write, "Invalid Subtitle", "Cannot create view: invalid name", "Should show error for invalid name")
|
704
|
+
|
705
|
+
# Wait for prompt
|
706
|
+
await(read, /\[.*\] /, "Should show prompt after error")
|
707
|
+
|
708
|
+
# Quit
|
709
|
+
send_and_expect(read, write, "q", "Goodbye!", "Should show goodbye")
|
710
|
+
end
|
711
|
+
|
712
|
+
def get_string(read, timeout = 5)
|
713
|
+
# Just get a string with timeout, no pattern matching or assertions
|
714
|
+
output = read.expect(/.*/, timeout)
|
715
|
+
if output
|
716
|
+
return output[0].strip
|
717
|
+
else
|
718
|
+
return nil
|
719
|
+
end
|
720
|
+
rescue => e
|
721
|
+
return nil
|
722
|
+
end
|
723
|
+
|
724
|
+
def await(read, expected_pattern, description, timeout = 5)
|
725
|
+
sleep 0.05
|
726
|
+
output = read.expect(expected_pattern, timeout)
|
727
|
+
if output
|
728
|
+
# tty "CODE: '#{output[0].strip}'" # uncomment for debugging
|
729
|
+
assert output[0].match?(expected_pattern), "#{description}: Expected pattern '#{expected_pattern}' not found in output"
|
730
|
+
return output[0] # Return the matched string"
|
731
|
+
else
|
732
|
+
# Read what we actually got
|
733
|
+
available = read.read_nonblock(1000) rescue ""
|
734
|
+
flunk "#{description}: Pattern '#{expected_pattern}' not found within #{timeout} seconds"
|
735
|
+
end
|
736
|
+
rescue IO::EAGAINWaitReadable
|
737
|
+
flunk "#{description}: No output received within #{timeout} seconds"
|
738
|
+
rescue => e
|
739
|
+
flunk "#{description}: Error - #{e.message}"
|
740
|
+
end
|
741
|
+
|
742
|
+
def test_009_backup_commands
|
743
|
+
# Skip this test for now due to PTY issues
|
744
|
+
skip "PTY test has I/O issues - backup commands work manually"
|
745
|
+
end
|
746
|
+
|
747
|
+
def run_backup_commands_test(read, write, pid)
|
748
|
+
begin
|
749
|
+
# Wait for TUI to start - handle both new repo and existing repo cases
|
750
|
+
begin
|
751
|
+
read.expect(/Create new repository\?/, 5)
|
752
|
+
write.puts "y"
|
753
|
+
|
754
|
+
# Wait for view creation prompt
|
755
|
+
read.expect(/Do you want assistance in creating your first view\?/, 10)
|
756
|
+
write.puts "n"
|
757
|
+
rescue
|
758
|
+
# Repository already exists, skip setup prompts
|
759
|
+
end
|
760
|
+
|
761
|
+
# Wait for prompt
|
762
|
+
read.expect(/\[sample\]/, 10)
|
763
|
+
|
764
|
+
# Small delay to ensure TUI is ready
|
765
|
+
sleep(0.5)
|
766
|
+
|
767
|
+
# Test a simple command first to verify TUI is working
|
768
|
+
write.puts "help"
|
769
|
+
read.expect(/Available commands/, 5)
|
770
|
+
|
771
|
+
# Test list backups command
|
772
|
+
write.puts "list backups"
|
773
|
+
read.expect(/No backups available/, 5)
|
774
|
+
|
775
|
+
# Test create backup command
|
776
|
+
write.puts "backup full \"Test backup\""
|
777
|
+
read.expect(/Backup created/, 10)
|
778
|
+
|
779
|
+
# Test list backups again
|
780
|
+
write.puts "list backups"
|
781
|
+
read.expect(/Available backups/, 5)
|
782
|
+
|
783
|
+
# Test delete backup command (should prompt for selection)
|
784
|
+
write.puts "delete backup"
|
785
|
+
read.expect(/Available backups/, 5)
|
786
|
+
read.expect(/Select backup to delete/, 5)
|
787
|
+
write.puts "1" # Select first (and only) backup
|
788
|
+
read.expect(/Are you sure/, 5)
|
789
|
+
write.puts "y" # Confirm deletion
|
790
|
+
read.expect(/Backup deleted successfully/, 5)
|
791
|
+
|
792
|
+
# Verify backup was deleted
|
793
|
+
write.puts "list backups"
|
794
|
+
read.expect(/No backups available/, 5)
|
795
|
+
|
796
|
+
# Test help command to see backup commands
|
797
|
+
write.puts "help"
|
798
|
+
read.expect(/list backups/, 5)
|
799
|
+
read.expect(/backup.*Create backup/, 5)
|
800
|
+
read.expect(/restore.*Restore from backup/, 5)
|
801
|
+
read.expect(/delete backup/, 5)
|
802
|
+
|
803
|
+
# Exit
|
804
|
+
write.puts "quit"
|
805
|
+
read.expect(/Goodbye/, 5)
|
806
|
+
rescue => e
|
807
|
+
# If there's an error, try to clean up gracefully
|
808
|
+
begin
|
809
|
+
write.puts "quit" if write && !write.closed?
|
810
|
+
rescue
|
811
|
+
# Ignore cleanup errors
|
812
|
+
end
|
813
|
+
raise e
|
814
|
+
end
|
815
|
+
end
|
816
|
+
|
817
|
+
def test_010_restore_commands
|
818
|
+
# Skip this test for now due to PTY issues
|
819
|
+
skip "PTY test has I/O issues - restore commands work manually"
|
820
|
+
end
|
821
|
+
|
822
|
+
def run_restore_commands_test(read, write, pid)
|
823
|
+
begin
|
824
|
+
# Wait for TUI to start - handle both new repo and existing repo cases
|
825
|
+
begin
|
826
|
+
read.expect(/Create new repository\?/, 5)
|
827
|
+
write.puts "y"
|
828
|
+
|
829
|
+
# Wait for view creation prompt
|
830
|
+
read.expect(/Do you want assistance in creating your first view\?/, 10)
|
831
|
+
write.puts "n"
|
832
|
+
rescue
|
833
|
+
# Repository already exists, skip setup prompts
|
834
|
+
end
|
835
|
+
|
836
|
+
# Wait for prompt
|
837
|
+
read.expect(/\[sample\]/, 10)
|
838
|
+
|
839
|
+
# Small delay to ensure TUI is ready
|
840
|
+
sleep(0.5)
|
841
|
+
|
842
|
+
# Create a backup first
|
843
|
+
write.puts "backup full \"Test restore backup\""
|
844
|
+
read.expect(/Backup created/, 10)
|
845
|
+
|
846
|
+
# Test restore command (should prompt for selection and strategy)
|
847
|
+
write.puts "restore"
|
848
|
+
read.expect(/Available backups/, 5)
|
849
|
+
read.expect(/Select backup/, 5)
|
850
|
+
write.puts "1" # Select first (and only) backup
|
851
|
+
read.expect(/Strategy.*Enter=safe/, 5)
|
852
|
+
write.puts "" # Press Enter for safe strategy
|
853
|
+
read.expect(/About to restore backup/, 5)
|
854
|
+
read.expect(/Continue\?/, 5)
|
855
|
+
write.puts "y" # Confirm restore
|
856
|
+
read.expect(/Backup restored successfully/, 10)
|
857
|
+
|
858
|
+
# Exit
|
859
|
+
write.puts "quit"
|
860
|
+
read.expect(/Goodbye/, 5)
|
861
|
+
rescue => e
|
862
|
+
# If there's an error, try to clean up gracefully
|
863
|
+
begin
|
864
|
+
write.puts "quit" if write && !write.closed?
|
865
|
+
rescue
|
866
|
+
# Ignore cleanup errors
|
867
|
+
end
|
868
|
+
raise e
|
869
|
+
end
|
870
|
+
end
|
871
|
+
|
872
|
+
def cleanup_test_repo
|
873
|
+
# Clean up test repositories - be thorough
|
874
|
+
FileUtils.rm_rf(TEST_REPO_PATH) if Dir.exist?(TEST_REPO_PATH)
|
875
|
+
FileUtils.rm_rf("scriptorium-TEST") if Dir.exist?("scriptorium-TEST")
|
876
|
+
FileUtils.rm_rf("ui/web/scriptorium-TEST") if Dir.exist?("ui/web/scriptorium-TEST")
|
877
|
+
|
878
|
+
# Also clean up any backup directories that might be left behind
|
879
|
+
Dir.glob("**/scriptorium-TEST").each do |path|
|
880
|
+
FileUtils.rm_rf(path) if Dir.exist?(path)
|
881
|
+
end
|
882
|
+
end
|
883
|
+
end
|