noumenon 0.0.3 → 0.1.0
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.
- data/.gitignore +3 -0
- data/.travis.yml +0 -4
- data/.yardopts +5 -0
- data/Gemfile +1 -3
- data/README.md +57 -80
- data/Rakefile +17 -6
- data/bin/noumenon +6 -0
- data/features/dynamic_template_rendering.feature +107 -0
- data/features/generator/site_generator.feature +25 -0
- data/features/mounted_applications.feature +30 -0
- data/features/static_template_rendering.feature +43 -0
- data/features/step_definitions/asset_steps.rb +7 -0
- data/features/step_definitions/content_steps.rb +7 -0
- data/features/step_definitions/generator_steps.rb +22 -0
- data/features/step_definitions/request_steps.rb +31 -0
- data/features/step_definitions/theme_steps.rb +19 -0
- data/features/support/env.rb +38 -0
- data/features/support/theme/theme.yml +5 -0
- data/features/theme_assets.feature +22 -0
- data/generators/repository/index.yml +3 -0
- data/generators/site/Gemfile +3 -0
- data/generators/site/config.ru +7 -0
- data/generators/theme/assets/style.css +1 -0
- data/generators/theme/layouts/default.nou.html +23 -0
- data/generators/theme/templates/default.nou.html +12 -0
- data/generators/theme/theme.yml +5 -0
- data/lib/noumenon/cli.rb +27 -0
- data/lib/noumenon/core.rb +70 -77
- data/lib/noumenon/repository/file_system.rb +102 -0
- data/lib/noumenon/repository.rb +39 -0
- data/lib/noumenon/spec/example_app.rb +19 -6
- data/lib/noumenon/spec/theme_helpers.rb +66 -0
- data/lib/noumenon/spec.rb +4 -7
- data/lib/noumenon/string_extensions.rb +21 -0
- data/lib/noumenon/template.rb +113 -72
- data/lib/noumenon/theme/assets_middleware.rb +21 -0
- data/lib/noumenon/theme.rb +106 -0
- data/lib/noumenon/version.rb +3 -1
- data/lib/noumenon.rb +68 -100
- data/noumenon.gemspec +13 -9
- data/spec/noumenon/repository/file_system_spec.rb +115 -0
- data/spec/noumenon/repository_spec.rb +40 -0
- data/spec/noumenon/template_spec.rb +9 -7
- data/spec/noumenon/theme_spec.rb +129 -0
- data/spec/noumenon_spec.rb +24 -80
- data/spec/spec_helper.rb +5 -14
- data/spec/support/file_matchers.rb +45 -0
- data/spec/support/templates/basic_template.html +1 -0
- data/spec/{fixtures/themes/example_without_layout → support}/templates/template_with_fields.html +1 -1
- metadata +143 -62
- data/lib/noumenon/configuration.rb +0 -28
- data/lib/noumenon/spec/fixtures.rb +0 -34
- data/spec/fixtures/fixture_specs/test +0 -1
- data/spec/fixtures/missing_application/mounted_app/config.yml +0 -1
- data/spec/fixtures/static_example/directory_with_index/index.yml +0 -1
- data/spec/fixtures/static_example/found.html +0 -1
- data/spec/fixtures/static_example/liquid_example.html +0 -1
- data/spec/fixtures/static_example/mounted_app/config.yml +0 -1
- data/spec/fixtures/static_example/template_with_substitutions.html +0 -1
- data/spec/fixtures/static_example/templates/basic_example.yml +0 -1
- data/spec/fixtures/static_example/templates/with_fields.yml +0 -2
- data/spec/fixtures/themes/example/assets/example.txt +0 -1
- data/spec/fixtures/themes/example/templates/layout.html +0 -3
- data/spec/fixtures/themes/example_without_layout/templates/basic_template.html +0 -1
- data/spec/fixtures/themes/example_without_layout/templates/fields.html +0 -1
- data/spec/fixtures/themes/external_theme/assets/example.txt +0 -1
- data/spec/fixtures/themes/unregistered/lib/unregistered.rb +0 -1
- data/spec/noumenon/config_spec.rb +0 -29
- data/spec/noumenon/core_spec.rb +0 -105
- data/spec/noumenon/spec/example_app_spec.rb +0 -14
- data/spec/noumenon/spec/fixtures_spec.rb +0 -41
- data/spec/noumenon/spec_spec.rb +0 -7
- data/watchr.rb +0 -2
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/.yardopts
ADDED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# Noumenon
|
2
2
|
|
3
|
-
|
3
|
+
I did have a description of where the name Noumenon came from here, but it doesn't actually fit that well. Maybe I'll
|
4
|
+
come up with a better reason for th name choice some day.
|
4
5
|
|
5
6
|
## What is This Thing?
|
6
7
|
|
@@ -11,54 +12,30 @@ populate of a content management system using the tools they are most comfortabl
|
|
11
12
|
In the case of developers (and some designers) that's version control and text editors, while in the case of content
|
12
13
|
editors thats more likely to be a web interface.
|
13
14
|
|
14
|
-
##
|
15
|
-
|
16
|
-
A Noumenon site has two fundamental components, a content repository, and a theme.
|
17
|
-
|
18
|
-
### The Content Repository
|
19
|
-
|
20
|
-
The content repository is used to store items of content for the site. By default they're represented by YAML files
|
21
|
-
in a directory tree which should match the URL structure you want to use:
|
15
|
+
## Getting Started
|
22
16
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
- /people.yml
|
28
|
-
- /company.yml
|
29
|
-
- /contact
|
30
|
-
- /config.yml
|
17
|
+
If you want to skip the theory, and just play around with things in practice then your best bet is to run `noumenon site example_site`
|
18
|
+
from a terminal, which will generate you a Gemfile, config.ru, content repository, and theme. If you want to run it
|
19
|
+
any Rack based application server should work. I've tested under Thin and Unicorn, and Heroku will work if you want
|
20
|
+
to publish a static site.
|
31
21
|
|
32
|
-
|
33
|
-
http://example.org/about/people will render /about/people.yml
|
34
|
-
|
35
|
-
Each item of content has this format:
|
36
|
-
|
37
|
-
template "page"
|
38
|
-
title: "People"
|
39
|
-
subtitle: "Our people are what makes us special"
|
40
|
-
body:
|
41
|
-
Here at Enormicorp we believe our people make us a great company.
|
42
|
-
|
43
|
-
Or at least the ones who's title starts with C and ends in O. Everyone else is just a cog really.
|
44
|
-
|
45
|
-
When requested a template with a matching name will be loaded from the current theme, and rendered with the fields
|
46
|
-
defined in the content item.
|
22
|
+
## How it Works
|
47
23
|
|
24
|
+
Noumenon splits your site into three parts:
|
48
25
|
|
49
26
|
### Themes
|
50
27
|
|
51
|
-
Themes define how your content should be presented, and can provide templates and assets.
|
52
|
-
|
53
|
-
|
54
|
-
For an example, take a look at http://github.com/Noumenon/example_theme
|
28
|
+
Themes define how your content should be presented, and can provide templates and assets. You can load a theme from any
|
29
|
+
filesystem path in your config.ru file. In the near future Ruby Gem based themes will also be supported.
|
55
30
|
|
56
31
|
#### Assets
|
57
32
|
|
58
33
|
Assets such as images, stylesheets, and javascripts are placed in the "assets" directory, and are accessible from your
|
59
|
-
application at http://example.org/themes/
|
34
|
+
application at http://example.org/themes/Theme Name/asset.png. The URL structure directly matches the directory structure
|
60
35
|
of your assets directory.
|
61
36
|
|
37
|
+
In the future some asset types will be served from the content repository instead, such as images embedded within a page.
|
38
|
+
|
62
39
|
#### Templates
|
63
40
|
|
64
41
|
The core of a theme is the templates it provides. Each template can list the fields that it supports, and mark some or all
|
@@ -92,38 +69,10 @@ If not specified the type defaults to "string", the label to a capitalised versi
|
|
92
69
|
|
93
70
|
Any fields provided to a template which aren't specified will still be available in the Liquid template part.
|
94
71
|
|
95
|
-
### Custom URL handlers
|
96
|
-
|
97
|
-
If part of your site requires something other then rendering a piece of content within a static template then you can use a
|
98
|
-
custom URL handler to provide that part of the site. In this example we'll provide a basic contact form.
|
99
|
-
|
100
|
-
#### Specifying the handler
|
101
|
-
|
102
|
-
Within your content repository create a directory with the same name as the URL you want to mount the application at, and add
|
103
|
-
a file called "config.yml" with the following content:
|
104
|
-
|
105
|
-
application: "Noumenon::Applications::ContactForm"
|
106
|
-
|
107
|
-
This specifies that instead of using the core Noumenon application you want to use the ContactForm application, an example implementation
|
108
|
-
is shown below - usually the application would be provided by a Rubygem or other source, and referenced in your Gemfile.
|
109
|
-
|
110
|
-
#### The ContactForm Handler
|
111
|
-
|
112
|
-
class Noumenon::Applications::ContactForm < Noumenon::Core
|
113
|
-
get '/' do
|
114
|
-
render_template "templates/contact/form.html"
|
115
|
-
end
|
116
|
-
|
117
|
-
post '/send' do
|
118
|
-
require 'pony'
|
119
|
-
Pony.send :to => "contact@example.org", :body => params[:body], :from => params[:from]
|
120
|
-
|
121
|
-
render_template "templates/contact/thanks.html", "body" => params[:body], "from" => params[:from]
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
72
|
#### Layouts
|
126
73
|
|
74
|
+
*WARNING:* This isn't implemented in the current version.
|
75
|
+
|
127
76
|
Layouts are used to wrap a piece of content with the overall look and feel of your website, and are provided with a single field
|
128
77
|
"body" containing the rendered content. Currently only one layout per theme is supported, and it should be called "layout.html".
|
129
78
|
|
@@ -155,27 +104,53 @@ Layouts are used to wrap a piece of content with the overall look and feel of yo
|
|
155
104
|
</body>
|
156
105
|
</html>
|
157
106
|
|
158
|
-
|
107
|
+
### A Content Repository
|
108
|
+
|
109
|
+
The site's content is stored within a repository. Each piece of content is represented by a set of key/value pairs, something
|
110
|
+
like this:
|
159
111
|
|
160
|
-
|
161
|
-
|
112
|
+
template: team_member
|
113
|
+
name: Jon Wood
|
114
|
+
position: Head Honcho of Awesomeness
|
115
|
+
description: Do you need a description after a position like that?
|
162
116
|
|
163
|
-
|
164
|
-
|
117
|
+
Currently the only available content repository uses YAML files to store your content, but shortly a MongoDB one will be created,
|
118
|
+
and the API for content repositories is simple enough that just about any datastore could be used if you want to implement an
|
119
|
+
adapater for it.
|
165
120
|
|
166
|
-
###
|
121
|
+
### Applications
|
167
122
|
|
168
|
-
If
|
123
|
+
If part of your site requires something other then rendering a piece of content within a static template then you can use a
|
124
|
+
custom URL handler to provide that part of the site. In this example we'll provide a basic contact form.
|
169
125
|
|
170
|
-
|
171
|
-
require 'noumenon'
|
126
|
+
#### The ContactForm Handler
|
172
127
|
|
173
|
-
Noumenon
|
174
|
-
|
175
|
-
|
128
|
+
class Noumenon::Applications::ContactForm < Noumenon::Core
|
129
|
+
def initialize(options = {})
|
130
|
+
@to = options[:to]
|
131
|
+
end
|
132
|
+
|
133
|
+
get '/' do
|
134
|
+
Noumenon.theme.template("templates/contact/form.html")
|
135
|
+
end
|
136
|
+
|
137
|
+
post '/send' do
|
138
|
+
require 'pony'
|
139
|
+
Pony.send :to => @to, :body => params[:body], :from => params[:from]
|
140
|
+
|
141
|
+
Noumenon.theme.template("templates/contact/thanks.html").render(body: params[:body], from: params[:from])
|
142
|
+
end
|
176
143
|
end
|
177
144
|
|
178
|
-
|
145
|
+
#### The Content item
|
146
|
+
|
147
|
+
To mount an application you need to put a content item in the tree where you want it, so in this example we'll put this at "/contact":
|
148
|
+
|
149
|
+
type: application
|
150
|
+
application: Noumenon::Applications::ContactForm
|
151
|
+
to: info@example.org
|
152
|
+
|
153
|
+
Make sure you've loaded the file that defines Noumenon::Applications::ContactForm.
|
179
154
|
|
180
155
|
## Getting Help and Contributing
|
181
156
|
|
@@ -185,6 +160,8 @@ on Noumenon as simple as possible. The best way to get in touch is to open an is
|
|
185
160
|
If you'd like to contribute fork this repository, and then submit a pull request when you're done. Please make sure to include some tests
|
186
161
|
so that your feature doesn't get broken in the future.
|
187
162
|
|
163
|
+
There are full API docs available at http://rubydoc.info/gems/noumenon/ which are generated whenever a new version is published.
|
164
|
+
|
188
165
|
## License
|
189
166
|
|
190
167
|
Noumenon is released under the MIT license by Blank Pad Development.
|
data/Rakefile
CHANGED
@@ -1,9 +1,20 @@
|
|
1
|
-
require '
|
2
|
-
|
1
|
+
require 'rspec/core/rake_task'
|
2
|
+
require 'cucumber/rake/task'
|
3
|
+
require 'yard'
|
4
|
+
require 'yard/rake/yardoc_task'
|
3
5
|
|
4
|
-
task :default =>
|
6
|
+
task :default => [ :spec, :cucumber ]
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
-
|
8
|
+
RSpec::Core::RakeTask.new
|
9
|
+
|
10
|
+
Cucumber::Rake::Task.new do |t|
|
11
|
+
t.cucumber_opts = %w(--format progress)
|
12
|
+
end
|
13
|
+
|
14
|
+
Cucumber::Rake::Task.new("cucumber:wip") do |t|
|
15
|
+
t.cucumber_opts = %w(--tags @wip:4 --wip)
|
16
|
+
end
|
17
|
+
|
18
|
+
YARD::Rake::YardocTask.new do |t|
|
19
|
+
t.name = :doc
|
9
20
|
end
|
data/bin/noumenon
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
Feature: Rendering dynamic templates
|
2
|
+
As a designer
|
3
|
+
I want to render a content item within a template
|
4
|
+
So that the end user can update their site
|
5
|
+
|
6
|
+
Background:
|
7
|
+
Given this template exists at "dynamic.nou.html"
|
8
|
+
"""
|
9
|
+
title:
|
10
|
+
required: true
|
11
|
+
body:
|
12
|
+
required: true
|
13
|
+
---
|
14
|
+
<h1>{{ title }}</h1>
|
15
|
+
<p>{{ body }}</p>
|
16
|
+
"""
|
17
|
+
|
18
|
+
Scenario: All fields provided
|
19
|
+
Given this content item exists at "/dynamic"
|
20
|
+
| template | dynamic |
|
21
|
+
| title | An example |
|
22
|
+
| body | Some content within the template. |
|
23
|
+
When I view "/dynamic"
|
24
|
+
Then the page should load
|
25
|
+
And the headline should be "An example"
|
26
|
+
And the body text should be "Some content within the template."
|
27
|
+
|
28
|
+
Scenario: Some fields are missing
|
29
|
+
Given this content item exists at "/dynamic"
|
30
|
+
| template | dynamic |
|
31
|
+
| title | An example |
|
32
|
+
When I view "/dynamic"
|
33
|
+
Then the page should return a 500 error
|
34
|
+
And the headline should be "Missing Fields"
|
35
|
+
And the body text should be "The following fields were missing from your content: body"
|
36
|
+
|
37
|
+
Scenario: Rendering within the default layout
|
38
|
+
Given this layout exists at "default.nou.html"
|
39
|
+
"""
|
40
|
+
<!doctype html>
|
41
|
+
<html>
|
42
|
+
<head>
|
43
|
+
<title>{{ title }}</title>
|
44
|
+
</head>
|
45
|
+
|
46
|
+
<body>
|
47
|
+
<header>
|
48
|
+
<h1>A Site</h1>
|
49
|
+
</header>
|
50
|
+
|
51
|
+
<section id="content">
|
52
|
+
{{ content }}
|
53
|
+
</section>
|
54
|
+
</body>
|
55
|
+
</html>
|
56
|
+
"""
|
57
|
+
And this content item exists at "/layout"
|
58
|
+
| template | dynamic |
|
59
|
+
| title | Hello, world! |
|
60
|
+
| body | Good morning world. |
|
61
|
+
When I view "/layout"
|
62
|
+
Then the page should load
|
63
|
+
And the page title should be "Hello, world!"
|
64
|
+
And the page header should be "A Site"
|
65
|
+
And the body text should be "Good morning world."
|
66
|
+
|
67
|
+
Scenario: Rendering with a non-default layout
|
68
|
+
Given this layout exists at "non_default_layout.nou.html"
|
69
|
+
"""
|
70
|
+
<!doctype html>
|
71
|
+
<html>
|
72
|
+
<head>
|
73
|
+
<title>{{ title }}</title>
|
74
|
+
</head>
|
75
|
+
|
76
|
+
<body>
|
77
|
+
<header>
|
78
|
+
<h1>A Site</h1>
|
79
|
+
</header>
|
80
|
+
|
81
|
+
<section id="content">
|
82
|
+
{{ content }}
|
83
|
+
</section>
|
84
|
+
</body>
|
85
|
+
</html>
|
86
|
+
"""
|
87
|
+
And this content item exists at "/layout"
|
88
|
+
| template | dynamic |
|
89
|
+
| layout | non_default_layout |
|
90
|
+
| title | Hello, world! |
|
91
|
+
| body | Good morning world. |
|
92
|
+
When I view "/layout"
|
93
|
+
Then the page should load
|
94
|
+
And the page title should be "Hello, world!"
|
95
|
+
And the page header should be "A Site"
|
96
|
+
And the body text should be "Good morning world."
|
97
|
+
|
98
|
+
Scenario: Rendering with a missing non-default layout
|
99
|
+
Given no layout exists at "non_default_layout.nou.html"
|
100
|
+
And this content item exists at "/layout"
|
101
|
+
| template | dynamic |
|
102
|
+
| layout | non_default_layout |
|
103
|
+
| title | Hello, world! |
|
104
|
+
| body | Good morning world. |
|
105
|
+
When I view "/layout"
|
106
|
+
Then the page should return a 500 error
|
107
|
+
And the body text should be "The layout 'non_default_layout' does not exist within the current theme."
|
@@ -0,0 +1,25 @@
|
|
1
|
+
Feature: Generating a Noumenon site
|
2
|
+
As a user
|
3
|
+
I want to generate a basic site
|
4
|
+
So that I don't I have to repeat the same steps everytime
|
5
|
+
|
6
|
+
Scenario: No arguments
|
7
|
+
When I run `bundle exec ../../bin/noumenon`
|
8
|
+
Then the output should match /Noumenon ([\d]+\.[\d]+\.[\d]+)/
|
9
|
+
And the output should contain "Tasks:"
|
10
|
+
And the output should contain "noumenon help [TASK]"
|
11
|
+
And the output should contain "noumenon site PATH"
|
12
|
+
|
13
|
+
Scenario: Site generator specified, but no path
|
14
|
+
When I run `bundle exec ../../bin/noumenon site`
|
15
|
+
Then the output should contain:
|
16
|
+
"""
|
17
|
+
"site" was called incorrectly. Call as "noumenon site PATH".
|
18
|
+
"""
|
19
|
+
|
20
|
+
Scenario: Site generator specified with a path
|
21
|
+
When I run `bundle exec ../../bin/noumenon site example_site`
|
22
|
+
Then a directory named "example_site" should exist
|
23
|
+
And the directory "example_site" should contain a Noumenon site
|
24
|
+
And the directory "example_site/theme" should contain a theme
|
25
|
+
And the directory "example_site/content" should contain a repository
|
@@ -0,0 +1,30 @@
|
|
1
|
+
Feature: Mounted Applications
|
2
|
+
As a developer
|
3
|
+
I want to mount an application at /app
|
4
|
+
So that I can provide extra functionality
|
5
|
+
In order to deliver the site my client wants
|
6
|
+
|
7
|
+
Scenario: An application has been mounted
|
8
|
+
Given this content item exists at "/app"
|
9
|
+
| type | application |
|
10
|
+
| application | Noumenon::Spec::ExampleApp |
|
11
|
+
When I view "/app"
|
12
|
+
Then the page should load
|
13
|
+
And the headline should be "This is a mounted application"
|
14
|
+
|
15
|
+
Scenario: Loading paths below the mounted application
|
16
|
+
Given this content item exists at "/app"
|
17
|
+
| type | application |
|
18
|
+
| application | Noumenon::Spec::ExampleApp |
|
19
|
+
When I view "/app/sub"
|
20
|
+
Then the page should load
|
21
|
+
And the headline should be "This is a sub-page"
|
22
|
+
|
23
|
+
Scenario: Passing configuration to an application
|
24
|
+
Given this content item exists at "/app"
|
25
|
+
| type | application |
|
26
|
+
| application | Noumenon::Spec::ExampleApp |
|
27
|
+
| message | Hello, world! |
|
28
|
+
When I view "/app"
|
29
|
+
Then the page should load
|
30
|
+
And the headline should be "Hello, world!"
|
@@ -0,0 +1,43 @@
|
|
1
|
+
Feature: Rendering a static template
|
2
|
+
In order to display a non-dynamic page
|
3
|
+
As a designer
|
4
|
+
I want to render a static template
|
5
|
+
|
6
|
+
Scenario: Template exists
|
7
|
+
Given this template exists at "static.nou.html"
|
8
|
+
"""
|
9
|
+
<h1>Static Template</h1>
|
10
|
+
<p>This is a static template which does not have any fields.</p>
|
11
|
+
"""
|
12
|
+
And this content item exists at "/static"
|
13
|
+
| template | static |
|
14
|
+
When I view "/static"
|
15
|
+
Then the page should load
|
16
|
+
And the headline should be "Static Template"
|
17
|
+
And the body text should be "This is a static template which does not have any fields."
|
18
|
+
|
19
|
+
Scenario: Template does not exist
|
20
|
+
Given no template exists at "static.nou.html"
|
21
|
+
And this content item exists at "/static"
|
22
|
+
| template | static |
|
23
|
+
When I view "/static"
|
24
|
+
Then the page should return a 500 error
|
25
|
+
And the headline should be "Missing Template"
|
26
|
+
And the body text should be "The template 'static' does not exist within the current theme."
|
27
|
+
|
28
|
+
Scenario: Template is not specified
|
29
|
+
Given this template exists at "default.nou.html"
|
30
|
+
"""
|
31
|
+
<h1>Default Template</h1>
|
32
|
+
"""
|
33
|
+
And this content item exists at "/default"
|
34
|
+
| key | value |
|
35
|
+
When I view "/default"
|
36
|
+
Then the page should load
|
37
|
+
And the headline should be "Default Template"
|
38
|
+
|
39
|
+
Scenario: Content item does not exist
|
40
|
+
Given no content item exists at "/static"
|
41
|
+
When I view "/static"
|
42
|
+
Then the page should return a 404 error
|
43
|
+
And the headline should be "Page Not Found"
|
@@ -0,0 +1,7 @@
|
|
1
|
+
Given /^the asset "([^"]*)" does not exist within the theme$/ do |asset_name|
|
2
|
+
# noop
|
3
|
+
end
|
4
|
+
|
5
|
+
Given /^the asset "([^"]*)" exists within the theme with this content:$/ do |asset_name, content|
|
6
|
+
File.open(File.join(Noumenon.theme.path, "assets", asset_name), "w") { |f| f.print content }
|
7
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
def generator_file(generator, file)
|
2
|
+
File.read File.expand_path("../../../generators/#{generator}/#{file}", __FILE__)
|
3
|
+
end
|
4
|
+
|
5
|
+
Then /^the directory "([^"]*)" should contain a Noumenon site$/ do |path|
|
6
|
+
Then %Q{a file named "#{path}/Gemfile" should exist}
|
7
|
+
And %Q{a file named "#{path}/config.ru" should exist}
|
8
|
+
|
9
|
+
check_exact_file_content "#{path}/Gemfile", generator_file("site", "Gemfile")
|
10
|
+
check_exact_file_content "#{path}/config.ru", generator_file("site", "config.ru")
|
11
|
+
end
|
12
|
+
|
13
|
+
Then /^the directory "([^"]*)" should contain a theme$/ do |path|
|
14
|
+
check_exact_file_content "#{path}/theme.yml", generator_file("theme", "theme.yml")
|
15
|
+
check_exact_file_content "#{path}/layouts/default.nou.html", generator_file("theme", "layouts/default.nou.html")
|
16
|
+
check_exact_file_content "#{path}/templates/default.nou.html", generator_file("theme", "templates/default.nou.html")
|
17
|
+
check_exact_file_content "#{path}/assets/style.css", generator_file("theme", "assets/style.css")
|
18
|
+
end
|
19
|
+
|
20
|
+
Then /^the directory "([^"]*)" should contain a repository$/ do |path|
|
21
|
+
check_exact_file_content "#{path}/index.yml", generator_file("repository", "index.yml")
|
22
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
When /^I view "([^"]*)"$/ do |path|
|
2
|
+
visit path
|
3
|
+
end
|
4
|
+
|
5
|
+
Then /^the page should load$/ do
|
6
|
+
page.status_code.should == 200
|
7
|
+
end
|
8
|
+
|
9
|
+
Then /^the page should return a (\d+) error$/ do |status|
|
10
|
+
page.status_code.should == status.to_i
|
11
|
+
end
|
12
|
+
|
13
|
+
Then /^the page content should be:$/ do |content|
|
14
|
+
page.source.should == content
|
15
|
+
end
|
16
|
+
|
17
|
+
Then /^the headline should be "([^"]*)"$/ do |headline|
|
18
|
+
page.should have_css "h1", :text => headline
|
19
|
+
end
|
20
|
+
|
21
|
+
Then /^the body text should be "([^"]*)"$/ do |body|
|
22
|
+
page.should have_css "p", :text => body
|
23
|
+
end
|
24
|
+
|
25
|
+
Then /^the page title should be "([^"]*)"$/ do |title|
|
26
|
+
page.should have_css "head title", :text => title
|
27
|
+
end
|
28
|
+
|
29
|
+
Then /^the page header should be "([^"]*)"$/ do |header|
|
30
|
+
page.should have_css "header h1", :text => header
|
31
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
Given /^this template exists at "([^"]*)"$/ do |path, template|
|
2
|
+
File.open(File.join(Noumenon.theme.path, "templates", path), "w") do |f|
|
3
|
+
f.write(template)
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
Given /^no template exists at "([^"]*)"$/ do |path|
|
8
|
+
# noop
|
9
|
+
end
|
10
|
+
|
11
|
+
Given /^this layout exists at "([^"]*)"$/ do |path, template|
|
12
|
+
File.open(File.join(Noumenon.theme.path, "layouts", path), "w") do |f|
|
13
|
+
f.write(template)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
Given /^no layout exists at "([^"]*)"$/ do |arg1|
|
18
|
+
# noop
|
19
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# Generated by cucumber-sinatra. (2011-05-20 13:59:19 +0100)
|
2
|
+
|
3
|
+
ENV['RACK_ENV'] = 'test'
|
4
|
+
|
5
|
+
require File.join(File.dirname(__FILE__), '..', '..', 'lib/noumenon.rb')
|
6
|
+
|
7
|
+
require 'aruba/cucumber'
|
8
|
+
require 'capybara/cucumber'
|
9
|
+
require 'rspec'
|
10
|
+
|
11
|
+
require 'fileutils'
|
12
|
+
|
13
|
+
include Noumenon::Spec::ThemeHelpers
|
14
|
+
|
15
|
+
Capybara.app = Noumenon.server
|
16
|
+
|
17
|
+
World do
|
18
|
+
include RSpec::Expectations
|
19
|
+
include RSpec::Matchers
|
20
|
+
|
21
|
+
def content_path
|
22
|
+
File.expand_path('../tmp/content', __FILE__)
|
23
|
+
end
|
24
|
+
|
25
|
+
true
|
26
|
+
end
|
27
|
+
|
28
|
+
Before do
|
29
|
+
Noumenon.theme = create_theme(name: "Example Theme")
|
30
|
+
|
31
|
+
FileUtils.mkdir_p content_path
|
32
|
+
Noumenon.content_repository = Noumenon::Repository::FileSystem.new(path: content_path)
|
33
|
+
end
|
34
|
+
|
35
|
+
After do
|
36
|
+
FileUtils.rm_r content_path
|
37
|
+
FileUtils.rm_r theme_path
|
38
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
Feature: Theme Assets
|
2
|
+
As a designer
|
3
|
+
I want to serve files from my theme
|
4
|
+
So that I can bundle any required images with it
|
5
|
+
In order to make using themes simpler
|
6
|
+
|
7
|
+
Scenario: The asset does not exist
|
8
|
+
Given the asset "foo.txt" does not exist within the theme
|
9
|
+
When I view "/themes/Example%20Theme/foo.txt"
|
10
|
+
Then the page should return a 404 error
|
11
|
+
|
12
|
+
Scenario: The asset does exist
|
13
|
+
Given the asset "foo.txt" exists within the theme with this content:
|
14
|
+
"""
|
15
|
+
Hello, world!
|
16
|
+
"""
|
17
|
+
When I view "/themes/Example%20Theme/foo.txt"
|
18
|
+
Then the page should load
|
19
|
+
And the page content should be:
|
20
|
+
"""
|
21
|
+
Hello, world!
|
22
|
+
"""
|
@@ -0,0 +1 @@
|
|
1
|
+
/* Your themes styles should go here. */
|