client_pages 0.0.2.alpha → 0.0.3.beta

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,274 @@
1
+ require 'spec_helper'
2
+
3
+ module ClientPages
4
+ describe 'MarkdownContent' do
5
+ subject { ClientPages::MarkdownContent::Renderer }
6
+
7
+ describe 'invalid path' do
8
+ before { ClientPages.config { |c| c.content_path = 'not_there' } }
9
+ it { expect(subject.render_content(:bar)).to eql('No such file or directory - bar') }
10
+ end
11
+
12
+ describe 'valid path' do
13
+ before { ClientPages.config { |c| c.content_path = 'spec/fixtures/foo' } }
14
+ it { expect(subject.render_content(:bar)).to eql("<h1>foo</h1>\n\n<p>bar</p>") }
15
+ end
16
+
17
+ it 'blends' do
18
+ expect(
19
+ subject.render_content(:test_content) do |c|
20
+ c.modify :h1, with: { class: 'mycss_class', 'data-foo' => 'bar' }, if: ->(m) { m.includes?('Content') }
21
+ c.modify :a, with: { class: 'fancy', title: 'woah' }, if: { href: 'http://somewhere.com' }
22
+ c.wrap :h1, :div, with: { id: 'my-id', class: 'foo' }
23
+ c.replace :p, :span, with: { class: 'bar', 'data-p' => 'no-more' }
24
+ end
25
+ ).to eql(
26
+ "<div id=\"my-id\" class=\"foo\"><h1 class=\"mycss_class\" data-foo=\"bar\">Content from "\
27
+ "<a href=\"http://somewhere.com\" class=\"fancy\" title=\"woah\">somewhere</a></h1></div>\n\n"\
28
+ "<span class=\"bar\" data-p=\"no-more\">Lorem do <em>incididunt</em> ut labore</span>\n\n"\
29
+ "<span class=\"bar\" data-p=\"no-more\">Pariatur: "\
30
+ "<a href=\"/bar.com\" title=\"baz\">Foo</a> culpa</span>\n"
31
+ )
32
+ end
33
+
34
+ describe 'Renderer' do
35
+ let(:markdown) { fixture('test_content') }
36
+
37
+ before do
38
+ ClientPages.config do |c|
39
+ c.remote = true
40
+ c.caching = false
41
+ c.remote_content_path = 'http://somewhere.com'
42
+ end
43
+ stub_request(:get, 'http://somewhere.com/test_content.md')
44
+ .to_return(body: markdown, status: 200)
45
+ end
46
+
47
+ context 'without a block' do
48
+ let(:rendered_content) { subject.render_content(:test_content) }
49
+
50
+ it 'renders HTML content for given markdown file from somewhere' do
51
+ expect(rendered_content).to include('<h1>Content from <a href="http://somewhere.com">somewhere</a></h1>')
52
+ end
53
+
54
+ describe 'raw markdown' do
55
+ before do
56
+ ClientPages.config { |c| c.raw_markdown = true }
57
+ end
58
+
59
+ it 'renders HTML content for given markdown' do
60
+ expect(subject.render_content('# *raw* markdown')).to eql('<h1><em>raw</em> markdown</h1>')
61
+ end
62
+ end
63
+ end
64
+
65
+ context 'with a block' do
66
+ let(:link_list) { fixture('link_list') }
67
+ let(:text_list) { fixture('text_list') }
68
+ before do
69
+ stub_request(:get, 'http://somewhere.com/link_list.md').to_return(body: link_list, status: 200)
70
+ stub_request(:get, 'http://somewhere.com/text_list.md').to_return(body: text_list, status: 200)
71
+ end
72
+
73
+ it 'returns a content builder' do
74
+ expect(
75
+ subject.render_content(:test_content) { |c| c }
76
+ ).to be_kind_of(MarkdownContent::ContentBuilder)
77
+ end
78
+
79
+ it 'modifies tags and html attributes' do
80
+ expect(
81
+ subject.render_content(:test_content) do |c|
82
+ c.modify :h1, with: { class: 'mycss_class', 'data-foo' => 'bar' }
83
+ c.modify :a, with: { class: 'fancy', title: 'woah' }
84
+ end
85
+ ).to include(
86
+ '<h1 class="mycss_class" data-foo="bar">'\
87
+ 'Content from <a href="http://somewhere.com" class="fancy" title="woah">somewhere</a>'\
88
+ '</h1>'
89
+ )
90
+ end
91
+
92
+ it 'adds attributes conditionally' do
93
+ expect(
94
+ subject.render_content(:test_content) do |c|
95
+ c.modify :h1, with: { class: 'add_me cool' }, if: true
96
+ c.modify :a, with: { class: 'add_me_not' }, if: false
97
+ end
98
+ ).to include(
99
+ '<h1 class="add_me cool">Content from <a href="http://somewhere.com">somewhere</a></h1>'
100
+ )
101
+ end
102
+
103
+ it 'adds any attribute conditionally and selective' do
104
+ expect(
105
+ subject.render_content(:link_list) do |c|
106
+ c.modify :li, with: { class: 'yay' }, if: ->(m) { m.match_any?(:href, '/link1') }
107
+ c.modify :a, with: { class: 'active' }, if: { href: '/link2' }
108
+ c.modify :a, with: { class: 'important', 'data-foo' => 'bar' }, if: { title: 'i haz title' }
109
+ end
110
+ ).to include(
111
+ "<li class=\"yay\"><a href=\"/link1\">link1</a></li>\n"\
112
+ "<li><a href=\"/link2\" class=\"active\">link2</a></li>\n"\
113
+ "<li><a href=\"/link3\" title=\"i haz title\" class=\"important\" data-foo=\"bar\">link3</a></li>"
114
+ )
115
+ end
116
+
117
+ it 'wraps multiple tags with container' do
118
+ expect(
119
+ subject.render_content(:text_list) do |c|
120
+ c.wrap :ul, :div, with: { class: 'wrapper foo' }
121
+ c.wrap :em, :span, with: { class: 'special' }, if: ->(m) { m.includes?('Bar') }
122
+ end
123
+ ).to eql(
124
+ "<div class=\"wrapper foo\"><ul>\n"\
125
+ "<li>Foo <span class=\"special\"><em>Bar</em></span></li>\n"\
126
+ "<li>Baz</li>\n"\
127
+ "</ul></div>\n"
128
+ )
129
+ end
130
+
131
+ it 'wraps and modifies tags' do
132
+ expect(
133
+ subject.render_content(:text_list) do |c|
134
+ c.wrap :ul, :div, with: { class: 'container' }
135
+ c.modify :em, with: { style: 'color: #c0ffee' }
136
+ end
137
+ ).to eql(
138
+ "<div class=\"container\"><ul>\n"\
139
+ "<li>Foo <em style=\"color: #c0ffee\">Bar</em></li>\n"\
140
+ "<li>Baz</li>\n"\
141
+ "</ul></div>\n"
142
+ )
143
+ end
144
+
145
+ it 'replaces tags and adds class' do
146
+ expect(
147
+ subject.render_content(:test_content) do |c|
148
+ c.replace :p, :div, with: { class: 'byebye' }
149
+ c.replace :em, :span, with: { id: 'i-am', class: 'cool', 'data-u' => 'r-not' }
150
+ end
151
+ ).to eql(
152
+ "<h1>Content from <a href=\"http://somewhere.com\">somewhere</a></h1>\n\n"\
153
+ "<div class=\"byebye\">"\
154
+ "Lorem do <span id=\"i-am\" class=\"cool\" data-u=\"r-not\">incididunt</span> ut labore"\
155
+ "</div>\n\n"\
156
+ "<div class=\"byebye\">Pariatur: <a href=\"/bar.com\" title=\"baz\">Foo</a> culpa</div>\n"
157
+ )
158
+ end
159
+
160
+ it 'wraps and replaces conditionally' do
161
+ expect(
162
+ subject.render_content(:test_content) do |c|
163
+ c.wrap :a, :span, with: { class: 'btn' }, if: { href: 'http://somewhere.com' }
164
+ c.replace :p, :div, if: ->(m) { m.includes?('Lorem') }
165
+ c.replace :em, :span, with: { class: 'replaced' }, if: ->(m) { m.includes?('incididunt') }
166
+ end
167
+ ).to eql(
168
+ "<h1>Content from <span class=\"btn\"><a href=\"http://somewhere.com\">somewhere</a></span></h1>\n\n"\
169
+ "<div>Lorem do <span class=\"replaced\">incididunt</span> ut labore</div>\n\n"\
170
+ "<p>Pariatur: <a href=\"/bar.com\" title=\"baz\">Foo</a> culpa</p>\n"
171
+ )
172
+ end
173
+ end
174
+
175
+ describe 'with caching' do
176
+ before(:each) { ClientPages.cache.clear }
177
+ after { ClientPages.config { |c| c.caching = false } }
178
+
179
+ context 'enabled' do
180
+ before do
181
+ ClientPages.config do |c|
182
+ c.caching = true
183
+ c.remote = true
184
+ c.remote_content_path = 'http://c.ly'
185
+ end
186
+ end
187
+
188
+ it 'populates cache when empty' do
189
+ request = stub_request(:get, /\/caching.md/).to_return(body: '**cache me**')
190
+ expect { subject.render_content(:caching) }
191
+ .to change { ClientPages.cache }
192
+ .to eql('http://c.ly/caching.md' => '**cache me**')
193
+ expect(request).to have_been_made.times(1)
194
+ end
195
+
196
+ it 'makes request only once' do
197
+ request = stub_request(:get, /\/caching.md/).to_return(body: '**cache me**')
198
+ 5.times { subject.render_content(:caching) }
199
+ expect { subject.render_content(:caching) }.to_not change { ClientPages.cache }
200
+ expect(request).to have_been_made.times(1)
201
+ end
202
+ end
203
+
204
+ context 'disabled' do
205
+ before do
206
+ ClientPages.config do |c|
207
+ c.caching = false
208
+ c.remote = true
209
+ c.remote_content_path = 'http://c.ly'
210
+ end
211
+ end
212
+
213
+ it 'will not cache' do
214
+ stub_request(:get, /\/no_caching.md/).to_return(body: '_u_no_cache_me_')
215
+ subject.render_content(:no_caching)
216
+ expect(ClientPages.cache).to be_empty
217
+ end
218
+
219
+ it 'makes a request per render_content call' do
220
+ request = stub_request(:get, /\/no_caching.md/).to_return(body: '_u_no_cache_me_')
221
+ 5.times { subject.render_content(:no_caching) }
222
+ expect(request).to have_been_made.times(5)
223
+ end
224
+ end
225
+ end
226
+
227
+ describe 'default templates' do
228
+ before do
229
+ ClientPages.templates do |t|
230
+ t.set(:basic) do |c|
231
+ c.modify :h1, with: { class: 'headers' }
232
+ c.wrap :a, :span, with: { class: 'links' }, if: ->(m) { m.includes?('somewhere') }
233
+ c.replace :p, :div
234
+ end
235
+ end
236
+ end
237
+
238
+ it 'uses templates and accepts additional block' do
239
+ expect(
240
+ subject.render_content(:test_content, template: :basic) do |c|
241
+ c.modify :h1, with: { 'data-foo' => 'bar' }
242
+ end
243
+ ).to eql(
244
+ "<h1 class=\"headers\" data-foo=\"bar\">Content from <span class=\"links\">"\
245
+ "<a href=\"http://somewhere.com\">somewhere</a></span></h1>\n\n"\
246
+ "<div>Lorem do <em>incididunt</em> ut labore</div>\n\n<div>Pariatur: "\
247
+ "<a href=\"/bar.com\" title=\"baz\">Foo</a> culpa</div>\n"
248
+ )
249
+ end
250
+ end
251
+ end
252
+
253
+ describe 'configuration' do
254
+ subject { ClientPages }
255
+ before { subject.configuration = nil }
256
+
257
+ it 'is configurable with a block' do
258
+ expect {
259
+ subject.config do |c|
260
+ c.content_path = 'somewhere'
261
+ c.render_options = { foo: 'bar' }
262
+ c.markdown_extensions = { bam: true }
263
+ end
264
+ }.to change {
265
+ subject.config.to_hash
266
+ }.to eql(
267
+ content_path: 'somewhere',
268
+ render_options: { foo: 'bar' },
269
+ markdown_extensions: { bam: true }
270
+ )
271
+ end
272
+ end
273
+ end
274
+ end
data/spec/spec_helper.rb CHANGED
@@ -8,6 +8,7 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
8
8
  require 'client_pages'
9
9
 
10
10
  require 'webmock/rspec'
11
+ require 'open-uri'
11
12
 
12
13
  RSpec.configure do |config|
13
14
  config.treat_symbols_as_metadata_keys_with_true_values = true
@@ -22,9 +23,31 @@ RSpec.configure do |config|
22
23
  config.mock_with :rspec do |c|
23
24
  c.syntax = :expect
24
25
  end
26
+
27
+ config.before(:each) do
28
+ ClientPages.config do |c|
29
+ c.remote = false
30
+ c.caching = false
31
+ c.content_path = 'spec/fixtures/content'
32
+ c.remote_content_path = nil
33
+ c.raw_markdown = false
34
+ c.render_options = {
35
+ hard_wrap: true,
36
+ with_toc_data: false
37
+ }
38
+ c.markdown_extensions = {
39
+ tables: true,
40
+ autolink: true,
41
+ lax_spacing: true,
42
+ space_after_headers: true,
43
+ underline: false,
44
+ no_intra_emphasis: true
45
+ }
46
+ end
47
+ end
25
48
  end
26
49
 
27
50
  # helper for markdown fixture files
28
51
  def fixture(name)
29
- File.open(File.expand_path("spec/fixtures/#{name}.md"), 'r')
52
+ open("#{ClientPages.config.content_path}/#{name}.md").read
30
53
  end
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+
3
+ module ClientPages
4
+ describe Configuration do
5
+
6
+ it 'has default config' do
7
+ config = {
8
+ content_path: 'content',
9
+ render_options: {},
10
+ markdown_extensions: {}
11
+ }
12
+ expect(subject.to_hash).to eql(config)
13
+ end
14
+
15
+ it 'is configurable' do
16
+ config = {
17
+ content_path: 'somewhere',
18
+ render_options: { foo: 'bar' },
19
+ markdown_extensions: { bam: true }
20
+ }
21
+ expect {
22
+ subject.content_path = 'somewhere'
23
+ subject.render_options = { foo: 'bar' }
24
+ subject.markdown_extensions = { bam: true }
25
+ }.to change {
26
+ subject.to_hash
27
+ }.to eql(config)
28
+ end
29
+
30
+ describe 'overwritable config' do
31
+ before do
32
+ subject.render_options = { opt1: true }
33
+ subject.markdown_extensions = { ext1: true }
34
+ end
35
+
36
+ it 'overwrites config and keeps untouched config settings' do
37
+ config = {
38
+ content_path: 'here',
39
+ render_options: { opt1: false, opt2: true },
40
+ markdown_extensions: { ext1: true, ext2: false }
41
+ }
42
+ expect {
43
+ subject.content_path = 'here'
44
+ subject.render_options = { opt1: false, opt2: true }
45
+ subject.markdown_extensions = { ext2: false }
46
+ }.to change {
47
+ subject.to_hash
48
+ }.to eql(config)
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+
3
+ module ClientPages
4
+ module MarkdownContent
5
+ describe ContentBuilder do
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ module ClientPages
4
+ describe Matcher do
5
+ subject { described_class.new(:span, '<span>foo</span>') }
6
+ it { expect(subject.tag).to eql(:span) }
7
+ it { expect(subject.line).to eql('<span>foo</span>') }
8
+ it { expect(subject.includes?('foo')).to be_true }
9
+ it { expect(subject.match?(nil, 'foo')).to be_false }
10
+ end
11
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+
3
+ module ClientPages
4
+ module MarkdownContent
5
+ describe Renderer do
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ module ClientPages
4
+ describe 'Template' do
5
+ let(:templates) { {} }
6
+
7
+ before do
8
+ expect(ClientPages).to receive(:template) { templates }
9
+ Template.new.set(:foo) { |args| 'foobar' + args }
10
+ end
11
+
12
+ it 'saves a referenceable block with arguments' do
13
+ expect(templates[:foo].call('bam')).to eql('foobarbam')
14
+ end
15
+ end
16
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: client_pages
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2.alpha
4
+ version: 0.0.3.beta
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marco Schaden
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-01 00:00:00.000000000 Z
11
+ date: 2014-03-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redcarpet
@@ -108,6 +108,20 @@ dependencies:
108
108
  - - ~>
109
109
  - !ruby/object:Gem::Version
110
110
  version: 0.18.1
111
+ - !ruby/object:Gem::Dependency
112
+ name: flog
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ~>
116
+ - !ruby/object:Gem::Version
117
+ version: 4.2.0
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ~>
123
+ - !ruby/object:Gem::Version
124
+ version: 4.2.0
111
125
  - !ruby/object:Gem::Dependency
112
126
  name: simplecov
113
127
  requirement: !ruby/object:Gem::Requirement
@@ -133,18 +147,30 @@ extensions: []
133
147
  extra_rdoc_files: []
134
148
  files:
135
149
  - .gitignore
150
+ - .rubocop.yml
136
151
  - Gemfile
137
152
  - LICENSE.txt
138
153
  - README.md
139
154
  - Rakefile
140
155
  - client_pages.gemspec
141
156
  - lib/client_pages.rb
157
+ - lib/client_pages/configuration.rb
158
+ - lib/client_pages/markdown_content/content_builder.rb
159
+ - lib/client_pages/markdown_content/renderer.rb
160
+ - lib/client_pages/matcher.rb
161
+ - lib/client_pages/template.rb
142
162
  - lib/client_pages/version.rb
143
- - spec/fixtures/link_list.md
144
- - spec/fixtures/test_content.md
145
- - spec/fixtures/text_list.md
163
+ - spec/fixtures/content/link_list.md
164
+ - spec/fixtures/content/test_content.md
165
+ - spec/fixtures/content/text_list.md
166
+ - spec/fixtures/foo/bar.md
167
+ - spec/integration/client_pages_spec.rb
146
168
  - spec/spec_helper.rb
147
- - spec/unit/client_pages_spec.rb
169
+ - spec/unit/configuration_spec.rb
170
+ - spec/unit/content_builder_spec.rb
171
+ - spec/unit/matcher_spec.rb
172
+ - spec/unit/renderer_spec.rb
173
+ - spec/unit/template_spec.rb
148
174
  homepage: ''
149
175
  licenses:
150
176
  - MIT
@@ -171,9 +197,15 @@ specification_version: 4
171
197
  summary: With client_pages you can separate your content from html markup and css
172
198
  styles
173
199
  test_files:
174
- - spec/fixtures/link_list.md
175
- - spec/fixtures/test_content.md
176
- - spec/fixtures/text_list.md
200
+ - spec/fixtures/content/link_list.md
201
+ - spec/fixtures/content/test_content.md
202
+ - spec/fixtures/content/text_list.md
203
+ - spec/fixtures/foo/bar.md
204
+ - spec/integration/client_pages_spec.rb
177
205
  - spec/spec_helper.rb
178
- - spec/unit/client_pages_spec.rb
206
+ - spec/unit/configuration_spec.rb
207
+ - spec/unit/content_builder_spec.rb
208
+ - spec/unit/matcher_spec.rb
209
+ - spec/unit/renderer_spec.rb
210
+ - spec/unit/template_spec.rb
179
211
  has_rdoc: