locomotivecms 3.0.0.rc3 → 3.0.0.rc4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +3 -3
- data/README.md +1 -1
- data/app/assets/stylesheets/locomotive/unauthorized/_public.scss +7 -4
- data/app/controllers/locomotive/errors_controller.rb +4 -0
- data/app/helpers/locomotive/errors_helper.rb +2 -4
- data/app/models/locomotive/concerns/content_entry/csv.rb +4 -0
- data/app/models/locomotive/concerns/content_entry/slug.rb +0 -2
- data/app/models/locomotive/concerns/content_type/sync.rb +2 -2
- data/app/models/locomotive/concerns/page/templatized.rb +1 -1
- data/app/models/locomotive/concerns/site/access_points.rb +3 -3
- data/app/models/locomotive/theme_asset.rb +0 -1
- data/app/views/locomotive/developers_documentation/_wagon.html.slim +2 -2
- data/app/views/locomotive/devise_mailer/reset_password_instructions.html.slim +1 -0
- data/app/views/locomotive/errors/no_site.json +1 -0
- data/app/views/locomotive/shared/_sidebar.html.slim +1 -1
- data/app/views/locomotive/shared/_sidebar_without_site.html.slim +1 -1
- data/app/views/locomotive/shared/header/_account_menu.html.slim +2 -2
- data/config/locales/en.yml +1 -1
- data/config/routes.rb +4 -2
- data/lib/generators/locomotive/install/install_generator.rb +9 -9
- data/lib/generators/locomotive/install/templates/carrierwave.rb +23 -12
- data/lib/generators/locomotive/install/templates/carrierwave_aws.rb +36 -0
- data/lib/generators/locomotive/install/templates/mongoid.yml +97 -35
- data/lib/locomotive/dependencies.rb +1 -1
- data/lib/locomotive/middlewares/site.rb +10 -4
- data/lib/locomotive/mongoid/patches.rb +1 -1
- data/lib/locomotive/steam_adaptor.rb +6 -4
- data/lib/locomotive/version.rb +1 -1
- data/spec/dummy/config/application.rb +0 -3
- data/spec/dummy/config/initializers/devise.rb +128 -58
- data/spec/dummy/config/mongoid.yml +95 -78
- data/spec/models/locomotive/content_entry_spec.rb +6 -6
- data/spec/requests/locomotive/steam/cache_spec.rb +1 -1
- data/spec/requests/site_spec.rb +25 -0
- data/spec/support/mongoid.rb +2 -0
- metadata +16 -189
- data/features/api/accounts.feature +0 -43
- data/features/api/authentication.feature +0 -41
- data/features/api/authorization/accounts.feature +0 -165
- data/features/api/authorization/content_assets.feature +0 -147
- data/features/api/authorization/content_entries.feature +0 -202
- data/features/api/authorization/content_types.feature +0 -237
- data/features/api/authorization/current_site.feature +0 -30
- data/features/api/authorization/memberships.feature +0 -225
- data/features/api/authorization/pages.feature +0 -189
- data/features/api/authorization/sites.feature +0 -212
- data/features/api/authorization/snippets.feature +0 -179
- data/features/api/authorization/theme_assets.feature +0 -185
- data/features/api/authorization/translations.feature +0 -253
- data/features/api/content_entries.feature +0 -184
- data/features/api/content_types.feature +0 -156
- data/features/api/editable_elements.feature +0 -190
- data/features/api/entries_custom_fields.feature +0 -150
- data/features/api/memberships.feature +0 -26
- data/features/api/pages.feature +0 -72
- data/features/backoffice/authorization/account_settings.feature +0 -28
- data/features/backoffice/authorization/content_type.feature +0 -35
- data/features/backoffice/authorization/current_site.feature +0 -53
- data/features/backoffice/authorization/inline_front_end_editing.feature +0 -46
- data/features/backoffice/authorization/pages.feature +0 -95
- data/features/backoffice/authorization/theme_assets.feature +0 -50
- data/features/backoffice/content_types/edit.feature +0 -20
- data/features/backoffice/content_types/email.feature +0 -26
- data/features/backoffice/content_types/has_many.feature +0 -80
- data/features/backoffice/content_types/integer.feature +0 -26
- data/features/backoffice/content_types/localized.feature +0 -63
- data/features/backoffice/content_types/many_to_many.feature +0 -70
- data/features/backoffice/content_types/tags.feature +0 -22
- data/features/backoffice/content_types/uniqueness.feature +0 -29
- data/features/backoffice/contents.feature +0 -93
- data/features/backoffice/editable_elements.feature +0 -22
- data/features/backoffice/installation.feature +0 -33
- data/features/backoffice/login.feature +0 -33
- data/features/backoffice/mounting.feature +0 -13
- data/features/backoffice/my_account.feature +0 -22
- data/features/backoffice/pages.feature +0 -73
- data/features/backoffice/regressions.feature +0 -19
- data/features/backoffice/site.feature +0 -71
- data/features/backoffice/snippets.feature +0 -39
- data/features/backoffice/theme_assets.feature +0 -72
- data/features/backoffice/translations.feature +0 -50
- data/features/public/basic.feature +0 -30
- data/features/public/contact_form.feature +0 -98
- data/features/public/content_entries.feature +0 -69
- data/features/public/editable_elements.feature +0 -138
- data/features/public/has_many.feature +0 -8
- data/features/public/inheritance.feature +0 -157
- data/features/public/inline_front_end_editing.feature +0 -26
- data/features/public/many_to_many.feature +0 -64
- data/features/public/new_contact_form.feature +0 -95
- data/features/public/pages.feature +0 -116
- data/features/public/pagination.feature +0 -8
- data/features/public/robots.feature +0 -22
- data/features/public/session.feature +0 -40
- data/features/public/sitemap.feature +0 -74
- data/features/public/snippets.feature +0 -21
- data/features/public/tablerow.feature +0 -42
- data/features/public/tags.feature +0 -45
- data/features/step_definitions/api_steps.rb +0 -179
- data/features/step_definitions/backoffice/mounting_steps.rb +0 -22
- data/features/step_definitions/backoffice_steps.rb +0 -47
- data/features/step_definitions/content_assets_steps.rb +0 -12
- data/features/step_definitions/content_types_steps.rb +0 -135
- data/features/step_definitions/current_site_steps.rb +0 -43
- data/features/step_definitions/editable_elements_steps.rb +0 -24
- data/features/step_definitions/membership_steps.rb +0 -19
- data/features/step_definitions/more_web_steps.rb +0 -131
- data/features/step_definitions/page_steps.rb +0 -133
- data/features/step_definitions/pagination_steps.rb +0 -35
- data/features/step_definitions/pickle_steps.rb +0 -100
- data/features/step_definitions/relationships_steps.rb +0 -110
- data/features/step_definitions/site_steps.rb +0 -111
- data/features/step_definitions/snippet_steps.rb +0 -37
- data/features/step_definitions/theme_asset_steps.rb +0 -64
- data/features/step_definitions/translation_steps.rb +0 -7
- data/features/step_definitions/web_steps.rb +0 -225
- data/features/step_definitions/within_steps.rb +0 -14
- data/features/support/cleaner.rb +0 -4
- data/features/support/env.rb +0 -82
- data/features/support/factory_girl.rb +0 -2
- data/features/support/http.rb +0 -22
- data/features/support/locales.rb +0 -5
- data/features/support/paths.rb +0 -62
- data/features/support/pickle.rb +0 -24
- data/features/support/selectors.rb +0 -57
@@ -1,95 +0,0 @@
|
|
1
|
-
Feature: Contact form [New way]
|
2
|
-
As a visitor
|
3
|
-
In order to keep in touch with the site
|
4
|
-
I want to be able to send them a message
|
5
|
-
|
6
|
-
Background:
|
7
|
-
Given I enable the CSRF protection for public submission requests
|
8
|
-
Given I have the site: "test site" set up
|
9
|
-
And I have a custom model named "Messages" with
|
10
|
-
| label | type | required |
|
11
|
-
| Email | string | true |
|
12
|
-
| Message | text | true |
|
13
|
-
| Category | select | true |
|
14
|
-
And I have "Design, Code, Business" as "Category" values of the "Messages" model
|
15
|
-
And I enable the public submission of the "Messages" model
|
16
|
-
And a page named "contact" with the template:
|
17
|
-
"""
|
18
|
-
<html>
|
19
|
-
<head></head>
|
20
|
-
<body>
|
21
|
-
{% if message %}Thanks {{ message.email }}{% endif %}
|
22
|
-
{% model_form "messages" %}
|
23
|
-
<label for="email">E-Mail Address</label>
|
24
|
-
<input type="text" id="email" name="content[email]" />
|
25
|
-
{% if message.errors.email %}Email is required{% endif %}
|
26
|
-
<label for="category">Category</label>
|
27
|
-
<select id="category" name="content[category]">
|
28
|
-
<option value=""></option>
|
29
|
-
{% for name in contents.messages.category_options %}
|
30
|
-
<option value="{{ name }}">{{ name }}</option>
|
31
|
-
{% endfor %}
|
32
|
-
</select>
|
33
|
-
<label for="message">Message</label>
|
34
|
-
<textarea name="content[message]" id="message"></textarea>
|
35
|
-
<input name="submit" type="submit" id="submit" value="Submit" />
|
36
|
-
{% endmodel_form %}
|
37
|
-
</body>
|
38
|
-
</html>
|
39
|
-
"""
|
40
|
-
And a page named "contact_with_redirection" with the template:
|
41
|
-
"""
|
42
|
-
<html>
|
43
|
-
<head></head>
|
44
|
-
<body>
|
45
|
-
{% model_form "messages", success: "/success" %}
|
46
|
-
<label for="email">E-Mail Address</label>
|
47
|
-
<input type="text" id="email" name="content[email]" />
|
48
|
-
{% if message.errors.email %}Email is required{% endif %}
|
49
|
-
<label for="category">Category</label>
|
50
|
-
<select id="category" name="content[category]">
|
51
|
-
<option value=""></option>
|
52
|
-
{% for name in contents.messages.category_options %}
|
53
|
-
<option value="{{ name }}">{{ name }}</option>
|
54
|
-
{% endfor %}
|
55
|
-
</select>
|
56
|
-
<label for="message">Message</label>
|
57
|
-
<textarea name="content[message]" id="message"></textarea>
|
58
|
-
<input name="submit" type="submit" id="submit" value="Submit" />
|
59
|
-
{% endmodel_form %}
|
60
|
-
</body>
|
61
|
-
</html>
|
62
|
-
"""
|
63
|
-
And a page named "success" with the template:
|
64
|
-
"""
|
65
|
-
Thanks {{ message.email }}!
|
66
|
-
"""
|
67
|
-
|
68
|
-
Scenario: Use the url of the current page for the contact form
|
69
|
-
When I view the rendered page at "/contact"
|
70
|
-
Then the rendered output should look like:
|
71
|
-
"""
|
72
|
-
<form method="POST" enctype="multipart/form-data">
|
73
|
-
"""
|
74
|
-
|
75
|
-
Scenario: Sending a message with success
|
76
|
-
When I view the rendered page at "/contact"
|
77
|
-
And I fill in "E-Mail Address" with "did@locomotivecms.com"
|
78
|
-
And I fill in "Message" with "LocomotiveCMS rocks"
|
79
|
-
And I select "Code" from "Category"
|
80
|
-
And I press "Submit"
|
81
|
-
Then I should see "Thanks did@locomotivecms.com"
|
82
|
-
|
83
|
-
Scenario: Display errors
|
84
|
-
When I view the rendered page at "/contact"
|
85
|
-
And I fill in "Message" with "LocomotiveCMS rocks"
|
86
|
-
And I press "Submit"
|
87
|
-
Then I should see "Email is required"
|
88
|
-
|
89
|
-
Scenario: Redirection after success
|
90
|
-
When I view the rendered page at "/contact_with_redirection"
|
91
|
-
And I fill in "E-Mail Address" with "estelle@locomotivecms.com"
|
92
|
-
And I fill in "Message" with "LocomotiveCMS rocks"
|
93
|
-
And I select "Code" from "Category"
|
94
|
-
And I press "Submit"
|
95
|
-
Then I should see "Thanks estelle@locomotivecms.com!"
|
@@ -1,116 +0,0 @@
|
|
1
|
-
Feature: Pages
|
2
|
-
As a designer
|
3
|
-
In order to improve my site navigation
|
4
|
-
I want to list its pages
|
5
|
-
|
6
|
-
Background:
|
7
|
-
Given I have the site: "test site" set up with name: "test site"
|
8
|
-
|
9
|
-
Scenario: List all of them
|
10
|
-
Given a page named "all" with the template:
|
11
|
-
"""
|
12
|
-
{% for page in site.pages %}{{ page.title }}, {% endfor %}
|
13
|
-
"""
|
14
|
-
When I view the rendered page at "/all"
|
15
|
-
Then the rendered output should look like:
|
16
|
-
"""
|
17
|
-
Home page, Page not found, All,
|
18
|
-
"""
|
19
|
-
|
20
|
-
Scenario: Scoped listing
|
21
|
-
Given a page named "hidden-page" with the template:
|
22
|
-
"""
|
23
|
-
Hidden content
|
24
|
-
"""
|
25
|
-
And the page "hidden-page" is unpublished
|
26
|
-
And a page named "hidden-pages" with the template:
|
27
|
-
"""
|
28
|
-
{% with_scope published: false %}
|
29
|
-
{% for page in site.pages %}{{ page.slug }}, {% endfor %}
|
30
|
-
{% endwith_scope %}
|
31
|
-
"""
|
32
|
-
When I view the rendered page at "/hidden-pages"
|
33
|
-
Then the rendered output should look like:
|
34
|
-
"""
|
35
|
-
hidden-page,
|
36
|
-
"""
|
37
|
-
|
38
|
-
Scenario: link_to tag
|
39
|
-
Given the site "test site" has locales "en, es"
|
40
|
-
And a page named "about-us" with the handle "about-us"
|
41
|
-
And the page named "about-us" has the title "Acerca de" in the "es" locale
|
42
|
-
And a page named "page-with-links" with the template:
|
43
|
-
"""
|
44
|
-
{% locale_switcher %}
|
45
|
-
{% link_to about-us %}
|
46
|
-
{% link_to about-us, locale: es %}
|
47
|
-
{% link_to about-us %}
|
48
|
-
<i class="icon-info-sign"></i> {{ target.title }}
|
49
|
-
{% endlink_to %}
|
50
|
-
"""
|
51
|
-
And the page named "page-with-links" has the title "Página con links" in the "es" locale
|
52
|
-
When I view the rendered page at "/page-with-links"
|
53
|
-
Then the rendered output should look like:
|
54
|
-
"""
|
55
|
-
<a href="/about-us">About us</a>
|
56
|
-
<a href="/es/acerca-de">Acerca de</a>
|
57
|
-
<a href="/about-us">
|
58
|
-
<i class="icon-info-sign"></i> About us
|
59
|
-
</a>
|
60
|
-
"""
|
61
|
-
When I follow "es"
|
62
|
-
Then the rendered output should look like:
|
63
|
-
"""
|
64
|
-
<a href="/es/acerca-de">Acerca de</a>
|
65
|
-
<a href="/es/acerca-de">Acerca de</a>
|
66
|
-
<a href="/es/acerca-de">
|
67
|
-
<i class="icon-info-sign"></i> Acerca de
|
68
|
-
</a>
|
69
|
-
"""
|
70
|
-
|
71
|
-
Scenario: link_to templatized page
|
72
|
-
Given I have a custom model named "Articles" with
|
73
|
-
| label | type | required |
|
74
|
-
| Title | string | true |
|
75
|
-
And I have entries for "Articles" with
|
76
|
-
| title |
|
77
|
-
| Hello world |
|
78
|
-
And a templatized page for the "Articles" model and with the template:
|
79
|
-
"""
|
80
|
-
Here is the title: "{{ article.title }}"
|
81
|
-
"""
|
82
|
-
And a page named "page-with-links" with the template:
|
83
|
-
"""
|
84
|
-
{% for article in contents.articles %}
|
85
|
-
Link to article: {% link_to article %}
|
86
|
-
{% endfor %}
|
87
|
-
"""
|
88
|
-
When I view the rendered page at "/page-with-links"
|
89
|
-
And I follow "Hello world"
|
90
|
-
Then the rendered output should look like:
|
91
|
-
"""
|
92
|
-
Here is the title: "Hello world"
|
93
|
-
"""
|
94
|
-
|
95
|
-
Scenario: Default locale fallback
|
96
|
-
Given the site "test site" has locales "en, es"
|
97
|
-
And a page named "only-english" with the template:
|
98
|
-
"""
|
99
|
-
Only english, please
|
100
|
-
"""
|
101
|
-
When I view the rendered page at "/es/only-english"
|
102
|
-
Then I should see "Only english, please"
|
103
|
-
|
104
|
-
|
105
|
-
Scenario: fetch_page tag
|
106
|
-
Given a page named "print-the-slug-of-a-page" with the template:
|
107
|
-
"""
|
108
|
-
{% fetch_page this-is-the-page-handle as my_page %}
|
109
|
-
{{ my_page.slug }}
|
110
|
-
"""
|
111
|
-
And a page named "this-is-the-slug" with the handle "this-is-the-page-handle"
|
112
|
-
When I view the rendered page at "/print-the-slug-of-a-page"
|
113
|
-
Then the rendered output should look like:
|
114
|
-
"""
|
115
|
-
this-is-the-slug
|
116
|
-
"""
|
@@ -1,22 +0,0 @@
|
|
1
|
-
Feature: Robots
|
2
|
-
As a designer
|
3
|
-
I want to be able to define a robots.txt file for my site
|
4
|
-
|
5
|
-
Background:
|
6
|
-
Given I have the site: "test site" set up
|
7
|
-
|
8
|
-
Scenario: Simple robots text
|
9
|
-
Given a robot_txt set to "robots text value"
|
10
|
-
When I view the rendered page at "/robots.txt"
|
11
|
-
Then the rendered output should look like:
|
12
|
-
"""
|
13
|
-
robots text value
|
14
|
-
"""
|
15
|
-
|
16
|
-
Scenario: Robots.txt should provide access to request_host and all other liquid variables
|
17
|
-
Given a robot_txt set to "host: {{request_host}} path: {{path}}"
|
18
|
-
When I view the rendered page at "/robots.txt"
|
19
|
-
Then the rendered output should look like:
|
20
|
-
"""
|
21
|
-
host: test.example.com path: /robots.txt
|
22
|
-
"""
|
@@ -1,40 +0,0 @@
|
|
1
|
-
Feature: Session
|
2
|
-
As a designer
|
3
|
-
I want to record objects in the session and reach them later
|
4
|
-
|
5
|
-
Background:
|
6
|
-
Given I have the site: "test site" set up
|
7
|
-
And a page named "store" with the template:
|
8
|
-
"""
|
9
|
-
Store a string in the session. {% session_assign foo = 'monkey' %}
|
10
|
-
"""
|
11
|
-
And a page named "retrieve" with the template:
|
12
|
-
"""
|
13
|
-
Retrieve a string from the session: {{ session.foo }}.
|
14
|
-
"""
|
15
|
-
And a page named "release" with the template:
|
16
|
-
"""
|
17
|
-
Remove a string from the session. {% session_assign foo = null %}
|
18
|
-
"""
|
19
|
-
|
20
|
-
Scenario: Store and retrieve a string in session
|
21
|
-
When I view the rendered page at "/retrieve"
|
22
|
-
Then the rendered output should look like:
|
23
|
-
"""
|
24
|
-
Retrieve a string from the session: .
|
25
|
-
"""
|
26
|
-
When I view the rendered page at "/store"
|
27
|
-
And I view the rendered page at "/retrieve"
|
28
|
-
Then the rendered output should look like:
|
29
|
-
"""
|
30
|
-
Retrieve a string from the session: monkey.
|
31
|
-
"""
|
32
|
-
|
33
|
-
Scenario: Remove a object from the session
|
34
|
-
When I view the rendered page at "/store"
|
35
|
-
And I view the rendered page at "/release"
|
36
|
-
And I view the rendered page at "/retrieve"
|
37
|
-
Then the rendered output should look like:
|
38
|
-
"""
|
39
|
-
Retrieve a string from the session: .
|
40
|
-
"""
|
@@ -1,74 +0,0 @@
|
|
1
|
-
Feature: Sitemap
|
2
|
-
As a designer
|
3
|
-
I want to have an automatically generated sitemap
|
4
|
-
|
5
|
-
Background:
|
6
|
-
Given I have the site: "test site" set up
|
7
|
-
|
8
|
-
Scenario: Simple sitemap
|
9
|
-
Given a page named "about" with the template:
|
10
|
-
"""
|
11
|
-
<html>
|
12
|
-
<body>About us</body>
|
13
|
-
</html>
|
14
|
-
"""
|
15
|
-
When I go to the sitemap
|
16
|
-
Then the response status should be 200
|
17
|
-
And I should see the following xml output:
|
18
|
-
"""
|
19
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
20
|
-
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
21
|
-
<url>
|
22
|
-
<loc>http://test.example.com:9886</loc>
|
23
|
-
<priority>1.0</priority>
|
24
|
-
</url>
|
25
|
-
<url>
|
26
|
-
<loc>http://test.example.com:9886/about</loc>
|
27
|
-
<lastmod>:now</lastmod>
|
28
|
-
<priority>0.9</priority>
|
29
|
-
</url>
|
30
|
-
</urlset>
|
31
|
-
"""
|
32
|
-
|
33
|
-
Scenario: Templatized page
|
34
|
-
Given I have a custom model named "Articles" with
|
35
|
-
| label | type | required |
|
36
|
-
| Title | string | true |
|
37
|
-
| Body | text | true |
|
38
|
-
And I have entries for "Articles" with
|
39
|
-
| title | body |
|
40
|
-
| Hello world | Lorem ipsum |
|
41
|
-
| Lorem ipsum | Lorem ipsum... |
|
42
|
-
And a templatized page for the "Articles" model and with the template:
|
43
|
-
"""
|
44
|
-
<html>
|
45
|
-
<body>Template for an article</body>
|
46
|
-
</html>
|
47
|
-
"""
|
48
|
-
When I go to the sitemap
|
49
|
-
Then the response status should be 200
|
50
|
-
And I should see the following xml output:
|
51
|
-
"""
|
52
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
53
|
-
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
54
|
-
<url>
|
55
|
-
<loc>http://test.example.com:9886</loc>
|
56
|
-
<priority>1.0</priority>
|
57
|
-
</url>
|
58
|
-
<url>
|
59
|
-
<loc>http://test.example.com:9886/articles</loc>
|
60
|
-
<lastmod>:now</lastmod>
|
61
|
-
<priority>0.9</priority>
|
62
|
-
</url>
|
63
|
-
<url>
|
64
|
-
<loc>http://test.example.com:9886/articles/hello-world</loc>
|
65
|
-
<lastmod>:now</lastmod>
|
66
|
-
<priority>0.9</priority>
|
67
|
-
</url>
|
68
|
-
<url>
|
69
|
-
<loc>http://test.example.com:9886/articles/lorem-ipsum</loc>
|
70
|
-
<lastmod>:now</lastmod>
|
71
|
-
<priority>0.9</priority>
|
72
|
-
</url>
|
73
|
-
</urlset>
|
74
|
-
"""
|
@@ -1,21 +0,0 @@
|
|
1
|
-
Feature: Snippets
|
2
|
-
As a designer
|
3
|
-
I want to insert re-usable piece of code among pages
|
4
|
-
|
5
|
-
Background:
|
6
|
-
Given I have the site: "test site" set up
|
7
|
-
And a snippet named "yield" with the template:
|
8
|
-
"""
|
9
|
-
HELLO WORLD !
|
10
|
-
"""
|
11
|
-
|
12
|
-
Scenario: Simple include
|
13
|
-
Given a page named "hello-world" with the template:
|
14
|
-
"""
|
15
|
-
My application says {% include 'yield' %}
|
16
|
-
"""
|
17
|
-
When I view the rendered page at "/hello-world"
|
18
|
-
Then the rendered output should look like:
|
19
|
-
"""
|
20
|
-
My application says HELLO WORLD !
|
21
|
-
"""
|
@@ -1,42 +0,0 @@
|
|
1
|
-
Feature: TableRow liquid tags
|
2
|
-
As a designer
|
3
|
-
I want to be able to use the tablerow liquid tag with locomotive contents
|
4
|
-
|
5
|
-
Background:
|
6
|
-
Given I have the site: "test site" set up
|
7
|
-
And I have a custom model named "Projects" with
|
8
|
-
| label | type | required |
|
9
|
-
| Name | string | true |
|
10
|
-
And I have entries for "Projects" with
|
11
|
-
| name | _position |
|
12
|
-
| Project 1 | 1 |
|
13
|
-
| Project 2 | 2 |
|
14
|
-
| Project 3 | 3 |
|
15
|
-
|
16
|
-
Scenario: Use the tablerow tag
|
17
|
-
Given a page named "project-table" with the template:
|
18
|
-
"""
|
19
|
-
<h1>Projects</h1>
|
20
|
-
<table>
|
21
|
-
{% tablerow project in contents.projects cols: 2 %}
|
22
|
-
{{ project.name }}
|
23
|
-
{% endtablerow %}
|
24
|
-
</table>
|
25
|
-
"""
|
26
|
-
When I view the rendered page at "/project-table"
|
27
|
-
Then the rendered output should look like:
|
28
|
-
"""
|
29
|
-
<h1>Projects</h1>
|
30
|
-
<table>
|
31
|
-
<tr class="row1">
|
32
|
-
<td class="col1">
|
33
|
-
Project 1
|
34
|
-
</td><td class="col2">
|
35
|
-
Project 2
|
36
|
-
</td></tr>
|
37
|
-
<tr class="row2"><td class="col1">
|
38
|
-
Project 3
|
39
|
-
</td></tr>
|
40
|
-
|
41
|
-
</table>
|
42
|
-
"""
|
@@ -1,45 +0,0 @@
|
|
1
|
-
Feature: Tagged content
|
2
|
-
As a designer
|
3
|
-
In order to organize my content
|
4
|
-
I want to be able to tag it
|
5
|
-
|
6
|
-
Background:
|
7
|
-
Given I have the site: "test site" set up
|
8
|
-
And I have a custom model named "Posts" with
|
9
|
-
| label | type | required |
|
10
|
-
| Title | string | true |
|
11
|
-
| Body | string | false |
|
12
|
-
| Tags | tags | false |
|
13
|
-
And I have entries for "Posts" with
|
14
|
-
| title | body | tags |
|
15
|
-
| Fashion post | Fashion body | blogging, fashion |
|
16
|
-
| Diet post | Diet body | blogging, diet |
|
17
|
-
|
18
|
-
Scenario: Navigate by tags
|
19
|
-
Given a page named "my-posts" with the template:
|
20
|
-
"""
|
21
|
-
{% if params.tag %}
|
22
|
-
{% with_scope tags: params.tag %}
|
23
|
-
{% assign posts = contents.posts.all %}
|
24
|
-
{% endwith_scope %}
|
25
|
-
{% else %}
|
26
|
-
{% assign posts = contents.posts.all %}
|
27
|
-
{% endif %}
|
28
|
-
|
29
|
-
{% for post in posts %}
|
30
|
-
{{ post.title }}<br>
|
31
|
-
{% for tag in post.tags %}
|
32
|
-
<a href="/my-posts?tag={{ tag }}">{{ tag }}</a>
|
33
|
-
{% endfor %}
|
34
|
-
<hr>
|
35
|
-
{% endfor %}
|
36
|
-
"""
|
37
|
-
When I view the rendered page at "/my-posts"
|
38
|
-
Then I should see "Fashion post"
|
39
|
-
And I should see "Diet post"
|
40
|
-
When I follow "blogging"
|
41
|
-
Then I should see "Fashion post"
|
42
|
-
And I should see "Diet post"
|
43
|
-
When I follow "fashion"
|
44
|
-
Then I should see "Fashion"
|
45
|
-
And I should not see "Diet"
|
@@ -1,179 +0,0 @@
|
|
1
|
-
def api_base_url
|
2
|
-
"http://#{Locomotive::Site.first.domains.first}/locomotive/api/"
|
3
|
-
end
|
4
|
-
|
5
|
-
def do_api_request(type, url, param_string_or_hash = nil)
|
6
|
-
begin
|
7
|
-
if param_string_or_hash
|
8
|
-
if param_string_or_hash.is_a? Hash
|
9
|
-
params = param_string_or_hash
|
10
|
-
else
|
11
|
-
# Do memory substitution from json_spec
|
12
|
-
params = JSON.parse(JsonSpec.remember(param_string_or_hash))
|
13
|
-
end
|
14
|
-
else
|
15
|
-
params = {}
|
16
|
-
end
|
17
|
-
transform_filenames_to_fixtured_files(params)
|
18
|
-
@json_response = do_request(type, api_base_url, url,
|
19
|
-
params.merge({ 'CONTENT_TYPE' => 'application/json' }))
|
20
|
-
rescue Pundit::NotAuthorizedError, Mongoid::Errors::DocumentNotFound
|
21
|
-
@error = $!
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def last_json
|
26
|
-
@json_response.try(:body) || page.source
|
27
|
-
end
|
28
|
-
|
29
|
-
def last_status
|
30
|
-
@json_response.try(:status) || page.status
|
31
|
-
end
|
32
|
-
|
33
|
-
# Deal with file fields
|
34
|
-
|
35
|
-
def file_fields
|
36
|
-
@file_fields ||= []
|
37
|
-
end
|
38
|
-
|
39
|
-
def add_file_field(json_path)
|
40
|
-
file_fields << json_path
|
41
|
-
end
|
42
|
-
|
43
|
-
def get_field_at_path(hash, path)
|
44
|
-
val = hash
|
45
|
-
path.split('/').each do |key|
|
46
|
-
if val.is_a?(Array)
|
47
|
-
val = val[key.to_i]
|
48
|
-
elsif val.has_key?(key)
|
49
|
-
val = val[key]
|
50
|
-
else
|
51
|
-
return nil
|
52
|
-
end
|
53
|
-
end
|
54
|
-
val
|
55
|
-
end
|
56
|
-
|
57
|
-
def set_field_at_path(hash, path, value)
|
58
|
-
obj = hash
|
59
|
-
keys = path.split('/')
|
60
|
-
last_key = keys.slice!(-1)
|
61
|
-
keys.each do |key|
|
62
|
-
if obj.is_a?(Array)
|
63
|
-
obj = obj[key.to_i]
|
64
|
-
else
|
65
|
-
obj = obj[key]
|
66
|
-
end
|
67
|
-
end
|
68
|
-
obj[last_key] = value
|
69
|
-
end
|
70
|
-
|
71
|
-
def transform_filenames_to_fixtured_files(params)
|
72
|
-
file_fields.each do |path|
|
73
|
-
filename = get_field_at_path(params, path)
|
74
|
-
return unless filename
|
75
|
-
|
76
|
-
file = Rack::Test::UploadedFile.new(Rails.root.join('..', 'fixtures', filename))
|
77
|
-
set_field_at_path(params, path, file)
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
Given /^I have an? "([^"]*)" API token$/ do |role|
|
82
|
-
@membership = Locomotive::Site.first.memberships.where(:role => role.downcase).first \
|
83
|
-
|| FactoryGirl.create(role.downcase.to_sym, :site => Locomotive::Site.first)
|
84
|
-
|
85
|
-
login_params = {
|
86
|
-
'email' => @membership.account.email,
|
87
|
-
'password' => 'easyone'
|
88
|
-
}
|
89
|
-
|
90
|
-
response = do_request('POST', api_base_url, 'tokens.json',
|
91
|
-
login_params.merge({ 'CONTENT_TYPE' => 'application/json' }))
|
92
|
-
|
93
|
-
if response.status == 200
|
94
|
-
@auth_token = JSON.parse(response.body)['token']
|
95
|
-
else
|
96
|
-
raise JSON.parse(response.body)['message']
|
97
|
-
end
|
98
|
-
|
99
|
-
add_default_params(:auth_token => @auth_token)
|
100
|
-
end
|
101
|
-
|
102
|
-
Given /^I do not have an API token$/ do
|
103
|
-
@auth_token = nil
|
104
|
-
end
|
105
|
-
|
106
|
-
Given /^the JSON request at "([^"]*)" is a file$/ do |path|
|
107
|
-
add_file_field(path)
|
108
|
-
end
|
109
|
-
|
110
|
-
When /^I visit "([^"]*)"$/ do |path|
|
111
|
-
@json_response = get("http://#{@site.domains.first}#{path}", { auth_token: @auth_token }, { 'CONTENT_TYPE' => 'application/json' })
|
112
|
-
end
|
113
|
-
|
114
|
-
# http://stackoverflow.com/questions/9009392/racktest-put-method-with-json-fails-to-convert-json-to-params
|
115
|
-
When /^I post to "([^"]*)"$/ do |path|
|
116
|
-
@json_response = post("http://#{@site.domains.first}#{path}", '', { 'CONTENT_TYPE' => 'application/json' })
|
117
|
-
end
|
118
|
-
|
119
|
-
When /^I post to "([^"]*)" with:$/ do |path, json_string|
|
120
|
-
@json_response = post("http://#{@site.domains.first}#{path}", json_string, { 'CONTENT_TYPE' => 'application/json' })
|
121
|
-
end
|
122
|
-
|
123
|
-
When /^I do an API (\w+) (?:request )?to ([\w.\/]+)$/ do |request_type, url|
|
124
|
-
do_api_request(request_type, url)
|
125
|
-
end
|
126
|
-
|
127
|
-
When /^I do an API (\w+) (?:request )?to ([\w.\/]+) with:$/ do |request_type, url, param_string|
|
128
|
-
do_api_request(request_type, url, param_string)
|
129
|
-
end
|
130
|
-
|
131
|
-
Then /^an access denied error should occur$/ do
|
132
|
-
if @error
|
133
|
-
@error.is_a?(CanCan::AccessDenied).should be_true
|
134
|
-
else
|
135
|
-
last_status.should == 401
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
Then /^it should not exist$/ do
|
140
|
-
if @error
|
141
|
-
@error.is_a?(Mongoid::Errors::DocumentNotFound).should be_true
|
142
|
-
else
|
143
|
-
last_status.should == 404
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
When /^I do a multipart API (\w+) (?:request )?to ([\w.\/]+) with base key "([^"]*)" and:$/ \
|
148
|
-
do |request_type, url, base_key, table|
|
149
|
-
params = {}
|
150
|
-
params = table.rows_hash
|
151
|
-
params.each do |key, filename|
|
152
|
-
params[key] = Rack::Test::UploadedFile.new(Rails.root.join('..', 'fixtures', filename))
|
153
|
-
end
|
154
|
-
do_api_request(request_type, url, { base_key => params })
|
155
|
-
end
|
156
|
-
|
157
|
-
Then /^the JSON at "([^"]*)" should match \/(.+)\/$/ do |path, regex|
|
158
|
-
parse_json(last_json, path).should =~ /#{regex}/
|
159
|
-
end
|
160
|
-
|
161
|
-
Then /^the response content type should match \/(.+)\/$/ do |regex|
|
162
|
-
@json_response.header['Content-Type'].should =~ /#{regex}/
|
163
|
-
end
|
164
|
-
|
165
|
-
Then /^the JSON at "([^"]*)" should be the time "(.+)"$/ do |path, time_str|
|
166
|
-
format = '%Y-%m-%dT%H:%M:%S%Z'
|
167
|
-
json_time_str = parse_json(last_json, path)
|
168
|
-
json_time = Time.strptime(json_time_str, format)
|
169
|
-
time = Time.strptime(time_str, format)
|
170
|
-
json_time.should == time
|
171
|
-
end
|
172
|
-
|
173
|
-
Then /^I print the JSON response$/ do
|
174
|
-
puts %{JSON (status=#{@json_response.status}): "#{last_json}" / #{last_json.inspect}}
|
175
|
-
end
|
176
|
-
|
177
|
-
Then /^I print the editable elements for page "([^"]*)"$/ do |id|
|
178
|
-
puts @site.pages.find(id).editable_elements.inspect
|
179
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
Given /^the engine is mounted on a non standard path$/ do
|
2
|
-
Rails.application.routes.draw do
|
3
|
-
mount Locomotive::Engine => '/my-custom-path', as: 'locomotive'
|
4
|
-
match '/foo' => 'foo#index', as: 'foo'
|
5
|
-
end
|
6
|
-
end
|
7
|
-
|
8
|
-
Then /^I should be able to access the backend$/ do
|
9
|
-
# Ensure we can access the backend
|
10
|
-
visit '/my-custom-path'
|
11
|
-
page.should have_content 'LocomotiveCMS'
|
12
|
-
|
13
|
-
# Ensure we can update the homepage content
|
14
|
-
within('#pages-list') do
|
15
|
-
click_link 'Home page'
|
16
|
-
end
|
17
|
-
click_button 'Save'
|
18
|
-
page.should have_content 'Page was successfully updated'
|
19
|
-
|
20
|
-
# Reset the routes back to normal once we are done
|
21
|
-
Rails.application.reload_routes!
|
22
|
-
end
|