scriptorium 0.0.3 → 0.6.1

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.
Files changed (292) hide show
  1. checksums.yaml +4 -4
  2. data/README.lt3 +324 -0
  3. data/README.md +3155 -1
  4. data/assets/.DS_Store +0 -0
  5. data/assets/README.md +44 -0
  6. data/assets/back-icon.png +0 -0
  7. data/assets/icons/facebook.svg +1 -0
  8. data/assets/icons/github.svg +1 -0
  9. data/assets/icons/instagram.svg +1 -0
  10. data/assets/icons/reddit.svg +1 -0
  11. data/assets/icons/ui/.DS_Store +0 -0
  12. data/assets/icons/ui/back.png +0 -0
  13. data/assets/icons/ui/copy.png +0 -0
  14. data/assets/icons/ui/down.png +0 -0
  15. data/assets/icons/ui/end.png +0 -0
  16. data/assets/icons/ui/exit.png +0 -0
  17. data/assets/icons/ui/foo +10 -0
  18. data/assets/icons/ui/home.png +0 -0
  19. data/assets/icons/ui/left.png +0 -0
  20. data/assets/icons/ui/next.png +0 -0
  21. data/assets/icons/ui/right.png +0 -0
  22. data/assets/icons/ui/start.png +0 -0
  23. data/assets/icons/ui/up.png +0 -0
  24. data/assets/icons/x.svg +1 -0
  25. data/assets/icons/youtube.svg +1 -0
  26. data/assets/samples/placeholder.svg +9 -0
  27. data/assets/themes/standard/favicon.svg +6 -0
  28. data/bin/scriptorium +1511 -0
  29. data/doc/README.txt +6 -0
  30. data/doc/anti-amnesia/20250727-054000-scriptorium-overview.md +95 -0
  31. data/doc/anti-amnesia/20250727-060000-api-design-tui-planning.md +34 -0
  32. data/doc/anti-amnesia/20250727-061000-runeblog-tui-analysis.md +50 -0
  33. data/doc/anti-amnesia/20250727-123000-anti-amnesia-conventions.md +31 -0
  34. data/doc/anti-amnesia/20250727-154000-livetext-plugin-file-stats.md +73 -0
  35. data/doc/anti-amnesia/20250727-172600-cursor-rbenv-ruby-version-mystery.md +64 -0
  36. data/doc/anti-amnesia/20250727-172600-unified-minitest-framework.md +70 -0
  37. data/doc/anti-amnesia/20250727-172900-ai-cognitive-assessment-capabilities.md +40 -0
  38. data/doc/anti-amnesia/20250727-173000-widget-testing-achievement.md +110 -0
  39. data/doc/anti-amnesia/20250727-180000-post-id-num-refactoring.md +73 -0
  40. data/doc/anti-amnesia/20250728-124243-aaa-syntax-clarification.md +46 -0
  41. data/doc/anti-amnesia/20250728-124421-conversation-summary-concise.md +124 -0
  42. data/doc/anti-amnesia/20250729-190000-scriptorium-tui-testing-complete.md +46 -0
  43. data/doc/anti-amnesia/20250729-200000-scriptorium-tui-testing-edit-file-workflow.md +97 -0
  44. data/doc/anti-amnesia/20250729-210000-reddit-autopost-integration-complete.md +158 -0
  45. data/doc/anti-amnesia/20250729-211500-dependency-management-system.md +211 -0
  46. data/doc/anti-amnesia/20250729-213000-python-virtual-environment-setup.md +141 -0
  47. data/doc/anti-amnesia/20250729-214500-theme-management-commands.md +211 -0
  48. data/doc/anti-amnesia/20250729-215000-version-update-to-0.6.0.md +134 -0
  49. data/doc/anti-amnesia/20250729-220000-user-guide-complete.md +41 -0
  50. data/doc/anti-amnesia/20250804-190500-cognitive-loop-bug.md +45 -0
  51. data/doc/anti-amnesia/20250804-190700-anti-amnesia-timestamping-fix.md +30 -0
  52. data/doc/anti-amnesia/20250804-213700-publishing-test-fix.md +49 -0
  53. data/doc/anti-amnesia/20250804-214400-additional-test-fixes.md +46 -0
  54. data/doc/anti-amnesia/20250804-220000-asset-function-logic-clarification.md +41 -0
  55. data/doc/anti-amnesia/20250806-202032-asset-function-logic-clarification.md +41 -0
  56. data/doc/anti-amnesia/20250807-213025.md +116 -0
  57. data/doc/anti-amnesia/20250813-082428-syntax-highlighting-and-navigation-improvements.md +256 -0
  58. data/doc/banner_svg_config.md +114 -0
  59. data/doc/contrib.lt3 +8 -0
  60. data/doc/dependencies.md +281 -0
  61. data/doc/hacker.lt3 +5 -0
  62. data/doc/reddit_credentials_template.json +8 -0
  63. data/doc/reddit_integration.md +207 -0
  64. data/doc/user.lt3 +38 -0
  65. data/doc/user_guide_section_1.md +137 -0
  66. data/doc/user_guide_section_10.md +515 -0
  67. data/doc/user_guide_section_11.md +708 -0
  68. data/doc/user_guide_section_2.md +233 -0
  69. data/doc/user_guide_section_3.md +5 -0
  70. data/doc/user_guide_section_4.md +221 -0
  71. data/doc/user_guide_section_5.md +243 -0
  72. data/doc/user_guide_section_6.md +147 -0
  73. data/doc/user_guide_section_7.md +311 -0
  74. data/doc/user_guide_section_8.md +224 -0
  75. data/doc/user_guide_section_9.md +375 -0
  76. data/doc/userdoc-toc.txt +88 -0
  77. data/lib/rouge/lexers/livetext.rb +74 -0
  78. data/lib/scriptorium/api.rb +640 -0
  79. data/lib/scriptorium/banner_svg.rb +742 -0
  80. data/lib/scriptorium/contract.rb +33 -0
  81. data/lib/scriptorium/exceptions.rb +170 -1
  82. data/lib/scriptorium/helpers.rb +475 -0
  83. data/lib/scriptorium/post.rb +195 -0
  84. data/lib/scriptorium/reddit.rb +83 -0
  85. data/lib/scriptorium/repo.rb +624 -0
  86. data/lib/scriptorium/standard_files.rb +515 -0
  87. data/lib/scriptorium/syntax_highlighter.rb +234 -0
  88. data/lib/scriptorium/theme.rb +179 -0
  89. data/lib/scriptorium/version.rb +2 -2
  90. data/lib/scriptorium/view.rb +976 -0
  91. data/lib/scriptorium/widgets/featured_posts.rb +149 -0
  92. data/lib/scriptorium/widgets/links.rb +112 -0
  93. data/lib/scriptorium/widgets/pages.rb +133 -0
  94. data/lib/scriptorium/widgets/widget.rb +133 -0
  95. data/lib/scriptorium.rb +21 -40
  96. data/lib/skeleton.rb +8 -2
  97. data/scriptorium.gemspec +15 -4
  98. data/test/README.md +69 -0
  99. data/test/all +43 -0
  100. data/test/api_demo.rb +99 -0
  101. data/test/assets/imagenotfound.jpg +0 -0
  102. data/test/assets/images/.DS_Store +0 -0
  103. data/test/assets/images/README.md +27 -0
  104. data/test/assets/images/odd_aspect.png +0 -0
  105. data/test/assets/images/perfect.png +0 -0
  106. data/test/assets/images/small.png +0 -0
  107. data/test/assets/images/tall.png +0 -0
  108. data/test/assets/images/very_tall.png +0 -0
  109. data/test/assets/images/very_wide.png +0 -0
  110. data/test/assets/images/wide.png +0 -0
  111. data/test/assets/testbanner.jpg +0 -0
  112. data/test/banner_svg/simple_helpers.rb +13 -0
  113. data/test/banner_svg/unit.rb +768 -0
  114. data/test/ed_test.rb +204 -0
  115. data/test/integration/cursor_banner_combinations.rb +193 -0
  116. data/test/integration/cursor_banner_features.rb +374 -0
  117. data/test/integration/integration_test.rb +326 -0
  118. data/test/livetext_plugin_test.rb +229 -0
  119. data/test/manual/asset_mgmt.rb +67 -0
  120. data/test/manual/banner-tests/config.txt +3 -0
  121. data/test/manual/banner-tests/index.html +45 -0
  122. data/test/manual/banner-tests/test01.html +58 -0
  123. data/test/manual/banner-tests/test02.html +58 -0
  124. data/test/manual/banner-tests/test03.html +58 -0
  125. data/test/manual/banner-tests/test04.html +65 -0
  126. data/test/manual/banner-tests/test05.html +65 -0
  127. data/test/manual/banner-tests/test06.html +65 -0
  128. data/test/manual/banner-tests/test07.html +65 -0
  129. data/test/manual/banner-tests/test08.html +59 -0
  130. data/test/manual/banner-tests/test09.html +59 -0
  131. data/test/manual/banner-tests/test10.html +59 -0
  132. data/test/manual/banner-tests/test11.html +59 -0
  133. data/test/manual/banner-tests/test12.html +59 -0
  134. data/test/manual/banner-tests/test13.html +59 -0
  135. data/test/manual/banner-tests/test14.html +59 -0
  136. data/test/manual/banner-tests/test15.html +58 -0
  137. data/test/manual/banner-tests/test16.html +58 -0
  138. data/test/manual/banner-tests/test17.html +58 -0
  139. data/test/manual/banner-tests/test18.html +68 -0
  140. data/test/manual/banner-tests/test19.html +68 -0
  141. data/test/manual/banner-tests/test20.html +68 -0
  142. data/test/manual/banner-tests/test21.html +68 -0
  143. data/test/manual/banner-tests/test22.html +68 -0
  144. data/test/manual/banner-tests/test23.html +68 -0
  145. data/test/manual/banner-tests/test24.html +68 -0
  146. data/test/manual/banner-tests/test25.html +67 -0
  147. data/test/manual/banner_environment.rb +192 -0
  148. data/test/manual/deploy_symlink_demo.rb +142 -0
  149. data/test/manual/environment.rb +67 -0
  150. data/test/manual/make_banner.rb +153 -0
  151. data/test/manual/sample_banner_config.txt +12 -0
  152. data/test/manual/symlink_demo.rb +117 -0
  153. data/test/manual/test1.rb +47 -0
  154. data/test/manual/test2.rb +12 -0
  155. data/test/manual/test3.rb +38 -0
  156. data/test/manual/test4.rb +40 -0
  157. data/test/manual/test5.rb +24 -0
  158. data/test/manual/test6.rb +73 -0
  159. data/test/manual/test_banner_combinations.rb +120 -0
  160. data/test/manual/test_banner_features.rb +306 -0
  161. data/test/manual/test_banner_from_file.rb +150 -0
  162. data/test/manual/test_banner_in_header.rb +35 -0
  163. data/test/manual/test_code_highlighting.rb +68 -0
  164. data/test/manual/test_complex_header.rb +74 -0
  165. data/test/manual/test_empty_header.rb +32 -0
  166. data/test/manual/test_radial_custom.rb +58 -0
  167. data/test/manual/test_radial_large_radius.rb +52 -0
  168. data/test/manual/test_svg_debug.rb +47 -0
  169. data/test/manual/test_syntax_highlighting.rb +147 -0
  170. data/test/pages-demo/config/currentview.txt +1 -0
  171. data/test/pages-demo/views/demo/config/bootstrap_css.txt +5 -0
  172. data/test/pages-demo/views/demo/config/bootstrap_js.txt +4 -0
  173. data/test/pages-demo/views/demo/config/common.js +57 -0
  174. data/test/pages-demo/views/demo/config/footer.txt +1 -0
  175. data/test/pages-demo/views/demo/config/global-head.txt +8 -0
  176. data/test/pages-demo/views/demo/config/header.txt +1 -0
  177. data/test/pages-demo/views/demo/config/layout.txt +1 -0
  178. data/test/pages-demo/views/demo/config/left.txt +1 -0
  179. data/test/pages-demo/views/demo/config/main.txt +1 -0
  180. data/test/pages-demo/views/demo/config/right.txt +1 -0
  181. data/test/pages-demo/views/demo/config.txt +3 -0
  182. data/test/pages-demo/views/demo/output/panes/footer.html +1 -0
  183. data/test/pages-demo/views/demo/output/panes/header.html +1 -0
  184. data/test/pages-demo/views/demo/output/panes/left.html +1 -0
  185. data/test/pages-demo/views/demo/output/panes/main.html +1 -0
  186. data/test/pages-demo/views/demo/output/panes/right.html +1 -0
  187. data/test/rubytext/rubytext_comprehensive_test.rb +307 -0
  188. data/test/rubytext/rubytext_demo_test.rb +42 -0
  189. data/test/rubytext/rubytext_testing_guide.md +277 -0
  190. data/test/run_automated_tests.rb +45 -0
  191. data/test/scriptorium-TEST-1754622690-146/config/bootstrap_css.txt +5 -0
  192. data/test/scriptorium-TEST-1754622690-146/config/bootstrap_js.txt +4 -0
  193. data/test/scriptorium-TEST-1754622690-146/config/common.js +57 -0
  194. data/test/scriptorium-TEST-1754622690-146/config/currentview.txt +1 -0
  195. data/test/scriptorium-TEST-1754622690-146/config/global-head.txt +9 -0
  196. data/test/scriptorium-TEST-1754622690-146/config/last_post_num.txt +1 -0
  197. data/test/scriptorium-TEST-1754622690-146/config/os_helpers.rb +4 -0
  198. data/test/scriptorium-TEST-1754622690-146/config/widgets.txt +3 -0
  199. data/test/scriptorium-TEST-1754622690-146/posts/0001/meta.txt +8 -0
  200. data/test/scriptorium-TEST-1754622690-146/posts/0001/source.lt3 +6 -0
  201. data/test/scriptorium-TEST-1754622690-146/themes/standard/README.txt +1 -0
  202. data/test/scriptorium-TEST-1754622690-146/themes/standard/config.txt +1 -0
  203. data/test/scriptorium-TEST-1754622690-146/themes/standard/initial/post.lt3 +12 -0
  204. data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/footer.txt +2 -0
  205. data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/header.txt +4 -0
  206. data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/left.txt +3 -0
  207. data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/main.txt +5 -0
  208. data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/right.txt +3 -0
  209. data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/gen/text.css +1 -0
  210. data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/layout.txt +5 -0
  211. data/test/scriptorium-TEST-1754622690-146/themes/standard/templates/index.lt3 +1 -0
  212. data/test/scriptorium-TEST-1754622690-146/themes/standard/templates/index_entry.lt3 +14 -0
  213. data/test/scriptorium-TEST-1754622690-146/themes/standard/templates/post.lt3 +13 -0
  214. data/test/scriptorium-TEST-1754622690-146/themes/standard/templates/widget.lt3 +1 -0
  215. data/test/scriptorium-TEST-1754622690-146/views/sample/config/bootstrap_css.txt +5 -0
  216. data/test/scriptorium-TEST-1754622690-146/views/sample/config/bootstrap_js.txt +4 -0
  217. data/test/scriptorium-TEST-1754622690-146/views/sample/config/common.js +57 -0
  218. data/test/scriptorium-TEST-1754622690-146/views/sample/config/deploy.txt +5 -0
  219. data/test/scriptorium-TEST-1754622690-146/views/sample/config/footer.txt +2 -0
  220. data/test/scriptorium-TEST-1754622690-146/views/sample/config/global-head.txt +9 -0
  221. data/test/scriptorium-TEST-1754622690-146/views/sample/config/header.txt +4 -0
  222. data/test/scriptorium-TEST-1754622690-146/views/sample/config/layout.txt +5 -0
  223. data/test/scriptorium-TEST-1754622690-146/views/sample/config/left.txt +3 -0
  224. data/test/scriptorium-TEST-1754622690-146/views/sample/config/main.txt +5 -0
  225. data/test/scriptorium-TEST-1754622690-146/views/sample/config/reddit.txt +10 -0
  226. data/test/scriptorium-TEST-1754622690-146/views/sample/config/right.txt +3 -0
  227. data/test/scriptorium-TEST-1754622690-146/views/sample/config/social.txt +7 -0
  228. data/test/scriptorium-TEST-1754622690-146/views/sample/config/status.txt +7 -0
  229. data/test/scriptorium-TEST-1754622690-146/views/sample/config.txt +3 -0
  230. data/test/scriptorium-TEST-1754622690-146/views/sample/layout/footer.html +3 -0
  231. data/test/scriptorium-TEST-1754622690-146/views/sample/layout/header.html +3 -0
  232. data/test/scriptorium-TEST-1754622690-146/views/sample/layout/left.html +3 -0
  233. data/test/scriptorium-TEST-1754622690-146/views/sample/layout/main.html +3 -0
  234. data/test/scriptorium-TEST-1754622690-146/views/sample/layout/right.html +3 -0
  235. data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/footer.html +1 -0
  236. data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/header.html +1 -0
  237. data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/left.html +1 -0
  238. data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/main.html +1 -0
  239. data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/right.html +1 -0
  240. data/test/staging/.DS_Store +0 -0
  241. data/test/syntax_highlighting_test.lt3 +124 -0
  242. data/test/test_helpers.rb +230 -0
  243. data/test/tui_editor_integration_test.rb +296 -0
  244. data/test/tui_integration_test.rb +637 -0
  245. data/test/unit/api.rb +1056 -0
  246. data/test/unit/asset_management.rb +245 -0
  247. data/test/unit/clipboard_test.rb +60 -0
  248. data/test/unit/contract_test.rb +91 -0
  249. data/test/unit/core.rb +857 -0
  250. data/test/unit/deploy_test.rb +187 -0
  251. data/test/unit/gem_asset_management.rb +189 -0
  252. data/test/unit/livetext_basic.rb +69 -0
  253. data/test/unit/livetext_compatibility.rb +89 -0
  254. data/test/unit/post.rb +244 -0
  255. data/test/unit/read_commented_file_test.rb +276 -0
  256. data/test/unit/reddit_test.rb +235 -0
  257. data/test/unit/repo.rb +548 -0
  258. data/test/unit/social_test.rb +369 -0
  259. data/test/unit/symlink_test.rb +213 -0
  260. data/test/unit/view.rb +431 -0
  261. data/test/unit/widgets.rb +669 -0
  262. data/test/wizard_test.rb +123 -0
  263. data/ui/README.md +67 -0
  264. data/ui/common/lib/ui_common.rb +8 -0
  265. data/ui/rubytext/README.md +191 -0
  266. data/ui/rubytext/bin/scriptorium-rubytext +402 -0
  267. data/ui/rubytext/lib/rubytext_ui.rb +300 -0
  268. data/ui/tui/bin/scriptorium +1420 -0
  269. data/ui/tui/test/tui_test.rb +23 -0
  270. data/ui/web/app/app.rb +1378 -0
  271. data/ui/web/app/error_helpers.rb +150 -0
  272. data/ui/web/app/views/advanced_config.erb +190 -0
  273. data/ui/web/app/views/asset_management.erb +589 -0
  274. data/ui/web/app/views/banner_config.erb +200 -0
  275. data/ui/web/app/views/configure_view.erb +401 -0
  276. data/ui/web/app/views/dashboard.erb +162 -0
  277. data/ui/web/app/views/deploy_config.erb +146 -0
  278. data/ui/web/app/views/edit_pages.erb +195 -0
  279. data/ui/web/app/views/edit_post.erb +54 -0
  280. data/ui/web/app/views/error_page.erb +29 -0
  281. data/ui/web/app/views/header_config.erb +155 -0
  282. data/ui/web/app/views/layout_config.erb +147 -0
  283. data/ui/web/app/views/navbar_config.erb +411 -0
  284. data/ui/web/app/views/view_dashboard.erb +138 -0
  285. data/ui/web/bin/scriptorium-web +153 -0
  286. data/ui/web/test/web_basic_test.rb +38 -0
  287. data/ui/web/test_navbar.txt +7 -0
  288. data/ui/web/tmp/web_server.log +5 -0
  289. data/ui/web/tmp/web_server.pid +1 -0
  290. metadata +359 -7
  291. data/lib/scriptorium/engine.rb +0 -22
  292. data/test/engine/unit.rb +0 -44
@@ -0,0 +1,296 @@
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 TUIEditorIntegrationTest < Minitest::Test
10
+ # Test repository path
11
+ TEST_REPO_PATH = "scriptorium-TEST"
12
+
13
+ def setup
14
+ cleanup_test_repo
15
+ end
16
+
17
+ def teardown
18
+ cleanup_test_repo
19
+ end
20
+
21
+ def test_001_links_widget_editing_workflow
22
+ # Test the complete links widget editing workflow using PTY
23
+ # Start with no repo, let TUI create it, trigger wizard, configure links widget, edit content
24
+
25
+ # Ensure clean start
26
+ cleanup_test_repo
27
+
28
+ ENV['NOREADLINE'] = '1'
29
+
30
+ PTY.spawn({'NOREADLINE' => '1'}, 'ruby bin/scriptorium') do |read, write, pid|
31
+ begin
32
+ run_links_widget_workflow(read, write)
33
+ ensure
34
+ # Clean up the process
35
+ Process.kill('TERM', pid) rescue nil
36
+ Process.wait(pid) rescue nil
37
+ end
38
+ end
39
+ ensure
40
+ ENV.delete('NOREADLINE')
41
+ end
42
+
43
+ def test_002_basic_tui_flow
44
+ # Test basic TUI flow without complex wizard
45
+ ENV['NOREADLINE'] = '1'
46
+
47
+ PTY.spawn({'NOREADLINE' => '1'}, 'ruby bin/scriptorium') do |read, write, pid|
48
+ begin
49
+ run_basic_tui_workflow(read, write)
50
+
51
+ ensure
52
+ # Clean up the process
53
+ Process.kill('TERM', pid) rescue nil
54
+ Process.wait(pid) rescue nil
55
+ end
56
+ end
57
+ ensure
58
+ ENV.delete('NOREADLINE')
59
+ end
60
+
61
+ def test_003_create_post_workflow
62
+ # Test creating a post through the TUI
63
+ ENV['NOREADLINE'] = '1'
64
+
65
+ PTY.spawn({'NOREADLINE' => '1'}, 'ruby bin/scriptorium') do |read, write, pid|
66
+ begin
67
+ run_create_post_workflow(read, write)
68
+ ensure
69
+ # Clean up the process
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
+ private
79
+
80
+ def get_string(read, pattern, message, timeout = 5)
81
+ # Convenience method to get a string matching a pattern with timeout
82
+ # Set VERBOSE=1 to see detailed output, defaults to silent
83
+ output = read.expect(pattern, timeout)
84
+ if output
85
+ puts "Found: #{output[0].strip}" if ENV['VERBOSE']
86
+ else
87
+ puts "Failed to find pattern: #{pattern}"
88
+ # Read what we actually got
89
+ available = read.read_nonblock(1000) rescue ""
90
+ puts "Available output: #{available.inspect}"
91
+ end
92
+ assert output, message
93
+ output[0] # Return the matched string
94
+ end
95
+
96
+ def cleanup_test_repo
97
+ # More aggressive cleanup - remove any test repositories
98
+ FileUtils.rm_rf(TEST_REPO_PATH) if Dir.exist?(TEST_REPO_PATH)
99
+ FileUtils.rm_rf("scriptorium-TEST") if Dir.exist?("scriptorium-TEST")
100
+ # Also clean up any other potential test repos
101
+ Dir.glob("scriptorium-*TEST*").each do |dir|
102
+ FileUtils.rm_rf(dir) if Dir.exist?(dir)
103
+ end
104
+ end
105
+
106
+ def send_and_expect(read, write, input, expected_pattern, description)
107
+ write.puts input
108
+ sleep 0.1 # Small delay to ensure input is processed
109
+ result = get_string(read, expected_pattern, description)
110
+ # Add explicit assertion for the expected pattern
111
+ assert result.match?(expected_pattern), "#{description}: Expected pattern '#{expected_pattern}' not found in output"
112
+ result
113
+ rescue Errno::EIO => e
114
+ # Handle case where TUI terminates immediately after output
115
+ if expected_pattern.to_s.include?("Goodbye!")
116
+ # If we're expecting Goodbye! and get an I/O error, that's probably OK
117
+ # The TUI terminated after outputting Goodbye!
118
+ return
119
+ else
120
+ raise e
121
+ end
122
+ end
123
+
124
+ def run_links_widget_workflow(read, write)
125
+ # Wait for initial output
126
+ get_string(read, /No repository found\./, "Should show 'No repository found'")
127
+
128
+ # Send 'y' to create new repository
129
+ send_and_expect(read, write, "y", "Created repository successfully.",
130
+ "Should show repository created")
131
+
132
+ # Wait for editor setup
133
+ get_string(read, "No editor configured", "Should show editor setup")
134
+
135
+ # Wait for editor list
136
+ get_string(read, "Available editors", "Should show available editors")
137
+
138
+ # Wait for editor choice prompt
139
+ get_string(read, "Choose editor", "Should prompt for editor selection")
140
+ send_and_expect(read, write, "4", "Selected editor: ed",
141
+ "Should show editor selection")
142
+
143
+ # Wait for setup completion
144
+ get_string(read, "Setup complete", "Should show setup completion")
145
+
146
+ # Wait for assistance question
147
+ get_string(read, "Do you want assistance in creating your first view", "Should ask about assistance")
148
+
149
+ # Send 'y' for assistance
150
+ send_and_expect(read, write, "y", "Enter view name",
151
+ "Should prompt for view name")
152
+
153
+ # Send view name
154
+ send_and_expect(read, write, "testview", "Enter view title",
155
+ "Should prompt for view title")
156
+
157
+ # Send view title
158
+ send_and_expect(read, write, "Test View", "Enter subtitle",
159
+ "Should prompt for subtitle")
160
+
161
+ # Send subtitle
162
+ send_and_expect(read, write, "Test Subtitle", "Would you like to edit the layout",
163
+ "Should ask about editing layout")
164
+
165
+ # Send 'n' to skip layout editing (avoid ed interaction issues)
166
+ send_and_expect(read, write, "n", "Would you like to configure header",
167
+ "Should ask about header configuration")
168
+
169
+ # Wait for container configuration questions (in wizard order: header, main, left, right, footer)
170
+ send_and_expect(read, write, "n", "Would you like to configure main",
171
+ "Should ask about main configuration")
172
+ send_and_expect(read, write, "n", "Would you like to configure left",
173
+ "Should ask about left configuration")
174
+
175
+ # Say yes to configure left sidebar
176
+ send_and_expect(read, write, "y", "Add widgets to left",
177
+ "Should ask about adding widgets to left")
178
+
179
+ # Say yes to add widgets
180
+ send_and_expect(read, write, "y", "Available widgets: links, pages, featuredposts",
181
+ "Should show available widgets")
182
+
183
+ send_and_expect(read, write, "y", /Add links widget\?/, "Should ask about adding links widget")
184
+
185
+ send_and_expect(read, write, "n", /Add pages widget\?/, "Should ask about adding pages widget")
186
+
187
+ send_and_expect(read, write, "n", /Add featuredposts widget\?/, "Should ask about adding featuredposts widget")
188
+
189
+ send_and_expect(read, write, "n", /Configure links widget\?/, "Should ask about configuring links widget")
190
+
191
+ # Say no to configure links widget - now should proceed to next container
192
+ send_and_expect(read, write, "n", "Would you like to configure right",
193
+ "Should ask about right configuration")
194
+
195
+
196
+ send_and_expect(read, write, "n", "Would you like to configure footer",
197
+ "Should ask about footer configuration")
198
+ send_and_expect(read, write, "n", "View setup complete",
199
+ "Should show setup completion")
200
+
201
+ # Wait for main prompt
202
+ get_string(read, "[testview]", "Should show main prompt")
203
+
204
+ # Send 'quit' to exit
205
+ send_and_expect(read, write, "quit", "Goodbye!",
206
+ "Should show goodbye message")
207
+ end
208
+
209
+ def run_basic_tui_workflow(read, write)
210
+ # Wait for initial output
211
+ get_string(read, "No repository found.", "Should show 'No repository found'")
212
+
213
+ # Send 'y' to create new repository
214
+ send_and_expect(read, write, "y", "Created repository successfully.",
215
+ "Should show repository created")
216
+
217
+ # Wait for editor setup
218
+ get_string(read, "No editor configured", "Should show editor setup")
219
+
220
+ # Wait for editor list
221
+ get_string(read, "Available editors", "Should show available editors")
222
+
223
+ # Wait for editor choice prompt
224
+ get_string(read, "Choose editor", "Should prompt for editor selection")
225
+ send_and_expect(read, write, "4", "Selected editor: ed",
226
+ "Should show editor selection")
227
+
228
+ # Wait for setup completion
229
+ get_string(read, "Setup complete", "Should show setup completion")
230
+
231
+ # Wait for assistance question
232
+ get_string(read, "Do you want assistance in creating your first view", "Should ask about assistance")
233
+
234
+ # Send 'n' to skip assistance
235
+ send_and_expect(read, write, "n", "[sample]", "Should show main prompt")
236
+
237
+ # Send 'quit' to exit
238
+ send_and_expect(read, write, "quit", "Goodbye!",
239
+ "Should show goodbye message")
240
+ end
241
+
242
+ def run_create_post_workflow(read, write)
243
+ # Wait for initial output
244
+ get_string(read, "No repository found.", "Should show 'No repository found'")
245
+
246
+ # Send 'y' to create new repository
247
+ send_and_expect(read, write, "y", "Created repository successfully.",
248
+ "Should show repository created")
249
+
250
+ # Wait for editor setup
251
+ get_string(read, "No editor configured", "Should show editor setup")
252
+
253
+ # Wait for editor list
254
+ get_string(read, "Available editors", "Should show available editors")
255
+
256
+ # Wait for editor choice prompt
257
+ get_string(read, "Choose editor", "Should prompt for editor selection")
258
+ send_and_expect(read, write, "4", "Selected editor: ed",
259
+ "Should show editor selection")
260
+
261
+ # Wait for setup completion
262
+ get_string(read, "Setup complete", "Should show setup completion")
263
+
264
+ # Wait for assistance question
265
+ get_string(read, "Do you want assistance in creating your first view", "Should ask about assistance")
266
+
267
+ # Send 'n' to skip assistance
268
+ send_and_expect(read, write, "n", "[sample]", "Should show main prompt")
269
+
270
+ # Create a post
271
+ send_and_expect(read, write, "new post Test Post", "Created draft",
272
+ "Should show draft created")
273
+
274
+ # Wait for editor opening
275
+ get_string(read, "Opening in ed", "Should show editor opening")
276
+
277
+ # Simulate ed interaction
278
+ sleep 1
279
+ write.puts "a"
280
+ write.puts "Test content"
281
+ write.puts "."
282
+ write.puts "w"
283
+ write.puts "q"
284
+ sleep 1
285
+
286
+ # Wait for post creation
287
+ get_string(read, "Post created", "Should show post created")
288
+
289
+ # Wait for main prompt
290
+ get_string(read, "[sample]", "Should show main prompt")
291
+
292
+ # Send 'quit' to exit
293
+ send_and_expect(read, write, "quit", "Goodbye!",
294
+ "Should show goodbye message")
295
+ end
296
+ end