monad 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (143) hide show
  1. data/CONTRIBUTING.md +68 -0
  2. data/Gemfile +2 -0
  3. data/LICENSE +21 -0
  4. data/README.md +88 -0
  5. data/Rakefile +136 -0
  6. data/bin/monad +102 -0
  7. data/cucumber.yml +3 -0
  8. data/features/create_sites.feature +112 -0
  9. data/features/data_sources.feature +76 -0
  10. data/features/drafts.feature +25 -0
  11. data/features/embed_filters.feature +60 -0
  12. data/features/markdown.feature +30 -0
  13. data/features/pagination.feature +54 -0
  14. data/features/permalinks.feature +65 -0
  15. data/features/post_data.feature +214 -0
  16. data/features/site_configuration.feature +206 -0
  17. data/features/site_data.feature +101 -0
  18. data/features/step_definitions/monad_steps.rb +175 -0
  19. data/features/support/env.rb +25 -0
  20. data/lib/monad.rb +90 -0
  21. data/lib/monad/command.rb +27 -0
  22. data/lib/monad/commands/build.rb +64 -0
  23. data/lib/monad/commands/doctor.rb +29 -0
  24. data/lib/monad/commands/new.rb +50 -0
  25. data/lib/monad/commands/serve.rb +33 -0
  26. data/lib/monad/configuration.rb +183 -0
  27. data/lib/monad/converter.rb +48 -0
  28. data/lib/monad/converters/identity.rb +21 -0
  29. data/lib/monad/converters/markdown.rb +43 -0
  30. data/lib/monad/converters/markdown/kramdown_parser.rb +44 -0
  31. data/lib/monad/converters/markdown/maruku_parser.rb +47 -0
  32. data/lib/monad/converters/markdown/rdiscount_parser.rb +35 -0
  33. data/lib/monad/converters/markdown/redcarpet_parser.rb +70 -0
  34. data/lib/monad/converters/textile.rb +50 -0
  35. data/lib/monad/convertible.rb +152 -0
  36. data/lib/monad/core_ext.rb +68 -0
  37. data/lib/monad/deprecator.rb +32 -0
  38. data/lib/monad/draft.rb +35 -0
  39. data/lib/monad/drivers/json_driver.rb +39 -0
  40. data/lib/monad/drivers/yaml_driver.rb +23 -0
  41. data/lib/monad/errors.rb +4 -0
  42. data/lib/monad/filters.rb +154 -0
  43. data/lib/monad/generator.rb +4 -0
  44. data/lib/monad/generators/pagination.rb +143 -0
  45. data/lib/monad/layout.rb +42 -0
  46. data/lib/monad/logger.rb +54 -0
  47. data/lib/monad/mime.types +85 -0
  48. data/lib/monad/page.rb +163 -0
  49. data/lib/monad/plugin.rb +75 -0
  50. data/lib/monad/post.rb +377 -0
  51. data/lib/monad/site.rb +455 -0
  52. data/lib/monad/static_file.rb +70 -0
  53. data/lib/monad/tags/gist.rb +30 -0
  54. data/lib/monad/tags/highlight.rb +85 -0
  55. data/lib/monad/tags/include.rb +37 -0
  56. data/lib/monad/tags/post_url.rb +61 -0
  57. data/lib/site_template/.gitignore +1 -0
  58. data/lib/site_template/_config.yml +2 -0
  59. data/lib/site_template/_layouts/default.html +46 -0
  60. data/lib/site_template/_layouts/post.html +9 -0
  61. data/lib/site_template/_posts/0000-00-00-welcome-to-monad.markdown.erb +24 -0
  62. data/lib/site_template/css/main.css +165 -0
  63. data/lib/site_template/css/syntax.css +60 -0
  64. data/lib/site_template/index.html +13 -0
  65. data/monad.gemspec +197 -0
  66. data/script/bootstrap +2 -0
  67. data/test/fixtures/broken_front_matter1.erb +5 -0
  68. data/test/fixtures/broken_front_matter2.erb +4 -0
  69. data/test/fixtures/broken_front_matter3.erb +7 -0
  70. data/test/fixtures/exploit_front_matter.erb +4 -0
  71. data/test/fixtures/front_matter.erb +4 -0
  72. data/test/fixtures/members.yaml +7 -0
  73. data/test/helper.rb +62 -0
  74. data/test/source/.htaccess +8 -0
  75. data/test/source/_includes/sig.markdown +3 -0
  76. data/test/source/_layouts/default.html +27 -0
  77. data/test/source/_layouts/simple.html +1 -0
  78. data/test/source/_plugins/dummy.rb +8 -0
  79. data/test/source/_posts/2008-02-02-not-published.textile +8 -0
  80. data/test/source/_posts/2008-02-02-published.textile +8 -0
  81. data/test/source/_posts/2008-10-18-foo-bar.textile +8 -0
  82. data/test/source/_posts/2008-11-21-complex.textile +8 -0
  83. data/test/source/_posts/2008-12-03-permalinked-post.textile +9 -0
  84. data/test/source/_posts/2008-12-13-include.markdown +8 -0
  85. data/test/source/_posts/2009-01-27-array-categories.textile +10 -0
  86. data/test/source/_posts/2009-01-27-categories.textile +7 -0
  87. data/test/source/_posts/2009-01-27-category.textile +7 -0
  88. data/test/source/_posts/2009-01-27-empty-categories.textile +7 -0
  89. data/test/source/_posts/2009-01-27-empty-category.textile +7 -0
  90. data/test/source/_posts/2009-03-12-hash-#1.markdown +6 -0
  91. data/test/source/_posts/2009-05-18-empty-tag.textile +6 -0
  92. data/test/source/_posts/2009-05-18-empty-tags.textile +6 -0
  93. data/test/source/_posts/2009-05-18-tag.textile +6 -0
  94. data/test/source/_posts/2009-05-18-tags.textile +9 -0
  95. data/test/source/_posts/2009-06-22-empty-yaml.textile +3 -0
  96. data/test/source/_posts/2009-06-22-no-yaml.textile +1 -0
  97. data/test/source/_posts/2010-01-08-triple-dash.markdown +5 -0
  98. data/test/source/_posts/2010-01-09-date-override.textile +7 -0
  99. data/test/source/_posts/2010-01-09-time-override.textile +7 -0
  100. data/test/source/_posts/2010-01-09-timezone-override.textile +7 -0
  101. data/test/source/_posts/2010-01-16-override-data.textile +4 -0
  102. data/test/source/_posts/2011-04-12-md-extension.md +7 -0
  103. data/test/source/_posts/2011-04-12-text-extension.text +0 -0
  104. data/test/source/_posts/2013-01-02-post-excerpt.markdown +14 -0
  105. data/test/source/_posts/2013-01-12-nil-layout.textile +6 -0
  106. data/test/source/_posts/2013-01-12-no-layout.textile +5 -0
  107. data/test/source/_posts/2013-03-19-not-a-post.markdown/.gitkeep +0 -0
  108. data/test/source/_posts/2013-04-11-custom-excerpt.markdown +10 -0
  109. data/test/source/_posts/2013-05-10-number-category.textile +7 -0
  110. data/test/source/_posts/es/2008-11-21-nested.textile +8 -0
  111. data/test/source/about.html +6 -0
  112. data/test/source/category/_posts/2008-9-23-categories.textile +6 -0
  113. data/test/source/contacts.html +5 -0
  114. data/test/source/contacts/bar.html +5 -0
  115. data/test/source/contacts/index.html +5 -0
  116. data/test/source/css/screen.css +76 -0
  117. data/test/source/deal.with.dots.html +7 -0
  118. data/test/source/foo/_posts/bar/2008-12-12-topical-post.textile +8 -0
  119. data/test/source/index.html +22 -0
  120. data/test/source/sitemap.xml +32 -0
  121. data/test/source/symlink-test/symlinked-file +22 -0
  122. data/test/source/win/_posts/2009-05-24-yaml-linebreak.markdown +7 -0
  123. data/test/source/z_category/_posts/2008-9-23-categories.textile +6 -0
  124. data/test/suite.rb +11 -0
  125. data/test/test_command.rb +39 -0
  126. data/test/test_configuration.rb +137 -0
  127. data/test/test_convertible.rb +51 -0
  128. data/test/test_core_ext.rb +88 -0
  129. data/test/test_filters.rb +102 -0
  130. data/test/test_generated_site.rb +83 -0
  131. data/test/test_json_driver.rb +63 -0
  132. data/test/test_kramdown.rb +35 -0
  133. data/test/test_new_command.rb +104 -0
  134. data/test/test_page.rb +193 -0
  135. data/test/test_pager.rb +115 -0
  136. data/test/test_post.rb +573 -0
  137. data/test/test_rdiscount.rb +22 -0
  138. data/test/test_redcarpet.rb +61 -0
  139. data/test/test_redcloth.rb +86 -0
  140. data/test/test_site.rb +374 -0
  141. data/test/test_tags.rb +310 -0
  142. data/test/test_yaml_driver.rb +35 -0
  143. metadata +554 -0
@@ -0,0 +1,22 @@
1
+ ---
2
+ layout: default
3
+ title: Tom Preston-Werner
4
+ ---
5
+
6
+ h1. Welcome to my site
7
+
8
+ h2. Please read our {{ site.posts | size }} Posts
9
+
10
+ <ul>
11
+ {% for post in site.posts %}
12
+ <li>{{ post.date }} <a href="{{ post.url }}">{{ post.title }}</a></li>
13
+ {% endfor %}
14
+ </ul>
15
+
16
+ {% assign first_post = site.posts.first %}
17
+ <div id="first_post">
18
+ <h1>{{ first_post.title }}</h1>
19
+ <div>
20
+ {{ first_post.content }}
21
+ </div>
22
+ </div>
@@ -0,0 +1,7 @@
1
+ ---
2
+ layout: post
3
+ title: "Test title"
4
+ tag: "Ruby"
5
+ ---
6
+
7
+ This is the content
@@ -0,0 +1,6 @@
1
+ ---
2
+ layout: default
3
+ title: Categories
4
+ ---
5
+
6
+ Categories _should_ work. Even if ordered after index.
@@ -0,0 +1,11 @@
1
+ require 'rubygems'
2
+ gem 'test-unit'
3
+ require 'test/unit'
4
+
5
+ # for some reason these tests fail when run via TextMate
6
+ # but succeed when run on the command line.
7
+
8
+ tests = Dir[File.expand_path("#{File.dirname(__FILE__)}/test_*.rb")]
9
+ tests.each do |file|
10
+ require file
11
+ end
@@ -0,0 +1,39 @@
1
+ require 'helper'
2
+
3
+ class TestCommand < Test::Unit::TestCase
4
+ context "when calling .globs" do
5
+ context "when non-default dest & source dirs" do
6
+ setup do
7
+ @source = source_dir
8
+ @dest = dest_dir
9
+ directory_with_contents(@dest)
10
+ @globs = Command.globs(@source, @dest)
11
+ end
12
+ should "return an array without the destination dir" do
13
+ assert @globs.is_a?(Array)
14
+ assert !@globs.include?(@dest)
15
+ end
16
+ teardown do
17
+ clear_dest
18
+ end
19
+ end
20
+ context "when using default dest dir" do
21
+ setup do
22
+ @source = test_dir
23
+ @dest = test_dir('_site')
24
+ directory_with_contents(@dest)
25
+ @globs = Command.globs(@source, @dest)
26
+ end
27
+ should "return an array without the destination dir" do
28
+ assert @globs.is_a?(Array)
29
+ assert !@globs.include?(@dest)
30
+ @globs.each do |glob|
31
+ assert !glob.include?(File.basename(@dest))
32
+ end
33
+ end
34
+ teardown do
35
+ FileUtils.rm_r(@dest)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,137 @@
1
+ require 'helper'
2
+
3
+ class TestConfiguration < Test::Unit::TestCase
4
+ context "#stringify_keys" do
5
+ setup do
6
+ @mixed_keys = Configuration[{
7
+ 'markdown' => 'maruku',
8
+ :permalink => 'date',
9
+ 'baseurl' => '/',
10
+ :include => ['.htaccess'],
11
+ :source => './'
12
+ }]
13
+ @string_keys = Configuration[{
14
+ 'markdown' => 'maruku',
15
+ 'permalink' => 'date',
16
+ 'baseurl' => '/',
17
+ 'include' => ['.htaccess'],
18
+ 'source' => './'
19
+ }]
20
+ end
21
+ should "stringify symbol keys" do
22
+ assert_equal @string_keys, @mixed_keys.stringify_keys
23
+ end
24
+ should "not mess with keys already strings" do
25
+ assert_equal @string_keys, @string_keys.stringify_keys
26
+ end
27
+ end
28
+ context "#config_files" do
29
+ setup do
30
+ @config = Configuration[{"source" => source_dir}]
31
+ @no_override = {}
32
+ @one_config_file = {"config" => "config.yml"}
33
+ @multiple_files = {"config" => %w[config/site.yml config/deploy.yml configuration.yml]}
34
+ end
35
+
36
+ should "always return an array" do
37
+ assert @config.config_files(@no_override).is_a?(Array)
38
+ assert @config.config_files(@one_config_file).is_a?(Array)
39
+ assert @config.config_files(@multiple_files).is_a?(Array)
40
+ end
41
+ should "return the default config path if no config files are specified" do
42
+ assert_equal [File.join(source_dir, "_config.yml")], @config.config_files(@no_override)
43
+ end
44
+ should "return the config if given one config file" do
45
+ assert_equal %w[config.yml], @config.config_files(@one_config_file)
46
+ end
47
+ should "return an array of the config files if given many config files" do
48
+ assert_equal %w[config/site.yml config/deploy.yml configuration.yml], @config.config_files(@multiple_files)
49
+ end
50
+ end
51
+ context "#backwards_compatibilize" do
52
+ setup do
53
+ @config = Configuration[{
54
+ "auto" => true,
55
+ "watch" => true,
56
+ "server" => true
57
+ }]
58
+ end
59
+ should "unset 'auto' and 'watch'" do
60
+ assert @config.has_key?("auto")
61
+ assert @config.has_key?("watch")
62
+ assert !@config.backwards_compatibilize.has_key?("auto")
63
+ assert !@config.backwards_compatibilize.has_key?("watch")
64
+ end
65
+ should "unset 'server'" do
66
+ assert @config.has_key?("server")
67
+ assert !@config.backwards_compatibilize.has_key?("server")
68
+ end
69
+ end
70
+ context "loading configuration" do
71
+ setup do
72
+ @path = File.join(Dir.pwd, '_config.yml')
73
+ end
74
+
75
+ should "fire warning with no _config.yml" do
76
+ mock(YAML).safe_load_file(@path) { raise SystemCallError, "No such file or directory - #{@path}" }
77
+ mock($stderr).puts("Configuration file: none".yellow)
78
+ assert_equal Monad::Configuration::DEFAULTS, Monad.configuration({})
79
+ end
80
+
81
+ should "load configuration as hash" do
82
+ mock(YAML).safe_load_file(@path) { Hash.new }
83
+ mock($stdout).puts("Configuration file: #{@path}")
84
+ assert_equal Monad::Configuration::DEFAULTS, Monad.configuration({})
85
+ end
86
+
87
+ should "fire warning with bad config" do
88
+ mock(YAML).safe_load_file(@path) { Array.new }
89
+ mock($stderr).puts(("WARNING: ".rjust(20) + "Error reading configuration. Using defaults (and options).").yellow)
90
+ mock($stderr).puts("Configuration file: (INVALID) #{@path}".yellow)
91
+ assert_equal Monad::Configuration::DEFAULTS, Monad.configuration({})
92
+ end
93
+ end
94
+ context "loading config from external file" do
95
+ setup do
96
+ @paths = {
97
+ :default => File.join(Dir.pwd, '_config.yml'),
98
+ :other => File.join(Dir.pwd, '_config.live.yml'),
99
+ :empty => ""
100
+ }
101
+ end
102
+
103
+ should "load default config if no config_file is set" do
104
+ mock(YAML).safe_load_file(@paths[:default]) { Hash.new }
105
+ mock($stdout).puts("Configuration file: #{@paths[:default]}")
106
+ assert_equal Monad::Configuration::DEFAULTS, Monad.configuration({})
107
+ end
108
+
109
+ should "load different config if specified" do
110
+ mock(YAML).safe_load_file(@paths[:other]) { {"baseurl" => "http://wahoo.dev"} }
111
+ mock($stdout).puts("Configuration file: #{@paths[:other]}")
112
+ assert_equal Monad::Configuration::DEFAULTS.deep_merge({ "baseurl" => "http://wahoo.dev" }), Monad.configuration({ "config" => @paths[:other] })
113
+ end
114
+
115
+ should "load default config if path passed is empty" do
116
+ mock(YAML).safe_load_file(@paths[:default]) { Hash.new }
117
+ mock($stdout).puts("Configuration file: #{@paths[:default]}")
118
+ assert_equal Monad::Configuration::DEFAULTS, Monad.configuration({ "config" => @paths[:empty] })
119
+ end
120
+
121
+ should "load multiple config files" do
122
+ mock(YAML).safe_load_file(@paths[:default]) { Hash.new }
123
+ mock(YAML).safe_load_file(@paths[:other]) { Hash.new }
124
+ mock($stdout).puts("Configuration file: #{@paths[:default]}")
125
+ mock($stdout).puts("Configuration file: #{@paths[:other]}")
126
+ assert_equal Monad::Configuration::DEFAULTS, Monad.configuration({ "config" => [@paths[:default], @paths[:other]] })
127
+ end
128
+
129
+ should "load multiple config files and last config should win" do
130
+ mock(YAML).safe_load_file(@paths[:default]) { {"baseurl" => "http://example.dev"} }
131
+ mock(YAML).safe_load_file(@paths[:other]) { {"baseurl" => "http://wahoo.dev"} }
132
+ mock($stdout).puts("Configuration file: #{@paths[:default]}")
133
+ mock($stdout).puts("Configuration file: #{@paths[:other]}")
134
+ assert_equal Monad::Configuration::DEFAULTS.deep_merge({ "baseurl" => "http://wahoo.dev" }), Monad.configuration({ "config" => [@paths[:default], @paths[:other]] })
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,51 @@
1
+ require 'helper'
2
+ require 'ostruct'
3
+
4
+ class TestConvertible < Test::Unit::TestCase
5
+ context "yaml front-matter" do
6
+ setup do
7
+ @convertible = OpenStruct.new
8
+ @convertible.extend Monad::Convertible
9
+ @base = File.expand_path('../fixtures', __FILE__)
10
+ end
11
+
12
+ should "parse the front-matter correctly" do
13
+ ret = @convertible.read_yaml(@base, 'front_matter.erb')
14
+ assert_equal({'test' => 'good'}, ret)
15
+ end
16
+
17
+ should "not parse if the front-matter is not at the start of the file" do
18
+ ret = @convertible.read_yaml(@base, 'broken_front_matter1.erb')
19
+ assert_equal({}, ret)
20
+ end
21
+
22
+ should "not parse if there is syntax error in front-matter" do
23
+ name = 'broken_front_matter2.erb'
24
+ out = capture_stdout do
25
+ ret = @convertible.read_yaml(@base, name)
26
+ assert_equal({}, ret)
27
+ end
28
+ assert_match(/YAML Exception|syntax error|Error reading file/, out)
29
+ assert_match(/#{File.join(@base, name)}/, out)
30
+ end
31
+
32
+ should "not allow ruby objects in yaml" do
33
+ out = capture_stdout do
34
+ @convertible.read_yaml(@base, 'exploit_front_matter.erb')
35
+ end
36
+ assert_no_match /undefined class\/module DoesNotExist/, out
37
+ end
38
+
39
+ if RUBY_VERSION >= '1.9.2'
40
+ should "not parse if there is encoding error in file" do
41
+ name = 'broken_front_matter3.erb'
42
+ out = capture_stdout do
43
+ ret = @convertible.read_yaml(@base, name)
44
+ assert_equal({}, ret)
45
+ end
46
+ assert_match(/invalid byte sequence in UTF-8/, out)
47
+ assert_match(/#{File.join(@base, name)}/, out)
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,88 @@
1
+ require 'helper'
2
+
3
+ class TestCoreExt < Test::Unit::TestCase
4
+ context "hash" do
5
+
6
+ context "pluralized_array" do
7
+
8
+ should "return empty array with no values" do
9
+ data = {}
10
+ assert_equal [], data.pluralized_array('tag', 'tags')
11
+ end
12
+
13
+ should "return empty array with no matching values" do
14
+ data = { 'foo' => 'bar' }
15
+ assert_equal [], data.pluralized_array('tag', 'tags')
16
+ end
17
+
18
+ should "return empty array with matching nil singular" do
19
+ data = { 'foo' => 'bar', 'tag' => nil, 'tags' => ['dog', 'cat'] }
20
+ assert_equal [], data.pluralized_array('tag', 'tags')
21
+ end
22
+
23
+ should "return single value array with matching singular" do
24
+ data = { 'foo' => 'bar', 'tag' => 'dog', 'tags' => ['dog', 'cat'] }
25
+ assert_equal ['dog'], data.pluralized_array('tag', 'tags')
26
+ end
27
+
28
+ should "return single value array with matching singular with spaces" do
29
+ data = { 'foo' => 'bar', 'tag' => 'dog cat', 'tags' => ['dog', 'cat'] }
30
+ assert_equal ['dog cat'], data.pluralized_array('tag', 'tags')
31
+ end
32
+
33
+ should "return empty array with matching nil plural" do
34
+ data = { 'foo' => 'bar', 'tags' => nil }
35
+ assert_equal [], data.pluralized_array('tag', 'tags')
36
+ end
37
+
38
+ should "return empty array with matching empty array" do
39
+ data = { 'foo' => 'bar', 'tags' => [] }
40
+ assert_equal [], data.pluralized_array('tag', 'tags')
41
+ end
42
+
43
+ should "return single value array with matching plural with single string value" do
44
+ data = { 'foo' => 'bar', 'tags' => 'dog' }
45
+ assert_equal ['dog'], data.pluralized_array('tag', 'tags')
46
+ end
47
+
48
+ should "return multiple value array with matching plural with single string value with spaces" do
49
+ data = { 'foo' => 'bar', 'tags' => 'dog cat' }
50
+ assert_equal ['dog', 'cat'], data.pluralized_array('tag', 'tags')
51
+ end
52
+
53
+ should "return single value array with matching plural with single value array" do
54
+ data = { 'foo' => 'bar', 'tags' => ['dog'] }
55
+ assert_equal ['dog'], data.pluralized_array('tag', 'tags')
56
+ end
57
+
58
+ should "return multiple value array with matching plural with multiple value array" do
59
+ data = { 'foo' => 'bar', 'tags' => ['dog', 'cat'] }
60
+ assert_equal ['dog', 'cat'], data.pluralized_array('tag', 'tags')
61
+ end
62
+
63
+ end
64
+
65
+ end
66
+
67
+ context "enumerable" do
68
+ context "glob_include?" do
69
+ should "return false with no glob patterns" do
70
+ assert ![].glob_include?("a.txt")
71
+ end
72
+
73
+ should "return false with all not match path" do
74
+ data = ["a*", "b?"]
75
+ assert !data.glob_include?("ca.txt")
76
+ assert !data.glob_include?("ba.txt")
77
+ end
78
+
79
+ should "return true with match path" do
80
+ data = ["a*", "b?", "**/a*"]
81
+ assert data.glob_include?("a.txt")
82
+ assert data.glob_include?("ba")
83
+ assert data.glob_include?("c/a/a.txt")
84
+ assert data.glob_include?("c/a/b/a.txt")
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,102 @@
1
+ require 'helper'
2
+
3
+ class TestFilters < Test::Unit::TestCase
4
+ class MonadFilter
5
+ include Monad::Filters
6
+
7
+ def initialize
8
+ site = Monad::Site.new(Monad.configuration({}))
9
+ @context = Liquid::Context.new({}, {}, { :site => site })
10
+ end
11
+ end
12
+
13
+ context "filters" do
14
+ setup do
15
+ @filter = MonadFilter.new
16
+ @sample_time = Time.utc(2013, 03, 27, 11, 22, 33)
17
+ @time_as_string = "September 11, 2001 12:46:30 -0000"
18
+ end
19
+
20
+ should "textilize with simple string" do
21
+ assert_equal "<p>something <strong>really</strong> simple</p>", @filter.textilize("something *really* simple")
22
+ end
23
+
24
+ should "markdownify with simple string" do
25
+ assert_equal "<p>something <strong>really</strong> simple</p>", @filter.markdownify("something **really** simple")
26
+ end
27
+
28
+ should "convert array to sentence string with no args" do
29
+ assert_equal "", @filter.array_to_sentence_string([])
30
+ end
31
+
32
+ should "convert array to sentence string with one arg" do
33
+ assert_equal "1", @filter.array_to_sentence_string([1])
34
+ assert_equal "chunky", @filter.array_to_sentence_string(["chunky"])
35
+ end
36
+
37
+ should "convert array to sentence string with two args" do
38
+ assert_equal "1 and 2", @filter.array_to_sentence_string([1, 2])
39
+ assert_equal "chunky and bacon", @filter.array_to_sentence_string(["chunky", "bacon"])
40
+ end
41
+
42
+ should "convert array to sentence string with multiple args" do
43
+ assert_equal "1, 2, 3, and 4", @filter.array_to_sentence_string([1, 2, 3, 4])
44
+ assert_equal "chunky, bacon, bits, and pieces", @filter.array_to_sentence_string(["chunky", "bacon", "bits", "pieces"])
45
+ end
46
+
47
+ context "date filters" do
48
+ context "with Time object" do
49
+ should "format a date with short format" do
50
+ assert_equal "27 Mar 2013", @filter.date_to_string(@sample_time)
51
+ end
52
+
53
+ should "format a date with long format" do
54
+ assert_equal "27 March 2013", @filter.date_to_long_string(@sample_time)
55
+ end
56
+
57
+ should "format a time with xmlschema" do
58
+ assert_equal "2013-03-27T11:22:33Z", @filter.date_to_xmlschema(@sample_time)
59
+ end
60
+
61
+ should "format a time according to RFC-822" do
62
+ assert_equal "Wed, 27 Mar 2013 11:22:33 -0000", @filter.date_to_rfc822(@sample_time)
63
+ end
64
+ end
65
+
66
+ context "with String object" do
67
+ should "format a date with short format" do
68
+ assert_equal "11 Sep 2001", @filter.date_to_string(@time_as_string)
69
+ end
70
+
71
+ should "format a date with long format" do
72
+ assert_equal "11 September 2001", @filter.date_to_long_string(@time_as_string)
73
+ end
74
+
75
+ should "format a time with xmlschema" do
76
+ assert_equal "2001-09-11T12:46:30Z", @filter.date_to_xmlschema(@time_as_string)
77
+ end
78
+
79
+ should "format a time according to RFC-822" do
80
+ assert_equal "Tue, 11 Sep 2001 12:46:30 -0000", @filter.date_to_rfc822(@time_as_string)
81
+ end
82
+ end
83
+ end
84
+
85
+ should "escape xml with ampersands" do
86
+ assert_equal "AT&amp;T", @filter.xml_escape("AT&T")
87
+ assert_equal "&lt;code&gt;command &amp;lt;filename&amp;gt;&lt;/code&gt;", @filter.xml_escape("<code>command &lt;filename&gt;</code>")
88
+ end
89
+
90
+ should "escape space as plus" do
91
+ assert_equal "my+things", @filter.cgi_escape("my things")
92
+ end
93
+
94
+ should "escape special characters" do
95
+ assert_equal "hey%21", @filter.cgi_escape("hey!")
96
+ end
97
+
98
+ should "escape space as %20" do
99
+ assert_equal "my%20things", @filter.uri_escape("my things")
100
+ end
101
+ end
102
+ end