spontaneous 0.2.0.beta9 → 0.2.0.beta10

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.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +61 -0
  3. data/LICENSE +18 -17
  4. data/Rakefile +1 -1
  5. data/application/css/core.css.scss +1 -1
  6. data/application/css/dialogue.css.scss +8 -20
  7. data/application/js/preview.js +28 -7
  8. data/application/js/publish.js +15 -4
  9. data/application/js/top_bar.js +0 -16
  10. data/application/js/views/piece_view.js +1 -1
  11. data/lib/spontaneous/asset/environment.rb +16 -1
  12. data/lib/spontaneous/box.rb +68 -0
  13. data/lib/spontaneous/capistrano/deploy.rb +7 -4
  14. data/lib/spontaneous/capistrano/sync.rb +2 -2
  15. data/lib/spontaneous/cli/init.rb +70 -19
  16. data/lib/spontaneous/cli/init/db.rb +34 -55
  17. data/lib/spontaneous/cli/init/mysql.rb +5 -5
  18. data/lib/spontaneous/cli/init/postgresql.rb +8 -9
  19. data/lib/spontaneous/cli/init/sqlite.rb +1 -2
  20. data/lib/spontaneous/cli/migrate.rb +0 -1
  21. data/lib/spontaneous/cli/site.rb +4 -0
  22. data/lib/spontaneous/collections/entry_set.rb +11 -0
  23. data/lib/spontaneous/data_mapper/content_model.rb +2 -0
  24. data/lib/spontaneous/data_mapper/content_model/serialization.rb +2 -2
  25. data/lib/spontaneous/extensions/array.rb +12 -2
  26. data/lib/spontaneous/field/base.rb +10 -0
  27. data/lib/spontaneous/field/file.rb +32 -2
  28. data/lib/spontaneous/field/image.rb +24 -2
  29. data/lib/spontaneous/field/select.rb +8 -0
  30. data/lib/spontaneous/field/webvideo.rb +8 -0
  31. data/lib/spontaneous/generators/site/config/initializers/fields.rb +55 -0
  32. data/lib/spontaneous/json.rb +3 -2
  33. data/lib/spontaneous/logger.rb +2 -2
  34. data/lib/spontaneous/media/file.rb +3 -3
  35. data/lib/spontaneous/media/image/attributes.rb +72 -6
  36. data/lib/spontaneous/media/image/renderable.rb +53 -20
  37. data/lib/spontaneous/media/store.rb +3 -3
  38. data/lib/spontaneous/media/store/backend.rb +16 -0
  39. data/lib/spontaneous/media/store/cloud.rb +52 -12
  40. data/lib/spontaneous/media/store/local.rb +6 -3
  41. data/lib/spontaneous/model.rb +3 -0
  42. data/lib/spontaneous/model/core/entries.rb +34 -13
  43. data/lib/spontaneous/model/core/entry.rb +3 -1
  44. data/lib/spontaneous/model/page/controllers.rb +1 -2
  45. data/lib/spontaneous/model/page/paths.rb +18 -7
  46. data/lib/spontaneous/output/context.rb +0 -8
  47. data/lib/spontaneous/output/template/renderer.rb +2 -0
  48. data/lib/spontaneous/plugins/application/state.rb +0 -4
  49. data/lib/spontaneous/prototypes/field_prototype.rb +4 -0
  50. data/lib/spontaneous/publishing/immediate.rb +0 -5
  51. data/lib/spontaneous/publishing/progress.rb +2 -2
  52. data/lib/spontaneous/publishing/rerender.rb +1 -4
  53. data/lib/spontaneous/publishing/simultaneous.rb +19 -17
  54. data/lib/spontaneous/publishing/steps.rb +12 -3
  55. data/lib/spontaneous/rack.rb +2 -0
  56. data/lib/spontaneous/rack/asset_server.rb +5 -2
  57. data/lib/spontaneous/rack/back.rb +9 -1
  58. data/lib/spontaneous/rack/back/base.rb +1 -0
  59. data/lib/spontaneous/rack/back/changes.rb +5 -0
  60. data/lib/spontaneous/rack/back/preview.rb +4 -4
  61. data/lib/spontaneous/rack/back/private.rb +11 -0
  62. data/lib/spontaneous/rack/middleware/scope.rb +16 -4
  63. data/lib/spontaneous/rack/page_controller.rb +2 -2
  64. data/lib/spontaneous/rack/public.rb +52 -4
  65. data/lib/spontaneous/sequel.rb +10 -13
  66. data/lib/spontaneous/site.rb +28 -8
  67. data/lib/spontaneous/site/publishing.rb +1 -1
  68. data/lib/spontaneous/site/storage.rb +7 -4
  69. data/lib/spontaneous/tasks/environment.rake +3 -0
  70. data/lib/spontaneous/utils/database/postgres_dumper.rb +23 -2
  71. data/lib/spontaneous/version.rb +1 -1
  72. data/spontaneous.gemspec +7 -12
  73. data/test/fixtures/assets/public1/css/data.css.scss +1 -1
  74. data/test/functional/test_application.rb +15 -0
  75. data/test/functional/test_cli.rb +109 -3
  76. data/test/functional/test_front.rb +108 -10
  77. data/test/test_helper.rb +3 -3
  78. data/test/unit/fields/test_boolean_fields.rb +80 -0
  79. data/test/unit/fields/test_date_fields.rb +47 -0
  80. data/test/unit/fields/test_file_field.rb +210 -0
  81. data/test/unit/{test_images.rb → fields/test_image_fields.rb} +133 -15
  82. data/test/unit/fields/test_location_fields.rb +41 -0
  83. data/test/unit/fields/test_option_fields.rb +61 -0
  84. data/test/unit/fields/test_tag_list_fields.rb +45 -0
  85. data/test/unit/fields/test_text_fields.rb +124 -0
  86. data/test/unit/fields/test_web_video_fields.rb +198 -0
  87. data/test/unit/test_assets.rb +22 -22
  88. data/test/unit/test_boxes.rb +34 -13
  89. data/test/unit/test_changesets.rb +1 -0
  90. data/test/unit/test_extensions.rb +17 -0
  91. data/test/unit/test_fields.rb +20 -643
  92. data/test/unit/test_media.rb +9 -9
  93. data/test/unit/test_page.rb +47 -0
  94. data/test/unit/test_publishing_pipeline.rb +2 -2
  95. data/test/unit/test_serialisation.rb +37 -0
  96. data/test/unit/test_storage.rb +42 -3
  97. metadata +37 -17
@@ -1,6 +1,6 @@
1
1
  # encoding: UTF-8
2
2
 
3
3
  module Spontaneous
4
- VERSION = "0.2.0.beta9"
4
+ VERSION = "0.2.0.beta10"
5
5
  GEM = false
6
6
  end
@@ -3,13 +3,14 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
3
  require 'spontaneous/version'
4
4
 
5
5
  Gem::Specification.new do |s|
6
- s.required_ruby_version = '>= 2.0.0'
7
-
8
6
  s.name = 'spontaneous'
9
7
  s.version = Spontaneous::VERSION
8
+ s.license = "MIT"
9
+
10
+ s.required_ruby_version = '>= 2.0.0'
10
11
 
11
- s.summary = "Spontaneous is a next-generation Ruby CMS"
12
- s.description = "Spontaneous is a next-generation Ruby CMS"
12
+ s.summary = "Next-generation Ruby CMS and web framework."
13
+ s.description = "Spontaneous is a content management framework that allows the easy development of sophisticated & beautiful websites with powerful developer tools & an elegant editing interface."
13
14
 
14
15
  s.authors = ['Garry Hill']
15
16
  s.email = 'garry@spontaneous.io'
@@ -20,12 +21,6 @@ Gem::Specification.new do |s|
20
21
  s.test_files = s.files.grep(%r{^test/})
21
22
  s.require_paths = %w[lib]
22
23
 
23
- s.rdoc_options = ['--charset=UTF-8']
24
- s.extra_rdoc_files = %w[LICENSE]
25
-
26
- # s.signing_key = '/Volumes/Keys/rubygems-garry-magnetised-net-private_key.pem'
27
- # s.cert_chain = ['gem-public_cert.pem']
28
-
29
24
  s.add_dependency('activesupport', ['~> 4.0'])
30
25
  s.add_dependency('coffee-script', ['~> 2.2'])
31
26
  s.add_dependency('bcrypt', ['~> 3.1'])
@@ -46,14 +41,14 @@ Gem::Specification.new do |s|
46
41
  s.add_dependency('sequel', ['~> 4.8'])
47
42
  s.add_dependency('simultaneous', ['~> 0.4.2'])
48
43
  s.add_dependency('sinatra', ['~> 1.3'])
49
- s.add_dependency('skeptick', ['~> 0.1'])
44
+ s.add_dependency('skeptick', ['~> 0.1.1'])
50
45
  s.add_dependency('sprockets', ['~> 2.9'])
51
46
  s.add_dependency('stringex', ['= 1.3'])
52
47
  s.add_dependency('thin', ['~> 1.2'])
53
48
  s.add_dependency('thor', ['~> 0.16'])
54
49
  s.add_dependency('uglifier', ['~> 1.3'])
55
50
  s.add_dependency('xapian-fu', ['~> 1.5'])
56
- s.add_dependency('yajl-ruby', ['~> 1.1'])
51
+ s.add_dependency('oj', ['~> 2.11'])
57
52
 
58
53
  s.add_development_dependency('minitest', ['~> 4.7.0'])
59
54
  s.add_development_dependency('minitest-colorize', ['~> 0.0.5'])
@@ -1,3 +1,3 @@
1
1
  div {
2
- background-image: url(asset-data-uri("i/y.png"));
2
+ background-image: asset-data-uri("i/y.png");
3
3
  }
@@ -196,4 +196,19 @@ describe "Application" do
196
196
  Spontaneous::Rack.port.must_equal 3002
197
197
  end
198
198
  end
199
+
200
+ describe 'ENV["DATABASE_URL"]' do
201
+ before do
202
+ ENV['DATABASE_URL'] = 'sqlite:///production.db'
203
+ @site = Spontaneous.init(:root => site_root, :mode => :front, :environment => :production)
204
+ end
205
+
206
+ after do
207
+ ENV.delete('DATABASE_URL')
208
+ end
209
+
210
+ it 'should override settings in database.yml' do
211
+ @site.config.db.must_equal 'sqlite:///production.db'
212
+ end
213
+ end
199
214
  end
@@ -16,18 +16,124 @@ describe "CLI" do
16
16
  end
17
17
  end
18
18
 
19
- def set_expectation(method, cmd = cmd)
19
+ def set_expectation(method, _cmd = cmd)
20
20
  quietly do
21
- cmd.any_instance.expects(method)
21
+ _cmd.any_instance.expects(method)
22
22
  end
23
23
  end
24
24
 
25
25
  describe "Init" do
26
26
  let(:cmd) { cli::Init }
27
+
28
+ after do
29
+ teardown_site
30
+ end
31
+
27
32
  it "maps 'spot init' to Init#init" do
28
- set_expectation(:initialize_size)
33
+ set_expectation(:initialize_site)
29
34
  run_command(["init"])
30
35
  end
36
+
37
+ describe 'DatabaseInitializer' do
38
+ let(:site) { setup_site }
39
+ let(:create_user) { false }
40
+ let(:env) { :development }
41
+ let(:cli) { mock }
42
+
43
+ def yaml_config(adapter)
44
+ { production: {adapter: adapter, database: 'spontaneous_db_production'}, development: {adapter: adapter, database: 'spontaneous_db'}, test: {adapter: adapter, database: 'spontaneous_db_test'} }
45
+ end
46
+
47
+ def with_yaml_config(adapter)
48
+ begin
49
+ site.stubs(:db_config_file).returns(yaml_config(adapter))
50
+ yield
51
+ ensure
52
+ site.unstub(:db_config_file)
53
+ end
54
+ end
55
+
56
+ def with_db_url(url)
57
+ begin
58
+ ENV['DATABASE_URL'] = url
59
+ yield
60
+ ensure
61
+ ENV.delete 'DATABASE_URL'
62
+ end
63
+ end
64
+
65
+ def init
66
+ Spontaneous::Cli::Init::DatabaseInitializer.new(cli, site)
67
+ end
68
+
69
+ it "runs a database initializer for development & test environments in development mode" do
70
+ init.database_environments(:development).must_equal [:development, :test]
71
+ end
72
+
73
+ it "runs a database initializer for only production in production mode" do
74
+ init.database_environments(:production).must_equal [:production]
75
+ end
76
+
77
+ describe 'DATABASE_URL' do
78
+ it "gets the db config from the ENV" do
79
+ with_db_url('mysql://localhost/something') do
80
+ init.database_config(:development).must_equal('mysql://localhost/something')
81
+ init.database_config(:test).must_equal('mysql://localhost/something')
82
+ end
83
+ end
84
+
85
+ it 'uses the right db initialization class for the adapter' do
86
+ with_db_url('mysql2://localhost/something') do
87
+ init.database_initializer(:development).must_be_instance_of Spontaneous::Cli::Init::MySQL
88
+ end
89
+ with_db_url('postgres://localhost/something') do
90
+ init.database_initializer(:development).must_be_instance_of Spontaneous::Cli::Init::Postgresql
91
+ end
92
+ with_db_url('sqlite://localhost/something') do
93
+ init.database_initializer(:development).must_be_instance_of Spontaneous::Cli::Init::Sqlite
94
+ end
95
+ end
96
+
97
+ it 'instantiates & calls #run on a db initializer for each env' do
98
+ with_db_url('sqlite://localhost/something') do
99
+ db_initializer = mock
100
+ db_initializer.expects(:run).once
101
+ Spontaneous::Cli::Init::Sqlite.expects(:new).with(cli, instance_of(Sequel::SQLite::Database)).returns(db_initializer).once
102
+ init.run(:development)
103
+ end
104
+ end
105
+ end
106
+
107
+ describe 'YAML' do
108
+ it "gets db settings from a config file if no ENV setting" do
109
+ with_yaml_config('postgres') do
110
+ init.database_config(:development).must_equal({adapter: 'postgres', database: 'spontaneous_db'})
111
+ init.database_config(:test).must_equal({adapter: 'postgres', database: 'spontaneous_db_test'})
112
+ end
113
+ end
114
+
115
+ it 'uses the right db initialization class for the adapter' do
116
+ with_yaml_config('mysql2') do
117
+ init.database_initializer(:development).must_be_instance_of Spontaneous::Cli::Init::MySQL
118
+ end
119
+ with_yaml_config('postgres') do
120
+ init.database_initializer(:development).must_be_instance_of Spontaneous::Cli::Init::Postgresql
121
+ end
122
+ with_yaml_config('sqlite') do
123
+ init.database_initializer(:development).must_be_instance_of Spontaneous::Cli::Init::Sqlite
124
+ end
125
+ end
126
+
127
+ it 'instantiates & calls #run on a db initializer for each env' do
128
+ with_yaml_config('mysql2') do
129
+ db_initializer = mock
130
+ db_initializer.expects(:run).once
131
+ Spontaneous::Cli::Init::MySQL.expects(:new).with(cli, instance_of(Sequel::Mysql2::Database)).returns(db_initializer).once
132
+ init.run(:production)
133
+ end
134
+ end
135
+ end
136
+ end
31
137
  end
32
138
 
33
139
  describe "Console" do
@@ -15,6 +15,17 @@ describe "Front" do
15
15
  Spontaneous::Output.write_compiled_scripts = true
16
16
 
17
17
 
18
+ class ::PageController < S::Rack::PageController
19
+ # Define a per-site base controller for all controller classes here so
20
+ # that we can test it's use later on.
21
+ # If I define it only in the test where it's used then it's too late as
22
+ # the controller hierarchy will have already been built upon some other
23
+ # base class.
24
+ #
25
+ # (Another argument for replacing these [start..finish] blocks with
26
+ # [before..after] ones)
27
+ end
28
+
18
29
  site = setup_site(site_root)
19
30
  let(:site) { site }
20
31
  S::State.delete
@@ -75,6 +86,11 @@ describe "Front" do
75
86
  layout { "${ path }.${ __format }" }
76
87
  end
77
88
 
89
+ class ::TakeItPage < ::Page
90
+ layout(:html) { "take it ${id} {{ splat }}" }
91
+ box :pages
92
+ end
93
+
78
94
  root = ::SitePage.create
79
95
  about = ::SitePage.create(:slug => "about", :uid => "about")
80
96
  feed = ::FeedPage.create(:slug => "feed", :uid => "feed")
@@ -83,6 +99,8 @@ describe "Front" do
83
99
  dynamic_request_params = ::DynamicRequestParams.create(slug: "dynamic-request-params", uid: "dynamic_request_params")
84
100
  dynamic_render_params = ::DynamicRenderParams.create(slug: "dynamic-render-params", uid: "dynamic_render_params")
85
101
  commentable = ::CommentablePage.create(slug:"commentable", uid: "commentable")
102
+ take_it = TakeItPage.create(slug: 'takeit', uid: 'takeit')
103
+ take_it_again = TakeItPage.create(slug: 'again', uid: 'again')
86
104
  root.pages << about
87
105
  root.pages << feed
88
106
  root.pages << news
@@ -90,12 +108,17 @@ describe "Front" do
90
108
  root.pages << dynamic_render_params
91
109
  root.pages << static
92
110
  root.pages << commentable
111
+ root.pages << take_it
112
+ take_it.pages << take_it_again
93
113
  root.save
114
+ take_it.save
94
115
 
95
116
  let(:root_id) { root.id }
96
117
  let(:about_id) { about.id }
97
118
  let(:feed_id) { feed.id }
98
119
  let(:news_id) { news.id }
120
+ let(:take_it_id) { take_it.id }
121
+ let(:take_it_again_id) { take_it_again.id }
99
122
  let(:dynamic_request_params_id) { dynamic_request_params.id }
100
123
  let(:dynamic_render_params_id) { dynamic_render_params.id }
101
124
  let(:static_id) { static.id }
@@ -111,7 +134,7 @@ describe "Front" do
111
134
  end
112
135
 
113
136
  finish do
114
- [:SitePage, :StaticPage, :DynamicRequestParams, :DynamicRenderParams, :CommentablePage, :FeedPage].each do |const|
137
+ [:SitePage, :StaticPage, :DynamicRequestParams, :DynamicRenderParams, :CommentablePage, :FeedPage, :TakeItPage, :PageController].each do |const|
115
138
  Object.send(:remove_const, const) rescue nil
116
139
  end
117
140
  if defined?(Content)
@@ -128,6 +151,8 @@ describe "Front" do
128
151
  let(:about) { Content[about_id] }
129
152
  let(:feed) { Content[feed_id] }
130
153
  let(:news) { Content[news_id] }
154
+ let(:take_it) { Content[take_it_id] }
155
+ let(:take_it_again) { Content[take_it_again_id] }
131
156
  let(:dynamic_request_params) { Content[dynamic_request_params_id] }
132
157
  let(:dynamic_render_params) { Content[dynamic_render_params_id] }
133
158
  let(:static) { Content[static_id] }
@@ -596,7 +621,7 @@ describe "Front" do
596
621
 
597
622
  after do
598
623
  Object.send(:remove_const, :SubPage) rescue nil
599
- CommentablePage.instance_variable_set(:@request_blocks, {})
624
+ CommentablePage.instance_variable_set(:@controllers, nil)
600
625
  CommentablePage.send(:remove_const, :StatusController) rescue nil
601
626
  CommentablePage.send(:remove_const, :TestController) rescue nil
602
627
  CommentablePage.send(:remove_const, :Test2Controller) rescue nil
@@ -711,10 +736,8 @@ describe "Front" do
711
736
 
712
737
  describe "overriding base controller class" do
713
738
  before do
714
- class ::PageController < S::Rack::PageController
715
- get '/nothing' do
716
- 'Something'
717
- end
739
+ ::PageController.get '/nothing' do
740
+ 'Something'
718
741
  end
719
742
 
720
743
  CommentablePage.controller :drummer do
@@ -724,10 +747,6 @@ describe "Front" do
724
747
  end
725
748
  end
726
749
 
727
- after do
728
- Object.send(:remove_const, :PageController)
729
- end
730
-
731
750
  it "affect all controller actions" do
732
751
  get "/commentable/@drummer/nothing"
733
752
  assert last_response.ok?, "Expected 200 got #{last_response.status}"
@@ -736,6 +755,85 @@ describe "Front" do
736
755
  end
737
756
  end
738
757
 
758
+ describe 'wildcard paths' do
759
+ let(:page) { take_it }
760
+ let(:again) { take_it_again }
761
+
762
+ after do
763
+ root.class.instance_variable_set(:@controllers, nil)
764
+ TakeItPage.instance_variable_set(:@controllers, nil)
765
+ end
766
+
767
+ it 'renders a url that resolves to a page accepting the path' do
768
+ TakeItPage.controller do
769
+ get '*' do
770
+ render splat: params[:splat].first
771
+ end
772
+ end
773
+ [
774
+ ["/something", page],
775
+ ["/something/else", page],
776
+ ["/really/something/else/entirely", page],
777
+ ["/something/else/entirely", again]
778
+ ].each do |path, expected|
779
+ get "#{expected.path}#{path}"
780
+ assert last_response.ok?, "Expected 200 got #{last_response.status}"
781
+ last_response.body.must_equal "take it #{expected.id} #{path}"
782
+ end
783
+ end
784
+
785
+ it 'returns 404 if the requested path doesn’t match the controller’s route' do
786
+ TakeItPage.controller do
787
+ get '/womble/?:where?' do
788
+ render splat: params[:where]
789
+ end
790
+ end
791
+ get "#{page.path}/womble/around"
792
+ assert last_response.ok?, "Expected 200 got #{last_response.status}"
793
+ last_response.body.must_equal "take it #{page.id} around"
794
+
795
+ get "#{page.path}/womble"
796
+ assert last_response.ok?, "Expected 200 got #{last_response.status}"
797
+ last_response.body.must_equal "take it #{page.id} "
798
+
799
+ get "#{page.path}/wimble/around"
800
+ assert last_response.status == 404
801
+ end
802
+
803
+ it 'returns 404 if the controller is only configured to match the root' do
804
+ TakeItPage.controller do
805
+ get do
806
+ render splat: 'root'
807
+ end
808
+ end
809
+ get page.path
810
+ assert last_response.ok?, "Expected 200 got #{last_response.status}"
811
+ last_response.body.must_equal "take it #{page.id} root"
812
+
813
+ get "#{page.path}/womble"
814
+ assert last_response.status == 404, "Expected 404 but got #{last_response.status}"
815
+ end
816
+
817
+ it 'can fall back to controllers defined on the site homepage' do
818
+ root.class.controller do
819
+ get '/' do
820
+ "ow"
821
+ end
822
+ get '/slimy/:who' do
823
+ "<#{params[:who]}>"
824
+ end
825
+ end
826
+
827
+ get '/slimy/monster'
828
+ assert last_response.ok?, "Expected 200 got #{last_response.status}"
829
+ last_response.body.must_equal "<monster>"
830
+
831
+ get '/'
832
+ assert last_response.ok?, "Expected 200 got #{last_response.status}"
833
+ last_response.body.must_equal "ow"
834
+ end
835
+ end
836
+
739
837
  describe "Static files" do
740
838
  before do
741
839
  @revision_dir = Spontaneous.instance.revision_dir(1)
@@ -35,6 +35,9 @@ else
35
35
  false
36
36
  end
37
37
 
38
+ require 'mysql2'
39
+ require 'pg'
40
+ require 'sqlite3'
38
41
 
39
42
  connection_string = \
40
43
  case ENV["SPOT_ADAPTER"]
@@ -44,7 +47,6 @@ when "postgres"
44
47
  Jdbc::Postgres.load_driver
45
48
  "jdbc:postgresql:///spontaneous2_test"
46
49
  else
47
- require 'pg'
48
50
  "postgres:///spontaneous2_test"
49
51
  end
50
52
  when "mysql"
@@ -53,7 +55,6 @@ when "mysql"
53
55
  Jdbc::MySQL.load_driver
54
56
  "jdbc:mysql://localhost/spontaneous2_test?user=root"
55
57
  else
56
- require 'mysql2'
57
58
  "mysql2://root@localhost/spontaneous2_test"
58
59
  end
59
60
  when "sqlite"
@@ -62,7 +63,6 @@ when "sqlite"
62
63
  Jdbc::SQLite3.load_driver
63
64
  "jdbc:sqlite::memory:"
64
65
  else
65
- require 'sqlite3'
66
66
  "sqlite:/" # in-memory
67
67
  end
68
68
  end
@@ -0,0 +1,80 @@
1
+ # encoding: UTF-8
2
+
3
+ require File.expand_path('../../../test_helper', __FILE__)
4
+
5
+ describe "Boolean fields" do
6
+
7
+ before do
8
+ @site = setup_site
9
+ @now = Time.now
10
+ stub_time(@now)
11
+ Spontaneous::State.delete
12
+ @site.background_mode = :immediate
13
+ @content_class = Class.new(::Piece)
14
+ @prototype = @content_class.field :switch
15
+ @content_class.stubs(:name).returns("ContentClass")
16
+ @instance = @content_class.create
17
+ @field = @instance.switch
18
+ end
19
+
20
+ it "has a distinct editor class" do
21
+ @prototype.instance_class.editor_class.must_equal "Spontaneous.Field.Boolean"
22
+ end
23
+
24
+ it "adopts any field called 'switch'" do
25
+ assert @field.is_a?(Spontaneous::Field::Boolean), "Field should be an instance of Boolean but instead has the following ancestors #{ @prototype.instance_class.ancestors }"
26
+ end
27
+
28
+ it "defaults to true" do
29
+ @field.value.must_equal true
30
+ @field.value(:html).must_equal "Yes"
31
+ @field.value(:string).must_equal "Yes"
32
+ end
33
+
34
+ it "changes string value to 'No'" do
35
+ @field.value = false
36
+ @field.value(:string).must_equal "No"
37
+ end
38
+
39
+ it "flags itself as 'empty' if false" do # I think...
40
+ @field.empty?.must_equal false
41
+ @field.value = false
42
+ @field.empty?.must_equal true
43
+ end
44
+
45
+ it "uses the given state labels" do
46
+ prototype = @content_class.field :boolean, true: "Enabled", false: "Disabled"
47
+ field = prototype.to_field(@instance)
48
+ field.value.must_equal true
49
+ field.value(:string).must_equal "Enabled"
50
+ field.value = false
51
+ field.value(:string).must_equal "Disabled"
52
+ field.value(:html).must_equal "Disabled"
53
+ end
54
+
55
+ it "uses the given default" do
56
+ prototype = @content_class.field :boolean, default: false, true: "On", false: "Off"
57
+ field = prototype.to_field(@instance)
58
+ field.value.must_equal false
59
+ field.value(:string).must_equal "Off"
60
+ end
61
+
62
+ it "returns the string value from #to_s" do
63
+ prototype = @content_class.field :boolean, default: false, true: "On", false: "Off"
64
+ field = prototype.to_field(@instance)
65
+ field.to_s.must_equal "Off"
66
+ end
67
+
68
+ it "has shortcut accessors" do
69
+ state = @field.value(:boolean)
70
+ @field.on?.must_equal state
71
+ @field.checked?.must_equal state
72
+ @field.enabled?.must_equal state
73
+ end
74
+
75
+ it "exports the labels to the interface" do
76
+ prototype = @content_class.field :boolean, default: false, true: "Yes Please", false: "No Thanks"
77
+ exported = prototype.instance_class.export(nil)
78
+ exported.must_equal({:labels=>{:true=>"Yes Please", :false=>"No Thanks"}})
79
+ end
80
+ end