landable 1.7.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.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +15 -0
- data/MIT-LICENSE +20 -0
- data/README.md +56 -0
- data/Rakefile +22 -0
- data/app/controllers/concerns/landable/variables_concern.rb +38 -0
- data/app/controllers/landable/api/access_tokens_controller.rb +48 -0
- data/app/controllers/landable/api/assets_controller.rb +55 -0
- data/app/controllers/landable/api/categories_controller.rb +13 -0
- data/app/controllers/landable/api/directories_controller.rb +19 -0
- data/app/controllers/landable/api/page_revisions_controller.rb +38 -0
- data/app/controllers/landable/api/pages_controller.rb +96 -0
- data/app/controllers/landable/api/templates_controller.rb +33 -0
- data/app/controllers/landable/api/themes_controller.rb +57 -0
- data/app/controllers/landable/api_controller.rb +75 -0
- data/app/controllers/landable/application_controller.rb +4 -0
- data/app/controllers/landable/public/pages_controller.rb +25 -0
- data/app/controllers/landable/public/preview/page_revisions_controller.rb +16 -0
- data/app/controllers/landable/public/preview/pages_controller.rb +16 -0
- data/app/controllers/landable/public/sitemap_controller.rb +18 -0
- data/app/decorators/landable/null_page_decorator.rb +26 -0
- data/app/decorators/landable/page_decorator.rb +40 -0
- data/app/helpers/landable/application_helper.rb +13 -0
- data/app/helpers/landable/pages_helper.rb +20 -0
- data/app/models/concerns/landable/has_assets.rb +74 -0
- data/app/models/concerns/landable/table_name.rb +12 -0
- data/app/models/concerns/landable/traffic/table_name.rb +14 -0
- data/app/models/landable/access_token.rb +20 -0
- data/app/models/landable/asset.rb +63 -0
- data/app/models/landable/asset_search_engine.rb +20 -0
- data/app/models/landable/author.rb +12 -0
- data/app/models/landable/category.rb +27 -0
- data/app/models/landable/directory.rb +23 -0
- data/app/models/landable/page.rb +259 -0
- data/app/models/landable/page_revision.rb +74 -0
- data/app/models/landable/page_search_engine.rb +20 -0
- data/app/models/landable/search_engine.rb +39 -0
- data/app/models/landable/template.rb +24 -0
- data/app/models/landable/theme.rb +20 -0
- data/app/models/landable/traffic/access.rb +11 -0
- data/app/models/landable/traffic/ad_group.rb +11 -0
- data/app/models/landable/traffic/ad_type.rb +11 -0
- data/app/models/landable/traffic/attribution.rb +38 -0
- data/app/models/landable/traffic/bid_match_type.rb +11 -0
- data/app/models/landable/traffic/browser.rb +11 -0
- data/app/models/landable/traffic/campaign.rb +11 -0
- data/app/models/landable/traffic/city.rb +11 -0
- data/app/models/landable/traffic/content.rb +11 -0
- data/app/models/landable/traffic/cookie.rb +16 -0
- data/app/models/landable/traffic/country.rb +11 -0
- data/app/models/landable/traffic/creative.rb +11 -0
- data/app/models/landable/traffic/device.rb +11 -0
- data/app/models/landable/traffic/device_type.rb +11 -0
- data/app/models/landable/traffic/domain.rb +12 -0
- data/app/models/landable/traffic/event.rb +12 -0
- data/app/models/landable/traffic/event_type.rb +11 -0
- data/app/models/landable/traffic/experiment.rb +11 -0
- data/app/models/landable/traffic/http_method.rb +11 -0
- data/app/models/landable/traffic/ip_address.rb +11 -0
- data/app/models/landable/traffic/ip_lookup.rb +12 -0
- data/app/models/landable/traffic/keyword.rb +11 -0
- data/app/models/landable/traffic/location.rb +11 -0
- data/app/models/landable/traffic/match_type.rb +11 -0
- data/app/models/landable/traffic/medium.rb +11 -0
- data/app/models/landable/traffic/mime_type.rb +11 -0
- data/app/models/landable/traffic/network.rb +11 -0
- data/app/models/landable/traffic/owner.rb +10 -0
- data/app/models/landable/traffic/ownership.rb +10 -0
- data/app/models/landable/traffic/page_view.rb +24 -0
- data/app/models/landable/traffic/path.rb +13 -0
- data/app/models/landable/traffic/placement.rb +11 -0
- data/app/models/landable/traffic/platform.rb +11 -0
- data/app/models/landable/traffic/position.rb +11 -0
- data/app/models/landable/traffic/query_string.rb +12 -0
- data/app/models/landable/traffic/referer.rb +11 -0
- data/app/models/landable/traffic/region.rb +11 -0
- data/app/models/landable/traffic/search_term.rb +11 -0
- data/app/models/landable/traffic/source.rb +11 -0
- data/app/models/landable/traffic/target.rb +11 -0
- data/app/models/landable/traffic/user_agent.rb +28 -0
- data/app/models/landable/traffic/user_agent_type.rb +11 -0
- data/app/models/landable/traffic/visit.rb +15 -0
- data/app/models/landable/traffic/visitor.rb +13 -0
- data/app/responders/landable/api_responder.rb +76 -0
- data/app/responders/landable/page_render_responder.rb +15 -0
- data/app/serializers/landable/access_token_serializer.rb +6 -0
- data/app/serializers/landable/asset_serializer.rb +14 -0
- data/app/serializers/landable/author_serializer.rb +5 -0
- data/app/serializers/landable/category_serializer.rb +5 -0
- data/app/serializers/landable/directory_serializer.rb +8 -0
- data/app/serializers/landable/page_revision_serializer.rb +15 -0
- data/app/serializers/landable/page_serializer.rb +31 -0
- data/app/serializers/landable/template_serializer.rb +5 -0
- data/app/serializers/landable/theme_serializer.rb +7 -0
- data/app/services/landable/authentication_service.rb +44 -0
- data/app/services/landable/registration_service.rb +13 -0
- data/app/services/landable/render_service.rb +86 -0
- data/app/services/landable/tidy_service.rb +155 -0
- data/app/uploaders/landable/asset_uploader.rb +9 -0
- data/app/validators/path_validator.rb +12 -0
- data/app/validators/url_validator.rb +13 -0
- data/app/views/templates/preview.liquid +122 -0
- data/bin/rails +8 -0
- data/bin/redb +7 -0
- data/config.ru +7 -0
- data/config/cucumber.yml +5 -0
- data/config/routes.rb +62 -0
- data/db/migrate/20130510221424_create_landable_schema.rb +338 -0
- data/db/migrate/20130909182713_landable_pages__add_updated_by.rb +11 -0
- data/db/migrate/20130909182715_landable_page_revisions__break_out_snapshot.rb +72 -0
- data/db/migrate/20130909191153_landable_pages__add_lock_version.rb +5 -0
- data/db/migrate/20131002220041_file_based_themes.rb +12 -0
- data/db/migrate/20131008164204_create_head_tag_on_page.rb +19 -0
- data/db/migrate/20131008193544_drop_status_codes_model.rb +44 -0
- data/db/migrate/20131028145652_add_traffic_schema.rb +276 -0
- data/db/migrate/20131101213623_add_dnt_column_to_visits.rb +7 -0
- data/db/migrate/20131104224120_add_meta_on_events.rb +7 -0
- data/db/migrate/20131106185946_add_index_on_page_revisions_path.rb +6 -0
- data/db/migrate/20131106193021_page_revisisons__path_status_code_index.rb +9 -0
- data/db/migrate/20131108212501_traffic_owner_ids_are_serials.rb +20 -0
- data/db/migrate/20131121150902_add_attribution_id_to_unique_index.rb +10 -0
- data/db/migrate/20131216214027_drop_browser_screenshot_tables.rb +6 -0
- data/db/migrate/20140128170659_file_backed_templates.rb +8 -0
- data/db/migrate/20140205193757_fix_status_codes.rb +24 -0
- data/db/migrate/20140206211322_add_response_time_to_traffic_page_views.rb +7 -0
- data/db/migrate/20140220170324_add_slug_to_categories.rb +14 -0
- data/db/migrate/20140220174630_add_abstract_and_hero_asset_to_pages_and_page_revisions.rb +8 -0
- data/db/migrate/20140224205516_rename_traffic_schema.rb +40 -0
- data/db/pgtap/pgtap.sql +9034 -0
- data/db/test/landable.access_tokens.sql +13 -0
- data/db/test/landable.assets.sql +16 -0
- data/db/test/landable.authors.sql +22 -0
- data/db/test/landable.categories.sql +9 -0
- data/db/test/landable.page_revisions.sql +41 -0
- data/db/test/landable.pages.sql +19 -0
- data/db/test/landable.templates.sql +15 -0
- data/db/test/landable.themes.sql +25 -0
- data/doc/schema/access_token.json +22 -0
- data/doc/schema/asset.json +65 -0
- data/doc/schema/author.json +30 -0
- data/doc/schema/directory.json +24 -0
- data/doc/schema/page.json +95 -0
- data/doc/schema/page_revision.json +70 -0
- data/doc/schema/theme.json +37 -0
- data/doc/schema/uuid.json +6 -0
- data/features/api/access_tokens.feature +84 -0
- data/features/api/assets.feature +46 -0
- data/features/api/cors.feature +25 -0
- data/features/api/pages.feature +42 -0
- data/features/api/preview.feature +16 -0
- data/features/api/templates.feature +33 -0
- data/features/api/themes.feature +33 -0
- data/features/liquid/body.feature +35 -0
- data/features/liquid/drops/categories.feature +54 -0
- data/features/liquid/tags.feature +168 -0
- data/features/public/content_types.feature +17 -0
- data/features/public/publishing.feature +45 -0
- data/features/public/status_codes.feature +25 -0
- data/features/public/views.feature +17 -0
- data/features/step_definitions/asset_steps.rb +60 -0
- data/features/step_definitions/core_api_steps.rb +139 -0
- data/features/step_definitions/debug_steps.rb +3 -0
- data/features/step_definitions/factory_steps.rb +124 -0
- data/features/step_definitions/html_steps.rb +9 -0
- data/features/step_definitions/liquid_steps.rb +79 -0
- data/features/step_definitions/revision_steps.rb +5 -0
- data/features/step_definitions/theme_steps.rb +43 -0
- data/features/support/env.rb +66 -0
- data/features/support/usefulness.rb +13 -0
- data/landable.gemspec +54 -0
- data/lib/generators/landable/collection/collection_generator.rb +0 -0
- data/lib/generators/landable/collection/templates/stylesheets/landable/%file_name%.less +0 -0
- data/lib/generators/landable/collection/templates/stylesheets/landable/%file_name%/mixins.less +0 -0
- data/lib/generators/landable/collection/templates/stylesheets/landable/%file_name%/variables.less +0 -0
- data/lib/generators/landable/component/component_generator.rb +0 -0
- data/lib/generators/landable/component/templates/javascripts/landable/%file_name%.less +0 -0
- data/lib/generators/landable/component/templates/stylesheets/landable/%file_name%.less +0 -0
- data/lib/generators/landable/install_generator.rb +19 -0
- data/lib/generators/landable/landable_generator.rb +22 -0
- data/lib/generators/templates/landable.rb +34 -0
- data/lib/landable.rb +30 -0
- data/lib/landable/configuration.rb +115 -0
- data/lib/landable/core_ext/ipaddr.rb +18 -0
- data/lib/landable/engine.rb +69 -0
- data/lib/landable/error.rb +16 -0
- data/lib/landable/inflections.rb +4 -0
- data/lib/landable/layout.rb +60 -0
- data/lib/landable/liquid.rb +27 -0
- data/lib/landable/liquid/asset_tags.rb +76 -0
- data/lib/landable/liquid/drops.rb +46 -0
- data/lib/landable/liquid/filters.rb +11 -0
- data/lib/landable/liquid/tags.rb +91 -0
- data/lib/landable/migration.rb +40 -0
- data/lib/landable/mime_types.rb +15 -0
- data/lib/landable/partial.rb +46 -0
- data/lib/landable/seeds.rb +36 -0
- data/lib/landable/traffic.rb +34 -0
- data/lib/landable/traffic/crawl_tracker.rb +9 -0
- data/lib/landable/traffic/noop_tracker.rb +8 -0
- data/lib/landable/traffic/ping_tracker.rb +9 -0
- data/lib/landable/traffic/scan_tracker.rb +9 -0
- data/lib/landable/traffic/scrape_tracker.rb +9 -0
- data/lib/landable/traffic/tracker.rb +283 -0
- data/lib/landable/traffic/user_tracker.rb +65 -0
- data/lib/landable/version.rb +10 -0
- data/lib/tasks/landable/cucumber.rake +67 -0
- data/lib/tasks/landable/data.rake +166 -0
- data/lib/tasks/landable/pgtap.rake +26 -0
- data/lib/tasks/landable/rdoc.rake +11 -0
- data/lib/tasks/landable/seed.rake +16 -0
- data/lib/tasks/landable/spec.rake +15 -0
- data/script/cucumber +10 -0
- data/spec/concerns/landable/has_assets_spec.rb +75 -0
- data/spec/concerns/landable/table_name_spec.rb +15 -0
- data/spec/concerns/landable/traffic/table_name_spec.rb +16 -0
- data/spec/controllers/concerns/landable/variables_concern_spec.rb +66 -0
- data/spec/controllers/landable/api/assets_controller_spec.rb +24 -0
- data/spec/controllers/landable/api/categories_controller_spec.rb +45 -0
- data/spec/controllers/landable/api/directories_controller_spec.rb +56 -0
- data/spec/controllers/landable/api/page_revisions_controller_spec.rb +29 -0
- data/spec/controllers/landable/api/pages_controller_spec.rb +271 -0
- data/spec/controllers/landable/api_controller_spec.rb +189 -0
- data/spec/controllers/public/preview/page_revisions_controller_spec.rb +41 -0
- data/spec/controllers/public/preview/pages_controller_spec.rb +36 -0
- data/spec/controllers/public/sitemap_controller_spec.rb +25 -0
- data/spec/decorators/page_decorator_spec.rb +90 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/images/foo.jpg +0 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/controllers/application_controller.rb +10 -0
- data/spec/dummy/app/controllers/concerns/.keep +0 -0
- data/spec/dummy/app/controllers/priority_controller.rb +7 -0
- data/spec/dummy/app/helpers/application_helper.rb +5 -0
- data/spec/dummy/app/mailers/.keep +0 -0
- data/spec/dummy/app/models/.keep +0 -0
- data/spec/dummy/app/models/concerns/.keep +0 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/app/views/layouts/priority.html.erb +18 -0
- data/spec/dummy/app/views/partials/_foobazz.html +1 -0
- data/spec/dummy/app/views/priority/show.html.erb +11 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +21 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +60 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +29 -0
- data/spec/dummy/config/environments/production.rb +80 -0
- data/spec/dummy/config/environments/test.rb +42 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/landable.rb +22 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +12 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +4 -0
- data/spec/dummy/db/structure.sql +3736 -0
- data/spec/dummy/lib/assets/.keep +0 -0
- data/spec/dummy/log/.keep +0 -0
- data/spec/dummy/public/404.html +58 -0
- data/spec/dummy/public/422.html +58 -0
- data/spec/dummy/public/500.html +57 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/factories/asset.rb +29 -0
- data/spec/factories/authors.rb +12 -0
- data/spec/factories/category.rb +6 -0
- data/spec/factories/page_revision.rb +6 -0
- data/spec/factories/pages.rb +33 -0
- data/spec/factories/template.rb +13 -0
- data/spec/factories/theme.rb +14 -0
- data/spec/fixtures/assets/cthulhu.jpg +0 -0
- data/spec/fixtures/assets/panda.png +0 -0
- data/spec/fixtures/assets/sloth.png +0 -0
- data/spec/fixtures/assets/small.pdf +0 -0
- data/spec/helpers/pages_helper_spec.rb +35 -0
- data/spec/lib/landable/configuration_spec.rb +20 -0
- data/spec/lib/landable/layout_spec.rb +25 -0
- data/spec/lib/landable/liquid_spec.rb +24 -0
- data/spec/lib/landable/migration_spec.rb +51 -0
- data/spec/lib/landable/partial_spec.rb +84 -0
- data/spec/lib/landable/tracking_spec.rb +62 -0
- data/spec/lib/landable/traffic_spec.rb +45 -0
- data/spec/models/landable/access_token_spec.rb +13 -0
- data/spec/models/landable/asset_spec.rb +48 -0
- data/spec/models/landable/directory_spec.rb +36 -0
- data/spec/models/landable/page/errors_spec.rb +30 -0
- data/spec/models/landable/page_revision_spec.rb +75 -0
- data/spec/models/landable/page_spec.rb +377 -0
- data/spec/models/landable/template_spec.rb +47 -0
- data/spec/models/landable/theme_spec.rb +8 -0
- data/spec/responders/page_render_responder_spec.rb +43 -0
- data/spec/routing/public_page_route_spec.rb +36 -0
- data/spec/services/landable/authentication_service_spec.rb +61 -0
- data/spec/services/landable/render_service_spec.rb +103 -0
- data/spec/services/landable/tidy_service_spec.rb +157 -0
- data/spec/spec_helper.rb +38 -0
- data/spec/support/behaviors.rb +107 -0
- data/spec/support/carrier_wave.rb +17 -0
- data/spec/support/categories.yml +2 -0
- data/spec/support/helpers.rb +22 -0
- metadata +795 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Landable
|
|
4
|
+
describe Partial do
|
|
5
|
+
# Defined in spec/dummy/app/views/partials/...
|
|
6
|
+
let(:partials) { ['partials/test', 'partials/foobazz'] }
|
|
7
|
+
|
|
8
|
+
describe '#to_template' do
|
|
9
|
+
context 'with configured partials' do
|
|
10
|
+
before :each do
|
|
11
|
+
Landable.configuration.stub(:partials_to_templates).and_return(partials)
|
|
12
|
+
Partial.all.map(&:to_template)
|
|
13
|
+
|
|
14
|
+
@foobazz = Landable::Template.where(file: 'partials/foobazz').first
|
|
15
|
+
@test = Landable::Template.where(file: 'partials/test').first
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it 'creates the templates' do
|
|
19
|
+
Landable::Template.all.should include(@foobazz)
|
|
20
|
+
Landable::Template.all.should include(@test)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
context 'the templates' do
|
|
24
|
+
it 'populates a name by humanizing the file' do
|
|
25
|
+
@foobazz.name.should == 'Partials Foobazz'
|
|
26
|
+
@test.name.should == 'Partials Test'
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it 'populates a description' do
|
|
30
|
+
@foobazz.description.should == 'Defined in Source Code at partials/foobazz'
|
|
31
|
+
@test.description.should == 'Defined in Source Code at partials/test'
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'are not editable' do
|
|
35
|
+
@foobazz.editable.should == false
|
|
36
|
+
@test.editable.should == false
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it 'are not layouts' do
|
|
40
|
+
@foobazz.is_layout.should == false
|
|
41
|
+
@test.is_layout.should == false
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it 'popules a thumbnail_url' do
|
|
45
|
+
@foobazz.thumbnail_url.should == 'http://placehold.it/300x200'
|
|
46
|
+
@test.thumbnail_url.should == 'http://placehold.it/300x200'
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it 'populates a body' do
|
|
50
|
+
@foobazz.body.should == ''
|
|
51
|
+
@test.body.should == ''
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it 'references the flle path' do
|
|
55
|
+
@foobazz.file.should == 'partials/foobazz'
|
|
56
|
+
@test.file.should == 'partials/test'
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it 'creates a slug by underscoring the name' do
|
|
60
|
+
@test.slug.should == 'partials_test'
|
|
61
|
+
@foobazz.slug.should == 'partials_foobazz'
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
describe '::files' do
|
|
68
|
+
it 'returns an array of files' do
|
|
69
|
+
Landable.configuration.stub(:partials_to_templates).and_return(partials)
|
|
70
|
+
|
|
71
|
+
Partial.files.count.should == 2
|
|
72
|
+
Partial.files.should include('partials/test', 'partials/foobazz')
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
context 'with no configured partials' do
|
|
76
|
+
it 'has no files' do
|
|
77
|
+
Landable.configuration.stub(:partials_to_templates).and_return([])
|
|
78
|
+
|
|
79
|
+
Partial.files.should == []
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Landable
|
|
4
|
+
describe Landable::Traffic::Tracker do
|
|
5
|
+
let(:referer) { "/something/ valid" }
|
|
6
|
+
let(:user_agent) { "type" }
|
|
7
|
+
let(:format) { double('format', { html?: true}) }
|
|
8
|
+
let(:request) { double('request', { query_parameters: {}, user_agent: user_agent, referer: referer, format: format }) }
|
|
9
|
+
let(:controller) { double('controller', { request: request }) }
|
|
10
|
+
|
|
11
|
+
describe "#for" do
|
|
12
|
+
it 'should default to UserTracker if user_agent does not exist' do
|
|
13
|
+
Landable::Traffic::Tracker.for(controller).should be_a(Landable::Traffic::UserTracker)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'should create the appropriate type of tracker based on user_agent' do
|
|
17
|
+
type = double('type', { user_agent_type: "Scan" })
|
|
18
|
+
fake_agent = {}
|
|
19
|
+
fake_agent["type"] = type
|
|
20
|
+
stub_const("Landable::Traffic::UserAgent", fake_agent)
|
|
21
|
+
|
|
22
|
+
Landable::Traffic::Tracker.for(controller).should be_a(Landable::Traffic::ScanTracker)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it 'should not bark if user_agent is nil' do
|
|
26
|
+
user_agent = nil
|
|
27
|
+
request = double('request', { query_parameters: {}, user_agent: user_agent, format: format })
|
|
28
|
+
controller = double('controller', { request: request })
|
|
29
|
+
|
|
30
|
+
Landable::Traffic::Tracker.for(controller).should be_a(Landable::Traffic::UserTracker)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'should set type to noop when non-html content' do
|
|
34
|
+
user_agent = nil
|
|
35
|
+
Landable.configuration.stub(:traffic_enabled).and_return(:html)
|
|
36
|
+
format = double('format', { html?: false })
|
|
37
|
+
request = double('request', { query_parameters: {}, user_agent: user_agent, format: format })
|
|
38
|
+
controller = double('controller', { request: request })
|
|
39
|
+
|
|
40
|
+
Landable::Traffic::Tracker.for(controller).should be_a(Landable::Traffic::NoopTracker)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it 'should allow non-html content if config says so' do
|
|
44
|
+
format = double('format', { html?: false})
|
|
45
|
+
request = double('request', { query_parameters: {}, user_agent: user_agent, format: format })
|
|
46
|
+
controller = double('controller', { request: request })
|
|
47
|
+
|
|
48
|
+
Landable::Traffic::Tracker.for(controller).should be_a(Landable::Traffic::UserTracker)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
describe '#referer_uri' do
|
|
53
|
+
it 'should encode special characters' do
|
|
54
|
+
tracker = Landable::Traffic::UserTracker.new controller
|
|
55
|
+
|
|
56
|
+
tracker.send(:referer_uri).path.should == "/something/%20valid"
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Landable
|
|
4
|
+
|
|
5
|
+
class TrackError < StandardError
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
class SaveError < StandardError
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
describe Traffic, type: :controller do
|
|
12
|
+
|
|
13
|
+
controller(ApplicationController) do
|
|
14
|
+
include Landable::Traffic
|
|
15
|
+
prepend_around_action :track_with_landable!
|
|
16
|
+
|
|
17
|
+
def my_method
|
|
18
|
+
render nothing: true
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
before do
|
|
23
|
+
routes.draw do
|
|
24
|
+
get 'my_method' => 'anonymous#my_method'
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
describe 'track_with_landable!' do
|
|
29
|
+
it 'should log errors' do
|
|
30
|
+
tracker = double('tracker')
|
|
31
|
+
|
|
32
|
+
Landable::Traffic::Tracker.stub(:for).and_return(tracker)
|
|
33
|
+
tracker.stub(:track).and_raise(TrackError)
|
|
34
|
+
tracker.stub(:save).and_raise(SaveError)
|
|
35
|
+
|
|
36
|
+
controller.should_receive(:newrelic_notice_error) { |error| error.should be_an_instance_of TrackError }
|
|
37
|
+
controller.should_receive(:newrelic_notice_error) { |error| error.should be_an_instance_of SaveError }
|
|
38
|
+
|
|
39
|
+
get :my_method
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Landable
|
|
4
|
+
describe AccessToken do
|
|
5
|
+
it { should_not have_valid(:author_id).when(nil) }
|
|
6
|
+
|
|
7
|
+
it "generates an expiration timestamp before creation" do
|
|
8
|
+
author = create :author
|
|
9
|
+
token = AccessToken.create!(author: author)
|
|
10
|
+
expect(token.expires_at).not_to be_nil
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Landable::Asset do
|
|
4
|
+
def asset_fixture(name)
|
|
5
|
+
File.expand_path("../../../fixtures/assets/#{name}", __FILE__)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
let(:png) { File.open(asset_fixture('panda.png')) }
|
|
9
|
+
let(:pdf) { File.open(asset_fixture('small.pdf')) }
|
|
10
|
+
|
|
11
|
+
after do
|
|
12
|
+
png.close
|
|
13
|
+
pdf.close
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it { should_not have_valid(:name).when(nil, '', 'No Spaces') }
|
|
17
|
+
it { should_not have_valid(:author).when(nil) }
|
|
18
|
+
it { should_not have_valid(:md5sum).when(nil, '') }
|
|
19
|
+
it { should_not have_valid(:mime_type).when(nil, '') }
|
|
20
|
+
it { should_not have_valid(:file_size).when(nil, 1.5) }
|
|
21
|
+
|
|
22
|
+
it "stores an md5sum of its contents" do
|
|
23
|
+
asset = build(:asset, data: png)
|
|
24
|
+
expect {
|
|
25
|
+
asset.valid?
|
|
26
|
+
}.to change { asset.md5sum }.from(nil).to('0f62ef551dbebcdb7379401528b6115c')
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "requires the md5sum to be unique" do
|
|
30
|
+
orig = create(:asset, data: png)
|
|
31
|
+
dupe = build(:asset, data: png)
|
|
32
|
+
|
|
33
|
+
expect(dupe).not_to be_valid
|
|
34
|
+
expect(dupe.errors_on(:md5sum)).to eql(['has already been taken'])
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "provides access to the other asset with the same contents" do
|
|
38
|
+
orig = create(:asset, data: png)
|
|
39
|
+
dupe = build(:asset, data: png)
|
|
40
|
+
expect(dupe.duplicate_of).to eql(orig)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "returns a list of pages using the asset" do
|
|
44
|
+
page = create(:page, body: "panda.png", path: "/testing/assets")
|
|
45
|
+
asset = create(:asset, data:pdf, name: "panda.png")
|
|
46
|
+
asset.associated_pages.should eq(["/testing/assets"])
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Landable
|
|
4
|
+
describe Directory, '.listing' do
|
|
5
|
+
def stub_contents
|
|
6
|
+
['/seo/foo', '/aff/bar', '/seo/baz', '/aff/deeply/nested', '/aff/deeply_nested', '/quux'].each do |path|
|
|
7
|
+
create :page, path: path
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'knows its own path' do
|
|
12
|
+
dir = Directory.listing '/'
|
|
13
|
+
dir.path.should == '/'
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'lists immediate children' do
|
|
17
|
+
stub_contents
|
|
18
|
+
|
|
19
|
+
dir = Directory.listing '/'
|
|
20
|
+
dir.subdirectories.map(&:path).should == ['/aff', '/seo']
|
|
21
|
+
dir.pages.map(&:path).should == ['/quux']
|
|
22
|
+
|
|
23
|
+
dir = Directory.listing '/aff'
|
|
24
|
+
dir.subdirectories.map(&:path).should == ['/aff/deeply']
|
|
25
|
+
dir.pages.map(&:path).should == ['/aff/bar', '/aff/deeply_nested']
|
|
26
|
+
|
|
27
|
+
dir = Directory.listing '/seo'
|
|
28
|
+
dir.subdirectories.should be_empty
|
|
29
|
+
dir.pages.map(&:path).should == ['/seo/baz', '/seo/foo']
|
|
30
|
+
|
|
31
|
+
dir = Directory.listing '/aff/deeply'
|
|
32
|
+
dir.subdirectories.should be_empty
|
|
33
|
+
dir.pages.map(&:path).should == ['/aff/deeply/nested']
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Landable
|
|
4
|
+
describe Page do
|
|
5
|
+
|
|
6
|
+
describe '#error?' do
|
|
7
|
+
describe 'yep' do
|
|
8
|
+
specify { build(:page, status_code: 418).should be_error }
|
|
9
|
+
specify { build(:page, status_code: 522).should be_error }
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
describe 'nope' do
|
|
13
|
+
specify { build(:page, status_code: 311).should_not be_error }
|
|
14
|
+
specify { build(:page, status_code: 200).should_not be_error }
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
describe '#error' do
|
|
19
|
+
def error_for code
|
|
20
|
+
build(:page, status_code: code).error
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
specify { error_for(410).should be_a Landable::Page::GoneError }
|
|
24
|
+
specify { error_for(555).should be_a Landable::Error }
|
|
25
|
+
specify { error_for(200).should be_nil }
|
|
26
|
+
specify { error_for(302).should be_nil }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Landable
|
|
4
|
+
describe PageRevision do
|
|
5
|
+
let(:author) { create(:author) }
|
|
6
|
+
let(:asset) { create(:asset) }
|
|
7
|
+
|
|
8
|
+
let(:page) do
|
|
9
|
+
create(:page, path: '/test/path', title: 'title', status_code: 200,
|
|
10
|
+
body: 'body', redirect_url: 'http://www.redirect.com/here',
|
|
11
|
+
meta_tags: {'key'=>'value'}, head_content: 'head_content')
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
let(:revision) do
|
|
15
|
+
PageRevision.new page_id: page.id, author_id: author.id
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it { should be_a HasAssets }
|
|
19
|
+
|
|
20
|
+
it 'defaults to is_published = true' do
|
|
21
|
+
PageRevision.new.is_published.should == true
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
describe '#page_id=' do
|
|
25
|
+
it 'should set page revision attributes matching the page' do
|
|
26
|
+
attrs = revision.attributes.except('page_revision_id','ordinal','notes','is_minor','is_published','author_id','created_at','updated_at', 'page_id')
|
|
27
|
+
attrs.should include(page.attributes.except(*PageRevision.ignored_page_attributes))
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
describe '#snapshot' do
|
|
32
|
+
it 'should build a page based on the cached page attributes' do
|
|
33
|
+
snapshot = revision.snapshot
|
|
34
|
+
snapshot.should be_new_record
|
|
35
|
+
snapshot.should be_an_instance_of Page
|
|
36
|
+
snapshot.title.should == page.title
|
|
37
|
+
snapshot.path.should == page.path
|
|
38
|
+
snapshot.head_content.should == page.head_content
|
|
39
|
+
snapshot.meta_tags.should == page.meta_tags
|
|
40
|
+
snapshot.body.should == page.body
|
|
41
|
+
snapshot.redirect_url.should == page.redirect_url
|
|
42
|
+
snapshot.category_id.should == page.category_id
|
|
43
|
+
snapshot.theme_id.should == page.theme_id
|
|
44
|
+
snapshot.status_code.should == page.status_code
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
describe '#is_published' do
|
|
49
|
+
it 'should set is_published to true and false as requested' do
|
|
50
|
+
revision = PageRevision.new
|
|
51
|
+
revision.page_id = page.id
|
|
52
|
+
revision.author_id = author.id
|
|
53
|
+
revision.unpublish!
|
|
54
|
+
revision.is_published.should == false
|
|
55
|
+
revision.publish!
|
|
56
|
+
revision.is_published.should == true
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
describe '#preview_path' do
|
|
61
|
+
it 'should return the preview path' do
|
|
62
|
+
revision.should_receive(:public_preview_page_revision_path) { 'foo' }
|
|
63
|
+
revision.preview_path.should == 'foo'
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
describe '#preview_url' do
|
|
68
|
+
it 'should return the preview url' do
|
|
69
|
+
revision.should_receive(:public_preview_page_revision_url) { 'foo' }
|
|
70
|
+
revision.preview_url.should == 'foo'
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Landable
|
|
4
|
+
describe Page do
|
|
5
|
+
it { should be_a HasAssets }
|
|
6
|
+
it { should_not have_valid(:status_code).when(nil,'') }
|
|
7
|
+
it { should have_valid(:status_code).when(200, 301, 302, 410) }
|
|
8
|
+
it { should_not have_valid(:status_code).when(201, 303, 405, 500, 404) }
|
|
9
|
+
|
|
10
|
+
# config.reserved_paths = %w(/reserved_path_set_in_initializer /reject/.* /admin.*)
|
|
11
|
+
context 'PathValidator' do
|
|
12
|
+
it { should_not have_valid(:path).when(nil, '', '/reserved_path_set_in_initializer') }
|
|
13
|
+
it { should_not have_valid(:path).when('/reject/this', '/admin', '/ADMIN', '/admin_something' '/admin/path') }
|
|
14
|
+
it { should have_valid(:path).when('/reserved_path_set_in_initializer_not', '/do/not/reject/path', '/', '/rejectwhatever', '/reject') }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'should set is_publishable to true on before_save' do
|
|
18
|
+
page = FactoryGirl.build :page, is_publishable: false
|
|
19
|
+
page.save!
|
|
20
|
+
page.is_publishable.should be_true
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
specify "#redirect?" do
|
|
24
|
+
Page.new.should_not be_redirect
|
|
25
|
+
Page.new().should_not be_redirect
|
|
26
|
+
Page.new(status_code: 200).should_not be_redirect
|
|
27
|
+
Page.new(status_code: 410).should_not be_redirect
|
|
28
|
+
|
|
29
|
+
Page.new(status_code: 301).should be_redirect
|
|
30
|
+
Page.new(status_code: 302).should be_redirect
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
describe '#published?' do
|
|
34
|
+
context 'when published' do
|
|
35
|
+
it 'should be true' do
|
|
36
|
+
page = create :page
|
|
37
|
+
page.publish! author: create(:author), notes: 'yo'
|
|
38
|
+
page.should be_published
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
context 'when not published' do
|
|
43
|
+
it 'should be false' do
|
|
44
|
+
page = create :page
|
|
45
|
+
page.should_not be_published
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
specify '#path_extension' do
|
|
51
|
+
Page.new(path: 'foo').path_extension.should be_nil
|
|
52
|
+
Page.new(path: 'foo.bar').path_extension.should == 'bar'
|
|
53
|
+
Page.new(path: 'foo.bar.baz').path_extension.should == 'baz'
|
|
54
|
+
Page.new(path: 'foo.bar-baz').path_extension.should be_nil
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
describe '#content_type' do
|
|
58
|
+
def content_type_for path
|
|
59
|
+
Page.new(path: path).content_type
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it 'should be text/html for html pages' do
|
|
63
|
+
content_type_for('asdf').should == 'text/html'
|
|
64
|
+
content_type_for('asdf.htm').should == 'text/html'
|
|
65
|
+
content_type_for('asdf.html').should == 'text/html'
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it 'should be application/json for json' do
|
|
69
|
+
content_type_for('asdf.json').should == 'application/json'
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it 'should be application/xml for xml' do
|
|
73
|
+
content_type_for('asdf.xml').should == 'application/xml'
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it 'should be text/plain for everything else' do
|
|
77
|
+
content_type_for('foo.bar').should == 'text/plain'
|
|
78
|
+
content_type_for('foo.txt').should == 'text/plain'
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
describe '#html?' do
|
|
83
|
+
let(:page) { build :page }
|
|
84
|
+
|
|
85
|
+
it 'should be true if content_type is text/html' do
|
|
86
|
+
page.should_receive(:content_type) { 'text/html' }
|
|
87
|
+
page.should be_html
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it 'should be false if content_type is not text/html' do
|
|
91
|
+
page.should_receive(:content_type) { 'text/plain' }
|
|
92
|
+
page.should_not be_html
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
describe '#redirect_url' do
|
|
97
|
+
it 'is required if redirect?' do
|
|
98
|
+
page = Page.new status_code: 301
|
|
99
|
+
page.should_not have_valid(:redirect_url).when(nil, '')
|
|
100
|
+
page.should have_valid(:redirect_url).when('http://example.com', 'http://www.somepath.com')
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it 'not required for 200, 410' do
|
|
104
|
+
page = Page.new
|
|
105
|
+
page.should have_valid(:redirect_url).when(nil, '')
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
describe '#meta_tags' do
|
|
110
|
+
it { subject.should have_valid(:meta_tags).when(nil) }
|
|
111
|
+
|
|
112
|
+
specify "quacks like a Hash" do
|
|
113
|
+
# Note the change from symbol to string; thus, always favor strings.
|
|
114
|
+
page = create :page, meta_tags: { keywords: 'foo' }
|
|
115
|
+
page.meta_tags.keys.should == [:keywords]
|
|
116
|
+
|
|
117
|
+
tags = Page.first.meta_tags
|
|
118
|
+
tags.should be_a(Enumerable)
|
|
119
|
+
tags.keys.should == ['keywords']
|
|
120
|
+
tags.values.should == ['foo']
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
describe '#head_content' do
|
|
125
|
+
it { subject.should have_valid(:meta_tags).when(nil) }
|
|
126
|
+
|
|
127
|
+
it 'works as a basic text area' do
|
|
128
|
+
page = create :page, head_content: "<head en='en'/>"
|
|
129
|
+
page.head_content.should == "<head en='en'/>"
|
|
130
|
+
|
|
131
|
+
page.head_content = "<head en='magic'/>"
|
|
132
|
+
page.save
|
|
133
|
+
|
|
134
|
+
page.head_content.should == "<head en='magic'/>"
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
describe '#path=' do
|
|
139
|
+
it 'ensures a leading "/" on path' do
|
|
140
|
+
Page.new(path: 'foo/bar').path.should == '/foo/bar'
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
it 'leaves nil and empty paths alone' do
|
|
144
|
+
Page.new(path: '').path.should == ''
|
|
145
|
+
Page.new(path: nil).path.should == nil
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
describe '#publish' do
|
|
150
|
+
let(:page) { FactoryGirl.create :page }
|
|
151
|
+
let(:author) { FactoryGirl.create :author }
|
|
152
|
+
|
|
153
|
+
it 'should create a page_revision' do
|
|
154
|
+
expect {page.publish!(author: author)}.to change{page.revisions.count}.from(0).to(1)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
it 'should have the provided author' do
|
|
158
|
+
page.publish! author: author
|
|
159
|
+
revision = page.revisions.last
|
|
160
|
+
|
|
161
|
+
revision.author.should == author
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
it 'should update the published_revision_id' do
|
|
165
|
+
page.publish! author: author
|
|
166
|
+
revision = page.revisions.last
|
|
167
|
+
|
|
168
|
+
page.published_revision.should == revision
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
it 'should set is_publishable to false' do
|
|
172
|
+
page.is_publishable = true
|
|
173
|
+
page.publish! author: author
|
|
174
|
+
page.is_publishable.should be_false
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
it 'should unset previous revision.is_published' do
|
|
178
|
+
page.publish! author: author
|
|
179
|
+
revision1 = page.published_revision
|
|
180
|
+
page.publish! author: author
|
|
181
|
+
revision1.is_published.should be_false
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
describe '#revert_to' do
|
|
186
|
+
let(:page) { FactoryGirl.create :page }
|
|
187
|
+
let(:author) { FactoryGirl.create :author }
|
|
188
|
+
|
|
189
|
+
it 'should NOT update published_revision for the page' do
|
|
190
|
+
page.title = 'Bar'
|
|
191
|
+
page.publish! author: author
|
|
192
|
+
revision = page.published_revision
|
|
193
|
+
|
|
194
|
+
page.title = 'Foo'
|
|
195
|
+
page.publish! author: author
|
|
196
|
+
|
|
197
|
+
page.revert_to! revision
|
|
198
|
+
|
|
199
|
+
page.published_revision.id.should_not == revision.id
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
it 'should copy revision attributes into the page model' do
|
|
203
|
+
page.title = 'Bar'
|
|
204
|
+
page.publish! author: author
|
|
205
|
+
|
|
206
|
+
revision = page.published_revision
|
|
207
|
+
|
|
208
|
+
page.title = 'Foo'
|
|
209
|
+
page.save!
|
|
210
|
+
page.publish! author: author
|
|
211
|
+
|
|
212
|
+
# ensure assignment for all copied attributes
|
|
213
|
+
keys = %w(title path body category_id theme_id status_code meta_tags redirect_url)
|
|
214
|
+
keys.each do |key|
|
|
215
|
+
page.should_receive("#{key}=").with(revision.send(key))
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
page.revert_to! revision
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
describe '#forbid_changing_path' do
|
|
223
|
+
context 'created_record' do
|
|
224
|
+
it 'does not allow a path to be changed' do
|
|
225
|
+
page = create :page, path: '/test'
|
|
226
|
+
page.path = '/different'
|
|
227
|
+
expect { page.save! }.to raise_error
|
|
228
|
+
|
|
229
|
+
page.reload
|
|
230
|
+
page.path.should == '/test'
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
context 'new_record' do
|
|
235
|
+
it 'allows the path to be changed' do
|
|
236
|
+
page = build :page, path: '/test'
|
|
237
|
+
page.save!
|
|
238
|
+
|
|
239
|
+
page.path.should == '/test'
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
describe '#preview_path' do
|
|
245
|
+
it 'should return the preview path' do
|
|
246
|
+
page = build :page
|
|
247
|
+
page.should_receive(:public_preview_page_path) { 'foo' }
|
|
248
|
+
page.preview_path.should == 'foo'
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
describe '#preview_url' do
|
|
253
|
+
it 'should return the preview url' do
|
|
254
|
+
page = build :page
|
|
255
|
+
page.should_receive(:public_preview_page_url) { 'foo' }
|
|
256
|
+
page.preview_url.should == 'foo'
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
describe '::sitemappable' do
|
|
261
|
+
let(:page) { create :page }
|
|
262
|
+
let(:page_2) { create :page, :redirect }
|
|
263
|
+
let(:page_3) { create :page, meta_tags: { 'robots' => 'noindex' } }
|
|
264
|
+
|
|
265
|
+
it 'only returns pages with a status code of 200 and dont have a noindex tag' do
|
|
266
|
+
page_2.status_code.should == 301
|
|
267
|
+
|
|
268
|
+
Landable::Page.sitemappable.should include(page)
|
|
269
|
+
Landable::Page.sitemappable.should_not include(page_2, page_3)
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
describe '#downcase_path' do
|
|
274
|
+
it 'should force a path to be lowercase' do
|
|
275
|
+
page = build :page, path: '/SEO'
|
|
276
|
+
page.should be_valid
|
|
277
|
+
page.path.should == '/seo'
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
it 'doesnt change a downcase path' do
|
|
281
|
+
page = build :page, path: '/seo'
|
|
282
|
+
page.should be_valid
|
|
283
|
+
page.path.should == '/seo'
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
describe '#redirect_url' do
|
|
288
|
+
context 'validater' do
|
|
289
|
+
before(:each) { @page = build :page, path: '/' }
|
|
290
|
+
|
|
291
|
+
it 'should correctly validate http://' do
|
|
292
|
+
@page.redirect_url = 'http://www.google.com'
|
|
293
|
+
@page.should be_valid
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
it 'should correctly validate https://' do
|
|
297
|
+
@page.redirect_url = 'http://www.google.com'
|
|
298
|
+
@page.should be_valid
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
it 'should correctly validate /' do
|
|
302
|
+
@page.redirect_url = '/some/uri'
|
|
303
|
+
@page.should be_valid
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
it 'should not validate www' do
|
|
307
|
+
@page.redirect_url = 'www.google.com'
|
|
308
|
+
@page.should_not be_valid
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
it 'should not validate bad urls' do
|
|
312
|
+
@page.redirect_url = 'hdasdfpou'
|
|
313
|
+
@page.should_not be_valid
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
end
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
describe '::generate_sitemap' do
|
|
320
|
+
it 'returns a sitemap' do
|
|
321
|
+
page = create :page
|
|
322
|
+
Landable::Page.generate_sitemap(host: 'example.com',
|
|
323
|
+
protocol: 'http',
|
|
324
|
+
exclude_categories: [],
|
|
325
|
+
sitemap_additional_paths: []).should include("<loc>http://example.com#{page.path}</loc>")
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
it 'does not include excluded categories' do
|
|
329
|
+
cat = create :category, name: 'Testing'
|
|
330
|
+
page = create :page, category: cat
|
|
331
|
+
Landable::Page.generate_sitemap(host: 'example.com',
|
|
332
|
+
protocol: 'http',
|
|
333
|
+
exclude_categories: ['Testing'],
|
|
334
|
+
sitemap_additional_paths: []).should_not include("<loc>http://example.com#{page.path}</loc>")
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
it 'can handle https protocol' do
|
|
338
|
+
page = create :page
|
|
339
|
+
Landable::Page.generate_sitemap(host: 'example.com',
|
|
340
|
+
protocol: 'https',
|
|
341
|
+
exclude_categories: [],
|
|
342
|
+
sitemap_additional_paths: []).should include("<loc>https://example.com#{page.path}</loc>")
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
it 'can handle additional pages' do
|
|
346
|
+
Landable::Page.generate_sitemap(host: 'example.com',
|
|
347
|
+
protocol: 'https',
|
|
348
|
+
exclude_categories: [],
|
|
349
|
+
sitemap_additional_paths: ['/terms.html']).should include("<loc>https://example.com/terms.html</loc>")
|
|
350
|
+
end
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
describe '::by_path' do
|
|
354
|
+
it 'returns first page with path name' do
|
|
355
|
+
page = create :page, path: '/seo'
|
|
356
|
+
Landable::Page.by_path('/seo').should == page
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
describe 'validate#body_strip_search' do
|
|
361
|
+
it 'raises errors if errors!' do
|
|
362
|
+
page = build :page, path: '/'
|
|
363
|
+
page.body = "{% image_tag 'bad_image' %}"
|
|
364
|
+
page.should_not be_valid
|
|
365
|
+
page.errors[:body].should_not be_empty
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
it 'does not raise error when no syntax error' do
|
|
369
|
+
page = build :page, path: '/'
|
|
370
|
+
page.body = 'body'
|
|
371
|
+
page.should be_valid
|
|
372
|
+
page.save!
|
|
373
|
+
page.body.should == 'body'
|
|
374
|
+
end
|
|
375
|
+
end
|
|
376
|
+
end
|
|
377
|
+
end
|