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.
- 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/back-icon.png +0 -0
- data/assets/icons/facebook.svg +1 -0
- data/assets/icons/github.svg +1 -0
- data/assets/icons/instagram.svg +1 -0
- data/assets/icons/reddit.svg +1 -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/icons/x.svg +1 -0
- data/assets/icons/youtube.svg +1 -0
- data/assets/samples/placeholder.svg +9 -0
- data/assets/themes/standard/favicon.svg +6 -0
- data/bin/scriptorium +1511 -0
- data/doc/README.txt +6 -0
- data/doc/anti-amnesia/20250727-054000-scriptorium-overview.md +95 -0
- data/doc/anti-amnesia/20250727-060000-api-design-tui-planning.md +34 -0
- data/doc/anti-amnesia/20250727-061000-runeblog-tui-analysis.md +50 -0
- data/doc/anti-amnesia/20250727-123000-anti-amnesia-conventions.md +31 -0
- data/doc/anti-amnesia/20250727-154000-livetext-plugin-file-stats.md +73 -0
- data/doc/anti-amnesia/20250727-172600-cursor-rbenv-ruby-version-mystery.md +64 -0
- data/doc/anti-amnesia/20250727-172600-unified-minitest-framework.md +70 -0
- data/doc/anti-amnesia/20250727-172900-ai-cognitive-assessment-capabilities.md +40 -0
- data/doc/anti-amnesia/20250727-173000-widget-testing-achievement.md +110 -0
- data/doc/anti-amnesia/20250727-180000-post-id-num-refactoring.md +73 -0
- data/doc/anti-amnesia/20250728-124243-aaa-syntax-clarification.md +46 -0
- data/doc/anti-amnesia/20250728-124421-conversation-summary-concise.md +124 -0
- data/doc/anti-amnesia/20250729-190000-scriptorium-tui-testing-complete.md +46 -0
- data/doc/anti-amnesia/20250729-200000-scriptorium-tui-testing-edit-file-workflow.md +97 -0
- data/doc/anti-amnesia/20250729-210000-reddit-autopost-integration-complete.md +158 -0
- data/doc/anti-amnesia/20250729-211500-dependency-management-system.md +211 -0
- data/doc/anti-amnesia/20250729-213000-python-virtual-environment-setup.md +141 -0
- data/doc/anti-amnesia/20250729-214500-theme-management-commands.md +211 -0
- data/doc/anti-amnesia/20250729-215000-version-update-to-0.6.0.md +134 -0
- data/doc/anti-amnesia/20250729-220000-user-guide-complete.md +41 -0
- data/doc/anti-amnesia/20250804-190500-cognitive-loop-bug.md +45 -0
- data/doc/anti-amnesia/20250804-190700-anti-amnesia-timestamping-fix.md +30 -0
- data/doc/anti-amnesia/20250804-213700-publishing-test-fix.md +49 -0
- data/doc/anti-amnesia/20250804-214400-additional-test-fixes.md +46 -0
- data/doc/anti-amnesia/20250804-220000-asset-function-logic-clarification.md +41 -0
- data/doc/anti-amnesia/20250806-202032-asset-function-logic-clarification.md +41 -0
- data/doc/anti-amnesia/20250807-213025.md +116 -0
- data/doc/anti-amnesia/20250813-082428-syntax-highlighting-and-navigation-improvements.md +256 -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/reddit_credentials_template.json +8 -0
- data/doc/reddit_integration.md +207 -0
- data/doc/user.lt3 +38 -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/doc/userdoc-toc.txt +88 -0
- data/lib/rouge/lexers/livetext.rb +74 -0
- data/lib/scriptorium/api.rb +640 -0
- data/lib/scriptorium/banner_svg.rb +742 -0
- data/lib/scriptorium/contract.rb +33 -0
- data/lib/scriptorium/exceptions.rb +170 -1
- data/lib/scriptorium/helpers.rb +475 -0
- data/lib/scriptorium/post.rb +195 -0
- data/lib/scriptorium/reddit.rb +83 -0
- data/lib/scriptorium/repo.rb +624 -0
- data/lib/scriptorium/standard_files.rb +515 -0
- data/lib/scriptorium/syntax_highlighter.rb +234 -0
- data/lib/scriptorium/theme.rb +179 -0
- data/lib/scriptorium/version.rb +2 -2
- data/lib/scriptorium/view.rb +976 -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 +21 -40
- data/lib/skeleton.rb +8 -2
- data/scriptorium.gemspec +15 -4
- data/test/README.md +69 -0
- data/test/all +43 -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 +768 -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/livetext_plugin_test.rb +229 -0
- data/test/manual/asset_mgmt.rb +67 -0
- data/test/manual/banner-tests/config.txt +3 -0
- data/test/manual/banner-tests/index.html +45 -0
- data/test/manual/banner-tests/test01.html +58 -0
- data/test/manual/banner-tests/test02.html +58 -0
- data/test/manual/banner-tests/test03.html +58 -0
- data/test/manual/banner-tests/test04.html +65 -0
- data/test/manual/banner-tests/test05.html +65 -0
- data/test/manual/banner-tests/test06.html +65 -0
- data/test/manual/banner-tests/test07.html +65 -0
- data/test/manual/banner-tests/test08.html +59 -0
- data/test/manual/banner-tests/test09.html +59 -0
- data/test/manual/banner-tests/test10.html +59 -0
- data/test/manual/banner-tests/test11.html +59 -0
- data/test/manual/banner-tests/test12.html +59 -0
- data/test/manual/banner-tests/test13.html +59 -0
- data/test/manual/banner-tests/test14.html +59 -0
- data/test/manual/banner-tests/test15.html +58 -0
- data/test/manual/banner-tests/test16.html +58 -0
- data/test/manual/banner-tests/test17.html +58 -0
- data/test/manual/banner-tests/test18.html +68 -0
- data/test/manual/banner-tests/test19.html +68 -0
- data/test/manual/banner-tests/test20.html +68 -0
- data/test/manual/banner-tests/test21.html +68 -0
- data/test/manual/banner-tests/test22.html +68 -0
- data/test/manual/banner-tests/test23.html +68 -0
- data/test/manual/banner-tests/test24.html +68 -0
- data/test/manual/banner-tests/test25.html +67 -0
- data/test/manual/banner_environment.rb +192 -0
- data/test/manual/deploy_symlink_demo.rb +142 -0
- data/test/manual/environment.rb +67 -0
- data/test/manual/make_banner.rb +153 -0
- data/test/manual/sample_banner_config.txt +12 -0
- data/test/manual/symlink_demo.rb +117 -0
- data/test/manual/test1.rb +47 -0
- data/test/manual/test2.rb +12 -0
- data/test/manual/test3.rb +38 -0
- data/test/manual/test4.rb +40 -0
- data/test/manual/test5.rb +24 -0
- data/test/manual/test6.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_from_file.rb +150 -0
- data/test/manual/test_banner_in_header.rb +35 -0
- data/test/manual/test_code_highlighting.rb +68 -0
- data/test/manual/test_complex_header.rb +74 -0
- data/test/manual/test_empty_header.rb +32 -0
- data/test/manual/test_radial_custom.rb +58 -0
- data/test/manual/test_radial_large_radius.rb +52 -0
- data/test/manual/test_svg_debug.rb +47 -0
- data/test/manual/test_syntax_highlighting.rb +147 -0
- data/test/pages-demo/config/currentview.txt +1 -0
- data/test/pages-demo/views/demo/config/bootstrap_css.txt +5 -0
- data/test/pages-demo/views/demo/config/bootstrap_js.txt +4 -0
- data/test/pages-demo/views/demo/config/common.js +57 -0
- data/test/pages-demo/views/demo/config/footer.txt +1 -0
- data/test/pages-demo/views/demo/config/global-head.txt +8 -0
- data/test/pages-demo/views/demo/config/header.txt +1 -0
- data/test/pages-demo/views/demo/config/layout.txt +1 -0
- data/test/pages-demo/views/demo/config/left.txt +1 -0
- data/test/pages-demo/views/demo/config/main.txt +1 -0
- data/test/pages-demo/views/demo/config/right.txt +1 -0
- data/test/pages-demo/views/demo/config.txt +3 -0
- data/test/pages-demo/views/demo/output/panes/footer.html +1 -0
- data/test/pages-demo/views/demo/output/panes/header.html +1 -0
- data/test/pages-demo/views/demo/output/panes/left.html +1 -0
- data/test/pages-demo/views/demo/output/panes/main.html +1 -0
- data/test/pages-demo/views/demo/output/panes/right.html +1 -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/scriptorium-TEST-1754622690-146/config/bootstrap_css.txt +5 -0
- data/test/scriptorium-TEST-1754622690-146/config/bootstrap_js.txt +4 -0
- data/test/scriptorium-TEST-1754622690-146/config/common.js +57 -0
- data/test/scriptorium-TEST-1754622690-146/config/currentview.txt +1 -0
- data/test/scriptorium-TEST-1754622690-146/config/global-head.txt +9 -0
- data/test/scriptorium-TEST-1754622690-146/config/last_post_num.txt +1 -0
- data/test/scriptorium-TEST-1754622690-146/config/os_helpers.rb +4 -0
- data/test/scriptorium-TEST-1754622690-146/config/widgets.txt +3 -0
- data/test/scriptorium-TEST-1754622690-146/posts/0001/meta.txt +8 -0
- data/test/scriptorium-TEST-1754622690-146/posts/0001/source.lt3 +6 -0
- data/test/scriptorium-TEST-1754622690-146/themes/standard/README.txt +1 -0
- data/test/scriptorium-TEST-1754622690-146/themes/standard/config.txt +1 -0
- data/test/scriptorium-TEST-1754622690-146/themes/standard/initial/post.lt3 +12 -0
- data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/footer.txt +2 -0
- data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/header.txt +4 -0
- data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/left.txt +3 -0
- data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/main.txt +5 -0
- data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/config/right.txt +3 -0
- data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/gen/text.css +1 -0
- data/test/scriptorium-TEST-1754622690-146/themes/standard/layout/layout.txt +5 -0
- data/test/scriptorium-TEST-1754622690-146/themes/standard/templates/index.lt3 +1 -0
- data/test/scriptorium-TEST-1754622690-146/themes/standard/templates/index_entry.lt3 +14 -0
- data/test/scriptorium-TEST-1754622690-146/themes/standard/templates/post.lt3 +13 -0
- data/test/scriptorium-TEST-1754622690-146/themes/standard/templates/widget.lt3 +1 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/bootstrap_css.txt +5 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/bootstrap_js.txt +4 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/common.js +57 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/deploy.txt +5 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/footer.txt +2 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/global-head.txt +9 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/header.txt +4 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/layout.txt +5 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/left.txt +3 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/main.txt +5 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/reddit.txt +10 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/right.txt +3 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/social.txt +7 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/config/status.txt +7 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/config.txt +3 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/layout/footer.html +3 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/layout/header.html +3 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/layout/left.html +3 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/layout/main.html +3 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/layout/right.html +3 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/footer.html +1 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/header.html +1 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/left.html +1 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/main.html +1 -0
- data/test/scriptorium-TEST-1754622690-146/views/sample/output/panes/right.html +1 -0
- data/test/staging/.DS_Store +0 -0
- data/test/syntax_highlighting_test.lt3 +124 -0
- data/test/test_helpers.rb +230 -0
- data/test/tui_editor_integration_test.rb +296 -0
- data/test/tui_integration_test.rb +637 -0
- data/test/unit/api.rb +1056 -0
- data/test/unit/asset_management.rb +245 -0
- data/test/unit/clipboard_test.rb +60 -0
- data/test/unit/contract_test.rb +91 -0
- data/test/unit/core.rb +857 -0
- data/test/unit/deploy_test.rb +187 -0
- data/test/unit/gem_asset_management.rb +189 -0
- data/test/unit/livetext_basic.rb +69 -0
- data/test/unit/livetext_compatibility.rb +89 -0
- data/test/unit/post.rb +244 -0
- data/test/unit/read_commented_file_test.rb +276 -0
- data/test/unit/reddit_test.rb +235 -0
- data/test/unit/repo.rb +548 -0
- data/test/unit/social_test.rb +369 -0
- data/test/unit/symlink_test.rb +213 -0
- data/test/unit/view.rb +431 -0
- data/test/unit/widgets.rb +669 -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 +1420 -0
- data/ui/tui/test/tui_test.rb +23 -0
- data/ui/web/app/app.rb +1378 -0
- data/ui/web/app/error_helpers.rb +150 -0
- data/ui/web/app/views/advanced_config.erb +190 -0
- data/ui/web/app/views/asset_management.erb +589 -0
- data/ui/web/app/views/banner_config.erb +200 -0
- data/ui/web/app/views/configure_view.erb +401 -0
- data/ui/web/app/views/dashboard.erb +162 -0
- data/ui/web/app/views/deploy_config.erb +146 -0
- data/ui/web/app/views/edit_pages.erb +195 -0
- data/ui/web/app/views/edit_post.erb +54 -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/view_dashboard.erb +138 -0
- data/ui/web/bin/scriptorium-web +153 -0
- data/ui/web/test/web_basic_test.rb +38 -0
- data/ui/web/test_navbar.txt +7 -0
- data/ui/web/tmp/web_server.log +5 -0
- data/ui/web/tmp/web_server.pid +1 -0
- metadata +359 -7
- data/lib/scriptorium/engine.rb +0 -22
- data/test/engine/unit.rb +0 -44
data/test/unit/core.rb
ADDED
@@ -0,0 +1,857 @@
|
|
1
|
+
# This test file primarily tests the core helper methods from lib/scriptorium/helpers.rb
|
2
|
+
# including file I/O operations, directory creation, system commands, and existence validation
|
3
|
+
# test/unit/core.rb
|
4
|
+
|
5
|
+
require 'minitest/autorun'
|
6
|
+
require_relative '../../lib/scriptorium'
|
7
|
+
require_relative '../test_helpers'
|
8
|
+
require 'fileutils'
|
9
|
+
require 'tempfile'
|
10
|
+
|
11
|
+
class TestReadWrite < Minitest::Test
|
12
|
+
include Scriptorium::Helpers
|
13
|
+
include Scriptorium::Exceptions
|
14
|
+
include TestHelpers
|
15
|
+
|
16
|
+
def setup
|
17
|
+
@test_dir = "test/core_test_files"
|
18
|
+
FileUtils.mkdir_p(@test_dir)
|
19
|
+
Scriptorium::Repo.testing = true # Ensure testing mode is enabled
|
20
|
+
end
|
21
|
+
|
22
|
+
def teardown
|
23
|
+
FileUtils.rm_rf(@test_dir) if File.exist?(@test_dir)
|
24
|
+
end
|
25
|
+
|
26
|
+
# ========================================
|
27
|
+
# need() tests
|
28
|
+
# ========================================
|
29
|
+
|
30
|
+
def test_001_need_file_basic_functionality
|
31
|
+
file_path = "#{@test_dir}/test_file.txt"
|
32
|
+
File.write(file_path, "test content")
|
33
|
+
|
34
|
+
result = need(:file, file_path)
|
35
|
+
assert_equal file_path, result
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_002_need_dir_basic_functionality
|
39
|
+
dir_path = "#{@test_dir}/test_dir"
|
40
|
+
Dir.mkdir(dir_path)
|
41
|
+
|
42
|
+
result = need(:dir, dir_path)
|
43
|
+
assert_equal dir_path, result
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_003_need_with_custom_exception
|
47
|
+
file_path = "#{@test_dir}/nonexistent.txt"
|
48
|
+
|
49
|
+
# Create a simple custom exception for testing
|
50
|
+
custom_error_class = Class.new(StandardError) do
|
51
|
+
def self.call(path)
|
52
|
+
new("Custom error for: #{path}")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
begin
|
57
|
+
need(:file, file_path, custom_error_class)
|
58
|
+
flunk "Expected need() to raise an error"
|
59
|
+
rescue custom_error_class => e
|
60
|
+
assert_match /Custom error for: #{file_path}/, e.message
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_004_need_nil_path_raises_error
|
65
|
+
assert_raises(CannotRequirePathNil) do
|
66
|
+
need(:file, nil)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_005_need_empty_path_raises_error
|
71
|
+
assert_raises(CannotRequirePathEmpty) do
|
72
|
+
need(:file, "")
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_006_need_whitespace_path_raises_error
|
77
|
+
assert_raises(CannotRequirePathEmpty) do
|
78
|
+
need(:file, " ")
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_007_need_invalid_type_raises_error
|
83
|
+
assert_raises(InvalidType) do
|
84
|
+
need(:invalid, "some/path")
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_008_need_file_nonexistent_raises_error
|
89
|
+
file_path = "#{@test_dir}/nonexistent.txt"
|
90
|
+
|
91
|
+
assert_raises(RequiredFileNotFound) do
|
92
|
+
need(:file, file_path)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_009_need_dir_nonexistent_raises_error
|
97
|
+
dir_path = "#{@test_dir}/nonexistent_dir"
|
98
|
+
|
99
|
+
assert_raises(RequiredFileNotFound) do
|
100
|
+
need(:dir, dir_path)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# ========================================
|
105
|
+
# system! tests
|
106
|
+
# ========================================
|
107
|
+
|
108
|
+
def test_010_system_basic_functionality
|
109
|
+
# Test a simple command that should succeed
|
110
|
+
result = system!("echo 'test' > /dev/null", "basic echo test")
|
111
|
+
assert result
|
112
|
+
end
|
113
|
+
|
114
|
+
def test_011_system_with_description
|
115
|
+
# Test that description is included in error message
|
116
|
+
begin
|
117
|
+
system!("false", "testing failure")
|
118
|
+
flunk "Expected system! to raise an error"
|
119
|
+
rescue CommandFailedWithDesc => e
|
120
|
+
assert_match /testing failure/, e.message
|
121
|
+
assert_match /Command failed/, e.message
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def test_012_system_nil_command_raises_error
|
126
|
+
assert_raises(CannotExecuteCommandNil) do
|
127
|
+
system!(nil)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_013_system_empty_command_raises_error
|
132
|
+
assert_raises(CannotExecuteCommandEmpty) do
|
133
|
+
system!("")
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def test_014_system_whitespace_command_raises_error
|
138
|
+
assert_raises(CannotExecuteCommandEmpty) do
|
139
|
+
system!(" ")
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def test_015_system_failing_command_raises_error
|
144
|
+
assert_raises(CommandFailedWithDesc) do
|
145
|
+
system!("false")
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def test_016_system_nonexistent_command_raises_error
|
150
|
+
assert_raises(CommandFailedWithDesc) do
|
151
|
+
system!("nonexistent_command_that_should_fail")
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# ========================================
|
156
|
+
# make_dir tests
|
157
|
+
# ========================================
|
158
|
+
|
159
|
+
def test_017_make_dir_basic_functionality
|
160
|
+
dir_path = "#{@test_dir}/new_dir"
|
161
|
+
|
162
|
+
make_dir(dir_path)
|
163
|
+
|
164
|
+
assert Dir.exist?(dir_path)
|
165
|
+
end
|
166
|
+
|
167
|
+
def test_018_make_dir_with_parents
|
168
|
+
dir_path = "#{@test_dir}/nested/deep/path"
|
169
|
+
|
170
|
+
make_dir(dir_path, create_parents: true)
|
171
|
+
|
172
|
+
assert Dir.exist?(dir_path)
|
173
|
+
assert Dir.exist?("#{@test_dir}/nested")
|
174
|
+
assert Dir.exist?("#{@test_dir}/nested/deep")
|
175
|
+
end
|
176
|
+
|
177
|
+
def test_019_make_dir_existing_directory
|
178
|
+
dir_path = "#{@test_dir}/existing_dir"
|
179
|
+
Dir.mkdir(dir_path)
|
180
|
+
|
181
|
+
# Should not raise an error
|
182
|
+
make_dir(dir_path)
|
183
|
+
|
184
|
+
assert Dir.exist?(dir_path)
|
185
|
+
end
|
186
|
+
|
187
|
+
def test_020_make_dir_nil_path_raises_error
|
188
|
+
assert_raises(CannotCreateDirectoryPathNil) do
|
189
|
+
make_dir(nil)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def test_021_make_dir_empty_path_raises_error
|
194
|
+
assert_raises(CannotCreateDirectoryPathEmpty) do
|
195
|
+
make_dir("")
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def test_022_make_dir_whitespace_path_raises_error
|
200
|
+
assert_raises(CannotCreateDirectoryPathEmpty) do
|
201
|
+
make_dir(" ")
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def test_023_make_dir_permission_denied_simulation
|
206
|
+
# Create a read-only directory
|
207
|
+
read_only_dir = "#{@test_dir}/readonly"
|
208
|
+
Dir.mkdir(read_only_dir)
|
209
|
+
FileUtils.chmod(0444, read_only_dir)
|
210
|
+
|
211
|
+
file_path = "#{read_only_dir}/test_dir"
|
212
|
+
|
213
|
+
# This should raise a permission denied error
|
214
|
+
assert_raises(CannotCreateDirectoryPermissionDenied) do
|
215
|
+
make_dir(file_path)
|
216
|
+
end
|
217
|
+
|
218
|
+
# Clean up
|
219
|
+
FileUtils.chmod(0755, read_only_dir)
|
220
|
+
end
|
221
|
+
|
222
|
+
# ========================================
|
223
|
+
# write_file tests
|
224
|
+
# ========================================
|
225
|
+
|
226
|
+
def test_024_write_file_basic_functionality
|
227
|
+
file_path = "#{@test_dir}/basic.txt"
|
228
|
+
content = ["line1", "line2", "line3"]
|
229
|
+
|
230
|
+
write_file(file_path, content.join("\n"))
|
231
|
+
|
232
|
+
assert File.exist?(file_path)
|
233
|
+
assert_equal content.join("\n") + "\n", File.read(file_path)
|
234
|
+
end
|
235
|
+
|
236
|
+
def test_025_write_file_creates_parent_directories
|
237
|
+
file_path = "#{@test_dir}/nested/deep/path/file.txt"
|
238
|
+
content = ["test content"]
|
239
|
+
|
240
|
+
write_file(file_path, content.join("\n"))
|
241
|
+
|
242
|
+
assert File.exist?(file_path)
|
243
|
+
assert File.exist?("#{@test_dir}/nested/deep/path")
|
244
|
+
end
|
245
|
+
|
246
|
+
def test_026_write_file_empty_content
|
247
|
+
file_path = "#{@test_dir}/empty.txt"
|
248
|
+
|
249
|
+
write_file(file_path, "")
|
250
|
+
|
251
|
+
assert File.exist?(file_path)
|
252
|
+
assert_equal "\n", File.read(file_path)
|
253
|
+
end
|
254
|
+
|
255
|
+
def test_027_write_file_single_line
|
256
|
+
file_path = "#{@test_dir}/single.txt"
|
257
|
+
content = "single line content"
|
258
|
+
|
259
|
+
write_file(file_path, content)
|
260
|
+
|
261
|
+
assert File.exist?(file_path)
|
262
|
+
assert_equal content + "\n", File.read(file_path)
|
263
|
+
end
|
264
|
+
|
265
|
+
def test_028_write_file_multiple_lines
|
266
|
+
file_path = "#{@test_dir}/multi.txt"
|
267
|
+
content = ["first line", "second line", "third line"]
|
268
|
+
|
269
|
+
write_file(file_path, content.join("\n"))
|
270
|
+
|
271
|
+
assert File.exist?(file_path)
|
272
|
+
expected = content.join("\n") + "\n"
|
273
|
+
assert_equal expected, File.read(file_path)
|
274
|
+
end
|
275
|
+
|
276
|
+
def test_029_write_file_nil_path_raises_error
|
277
|
+
assert_raises(CannotWriteFilePathNil) do
|
278
|
+
write_file(nil, "content")
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
def test_030_write_file_empty_path_raises_error
|
283
|
+
assert_raises(CannotWriteFilePathEmpty) do
|
284
|
+
write_file("", "content")
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
def test_031_write_file_whitespace_path_raises_error
|
289
|
+
assert_raises(CannotWriteFilePathEmpty) do
|
290
|
+
write_file(" ", "content")
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
def test_032_write_file_permission_denied_simulation
|
295
|
+
# Create a read-only directory
|
296
|
+
read_only_dir = "#{@test_dir}/readonly"
|
297
|
+
FileUtils.mkdir_p(read_only_dir)
|
298
|
+
FileUtils.chmod(0444, read_only_dir)
|
299
|
+
|
300
|
+
file_path = "#{read_only_dir}/test.txt"
|
301
|
+
|
302
|
+
# This should raise a permission denied error
|
303
|
+
assert_raises(CannotWriteFilePermissionDenied) do
|
304
|
+
write_file(file_path, "content")
|
305
|
+
end
|
306
|
+
|
307
|
+
# Clean up
|
308
|
+
FileUtils.chmod(0755, read_only_dir)
|
309
|
+
end
|
310
|
+
|
311
|
+
# ========================================
|
312
|
+
# read_file tests
|
313
|
+
# ========================================
|
314
|
+
|
315
|
+
def test_033_read_file_basic_functionality
|
316
|
+
file_path = "#{@test_dir}/read_test.txt"
|
317
|
+
content = "line1\nline2\nline3"
|
318
|
+
File.write(file_path, content)
|
319
|
+
|
320
|
+
result = read_file(file_path)
|
321
|
+
|
322
|
+
assert_equal content, result
|
323
|
+
end
|
324
|
+
|
325
|
+
def test_034_read_file_as_lines
|
326
|
+
file_path = "#{@test_dir}/lines_test.txt"
|
327
|
+
content = "line1\nline2\nline3"
|
328
|
+
File.write(file_path, content)
|
329
|
+
|
330
|
+
result = read_file(file_path, lines: true)
|
331
|
+
|
332
|
+
assert_equal ["line1\n", "line2\n", "line3"], result
|
333
|
+
end
|
334
|
+
|
335
|
+
def test_035_read_file_as_lines_with_chomp
|
336
|
+
file_path = "#{@test_dir}/chomp_test.txt"
|
337
|
+
content = "line1\nline2\nline3\n"
|
338
|
+
File.write(file_path, content)
|
339
|
+
|
340
|
+
result = read_file(file_path, lines: true, chomp: true)
|
341
|
+
|
342
|
+
assert_equal ["line1", "line2", "line3"], result
|
343
|
+
end
|
344
|
+
|
345
|
+
def test_036_read_file_as_lines_without_chomp
|
346
|
+
file_path = "#{@test_dir}/no_chomp_test.txt"
|
347
|
+
content = "line1\nline2\nline3\n"
|
348
|
+
File.write(file_path, content)
|
349
|
+
|
350
|
+
result = read_file(file_path, lines: true, chomp: false)
|
351
|
+
|
352
|
+
assert_equal ["line1\n", "line2\n", "line3\n"], result
|
353
|
+
end
|
354
|
+
|
355
|
+
def test_037_read_file_missing_file_with_fallback
|
356
|
+
file_path = "#{@test_dir}/nonexistent.txt"
|
357
|
+
fallback = "fallback content"
|
358
|
+
|
359
|
+
result = read_file(file_path, missing_fallback: fallback)
|
360
|
+
|
361
|
+
assert_equal fallback, result
|
362
|
+
end
|
363
|
+
|
364
|
+
def test_038_read_file_missing_file_without_fallback_raises_error
|
365
|
+
file_path = "#{@test_dir}/nonexistent.txt"
|
366
|
+
|
367
|
+
assert_raises(CannotReadFileNotFound) do
|
368
|
+
read_file(file_path)
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
372
|
+
def test_039_read_file_nil_path_raises_error
|
373
|
+
assert_raises(CannotReadFilePathNil) do
|
374
|
+
read_file(nil)
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
def test_040_read_file_empty_path_raises_error
|
379
|
+
assert_raises(CannotReadFilePathEmpty) do
|
380
|
+
read_file("")
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
def test_041_read_file_whitespace_path_raises_error
|
385
|
+
assert_raises(CannotReadFilePathEmpty) do
|
386
|
+
read_file(" ")
|
387
|
+
end
|
388
|
+
end
|
389
|
+
|
390
|
+
def test_042_read_file_permission_denied_simulation
|
391
|
+
# Create a file and make it unreadable
|
392
|
+
file_path = "#{@test_dir}/unreadable.txt"
|
393
|
+
File.write(file_path, "content")
|
394
|
+
FileUtils.chmod(0000, file_path)
|
395
|
+
|
396
|
+
assert_raises(CannotReadFilePermissionDenied) do
|
397
|
+
read_file(file_path)
|
398
|
+
end
|
399
|
+
|
400
|
+
# Clean up
|
401
|
+
FileUtils.chmod(0644, file_path)
|
402
|
+
end
|
403
|
+
|
404
|
+
def test_043_read_file_empty_file
|
405
|
+
file_path = "#{@test_dir}/empty.txt"
|
406
|
+
File.write(file_path, "")
|
407
|
+
|
408
|
+
result = read_file(file_path)
|
409
|
+
|
410
|
+
assert_equal "", result
|
411
|
+
end
|
412
|
+
|
413
|
+
def test_044_read_file_empty_file_as_lines
|
414
|
+
file_path = "#{@test_dir}/empty_lines.txt"
|
415
|
+
File.write(file_path, "")
|
416
|
+
|
417
|
+
result = read_file(file_path, lines: true)
|
418
|
+
|
419
|
+
assert_equal [], result
|
420
|
+
end
|
421
|
+
|
422
|
+
def test_045_read_file_single_line
|
423
|
+
file_path = "#{@test_dir}/single_line.txt"
|
424
|
+
content = "single line"
|
425
|
+
File.write(file_path, content)
|
426
|
+
|
427
|
+
result = read_file(file_path)
|
428
|
+
|
429
|
+
assert_equal content, result
|
430
|
+
end
|
431
|
+
|
432
|
+
def test_046_read_file_single_line_as_lines
|
433
|
+
file_path = "#{@test_dir}/single_line.txt"
|
434
|
+
content = "single line"
|
435
|
+
File.write(file_path, content)
|
436
|
+
|
437
|
+
result = read_file(file_path, lines: true)
|
438
|
+
|
439
|
+
assert_equal [content], result
|
440
|
+
end
|
441
|
+
|
442
|
+
def test_047_read_file_with_trailing_newline
|
443
|
+
file_path = "#{@test_dir}/trailing_newline.txt"
|
444
|
+
content = "line1\nline2\n"
|
445
|
+
File.write(file_path, content)
|
446
|
+
|
447
|
+
result = read_file(file_path)
|
448
|
+
|
449
|
+
assert_equal content, result
|
450
|
+
end
|
451
|
+
|
452
|
+
def test_048_read_file_with_trailing_newline_as_lines
|
453
|
+
file_path = "#{@test_dir}/trailing_newline.txt"
|
454
|
+
content = "line1\nline2\n"
|
455
|
+
File.write(file_path, content)
|
456
|
+
|
457
|
+
result = read_file(file_path, lines: true)
|
458
|
+
|
459
|
+
assert_equal ["line1\n", "line2\n"], result
|
460
|
+
end
|
461
|
+
|
462
|
+
def test_049_read_file_with_trailing_newline_as_lines_no_chomp
|
463
|
+
file_path = "#{@test_dir}/trailing_newline.txt"
|
464
|
+
content = "line1\nline2\n"
|
465
|
+
File.write(file_path, content)
|
466
|
+
|
467
|
+
result = read_file(file_path, lines: true, chomp: false)
|
468
|
+
|
469
|
+
assert_equal ["line1\n", "line2\n"], result
|
470
|
+
end
|
471
|
+
|
472
|
+
# ========================================
|
473
|
+
# Integration tests
|
474
|
+
# ========================================
|
475
|
+
|
476
|
+
def test_050_write_then_read_cycle
|
477
|
+
file_path = "#{@test_dir}/cycle.txt"
|
478
|
+
original_content = ["first line", "second line", "third line"]
|
479
|
+
|
480
|
+
# Write content
|
481
|
+
write_file(file_path, original_content.join("\n"))
|
482
|
+
|
483
|
+
# Read it back
|
484
|
+
read_content = read_file(file_path)
|
485
|
+
|
486
|
+
# Verify
|
487
|
+
expected_content = original_content.join("\n") + "\n"
|
488
|
+
assert_equal expected_content, read_content
|
489
|
+
end
|
490
|
+
|
491
|
+
def test_051_write_then_read_as_lines_cycle
|
492
|
+
file_path = "#{@test_dir}/cycle_lines.txt"
|
493
|
+
original_content = ["first line", "second line", "third line"]
|
494
|
+
|
495
|
+
# Write content
|
496
|
+
write_file(file_path, original_content.join("\n"))
|
497
|
+
|
498
|
+
# Read it back as lines
|
499
|
+
read_content = read_file(file_path, lines: true)
|
500
|
+
|
501
|
+
# Verify
|
502
|
+
assert_equal ["first line\n", "second line\n", "third line\n"], read_content
|
503
|
+
end
|
504
|
+
|
505
|
+
def test_052_multiple_write_operations
|
506
|
+
file_path = "#{@test_dir}/multiple.txt"
|
507
|
+
|
508
|
+
# First write
|
509
|
+
write_file(file_path, "first content")
|
510
|
+
assert_equal "first content\n", File.read(file_path)
|
511
|
+
|
512
|
+
# Second write (should overwrite)
|
513
|
+
write_file(file_path, "second content")
|
514
|
+
assert_equal "second content\n", File.read(file_path)
|
515
|
+
end
|
516
|
+
|
517
|
+
def test_053_write_file_with_special_characters
|
518
|
+
file_path = "#{@test_dir}/special.txt"
|
519
|
+
content = ["line with spaces", "line\twith\ttabs", "line with # comments"]
|
520
|
+
|
521
|
+
write_file(file_path, content.join("\n"))
|
522
|
+
|
523
|
+
result = read_file(file_path, lines: true)
|
524
|
+
assert_equal ["line with spaces\n", "line\twith\ttabs\n", "line with # comments\n"], result
|
525
|
+
end
|
526
|
+
|
527
|
+
def test_054_read_file_with_unicode_content
|
528
|
+
file_path = "#{@test_dir}/unicode.txt"
|
529
|
+
content = ["café", "naïve", "résumé", "über"]
|
530
|
+
|
531
|
+
write_file(file_path, content.join("\n"))
|
532
|
+
|
533
|
+
result = read_file(file_path, lines: true)
|
534
|
+
assert_equal ["café\n", "naïve\n", "résumé\n", "über\n"], result
|
535
|
+
end
|
536
|
+
|
537
|
+
# ========================================
|
538
|
+
# Edge case tests
|
539
|
+
# ========================================
|
540
|
+
|
541
|
+
def test_055_write_file_with_nil_lines
|
542
|
+
file_path = "#{@test_dir}/nil_lines.txt"
|
543
|
+
|
544
|
+
write_file!(file_path, nil, "content", nil)
|
545
|
+
|
546
|
+
result = read_file(file_path, lines: true)
|
547
|
+
assert_equal ["\n", "content\n", "\n"], result
|
548
|
+
end
|
549
|
+
|
550
|
+
def test_056_write_file_with_empty_strings
|
551
|
+
file_path = "#{@test_dir}/empty_strings.txt"
|
552
|
+
|
553
|
+
write_file!(file_path, "", "content", "")
|
554
|
+
|
555
|
+
result = read_file(file_path, lines: true)
|
556
|
+
assert_equal ["\n", "content\n", "\n"], result
|
557
|
+
end
|
558
|
+
|
559
|
+
def test_057_read_file_missing_fallback_with_lines_option
|
560
|
+
file_path = "#{@test_dir}/nonexistent.txt"
|
561
|
+
fallback = ["fallback", "lines"]
|
562
|
+
|
563
|
+
result = read_file(file_path, lines: true, missing_fallback: fallback)
|
564
|
+
|
565
|
+
assert_equal fallback, result
|
566
|
+
end
|
567
|
+
|
568
|
+
def test_058_read_file_missing_fallback_with_chomp_option
|
569
|
+
file_path = "#{@test_dir}/nonexistent.txt"
|
570
|
+
fallback = ["fallback", "lines"]
|
571
|
+
|
572
|
+
result = read_file(file_path, lines: true, chomp: true, missing_fallback: fallback)
|
573
|
+
|
574
|
+
assert_equal fallback, result
|
575
|
+
end
|
576
|
+
|
577
|
+
def test_059_write_file_very_long_line
|
578
|
+
file_path = "#{@test_dir}/long_line.txt"
|
579
|
+
long_line = "x" * 10000
|
580
|
+
|
581
|
+
write_file(file_path, long_line)
|
582
|
+
|
583
|
+
result = read_file(file_path)
|
584
|
+
assert_equal long_line + "\n", result
|
585
|
+
end
|
586
|
+
|
587
|
+
def test_060_write_file_many_lines
|
588
|
+
file_path = "#{@test_dir}/many_lines.txt"
|
589
|
+
many_lines = (1..1000).map { |i| "line #{i}" }
|
590
|
+
|
591
|
+
write_file(file_path, many_lines.join("\n"))
|
592
|
+
|
593
|
+
result = read_file(file_path, lines: true)
|
594
|
+
expected_lines = many_lines.map { |line| line + "\n" }
|
595
|
+
assert_equal expected_lines, result
|
596
|
+
end
|
597
|
+
|
598
|
+
# ========================================
|
599
|
+
# Moved helper method tests (3 tests)
|
600
|
+
# ========================================
|
601
|
+
|
602
|
+
def test_061_change_config
|
603
|
+
cfg_file = "#{@test_dir}/myconfig.txt"
|
604
|
+
File.open(cfg_file, "w") do |f|
|
605
|
+
f.puts <<~EOS
|
606
|
+
alpha foo # nothing much
|
607
|
+
beta bar # meh again
|
608
|
+
gamma baz # whatever
|
609
|
+
EOS
|
610
|
+
end
|
611
|
+
change_config(cfg_file, "beta", "new-value")
|
612
|
+
lines = File.readlines(cfg_file).map(&:chomp)
|
613
|
+
assert lines[0] == "alpha foo # nothing much", "Expected alpha text"
|
614
|
+
assert lines[1] == "beta new-value # meh again", "Expected beta text"
|
615
|
+
assert lines[2] == "gamma baz # whatever", "Expected gamma text"
|
616
|
+
end
|
617
|
+
|
618
|
+
def test_062_read_commented_file
|
619
|
+
# Setup: Create a temporary test config file
|
620
|
+
test_file = "#{@test_dir}/test_config.txt"
|
621
|
+
File.open(test_file, "w") do |f|
|
622
|
+
f.puts "# This is a comment"
|
623
|
+
f.puts ""
|
624
|
+
f.puts "header 20% # This is a header line with a comment"
|
625
|
+
f.puts "footer # This is a footer line with another comment"
|
626
|
+
f.puts "# Another full-line comment"
|
627
|
+
f.puts "main # Main content area"
|
628
|
+
end
|
629
|
+
|
630
|
+
# Expected result: an array of non-comment lines, with comments stripped
|
631
|
+
expected_result = ["header 20%", "footer", "main"]
|
632
|
+
|
633
|
+
# Run the method
|
634
|
+
result = read_commented_file(test_file)
|
635
|
+
|
636
|
+
# Assert the result matches the expected array
|
637
|
+
assert_equal expected_result, result
|
638
|
+
end
|
639
|
+
|
640
|
+
def test_063_get_asset_path
|
641
|
+
name = "back-icon.png"
|
642
|
+
result = get_asset_path(name)
|
643
|
+
assert result == "assets/#{name}", "Expected #{name} to be in assets (got #{result})"
|
644
|
+
assert_raises(AssetNotFound) { get_asset_path("nonexistent.png") }
|
645
|
+
end
|
646
|
+
|
647
|
+
# ========================================
|
648
|
+
# New helper method tests
|
649
|
+
# ========================================
|
650
|
+
|
651
|
+
def test_064_slugify_basic
|
652
|
+
result = slugify(42, "My Test Post")
|
653
|
+
assert_equal "0042-my-test-post", result
|
654
|
+
end
|
655
|
+
|
656
|
+
def test_065_slugify_with_special_characters
|
657
|
+
result = slugify(1, "Post with & < > \" ' characters!")
|
658
|
+
assert_equal "0001-post-with-characters", result
|
659
|
+
end
|
660
|
+
|
661
|
+
def test_066_slugify_with_underscores_and_hyphens
|
662
|
+
result = slugify(123, "Post with_underscores-and-hyphens")
|
663
|
+
assert_equal "0123-post-with-underscores-and-hyphens", result
|
664
|
+
end
|
665
|
+
|
666
|
+
def test_067_slugify_with_multiple_spaces
|
667
|
+
result = slugify(5, "Post with multiple spaces")
|
668
|
+
assert_equal "0005-post-with-multiple-spaces", result
|
669
|
+
end
|
670
|
+
|
671
|
+
def test_068_slugify_with_leading_trailing_hyphens
|
672
|
+
result = slugify(99, "-Post with leading/trailing hyphens-")
|
673
|
+
assert_equal "0099-post-with-leadingtrailing-hyphens", result
|
674
|
+
end
|
675
|
+
|
676
|
+
# ========================================
|
677
|
+
# clean_slugify tests
|
678
|
+
# ========================================
|
679
|
+
|
680
|
+
def test_083_clean_slugify_basic
|
681
|
+
result = clean_slugify("My Test Post")
|
682
|
+
assert_equal "my-test-post", result
|
683
|
+
end
|
684
|
+
|
685
|
+
def test_084_clean_slugify_with_special_characters
|
686
|
+
result = clean_slugify("Post with & < > \" ' characters!")
|
687
|
+
assert_equal "post-with-characters", result
|
688
|
+
end
|
689
|
+
|
690
|
+
def test_085_clean_slugify_with_underscores_and_hyphens
|
691
|
+
result = clean_slugify("Post with_underscores-and-hyphens")
|
692
|
+
assert_equal "post-with-underscores-and-hyphens", result
|
693
|
+
end
|
694
|
+
|
695
|
+
def test_086_clean_slugify_with_multiple_spaces
|
696
|
+
result = clean_slugify("Post with multiple spaces")
|
697
|
+
assert_equal "post-with-multiple-spaces", result
|
698
|
+
end
|
699
|
+
|
700
|
+
def test_087_clean_slugify_with_leading_trailing_hyphens
|
701
|
+
result = clean_slugify("-Post with leading/trailing hyphens-")
|
702
|
+
assert_equal "post-with-leadingtrailing-hyphens", result
|
703
|
+
end
|
704
|
+
|
705
|
+
def test_088_clean_slugify_empty_string
|
706
|
+
result = clean_slugify("")
|
707
|
+
assert_equal "", result
|
708
|
+
end
|
709
|
+
|
710
|
+
def test_089_clean_slugify_nil_string
|
711
|
+
result = clean_slugify(nil)
|
712
|
+
assert_equal "title-is-missing", result
|
713
|
+
end
|
714
|
+
|
715
|
+
def test_069_escape_html_basic
|
716
|
+
result = escape_html("<script>alert('test')</script>")
|
717
|
+
assert_equal "<script>alert('test')</script>", result
|
718
|
+
end
|
719
|
+
|
720
|
+
def test_070_escape_html_with_quotes
|
721
|
+
result = escape_html('He said "Hello" and she said \'Hi\'')
|
722
|
+
assert_equal "He said "Hello" and she said 'Hi'", result
|
723
|
+
end
|
724
|
+
|
725
|
+
def test_071_escape_html_with_ampersand
|
726
|
+
result = escape_html("Fish & Chips")
|
727
|
+
assert_equal "Fish & Chips", result
|
728
|
+
end
|
729
|
+
|
730
|
+
def test_072_escape_html_with_mixed_content
|
731
|
+
result = escape_html('<a href="test">Link & Text</a>')
|
732
|
+
assert_equal "<a href="test">Link & Text</a>", result
|
733
|
+
end
|
734
|
+
|
735
|
+
def test_073_getvars_basic
|
736
|
+
config_file = "#{@test_dir}/config.txt"
|
737
|
+
File.write(config_file, <<~EOS)
|
738
|
+
title My Blog
|
739
|
+
subtitle A test blog
|
740
|
+
theme standard
|
741
|
+
EOS
|
742
|
+
|
743
|
+
result = getvars(config_file)
|
744
|
+
assert_equal "My Blog", result[:title]
|
745
|
+
assert_equal "A test blog", result[:subtitle]
|
746
|
+
assert_equal "standard", result[:theme]
|
747
|
+
end
|
748
|
+
|
749
|
+
def test_074_getvars_with_comments
|
750
|
+
config_file = "#{@test_dir}/config_with_comments.txt"
|
751
|
+
File.write(config_file, <<~EOS)
|
752
|
+
# This is a comment
|
753
|
+
title My Blog # Another comment
|
754
|
+
subtitle A test blog
|
755
|
+
# Empty line below
|
756
|
+
|
757
|
+
theme standard
|
758
|
+
EOS
|
759
|
+
|
760
|
+
result = getvars(config_file)
|
761
|
+
assert_equal "My Blog", result[:title]
|
762
|
+
assert_equal "A test blog", result[:subtitle]
|
763
|
+
assert_equal "standard", result[:theme]
|
764
|
+
assert_equal 3, result.size # Only valid key-value pairs
|
765
|
+
end
|
766
|
+
|
767
|
+
def test_075_getvars_with_empty_values
|
768
|
+
config_file = "#{@test_dir}/config_empty.txt"
|
769
|
+
File.write(config_file, <<~EOS)
|
770
|
+
title My Blog
|
771
|
+
subtitle
|
772
|
+
theme standard
|
773
|
+
EOS
|
774
|
+
|
775
|
+
result = getvars(config_file)
|
776
|
+
assert_equal "My Blog", result[:title]
|
777
|
+
assert_nil result[:subtitle] # When no value after key, split returns nil
|
778
|
+
assert_equal "standard", result[:theme]
|
779
|
+
end
|
780
|
+
|
781
|
+
def test_076_d4_basic
|
782
|
+
assert_equal "0001", d4(1)
|
783
|
+
assert_equal "0042", d4(42)
|
784
|
+
assert_equal "0123", d4(123)
|
785
|
+
assert_equal "9999", d4(9999)
|
786
|
+
end
|
787
|
+
|
788
|
+
def test_077_d4_with_large_numbers
|
789
|
+
assert_equal "10000", d4(10000)
|
790
|
+
assert_equal "12345", d4(12345)
|
791
|
+
end
|
792
|
+
|
793
|
+
def test_078_substitute_with_hash
|
794
|
+
vars = {title: "My Title", content: "My Content"}
|
795
|
+
template = "Title: %{title}\nContent: %{content}"
|
796
|
+
|
797
|
+
result = substitute(vars, template)
|
798
|
+
assert_equal "Title: My Title\nContent: My Content", result
|
799
|
+
end
|
800
|
+
|
801
|
+
def test_079_substitute_with_object
|
802
|
+
# Create a mock object with vars method
|
803
|
+
mock_obj = Object.new
|
804
|
+
def mock_obj.vars
|
805
|
+
{title: "My Title", content: "My Content"}
|
806
|
+
end
|
807
|
+
|
808
|
+
template = "Title: %{title}\nContent: %{content}"
|
809
|
+
result = substitute(mock_obj, template)
|
810
|
+
assert_equal "Title: My Title\nContent: My Content", result
|
811
|
+
end
|
812
|
+
|
813
|
+
def test_080_substitute_with_missing_vars
|
814
|
+
vars = {title: "My Title"}
|
815
|
+
template = "Title: %{title}\nContent: %{content}"
|
816
|
+
|
817
|
+
# The substitute method raises KeyError for missing keys
|
818
|
+
assert_raises(KeyError) do
|
819
|
+
substitute(vars, template)
|
820
|
+
end
|
821
|
+
end
|
822
|
+
|
823
|
+
def test_081_make_tree_basic
|
824
|
+
tree_text = <<~EOS
|
825
|
+
test_tree/
|
826
|
+
├── file1.txt
|
827
|
+
├── dir1/
|
828
|
+
│ ├── file2.txt
|
829
|
+
│ └── subdir/
|
830
|
+
│ └── file3.txt
|
831
|
+
└── file4.txt
|
832
|
+
EOS
|
833
|
+
|
834
|
+
make_tree(@test_dir, tree_text)
|
835
|
+
|
836
|
+
assert File.exist?("#{@test_dir}/test_tree/file1.txt")
|
837
|
+
assert File.exist?("#{@test_dir}/test_tree/dir1/file2.txt")
|
838
|
+
assert File.exist?("#{@test_dir}/test_tree/dir1/subdir/file3.txt")
|
839
|
+
assert File.exist?("#{@test_dir}/test_tree/file4.txt")
|
840
|
+
end
|
841
|
+
|
842
|
+
def test_082_make_tree_with_comments
|
843
|
+
tree_text = <<~EOS
|
844
|
+
test_tree_with_comments/
|
845
|
+
├── file1.txt # This is a comment
|
846
|
+
├── dir1/ # Another comment
|
847
|
+
│ └── file2.txt
|
848
|
+
└── file3.txt
|
849
|
+
EOS
|
850
|
+
|
851
|
+
make_tree(@test_dir, tree_text)
|
852
|
+
|
853
|
+
assert File.exist?("#{@test_dir}/test_tree_with_comments/file1.txt")
|
854
|
+
assert File.exist?("#{@test_dir}/test_tree_with_comments/dir1/file2.txt")
|
855
|
+
assert File.exist?("#{@test_dir}/test_tree_with_comments/file3.txt")
|
856
|
+
end
|
857
|
+
end
|