ruber 0.0.1.1

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 (166) hide show
  1. data/COPYING +339 -0
  2. data/INSTALL +137 -0
  3. data/LICENSE +8 -0
  4. data/bin/ruber +65 -0
  5. data/data/share/apps/ruber/core_components.yaml +31 -0
  6. data/data/share/apps/ruber/ruberui.rc +109 -0
  7. data/data/share/icons/ruber.png +0 -0
  8. data/data/share/pixmaps/ruby.png +0 -0
  9. data/icons/ruber-16.png +0 -0
  10. data/icons/ruber-32.png +0 -0
  11. data/icons/ruber-48.png +0 -0
  12. data/icons/ruber-8.png +0 -0
  13. data/lib/ruber/application/application.rb +288 -0
  14. data/lib/ruber/application/plugin.yaml +11 -0
  15. data/lib/ruber/component_manager.rb +899 -0
  16. data/lib/ruber/config/config.rb +82 -0
  17. data/lib/ruber/config/plugin.yaml +3 -0
  18. data/lib/ruber/document_project.rb +209 -0
  19. data/lib/ruber/documents/document_list.rb +416 -0
  20. data/lib/ruber/documents/plugin.yaml +4 -0
  21. data/lib/ruber/editor/document.rb +506 -0
  22. data/lib/ruber/editor/editor_view.rb +167 -0
  23. data/lib/ruber/editor/ktexteditor_wrapper.rb +202 -0
  24. data/lib/ruber/exception_widgets.rb +245 -0
  25. data/lib/ruber/external_program_plugin.rb +397 -0
  26. data/lib/ruber/filtered_output_widget.rb +342 -0
  27. data/lib/ruber/gui_states_handler.rb +231 -0
  28. data/lib/ruber/kde_config_option_backend.rb +167 -0
  29. data/lib/ruber/kde_sugar.rb +249 -0
  30. data/lib/ruber/main_window/choose_plugins_dlg.rb +353 -0
  31. data/lib/ruber/main_window/main_window.rb +524 -0
  32. data/lib/ruber/main_window/main_window_actions.rb +537 -0
  33. data/lib/ruber/main_window/main_window_internal.rb +239 -0
  34. data/lib/ruber/main_window/open_file_in_project_dlg.rb +212 -0
  35. data/lib/ruber/main_window/output_color_widget.rb +35 -0
  36. data/lib/ruber/main_window/plugin.yaml +58 -0
  37. data/lib/ruber/main_window/save_modified_files_dlg.rb +89 -0
  38. data/lib/ruber/main_window/status_bar.rb +156 -0
  39. data/lib/ruber/main_window/ui/choose_plugins_widget.rb +90 -0
  40. data/lib/ruber/main_window/ui/choose_plugins_widget.ui +77 -0
  41. data/lib/ruber/main_window/ui/main_window_settings_widget.rb +108 -0
  42. data/lib/ruber/main_window/ui/main_window_settings_widget.ui +89 -0
  43. data/lib/ruber/main_window/ui/new_project_widget.rb +119 -0
  44. data/lib/ruber/main_window/ui/new_project_widget.ui +178 -0
  45. data/lib/ruber/main_window/ui/open_file_in_project_dlg.rb +109 -0
  46. data/lib/ruber/main_window/ui/open_file_in_project_dlg.ui +168 -0
  47. data/lib/ruber/main_window/ui/output_color_widget.rb +241 -0
  48. data/lib/ruber/main_window/ui/output_color_widget.ui +204 -0
  49. data/lib/ruber/main_window/workspace.rb +442 -0
  50. data/lib/ruber/output_widget.rb +1093 -0
  51. data/lib/ruber/plugin.rb +264 -0
  52. data/lib/ruber/plugin_like.rb +589 -0
  53. data/lib/ruber/plugin_specification.rb +106 -0
  54. data/lib/ruber/plugin_specification_reader.rb +451 -0
  55. data/lib/ruber/project.rb +493 -0
  56. data/lib/ruber/project_backend.rb +105 -0
  57. data/lib/ruber/projects/plugin.yaml +11 -0
  58. data/lib/ruber/projects/project_files_list.rb +314 -0
  59. data/lib/ruber/projects/project_files_widget.rb +301 -0
  60. data/lib/ruber/projects/project_list.rb +314 -0
  61. data/lib/ruber/projects/ui/project_files_rule_chooser_widget.rb +74 -0
  62. data/lib/ruber/projects/ui/project_files_rule_chooser_widget.ui +61 -0
  63. data/lib/ruber/projects/ui/project_files_widget.rb +117 -0
  64. data/lib/ruber/projects/ui/project_files_widget.ui +123 -0
  65. data/lib/ruber/qt_sugar.rb +673 -0
  66. data/lib/ruber/settings_container.rb +515 -0
  67. data/lib/ruber/settings_dialog.rb +244 -0
  68. data/lib/ruber/settings_dialog_manager.rb +503 -0
  69. data/lib/ruber/utils.rb +414 -0
  70. data/lib/ruber/yaml_option_backend.rb +159 -0
  71. data/outsider_files +15 -0
  72. data/plugins/autosave/autosave.rb +404 -0
  73. data/plugins/autosave/plugin.yaml +16 -0
  74. data/plugins/autosave/ui/autosave_config_widget.rb +83 -0
  75. data/plugins/autosave/ui/autosave_config_widget.ui +68 -0
  76. data/plugins/command/command.png +0 -0
  77. data/plugins/command/command.rb +74 -0
  78. data/plugins/command/plugin.yaml +11 -0
  79. data/plugins/find_in_files/find_in_files.rb +337 -0
  80. data/plugins/find_in_files/find_in_files_dlg.rb +411 -0
  81. data/plugins/find_in_files/find_in_files_ui.rc +11 -0
  82. data/plugins/find_in_files/find_in_files_widgets.rb +485 -0
  83. data/plugins/find_in_files/plugin.yaml +23 -0
  84. data/plugins/find_in_files/ui/config_widget.rb +58 -0
  85. data/plugins/find_in_files/ui/config_widget.ui +41 -0
  86. data/plugins/find_in_files/ui/find_in_files_widget.rb +260 -0
  87. data/plugins/find_in_files/ui/find_in_files_widget.ui +324 -0
  88. data/plugins/project_browser/plugin.yaml +10 -0
  89. data/plugins/project_browser/project_browser.rb +245 -0
  90. data/plugins/rake/plugin.yaml +39 -0
  91. data/plugins/rake/rake.png +0 -0
  92. data/plugins/rake/rake.rb +567 -0
  93. data/plugins/rake/rake_extension.rb +153 -0
  94. data/plugins/rake/rake_widgets.rb +615 -0
  95. data/plugins/rake/rakeui.rc +27 -0
  96. data/plugins/rake/ui/add_quick_task_widget.rb +71 -0
  97. data/plugins/rake/ui/add_quick_task_widget.ui +59 -0
  98. data/plugins/rake/ui/choose_task_widget.rb +77 -0
  99. data/plugins/rake/ui/choose_task_widget.ui +72 -0
  100. data/plugins/rake/ui/config_widget.rb +127 -0
  101. data/plugins/rake/ui/config_widget.ui +123 -0
  102. data/plugins/rake/ui/project_widget.rb +217 -0
  103. data/plugins/rake/ui/project_widget.ui +246 -0
  104. data/plugins/rspec/plugin.yaml +30 -0
  105. data/plugins/rspec/rspec.png +0 -0
  106. data/plugins/rspec/rspec.rb +945 -0
  107. data/plugins/rspec/rspec.svg +90 -0
  108. data/plugins/rspec/rspecui.rc +20 -0
  109. data/plugins/rspec/ruber_rspec_formatter.rb +312 -0
  110. data/plugins/rspec/ui/rspec_project_widget.rb +170 -0
  111. data/plugins/rspec/ui/rspec_project_widget.ui +193 -0
  112. data/plugins/ruby_development/plugin.yaml +27 -0
  113. data/plugins/ruby_development/ruby_development.png +0 -0
  114. data/plugins/ruby_development/ruby_development.rb +453 -0
  115. data/plugins/ruby_development/ruby_developmentui.rc +19 -0
  116. data/plugins/ruby_development/ui/project_widget.rb +112 -0
  117. data/plugins/ruby_development/ui/project_widget.ui +108 -0
  118. data/plugins/ruby_runner/config_widget.rb +116 -0
  119. data/plugins/ruby_runner/plugin.yaml +26 -0
  120. data/plugins/ruby_runner/project_widget.rb +62 -0
  121. data/plugins/ruby_runner/ruby.png +0 -0
  122. data/plugins/ruby_runner/ruby_interpretersui.rc +26 -0
  123. data/plugins/ruby_runner/ruby_runner.rb +411 -0
  124. data/plugins/ruby_runner/ui/config_widget.rb +92 -0
  125. data/plugins/ruby_runner/ui/config_widget.ui +91 -0
  126. data/plugins/ruby_runner/ui/project_widget.rb +60 -0
  127. data/plugins/ruby_runner/ui/project_widget.ui +48 -0
  128. data/plugins/ruby_runner/ui/ruby_runnner_plugin_option_widget.rb +59 -0
  129. data/plugins/ruby_runner/ui/ruby_runnner_plugin_option_widget.ui +44 -0
  130. data/plugins/state/plugin.yaml +28 -0
  131. data/plugins/state/state.rb +520 -0
  132. data/plugins/state/ui/config_widget.rb +92 -0
  133. data/plugins/state/ui/config_widget.ui +89 -0
  134. data/plugins/syntax_checker/plugin.yaml +18 -0
  135. data/plugins/syntax_checker/syntax_checker.rb +662 -0
  136. data/ruber.desktop +10 -0
  137. data/spec/annotation_model_spec.rb +174 -0
  138. data/spec/common.rb +119 -0
  139. data/spec/component_manager_spec.rb +1259 -0
  140. data/spec/document_list_spec.rb +626 -0
  141. data/spec/document_project_spec.rb +373 -0
  142. data/spec/document_spec.rb +779 -0
  143. data/spec/editor_view_spec.rb +167 -0
  144. data/spec/external_program_plugin_spec.rb +676 -0
  145. data/spec/filtered_output_widget_spec.rb +642 -0
  146. data/spec/gui_states_handler_spec.rb +304 -0
  147. data/spec/kde_config_option_backend_spec.rb +214 -0
  148. data/spec/kde_sugar_spec.rb +101 -0
  149. data/spec/ktexteditor_wrapper_spec.rb +305 -0
  150. data/spec/output_widget_spec.rb +1703 -0
  151. data/spec/plugin_spec.rb +1393 -0
  152. data/spec/plugin_specification_reader_spec.rb +1765 -0
  153. data/spec/plugin_specification_spec.rb +401 -0
  154. data/spec/project_backend_spec.rb +172 -0
  155. data/spec/project_files_list_spec.rb +401 -0
  156. data/spec/project_list_spec.rb +511 -0
  157. data/spec/project_spec.rb +990 -0
  158. data/spec/qt_sugar_spec.rb +328 -0
  159. data/spec/settings_container_spec.rb +617 -0
  160. data/spec/settings_dialog_manager_spec.rb +773 -0
  161. data/spec/settings_dialog_spec.rb +419 -0
  162. data/spec/state_spec.rb +991 -0
  163. data/spec/utils_spec.rb +406 -0
  164. data/spec/workspace_spec.rb +869 -0
  165. data/spec/yaml_option_backend_spec.rb +246 -0
  166. metadata +284 -0
@@ -0,0 +1,419 @@
1
+ require 'spec/common'
2
+
3
+ require 'ruber/settings_dialog'
4
+ require 'ruber/settings_container'
5
+
6
+ describe 'Ruber::SettingsDialog, when created' do
7
+
8
+ include FlexMock::ArgumentTypes
9
+
10
+ before do
11
+ @back = flexmock('backend'){|m| m.should_ignore_missing}
12
+ @cont = Object.new
13
+ @cont.extend Ruber::SettingsContainer
14
+ @cont.send :setup_container, @back
15
+ @widgets = [
16
+ OS.new({:caption => 'C1', :class_obj => Qt::CheckBox}),
17
+ OS.new({:caption => 'C2', :class_obj => Qt::LineEdit}),
18
+ OS.new({:caption => 'C2', :code => 'Qt::PushButton.new("test")'}),
19
+ OS.new({:caption => 'C1', :class_obj => Qt::RadioButton, :code => 'Qt::ComboBox.new'})
20
+ ]
21
+ @mw = Qt::Widget.new
22
+ flexmock(Ruber).should_receive(:[]).with(:main_window).by_default.and_return @mw
23
+ end
24
+
25
+ it 'should set its title to the fourth argument, if given' do
26
+ dlg = Ruber::SettingsDialog.new @cont, {}, [], 'Title'
27
+ dlg.window_title.should == 'Title'
28
+ dlg = Ruber::SettingsDialog.new @cont, {}, []
29
+ dlg.window_title.should == KDE::Application.instance.application_name
30
+ end
31
+
32
+ it 'should store the first argument in the @container instance variable' do
33
+ dlg = Ruber::SettingsDialog.new @cont, {}, []
34
+ dlg.instance_variable_get(:@container).should equal(@cont)
35
+ end
36
+
37
+ it 'should create the widgets specified in the third argument and store it in the @pages instance variable, grouped by captions' do
38
+ @widgets.each{|w| @cont.add_widget w}
39
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
40
+ res = dlg.instance_variable_get(:@widgets)
41
+ res['C1'][0].should be_a(Qt::CheckBox)
42
+ res['C1'][1].should be_a(Qt::ComboBox)
43
+ res['C2'][0].should be_a(Qt::LineEdit)
44
+ res['C2'][1].should be_a(Qt::PushButton)
45
+ res['C2'][1].text.should == 'test'
46
+ end
47
+
48
+ it 'should add an @settings_dialog instance variable and set it to self for each widget it creates' do
49
+ @widgets.each{|w| @cont.add_widget w}
50
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
51
+ widgets = dlg.instance_variable_get(:@widgets).values.flatten
52
+ widgets.each{|w| w.instance_variable_get(:@settings_dialog).should equal(dlg)}
53
+ end
54
+
55
+ it 'should add a page for each caption and store the corresponding PageWidgetItems in the @page_items instance variable' do
56
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
57
+ dlg.instance_variable_get(:@page_items).size.should == 2
58
+ end
59
+
60
+ it 'should create a page for each caption, in alphabetical order, with the widgets stored in a vertical layout, from first to last' do
61
+ @widgets.unshift @widgets.delete_at(1)
62
+ @widgets.each{|w| @cont.add_widget w}
63
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
64
+ items = dlg.instance_variable_get :@page_items
65
+
66
+ l = items[0].widget.layout
67
+ l.should be_a(Qt::VBoxLayout)
68
+ l.item_at(0).widget.should be_a(Qt::CheckBox)
69
+ l.item_at(1).widget.should be_a(Qt::ComboBox)
70
+
71
+ l = items[1].widget.layout
72
+ l.item_at(0).widget.should be_a(Qt::LineEdit)
73
+ l.item_at(1).widget.should be_a(Qt::PushButton)
74
+ end
75
+
76
+ it 'should use the first specified icon for each page' do
77
+ %w[xyz.png 123.png 456.png abc.png].each_with_index{|p, i| @widgets[i].pixmap = p}
78
+ @widgets.each{|w| @cont.add_widget w}
79
+ icons = [KDE::Icon.new( 'xyz.png'), KDE::Icon.new('123.png')]
80
+ flexmock(KDE::Icon).should_receive(:new).once.with('xyz.png').and_return(icons[0])
81
+ flexmock(KDE::Icon).should_receive(:new).once.with('123.png').and_return(icons[1])
82
+ flexmock(KDE::Icon).should_receive(:new).with('abc.png').never
83
+ flexmock(KDE::Icon).should_receive(:new).with('456.png').never
84
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
85
+ items = dlg.instance_variable_get :@page_items
86
+ end
87
+
88
+ it 'should create an instance of the SettingsDialogManager class, passing it self, the widgets and the options' do
89
+ options = {
90
+ OS.new({:group => 'G1', :name => :o1, :default => 2}) => 3,
91
+ OS.new({:group => :G2, :name => :o2, :default => 'xyz'}) => 'abc'
92
+ }
93
+ @widgets.each{|w| @cont.add_widget w}
94
+ flexmock(Ruber::SettingsDialogManager).should_receive(:new).once.with(Ruber::SettingsDialog, options, on{|a| a.map(&:class) == [Qt::CheckBox, Qt::ComboBox, Qt::LineEdit, Qt::PushButton]})
95
+ dlg = Ruber::SettingsDialog.new @cont, options, @widgets
96
+ end
97
+
98
+ end
99
+
100
+ describe 'Ruber::SettingsDialog#read_settings' do
101
+
102
+ before do
103
+ @mw = Qt::Widget.new
104
+ flexmock(Ruber).should_receive(:[]).with(:main_window).by_default.and_return @mw
105
+ @back = flexmock('backend'){|m| m.should_ignore_missing}
106
+ @cont = Object.new
107
+ @cont.extend Ruber::SettingsContainer
108
+ @cont.send :setup_container, @back
109
+ @widgets = [
110
+ OS.new({:caption => 'C1', :class_obj => Qt::CheckBox}),
111
+ OS.new({:caption => 'C2', :class_obj => Qt::LineEdit}),
112
+ OS.new({:caption => 'C2', :code => 'Qt::PushButton.new("test")'}),
113
+ OS.new({:caption => 'C1', :class_obj => Qt::RadioButton, :code => 'Qt::ComboBox.new'})
114
+ ]
115
+ end
116
+
117
+ it 'should call the read_settings method of each widget which provides it' do
118
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
119
+ widgets = dlg.instance_variable_get(:@widgets)
120
+
121
+ widgets['C1'][0].instance_eval do
122
+ def read_settings
123
+ end
124
+ end
125
+ flexmock(widgets['C1'][0]).should_receive(:read_settings).once
126
+
127
+ widgets['C1'][1].instance_eval do
128
+ def read_settings
129
+ end
130
+ end
131
+ flexmock(widgets['C1'][1]).should_receive(:read_settings).once
132
+
133
+ widgets['C2'][0].instance_eval do
134
+ def read_settings
135
+ end
136
+ end
137
+ flexmock(widgets['C2'][0]).should_receive(:read_settings).once
138
+
139
+ dlg.read_settings
140
+ end
141
+
142
+ it 'should call the read_settings method of the option manager' do
143
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
144
+ flexmock(dlg.instance_variable_get(:@manager)).should_receive(:read_settings).once
145
+ dlg.read_settings
146
+ end
147
+
148
+ end
149
+
150
+ describe 'Ruber::SettingsDialog#store_settings' do
151
+
152
+ before do
153
+ @mw = Qt::Widget.new
154
+ flexmock(Ruber).should_receive(:[]).with(:main_window).by_default.and_return @mw
155
+ @back = flexmock('backend'){|m| m.should_ignore_missing}
156
+ @cont = Object.new
157
+ @cont.extend Ruber::SettingsContainer
158
+ @cont.send :setup_container, @back
159
+ @widgets = [
160
+ OS.new({:caption => 'C1', :class_obj => Qt::CheckBox}),
161
+ OS.new({:caption => 'C2', :class_obj => Qt::LineEdit}),
162
+ OS.new({:caption => 'C2', :code => 'Qt::PushButton.new("test")'}),
163
+ OS.new({:caption => 'C1', :class_obj => Qt::RadioButton, :code => 'Qt::ComboBox.new'})
164
+ ]
165
+ end
166
+
167
+ it 'should call the store_settings method of each widget which provides it' do
168
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
169
+ widgets = dlg.instance_variable_get(:@widgets)
170
+
171
+ widgets['C1'][0].instance_eval do
172
+ def store_settings
173
+ end
174
+ end
175
+ flexmock(widgets['C1'][0]).should_receive(:store_settings).once
176
+
177
+ widgets['C1'][1].instance_eval do
178
+ def store_settings
179
+ end
180
+ end
181
+ flexmock(widgets['C1'][1]).should_receive(:store_settings).once
182
+
183
+ widgets['C2'][0].instance_eval do
184
+ def store_settings
185
+ end
186
+ end
187
+ flexmock(widgets['C2'][0]).should_receive(:store_settings).once
188
+
189
+ dlg.store_settings
190
+ end
191
+
192
+ it 'should call the store_settings method of the option manager' do
193
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
194
+ flexmock(dlg.instance_variable_get(:@manager)).should_receive(:store_settings).once
195
+ dlg.store_settings
196
+ end
197
+
198
+ it 'should call the "write" method of the container, after all the store_settings methods have been called' do
199
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
200
+ widgets = dlg.instance_variable_get(:@widgets)
201
+ widgets['C1'][0].instance_eval do
202
+ def store_settings
203
+ end
204
+ end
205
+ flexmock(dlg.instance_variable_get(:@manager)).should_receive(:store_settings).once.globally.ordered
206
+ flexmock(widgets['C1'][0]).should_receive(:store_settings).once.globally.ordered
207
+ flexmock(@cont).should_receive(:write).once.globally.ordered
208
+ dlg.store_settings
209
+ end
210
+
211
+ it 'should be called when the Ok button is clicked' do
212
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
213
+ flexmock(dlg).should_receive(:store_settings).once
214
+ dlg.instance_eval{emit okClicked}
215
+ end
216
+
217
+ it 'should be called when the Apply button is clicked' do
218
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
219
+ flexmock(dlg).should_receive(:store_settings).once
220
+ dlg.instance_eval{emit applyClicked}
221
+ end
222
+
223
+ end
224
+
225
+ describe 'Ruber::SettingsDialog#read_default_settings' do
226
+
227
+ before do
228
+ @mw = Qt::Widget.new
229
+ flexmock(Ruber).should_receive(:[]).with(:main_window).by_default.and_return @mw
230
+ @back = flexmock('backend'){|m| m.should_ignore_missing}
231
+ @cont = Object.new
232
+ @cont.extend Ruber::SettingsContainer
233
+ @cont.send :setup_container, @back
234
+ @widgets = [
235
+ OS.new({:caption => 'C1', :class_obj => Qt::CheckBox}),
236
+ OS.new({:caption => 'C2', :class_obj => Qt::LineEdit}),
237
+ OS.new({:caption => 'C2', :code => 'Qt::PushButton.new("test")'}),
238
+ OS.new({:caption => 'C1', :class_obj => Qt::RadioButton, :code => 'Qt::ComboBox.new'})
239
+ ]
240
+ end
241
+
242
+ it 'should call the read_default_settings method of each widget which provides it' do
243
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
244
+ widgets = dlg.instance_variable_get(:@widgets)
245
+
246
+ widgets['C1'][0].instance_eval do
247
+ def read_default_settings
248
+ end
249
+ end
250
+ flexmock(widgets['C1'][0]).should_receive(:read_default_settings).once
251
+
252
+ widgets['C1'][1].instance_eval do
253
+ def read_default_settings
254
+ end
255
+ end
256
+ flexmock(widgets['C1'][1]).should_receive(:read_default_settings).once
257
+
258
+ widgets['C2'][0].instance_eval do
259
+ def read_default_settings
260
+ end
261
+ end
262
+ flexmock(widgets['C2'][0]).should_receive(:read_default_settings).once
263
+
264
+ dlg.read_default_settings
265
+ end
266
+
267
+ it 'should call the read_default_settings method of the option manager' do
268
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
269
+ flexmock(dlg.instance_variable_get(:@manager)).should_receive(:read_default_settings).once
270
+ dlg.read_default_settings
271
+ end
272
+
273
+ it 'should be called when the Default button is clicked' do
274
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
275
+ flexmock(dlg).should_receive(:read_default_settings).once
276
+ dlg.instance_eval{emit defaultClicked}
277
+ end
278
+
279
+ end
280
+
281
+ describe 'Ruber::SettingsDialog#exec' do
282
+
283
+ before(:all) do
284
+ class ::KDE::PageDialog
285
+ def exec
286
+ end
287
+ end
288
+ end
289
+
290
+ after(:all) do
291
+ class ::KDE::PageDialog
292
+ undef_method :exec
293
+ end
294
+ end
295
+
296
+ before do
297
+ @mw = Qt::Widget.new
298
+ flexmock(Ruber).should_receive(:[]).with(:main_window).by_default.and_return @mw
299
+ @back = flexmock('backend'){|m| m.should_ignore_missing}
300
+ @cont = Object.new
301
+ @cont.extend Ruber::SettingsContainer
302
+ @cont.send :setup_container, @back
303
+ @widgets = [
304
+ OS.new({:caption => 'C1', :class_obj => Qt::CheckBox}),
305
+ OS.new({:caption => 'C2', :class_obj => Qt::LineEdit}),
306
+ OS.new({:caption => 'C2', :code => 'Qt::PushButton.new("test")'}),
307
+ OS.new({:caption => 'C1', :class_obj => Qt::RadioButton, :code => 'Qt::ComboBox.new'})
308
+ ]
309
+ end
310
+
311
+ it 'should call the read_settings method' do
312
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
313
+ flexmock(dlg).should_receive(:read_settings).once
314
+ dlg.exec
315
+ end
316
+
317
+ it 'should make the first page current' do
318
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
319
+ # It seems that comparing the objects themselves doesn't work, as they seem to
320
+ # have different object_id s. To avoid problems, we give a name to each
321
+ dlg.instance_variable_get(:@page_items).each_with_index{|w, i| w.object_name = i.to_s}
322
+ dlg.current_page = dlg.instance_variable_get(:@page_items)[1]
323
+ dlg.exec
324
+ dlg.current_page.object_name.should == '0'
325
+ end
326
+
327
+ it 'should give focus to the first widget in the page' do
328
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
329
+ flexmock(dlg.instance_variable_get(:@widgets)['C1'][0]).should_receive(:set_focus).once
330
+ dlg.exec
331
+ end
332
+
333
+ it 'shouldn\'t attempt to make the first page current if there are no pages' do
334
+ dlg = Ruber::SettingsDialog.new @cont, [], []
335
+ lambda{dlg.exec}.should_not raise_error
336
+ end
337
+
338
+ end
339
+
340
+ describe 'Ruber::SettingsDialog#show' do
341
+
342
+ before(:all) do
343
+ class ::KDE::PageDialog
344
+ def show
345
+ end
346
+ end
347
+ end
348
+
349
+ after(:all) do
350
+ class ::KDE::PageDialog
351
+ undef_method :show
352
+ end
353
+ end
354
+
355
+ before do
356
+ @mw = Qt::Widget.new
357
+ flexmock(Ruber).should_receive(:[]).with(:main_window).by_default.and_return @mw
358
+ @back = flexmock('backend'){|m| m.should_ignore_missing}
359
+ @cont = Object.new
360
+ @cont.extend Ruber::SettingsContainer
361
+ @cont.send :setup_container, @back
362
+ @widgets = [
363
+ OS.new({:caption => 'C1', :class_obj => Qt::CheckBox}),
364
+ OS.new({:caption => 'C2', :class_obj => Qt::LineEdit}),
365
+ OS.new({:caption => 'C2', :code => 'Qt::PushButton.new("test")'}),
366
+ OS.new({:caption => 'C1', :class_obj => Qt::RadioButton, :code => 'Qt::ComboBox.new'})
367
+ ]
368
+ end
369
+
370
+ it 'should call the read_settings method' do
371
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
372
+ flexmock(dlg).should_receive(:read_settings).once
373
+ dlg.show
374
+ end
375
+
376
+ it 'should make the first page current' do
377
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
378
+ # It seems that comparing the objects themselves doesn't work, as they seem to
379
+ # have different object_id s. To avoid problems, we give a name to each
380
+ dlg.instance_variable_get(:@page_items).each_with_index{|w, i| w.object_name = i.to_s}
381
+ dlg.current_page = dlg.instance_variable_get(:@page_items)[1]
382
+ dlg.show
383
+ dlg.current_page.object_name.should == '0'
384
+ end
385
+
386
+ it 'should give focus to the first widget in the page' do
387
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
388
+ flexmock(dlg.instance_variable_get(:@widgets)['C1'][0]).should_receive(:set_focus).once
389
+ dlg.show
390
+ end
391
+
392
+ end
393
+
394
+ describe 'SettingsDialog#widgets' do
395
+
396
+ it 'should return an array containing all the added widgets' do
397
+ @mw = Qt::Widget.new
398
+ flexmock(Ruber).should_receive(:[]).with(:main_window).by_default.and_return @mw
399
+ @back = flexmock('backend'){|m| m.should_ignore_missing}
400
+ @cont = Object.new
401
+ @cont.extend Ruber::SettingsContainer
402
+ @cont.send :setup_container, @back
403
+ @widgets = [
404
+ OS.new({:caption => 'C1', :class_obj => Qt::CheckBox}),
405
+ OS.new({:caption => 'C2', :class_obj => Qt::LineEdit}),
406
+ OS.new({:caption => 'C2', :code => 'Qt::PushButton.new("test")'}),
407
+ OS.new({:caption => 'C1', :class_obj => Qt::RadioButton, :code => 'Qt::ComboBox.new'})
408
+ ]
409
+ dlg = Ruber::SettingsDialog.new @cont, [], @widgets
410
+ res = dlg.widgets
411
+ internal = dlg.instance_variable_get(:@widgets)
412
+ res.size.should == 4
413
+ res.should include(internal['C1'][0])
414
+ res.should include(internal['C1'][1])
415
+ res.should include(internal['C2'][0])
416
+ res.should include(internal['C2'][1])
417
+ end
418
+
419
+ end
@@ -0,0 +1,991 @@
1
+ require 'spec/common'
2
+
3
+ require 'tempfile'
4
+ require 'fileutils'
5
+
6
+ require 'ruber/plugin_specification'
7
+ require 'ruber/editor/document'
8
+
9
+ require 'plugins/state/state'
10
+
11
+ describe Ruber::State::Plugin do
12
+
13
+ before do
14
+ #Needed because the Qt::Object connect method doesn't like @components not being a
15
+ #Qt::Object
16
+ class Ruber::State::Plugin
17
+ def connect *args
18
+ end
19
+ end
20
+ @components = flexmock('components'){|m| m.should_ignore_missing}
21
+ @config = flexmock('config'){|m| m.should_ignore_missing}
22
+ flexmock(Ruber).should_receive(:[]).with(:components).and_return(@components).by_default
23
+ flexmock(Ruber).should_receive(:[]).with(:app).and_return(KDE::Application.instance).by_default
24
+ flexmock(Ruber).should_receive(:[]).with(:config).and_return(@config).by_default
25
+ pdf = Ruber::PluginSpecification.full :name => :state
26
+ @plug = Ruber::State::Plugin.new pdf
27
+ end
28
+
29
+ after do
30
+ class Ruber::State::Plugin
31
+ remove_method :connect rescue nil
32
+ end
33
+ end
34
+
35
+ it 'inherits Ruber::Plugin' do
36
+ Ruber::State::Plugin.ancestors.should include(Ruber::Plugin)
37
+ end
38
+
39
+ describe '#when created' do
40
+
41
+ it 'sets the @force_restore_project_files instance variable to nil' do
42
+ @plug.instance_variables.should include(:@force_restore_project_files)
43
+ @plug.instance_variable_get(:@force_restore_project_files).should be_nil
44
+ end
45
+
46
+ it 'sets the @force_restore_cursor_position instance variable to nil' do
47
+ @plug.instance_variables.should include(:@force_restore_cursor_position)
48
+ @plug.instance_variable_get(:@force_restore_cursor_position).should be_nil
49
+ end
50
+
51
+ end
52
+
53
+ describe '#delayed_initialize' do
54
+
55
+ before do
56
+ @documents = flexmock('documents')
57
+ @projects = flexmock('projects')
58
+ flexmock(KDE::Application.instance).should_receive(:starting?).and_return(true).by_default
59
+ flexmock(Ruber).should_receive(:[]).with(:docs).and_return(@documents).by_default
60
+ flexmock(Ruber).should_receive(:[]).with(:projects).and_return(@projects).by_default
61
+ end
62
+
63
+ it 'calls the restore_last_state method if there\'s no open project and the only open document is pristine' do
64
+ doc = flexmock('doc', :pristine? => true)
65
+ @documents.should_receive(:to_a).once.and_return [doc]
66
+ @documents.should_receive(:[]).with(0).once.and_return doc
67
+ @projects.should_receive(:to_a).once.and_return []
68
+ flexmock(@plug).should_receive(:restore_last_state).once
69
+ @plug.send :delayed_initialize
70
+ end
71
+
72
+ it 'doesn\'t call the restore_last_state method if there are open projects' do
73
+ prj = flexmock('project')
74
+ @projects.should_receive(:to_a).once.and_return [prj]
75
+ flexmock(@plug).should_receive(:restore_last_state).never
76
+ @plug.send :delayed_initialize
77
+ end
78
+
79
+ it 'doesn\'t call the restore_last_state method if there is more than one open document' do
80
+ @documents.should_receive(:to_a).once.and_return 2.times.map{flexmock}
81
+ @projects.should_receive(:to_a).once.and_return []
82
+ flexmock(@plug).should_receive(:restore_last_state).never
83
+ @plug.send :delayed_initialize
84
+ end
85
+
86
+ it 'doesn\'t call the restore_last_state method if there aren\'t open documents' do
87
+ @documents.should_receive(:to_a).once.and_return []
88
+ @projects.should_receive(:to_a).once.and_return []
89
+ flexmock(@plug).should_receive(:restore_last_state).never
90
+ @plug.send :delayed_initialize
91
+ end
92
+
93
+ it 'doesn\'t call the restore_last_state method if the only open document isn\'t pristine' do
94
+ doc = flexmock('doc', :pristine? => false)
95
+ @documents.should_receive(:to_a).once.and_return [doc]
96
+ @documents.should_receive(:[]).with(0).once.and_return doc
97
+ @projects.should_receive(:to_a).once.and_return []
98
+ flexmock(@plug).should_receive(:restore_last_state).never
99
+ @plug.send :delayed_initialize
100
+ end
101
+
102
+ it 'does nothing if the application is already running' do
103
+ doc = flexmock('doc', :pristine? => true)
104
+ @documents.should_receive(:to_a).and_return [doc]
105
+ @documents.should_receive(:[]).with(0).and_return doc
106
+ @projects.should_receive(:to_a).and_return []
107
+ flexmock(KDE::Application.instance).should_receive(:starting?).and_return false
108
+ flexmock(@plug).should_receive(:restore_last_state).never
109
+ @plug.send :delayed_initialize
110
+ end
111
+
112
+ end
113
+
114
+ describe '#gather_settings' do
115
+
116
+ before do
117
+ @projects = flexmock('projects') do |m|
118
+ m.should_receive(:projects).and_return([]).by_default
119
+ m.should_receive(:current).and_return(nil).by_default
120
+ end
121
+ @documents = flexmock('documents') do |m|
122
+ m.should_receive(:documents).and_return([]).by_default
123
+ m.should_receive(:current).and_return(nil).by_default
124
+ end
125
+ @mw = flexmock('main window'){|m| m.should_ignore_missing}
126
+ flexmock(Ruber).should_receive(:[]).with(:projects).and_return(@projects).by_default
127
+ flexmock(Ruber).should_receive(:[]).with(:docs).and_return(@documents).by_default
128
+ flexmock(Ruber).should_receive(:[]).with(:main_window).and_return(@mw).by_default
129
+ end
130
+
131
+ it 'stores a list with the project file of each open project under the :open_projects key' do
132
+ prjs = 5.times.map{|i| flexmock(i.to_s){|m| m.should_receive(:project_file).and_return i.to_s}}
133
+ @projects.should_receive(:projects).once.and_return(prjs)
134
+ @projects.should_receive(:current).once.and_return(nil)
135
+ @plug.send(:gather_settings).should have_entries(:open_projects => (0...5).map(&:to_s))
136
+ end
137
+
138
+ it 'puts the file corresponding to the open project at the beginning of the :open_projects entry' do
139
+ prjs = 5.times.map{|i| flexmock(i.to_s, :project_file => i.to_s)}
140
+ @projects.should_receive(:projects).once.and_return(prjs)
141
+ @projects.should_receive(:current).once.and_return prjs[2]
142
+ @plug.send(:gather_settings).should have_entries(:open_projects => %w[2 0 1 3 4])
143
+ end
144
+
145
+ it 'stores the project files in an arbitrary order if there\'s no active project' do
146
+ prjs = 5.times.map{|i| flexmock(i.to_s){|m| m.should_receive(:project_file).and_return i.to_s}}
147
+ @projects.should_receive(:projects).once.and_return(prjs)
148
+ @projects.should_receive(:current).once.and_return nil
149
+ @plug.send(:gather_settings).should have_entries(:open_projects => (0...5).map(&:to_s))
150
+ end
151
+
152
+ it 'stores an empty array under the :open_projects key if there are no open projects' do
153
+ @plug.send(:gather_settings).should have_entries(:open_projects => [])
154
+ end
155
+
156
+ it 'stores a list of the paths of the files associated with all open documents under the :open_files key' do
157
+ docs = 5.times.map{|i| flexmock(i.to_s){|m| m.should_receive(:path).and_return i.to_s}}
158
+ @documents.should_receive(:documents).once.and_return(docs)
159
+ @plug.send(:gather_settings).should have_entries(:open_documents => (0...5).map(&:to_s))
160
+ end
161
+
162
+ it 'ignores documents which aren\'t associated with a file' do
163
+ docs = 5.times.map do |i|
164
+ flexmock(i.to_s) do |m|
165
+ m.should_receive(:path).and_return(i % 2 == 0 ? i.to_s : '')
166
+ end
167
+ end
168
+ @documents.should_receive(:documents).once.and_return(docs)
169
+ @plug.send(:gather_settings).should have_entries(:open_documents => %w[0 2 4])
170
+ end
171
+
172
+ it 'stores an empty array under the :open_files key if there are no open documents or if no open document is associated with a file' do
173
+ docs = 5.times.map{flexmock(:path => '')}
174
+ @documents.should_receive(:documents).once.and_return(docs).once
175
+ @documents.should_receive(:documents).once.and_return([]).once
176
+ @plug.send(:gather_settings).should have_entries(:open_documents => [])
177
+ @plug.send(:gather_settings).should have_entries(:open_documents => [])
178
+ end
179
+
180
+ it 'stores the path of the active document under the :active_document key' do
181
+ docs = 5.times.map{|i| flexmock(i.to_s){|m| m.should_receive(:path).and_return i.to_s}}
182
+ @documents.should_receive(:documents).once.and_return(docs)
183
+ @mw.should_receive(:current_document).once.and_return(docs[1])
184
+ @plug.send(:gather_settings).should have_entries(:active_document => "1")
185
+ end
186
+
187
+ it 'stores nil under the :active_document key if there\'s no current document' do
188
+ @mw.should_receive(:current_document).once.and_return nil
189
+ @plug.send(:gather_settings).should have_entries(:active_document => nil)
190
+ end
191
+
192
+ it 'stores nil under the :active_document key if the current document isn\'t associated with a file' do
193
+ doc = flexmock('doc', :path => '')
194
+ @mw.should_receive(:current_document).once.and_return doc
195
+ @plug.send(:gather_settings).should have_entries(:active_document => nil)
196
+ end
197
+
198
+ end
199
+
200
+ describe '#save_settings' do
201
+
202
+ it 'stores the value corresponding to the :open_projects key in the hash returned by gather_settings in the state/open_projects setting' do
203
+ flexmock(@plug).should_receive(:gather_settings).once.and_return(:open_projects => %w[x y z])
204
+ @config.should_receive(:[]=).with(:state, :open_projects, %w[x y z]).once
205
+ @config.should_receive(:[]=)
206
+ @plug.save_settings
207
+ end
208
+
209
+ it 'stores the value corresponding to the :open_documents key in the hash returned by gather_settings in the state/open_documents setting' do
210
+ flexmock(@plug).should_receive(:gather_settings).once.and_return(:open_documents => %w[x y z])
211
+ @config.should_receive(:[]=).with(:state, :open_documents, %w[x y z]).once
212
+ @config.should_receive(:[]=)
213
+ @plug.save_settings
214
+ end
215
+
216
+ it 'stores the value corresponding to the :active_document key in the hash returned by gather_settings in the state/active_document setting' do
217
+ flexmock(@plug).should_receive(:gather_settings).once.and_return(:active_document => 'x')
218
+ @config.should_receive(:[]=).with(:state, :active_document, 'x').once
219
+ @config.should_receive(:[]=)
220
+ @plug.save_settings
221
+ end
222
+
223
+ end
224
+
225
+ describe '#restore_cursor_position?' do
226
+
227
+ it 'returns the value of the state/restore_cursor_position config entry if the @force_restore_cursor_position instance variable is nil' do
228
+ @config.should_receive(:[]).with(:state, :restore_cursor_position).once.and_return(true)
229
+ @config.should_receive(:[]).with(:state, :restore_cursor_position).once.and_return(false)
230
+ @plug.instance_variable_set :@force_restore_cursor_position, nil
231
+ @plug.restore_cursor_position?.should == true
232
+ @plug.restore_cursor_position?.should == false
233
+ end
234
+
235
+ it 'returns the value of the @force_restore_cursor_position instance variable if it is not nil' do
236
+ @config.should_receive(:[]).with(:state, :restore_cursor_position).never
237
+ @plug.instance_variable_set :@force_restore_cursor_position, true
238
+ @plug.restore_cursor_position?.should == true
239
+ @plug.instance_variable_set :@force_restore_cursor_position, false
240
+ @plug.restore_cursor_position?.should == false
241
+ end
242
+
243
+ end
244
+
245
+ describe '#restore_project_files?' do
246
+
247
+ it 'returns the value of the state/restore_project_files config entry if the @force_restore_project_files instance variable is nil' do
248
+ @config.should_receive(:[]).with(:state, :restore_project_files).once.and_return(true)
249
+ @config.should_receive(:[]).with(:state, :restore_project_files).once.and_return(false)
250
+ @plug.instance_variable_set :@force_restore_project_files, nil
251
+ @plug.restore_project_files?.should == true
252
+ @plug.restore_project_files?.should == false
253
+ end
254
+
255
+ it 'returns the value of the @force_restore_project_files instance variable if it is not nil' do
256
+ @config.should_receive(:[]).with(:state, :restore_project_files).never
257
+ @plug.instance_variable_set :@force_restore_project_files, true
258
+ @plug.restore_project_files?.should == true
259
+ @plug.instance_variable_set :@force_restore_project_files, false
260
+ @plug.restore_project_files?.should == false
261
+ end
262
+
263
+ end
264
+
265
+ describe 'session_data' do
266
+
267
+ it 'returns a hash containing the hash returned by the gather_settings method under the "State" key' do
268
+ hash = {
269
+ :open_projects => %w[a b c],
270
+ :open_documents => %w[x y z],
271
+ :active_document => 'z'
272
+ }
273
+ flexmock(@plug).should_receive(:gather_settings).once.and_return hash
274
+ res = @plug.session_data
275
+ res['State'].should == hash
276
+ end
277
+
278
+ end
279
+
280
+ describe '#restore_session' do
281
+
282
+ it 'calls restore from within a with block with :restore_cursor_position and :restore_project_files set to true passing the hash contained in the State entry of the argument' do
283
+ hash = {
284
+ 'State' => {
285
+ :open_projects => %w[a b c],
286
+ :open_documents => %w[x y z],
287
+ :active_document => 'z'
288
+ }
289
+ }
290
+ exp_hash = {
291
+ [:state, :open_projects] => %w[a b c],
292
+ [:state, :open_documents] => %w[x y z],
293
+ [:state, :active_document] => 'z'
294
+ }
295
+ default = {:open_projects => [], :open_documents => [], :active_document => nil}
296
+ flexmock(@plug).should_receive(:with).with({:restore_cursor_position => true, :restore_project_files => true, :force => true}, FlexMock.on{|a| a.call || a.is_a?(Proc)}).once
297
+ flexmock(@plug).should_receive(:restore).with(FlexMock.on{|a| a == exp_hash and a[:state, :open_projects] == %w[a b c]}).once
298
+ @plug.restore_session hash
299
+ end
300
+
301
+ end
302
+
303
+ describe '#with' do
304
+
305
+ describe ', when the @force_restore_cursor_position instance variable is nil' do
306
+
307
+ it 'calls the given block after setting the @force_restore_project_files instance variable to the :restore_cursor_position entry if the entry is a true value' do
308
+ restore_doc = nil
309
+ @plug.with(:restore_cursor_position => 'x'){restore_doc = @plug.instance_variable_get(:@force_restore_cursor_position)}
310
+ restore_doc.should == 'x'
311
+ end
312
+
313
+ it 'calls the given block after setting the @force_restore_project_files instance variable to false if the :restore_cursor_position entry is given and is a false value' do
314
+ restore_doc = nil
315
+ @plug.with(:restore_cursor_position => false){restore_doc = @plug.instance_variable_get(:@force_restore_cursor_position)}
316
+ restore_doc.should == false
317
+ restore_doc = nil
318
+ @plug.instance_variable_set :@force_restore_cursor_position, nil
319
+ @plug.with(:restore_cursor_position => nil){restore_doc = @plug.instance_variable_get(:@force_restore_cursor_position)}
320
+ restore_doc.should == false
321
+ end
322
+
323
+ it 'calls the block without changing the @force_restore_cursor_position instance variable if the :restore_cursor_position entry isn\'t given' do
324
+ restore_doc = true
325
+ @plug.with({}){restore_doc = @plug.instance_variable_get(:@force_restore_cursor_position)}
326
+ restore_doc.should be_nil
327
+ end
328
+
329
+ it 'sets the @force_restore_cursor_position back to nil after executing the block, even if the block raises an exception' do
330
+ @plug.with(:restore_cursor_position => true){@plug.instance_variable_get(:@force_restore_cursor_position).should be_true}
331
+ @plug.instance_variable_get(:@force_restore_cursor_position).should be_nil
332
+ @plug.with(:restore_cursor_position => false){@plug.instance_variable_get(:@force_restore_cursor_position).should == false}
333
+ @plug.instance_variable_get(:@force_restore_cursor_position).should be_nil
334
+ begin @plug.with(:restore_cursor_position => true){raise Exception}
335
+ rescue Exception
336
+ end
337
+ @plug.instance_variable_get(:@force_restore_cursor_position).should be_nil
338
+ end
339
+
340
+ end
341
+
342
+ describe ', when the @force_restore_cursor_position instance variable is not nil' do
343
+
344
+ describe ' and the :force entry isn\'t true' do
345
+
346
+ it 'calls the block without changing the value of the @force_restore_cursor_position instance variable' do
347
+ restore = nil
348
+ @plug.instance_variable_set(:@force_restore_cursor_position, 'x')
349
+ @plug.with(:restore_cursor_position => 'y'){restore = @plug.instance_variable_get(:@force_restore_cursor_position)}
350
+ restore.should == 'x'
351
+ end
352
+
353
+ end
354
+
355
+ describe ' and the :force entry is true' do
356
+
357
+ before do
358
+ @plug.instance_variable_set :@force_restore_cursor_position, 'y'
359
+ end
360
+
361
+ it 'calls the given block after setting the @force_restore_project_files instance variable to the :restore_cursor_position entry if the entry is a true value' do
362
+ restore_doc = nil
363
+ @plug.with(:restore_cursor_position => 'x', :force => true){restore_doc = @plug.instance_variable_get(:@force_restore_cursor_position)}
364
+ restore_doc.should == 'x'
365
+ end
366
+
367
+ it 'calls the given block after setting the @force_restore_project_files instance variable to false if the :restore_cursor_position entry is given and is a false value' do
368
+ restore_doc = nil
369
+ @plug.with(:restore_cursor_position => false, :force => true){restore_doc = @plug.instance_variable_get(:@force_restore_cursor_position)}
370
+ restore_doc.should == false
371
+ restore_doc = nil
372
+ @plug.instance_variable_set :@force_restore_cursor_position, nil
373
+ @plug.with(:restore_cursor_position => nil, :force => true){restore_doc = @plug.instance_variable_get(:@force_restore_cursor_position)}
374
+ restore_doc.should == false
375
+ end
376
+
377
+ it 'calls the block without changing the @force_restore_cursor_position instance variable if the :restore_cursor_position entry isn\'t given' do
378
+ restore_doc = true
379
+ @plug.with({:force => true}){restore_doc = @plug.instance_variable_get(:@force_restore_cursor_position)}
380
+ restore_doc.should == 'y'
381
+ end
382
+
383
+ it 'sets the @force_restore_cursor_position back to the original value after executing the block, even if the block raises an exception' do
384
+ @plug.with(:restore_cursor_position => true, :force => true){@plug.instance_variable_get(:@force_restore_cursor_position).should be_true}
385
+ @plug.instance_variable_get(:@force_restore_cursor_position).should == 'y'
386
+ @plug.with(:restore_cursor_position => false, :force => true){@plug.instance_variable_get(:@force_restore_cursor_position).should == false}
387
+ @plug.instance_variable_get(:@force_restore_cursor_position).should == 'y'
388
+ begin @plug.with(:restore_cursor_position => true, :force => true){raise Exception}
389
+ rescue Exception
390
+ end
391
+ @plug.instance_variable_get(:@force_restore_cursor_position).should == 'y'
392
+ end
393
+
394
+ end
395
+
396
+ end
397
+
398
+ describe ', when the @force_restore_cursor_position instance variable is nil' do
399
+
400
+ it 'calls the given block after setting the @force_restore_project_files instance variable to the :restore_cursor_position entry if the entry is a true value' do
401
+ restore_doc = nil
402
+ @plug.with(:restore_cursor_position => 'x'){restore_doc = @plug.instance_variable_get(:@force_restore_cursor_position)}
403
+ restore_doc.should == 'x'
404
+ end
405
+
406
+ it 'calls the given block after setting the @force_restore_project_files instance variable to false if the :restore_cursor_position entry is given and is a false value' do
407
+ restore_doc = nil
408
+ @plug.with(:restore_cursor_position => false){restore_doc = @plug.instance_variable_get(:@force_restore_cursor_position)}
409
+ restore_doc.should == false
410
+ restore_doc = nil
411
+ @plug.instance_variable_set :@force_restore_cursor_position, nil
412
+ @plug.with(:restore_cursor_position => nil){restore_doc = @plug.instance_variable_get(:@force_restore_cursor_position)}
413
+ restore_doc.should == false
414
+ end
415
+
416
+ it 'calls the block without changing the @force_restore_cursor_position instance variable if the :restore_cursor_position entry isn\'t given' do
417
+ restore_doc = true
418
+ @plug.with({}){restore_doc = @plug.instance_variable_get(:@force_restore_cursor_position)}
419
+ restore_doc.should be_nil
420
+ end
421
+
422
+ it 'sets the @force_restore_cursor_position back to nil after executing the block, even if the block raises an exception' do
423
+ @plug.with(:restore_cursor_position => true){@plug.instance_variable_get(:@force_restore_cursor_position).should be_true}
424
+ @plug.instance_variable_get(:@force_restore_cursor_position).should be_nil
425
+ @plug.with(:restore_cursor_position => false){@plug.instance_variable_get(:@force_restore_cursor_position).should == false}
426
+ @plug.instance_variable_get(:@force_restore_cursor_position).should be_nil
427
+ begin @plug.with(:restore_cursor_position => true){raise Exception}
428
+ rescue Exception
429
+ end
430
+ @plug.instance_variable_get(:@force_restore_cursor_position).should be_nil
431
+ end
432
+
433
+ end
434
+
435
+ describe ', when the @force_restore_project_files instance variable is not nil' do
436
+
437
+ describe ' and the :force entry isn\'t true' do
438
+
439
+ it 'calls the block without changing the value of the @force_restore_project_files instance variable' do
440
+ restore = nil
441
+ @plug.instance_variable_set(:@force_restore_project_files, 'x')
442
+ @plug.with(:restore_project_files => 'y'){restore = @plug.instance_variable_get(:@force_restore_project_files)}
443
+ restore.should == 'x'
444
+ end
445
+
446
+ end
447
+
448
+ describe ' and the :force entry is true' do
449
+
450
+ before do
451
+ @plug.instance_variable_set :@force_restore_project_files, 'y'
452
+ end
453
+
454
+ it 'calls the given block after setting the @force_restore_project_files instance variable to the :restore_project_files entry if the entry is a true value' do
455
+ restore_prj = nil
456
+ @plug.with(:restore_project_files => 'x', :force => true){restore_prj = @plug.instance_variable_get(:@force_restore_project_files)}
457
+ restore_prj.should == 'x'
458
+ end
459
+
460
+ it 'calls the given block after setting the @force_restore_project_files instance variable to false if the :restore_project_files entry is given and is a false value' do
461
+ restore_prj = nil
462
+ @plug.with(:restore_project_files => false, :force => true){restore_prj = @plug.instance_variable_get(:@force_restore_project_files)}
463
+ restore_prj.should == false
464
+ restore_prj = nil
465
+ @plug.instance_variable_set :@force_restore_project_files, nil
466
+ @plug.with(:restore_project_files => nil, :force => true){restore_prj = @plug.instance_variable_get(:@force_restore_project_files)}
467
+ restore_prj.should == false
468
+ end
469
+
470
+ it 'calls the block without changing the @force_restore_project_files instance variable if the :restore_project_files entry isn\'t given' do
471
+ restore_prj = true
472
+ @plug.with({:force => true}){restore_prj = @plug.instance_variable_get(:@force_restore_project_files)}
473
+ restore_prj.should == 'y'
474
+ end
475
+
476
+ it 'sets the @force_restore_project_files back to the original value after executing the block, even if the block raises an exception' do
477
+ @plug.with(:restore_project_files => true, :force => true){@plug.instance_variable_get(:@force_restore_project_files).should be_true}
478
+ @plug.instance_variable_get(:@force_restore_project_files).should == 'y'
479
+ @plug.with(:restore_project_files => false, :force => true){@plug.instance_variable_get(:@force_restore_project_files).should == false}
480
+ @plug.instance_variable_get(:@force_restore_project_files).should == 'y'
481
+ begin @plug.with(:restore_project_files => true, :force => true){raise Exception}
482
+ rescue Exception
483
+ end
484
+ @plug.instance_variable_get(:@force_restore_project_files).should == 'y'
485
+ end
486
+
487
+ end
488
+
489
+ end
490
+
491
+ end
492
+
493
+ describe '#restore_document' do
494
+
495
+ it 'calls the document\'s state extension\'s restore method' do
496
+ ext = flexmock('extension'){|m| m.should_receive(:restore).once}
497
+ doc = flexmock('doc'){|m| m.should_receive(:extension).once.with(:state).and_return ext}
498
+ @plug.restore_document doc
499
+ end
500
+
501
+ end
502
+
503
+ describe '#restore_project' do
504
+
505
+ it 'calls the project\'s state extension\'s restore method' do
506
+ ext = flexmock('extension'){|m| m.should_receive(:restore).once}
507
+ prj = flexmock('prj'){|m| m.should_receive(:extension).once.with(:state).and_return ext}
508
+ @plug.restore_project prj
509
+ end
510
+
511
+ end
512
+
513
+ describe '#restore_projects' do
514
+
515
+ before do
516
+ @projects = flexmock('projects'){|m| m.should_ignore_missing}
517
+ flexmock(Ruber).should_receive(:[]).with(:projects).and_return(@projects).by_default
518
+ @mw = flexmock{|m| m.should_ignore_missing}
519
+ flexmock(Ruber).should_receive(:[]).with(:main_window).and_return(@mw).by_default
520
+ end
521
+
522
+ it 'closes all projects' do
523
+ prjs = 3.times.map{|i| flexmock(i.to_s)}
524
+ prjs.each{|pr| @projects.should_receive(:close_project).with(pr).once}
525
+ @projects.should_receive(:to_a).once.and_return(prjs)
526
+ @plug.restore_projects
527
+ end
528
+
529
+ it 'uses the safe_open_project method of the main window to open the first entry of the state/open_projects setting' do
530
+ @config.should_receive(:[]).with(:state, :open_projects).once.and_return %w[/x/y/z.ruprj /a/b/c.ruprj]
531
+ prj = flexmock('project')
532
+ @mw.should_receive(:safe_open_project).once.with('/x/y/z.ruprj').and_return prj
533
+ @plug.restore_projects
534
+ end
535
+
536
+ it 'activates the project returned by safe_open_project' do
537
+ @config.should_receive(:[]).with(:state, :open_projects).once.and_return %w[/x/y/z.ruprj /a/b/c.ruprj]
538
+ prj = flexmock('project')
539
+ @mw.should_receive(:safe_open_project).once.with('/x/y/z.ruprj').and_return prj
540
+ @projects.should_receive(:current_project=).once.with(prj)
541
+ @plug.restore_projects
542
+ end
543
+
544
+ it 'doesn\'t attempt to activate the project if safe_open_project returned nil' do
545
+ @config.should_receive(:[]).with(:state, :open_projects).once.and_return %w[/x/y/z.ruprj /a/b/c.ruprj]
546
+ prj = flexmock('project')
547
+ @mw.should_receive(:safe_open_project).once.with('/x/y/z.ruprj').and_return nil
548
+ @projects.should_receive(:current_project=).never
549
+ lambda{@plug.restore_projects}.should_not raise_error
550
+ end
551
+
552
+ it 'does nothing if the state/open_projects setting is empty' do
553
+ @config.should_receive(:[]).with(:state, :open_projects).once.and_return []
554
+ prj = flexmock('project')
555
+ @projects.should_receive(:project).never
556
+ @projects.should_receive(:current_project=).never
557
+ @plug.restore_projects
558
+ end
559
+
560
+ it 'reads the settings from the argument, if given, rather than from the config object' do
561
+ @config.should_receive(:[]).never
562
+ h = {[:state, :open_projects] => ['/x/y/z.ruprj']}
563
+ def h.[] group, name
564
+ super [group, name]
565
+ end
566
+ prj = flexmock('project')
567
+ @mw.should_receive(:safe_open_project).once.with('/x/y/z.ruprj').and_return prj
568
+ @projects.should_receive(:current_project=).once.with(prj)
569
+ @plug.restore_projects h
570
+ end
571
+
572
+ end
573
+
574
+ describe '#restore_documents' do
575
+
576
+ before do
577
+ @mw = flexmock('main window'){|m| m.should_ignore_missing}
578
+ @docs = flexmock('documents'){|m| m.should_ignore_missing}
579
+ flexmock(Ruber).should_receive(:[]).with(:main_window).and_return(@mw).by_default
580
+ flexmock(Ruber).should_receive(:[]).with(:docs).and_return(@docs).by_default
581
+ end
582
+
583
+ it 'closes all open documents' do
584
+ @docs.should_receive(:close_all).once
585
+ @plug.restore_documents
586
+ end
587
+
588
+ it 'creates a new document for each entry in the state/open_documents from within a block passed to the main window\'s without_activating method' do
589
+ files = %w[/x/y/f1.rb /a/b/f2.rb /f3.rb]
590
+ @config.should_receive(:[]).with(:state, :open_documents).once.and_return files
591
+ @config.should_receive(:[]).with(:state, :active_document)
592
+ files.each{|f| @mw.should_receive(:editor_for!).once.with(f).ordered}
593
+ @mw.should_receive(:without_activating).once.with(FlexMock.on{|a| a.call || a.is_a?(Proc)})
594
+ @plug.restore_documents
595
+ end
596
+
597
+ it 'activates the document corresponding to the file specified in the state/active_document setting' do
598
+ files = %w[/x/y/f1.rb /a/b/f2.rb /f3.rb]
599
+ @config.should_receive(:[]).with(:state, :open_documents).once.and_return files
600
+ @config.should_receive(:[]).with(:state, :active_document).once.and_return files[1]
601
+ 3.times{|i| @mw.should_receive(:editor_for!).once.with(files[i])}
602
+ @mw.should_receive(:display_document).once.with(files[1])
603
+ @mw.should_receive(:without_activating).once.with(FlexMock.on{|a| a.call || a.is_a?(Proc)})
604
+ @plug.restore_documents
605
+ end
606
+
607
+ it 'it activates the last document if the state/active_document setting is nil or if it doesn\'t correspond to an existing document' do
608
+ files = %w[/x/y/f1.rb /a/b/f2.rb /f3.rb]
609
+ @config.should_receive(:[]).with(:state, :open_documents).twice.and_return files
610
+ @config.should_receive(:[]).with(:state, :active_document).once.and_return nil
611
+ @config.should_receive(:[]).with(:state, :active_document).once.and_return random_string
612
+ @mw.should_receive(:display_document).twice.with(files[-1])
613
+ @mw.should_receive(:without_activating).twice.with(FlexMock.on{|a| a.call || a.is_a?(Proc)})
614
+ @plug.restore_documents
615
+ @plug.restore_documents
616
+ end
617
+
618
+ it 'does nothing if the state/open_files entry is empty' do
619
+ @config.should_receive(:[]).with(:state, :open_documents).once.and_return []
620
+ lambda{@plug.restore_documents}.should_not raise_error
621
+ end
622
+
623
+ it 'reads the settings from the argument, if given, rather than from the config object' do
624
+ @config.should_receive(:[]).never
625
+ files = %w[/x/y/f1.rb /a/b/f2.rb /f3.rb]
626
+ files.each{|f| @mw.should_receive(:editor_for!).once.with(f).ordered}
627
+ @mw.should_receive(:without_activating).once.with(FlexMock.on{|a| a.call || a.is_a?(Proc)})
628
+ h = {[:state, :open_documents] => files, [:state, :active_document] => nil}
629
+ def h.[] group, name
630
+ super [group, name]
631
+ end
632
+ @plug.restore_documents h
633
+ end
634
+
635
+ end
636
+
637
+ describe 'restore' do
638
+
639
+ it 'calls the restore_projects method if the state/open_project setting is not empty' do
640
+ @config.should_receive(:[]).with(:state, :open_projects).and_return %w[/xyz/abc.ruprj]
641
+ flexmock(@plug).should_receive(:restore_projects).once.with(@config)
642
+ @plug.restore
643
+ end
644
+
645
+ it 'calls the restore_documents method if the state/open_projects setting is empty' do
646
+ @config.should_receive(:[]).with(:state, :open_projects).and_return []
647
+ flexmock(@plug).should_receive(:restore_documents).once.with(@config)
648
+ @plug.restore
649
+ end
650
+
651
+ it 'uses the argument, rather than the config object, if one is given' do
652
+ @config.should_receive(:[]).never
653
+ h = {[:state, :open_projects] => %w[/xyz/abc.ruprj]}
654
+ def h.[](group, name)
655
+ super [group, name]
656
+ end
657
+ flexmock(@plug).should_receive(:restore_projects).once.with(h)
658
+ @plug.restore h
659
+ h[[:state, :open_projects]] = []
660
+ flexmock(@plug).should_receive(:restore_documents).once.with(h)
661
+ @plug.restore h
662
+ end
663
+
664
+ end
665
+
666
+ describe 'restore_last_state' do
667
+
668
+ describe ', when the state/startup_behaviour option is :restore_all' do
669
+
670
+ it 'calls the restore method' do
671
+ @config.should_receive(:[]).with(:state, :startup_behaviour).once.and_return :restore_all
672
+ flexmock(@plug).should_receive(:restore).once
673
+ @plug.restore_last_state
674
+ end
675
+
676
+ end
677
+
678
+ describe ', when the state/startup_behaviour option is :restore_projects_only' do
679
+
680
+ it 'calls restore_project from within a with block with :restore_project_files set to false' do
681
+ @config.should_receive(:[]).with(:state, :startup_behaviour).once.and_return :restore_projects_only
682
+ flexmock(@plug).should_receive(:restore_projects).once
683
+ flexmock(@plug).should_receive(:with).once.with({:restore_project_files => false}, FlexMock.on{|a| a.call || a.is_a?(Proc)})
684
+ @plug.restore_last_state
685
+ end
686
+
687
+ end
688
+
689
+ describe ', when the state/startup_behaviour option is :restore_documents_only' do
690
+
691
+ it 'calls restore_documents' do
692
+ @config.should_receive(:[]).with(:state, :startup_behaviour).once.and_return :restore_documents_only
693
+ flexmock(@plug).should_receive(:restore_documents).once
694
+ @plug.restore_last_state
695
+ end
696
+
697
+ end
698
+
699
+ describe ', when the state/startup_behaviour option is :restore_nothing' do
700
+
701
+ it 'does nothing' do
702
+ @config.should_receive(:[]).with(:state, :startup_behaviour).once.and_return :restore_nothing
703
+ flexmock(@plug).should_receive(:with).never
704
+ flexmock(@plug).should_receive(:restore_projects).never
705
+ flexmock(@plug).should_receive(:restore_documents).never
706
+ flexmock(@plug).should_receive(:restore).never
707
+ @plug.restore_last_state
708
+ end
709
+
710
+ end
711
+
712
+ end
713
+
714
+ end
715
+
716
+ describe Ruber::State::DocumentExtension do
717
+
718
+ it 'inherits from Qt::Object' do
719
+ Ruber::State::DocumentExtension.ancestors.should include(Qt::Object)
720
+ end
721
+
722
+ it 'includes the Ruber::Extension module' do
723
+ Ruber::State::DocumentExtension.ancestors.should include(Ruber::Extension)
724
+ end
725
+
726
+ before do
727
+ @components = flexmock{|m| m.should_ignore_missing}
728
+ flexmock(Ruber).should_receive(:[]).with(:components).and_return(@components).by_default
729
+ @doc = Ruber::Document.new nil, __FILE__
730
+ @ext = Ruber::State::DocumentExtension.new @doc.own_project
731
+ @doc.own_project.add_extension :state, @ext
732
+ end
733
+
734
+ describe ', when created' do
735
+
736
+ it 'connects the document\'s view_created(QObject*, QObject*) signal to its auto_restore slot' do
737
+ flexmock(@ext).should_receive(:auto_restore).once
738
+ @doc.create_view
739
+ end
740
+
741
+ end
742
+
743
+ describe '#restore' do
744
+
745
+ before do
746
+ #Needed to avoid the need of creating a mock State plugin
747
+ @doc.disconnect SIGNAL('view_created(QObject*, QObject*)'), @ext
748
+ end
749
+
750
+ it 'moves the cursor to the position stored in the document\'s project state/cursor_position setting' do
751
+ view = @doc.create_view
752
+ flexmock(@doc.own_project).should_receive(:[]).with(:state, :cursor_position).once.and_return([100, 20])
753
+ flexmock(@doc.view).should_receive(:go_to).with(100, 20).once
754
+ @ext.restore
755
+ end
756
+
757
+ it 'does nothing if the document doesn\'t have a view' do
758
+ lambda{@ext.restore}.should_not raise_error
759
+ end
760
+
761
+ end
762
+
763
+ describe '#save_settings' do
764
+
765
+ before do
766
+ #Needed to avoid the need of creating a mock State plugin
767
+ @doc.disconnect SIGNAL('view_created(QObject*, QObject*)'), @ext
768
+ end
769
+
770
+ it 'stores an array containing the cursor position in the document\'s project state/cursor_position setting' do
771
+ view = @doc.create_view
772
+ flexmock(@doc.own_project).should_receive(:[]=).with(:state, :cursor_position, [100, 20]).once
773
+ cur = KTextEditor::Cursor.new(100, 20)
774
+ flexmock(@doc.view).should_receive(:cursor_position).once.and_return cur
775
+ @ext.save_settings
776
+ end
777
+
778
+ it 'uses [0,0] as cursor position if the document doesn\'t have any view' do
779
+ flexmock(@doc.own_project).should_receive(:[]=).with(:state, :cursor_position, [0, 0]).once
780
+ lambda{@ext.save_settings}.should_not raise_error
781
+ end
782
+
783
+ end
784
+
785
+ describe 'auto_restore' do
786
+
787
+ before do
788
+ @plug = Object.new
789
+ @plug.instance_variable_set :@force_restore_cursor_position, nil
790
+ flexmock(Ruber).should_receive(:[]).with(:state).and_return(@plug).by_default
791
+ end
792
+
793
+ it 'calls the restore method if the State plugins wants the curesor position restored' do
794
+ flexmock(@plug).should_receive(:restore_cursor_position?).once.and_return true
795
+ flexmock(@ext).should_receive(:restore).once
796
+ @ext.send :auto_restore
797
+ end
798
+
799
+ it 'does noting if the State plugins doesn\'t want the curesor position restored' do
800
+ flexmock(@plug).should_receive(:restore_cursor_position?).once.and_return false
801
+ flexmock(@ext).should_receive(:restore).never
802
+ @ext.send :auto_restore
803
+ end
804
+
805
+ end
806
+
807
+ end
808
+
809
+ describe Ruber::State::ProjectExtension do
810
+
811
+ it 'inherits from Qt::Object' do
812
+ Ruber::State::ProjectExtension.ancestors.should include(Qt::Object)
813
+ end
814
+
815
+ it 'includes the Ruber::Extension module' do
816
+ Ruber::State::ProjectExtension.ancestors.should include(Ruber::Extension)
817
+ end
818
+
819
+ before do
820
+ @dir = File.join Dir.tmpdir, random_string(10)
821
+ FileUtils.mkdir @dir
822
+ @components = flexmock{|m| m.should_ignore_missing}
823
+ @projects = Qt::Object.new
824
+ flexmock(Ruber).should_receive(:[]).with(:components).and_return(@components).by_default
825
+ flexmock(Ruber).should_receive(:[]).with(:projects).and_return(@projects).by_default
826
+ @prj = Ruber::Project.new 'Test', File.join(@dir, 'test.ruprj')
827
+ @ext = Ruber::State::ProjectExtension.new @prj
828
+ @prj.add_extension :state, @ext
829
+ end
830
+
831
+ after do
832
+ FileUtils.rm_rf @dir
833
+ end
834
+
835
+ describe ', when created' do
836
+
837
+ it 'connects the project\'s activated() signal to its auto_restore slot' do
838
+ flexmock(@ext).should_receive(:auto_restore).once
839
+ @prj.activate
840
+ end
841
+
842
+ end
843
+
844
+ describe '#restore' do
845
+
846
+ before do
847
+ @mw = flexmock('main window'){|m| m.should_ignore_missing}
848
+ @config = flexmock('config')
849
+ @docs = flexmock('docs'){|m| m.should_ignore_missing}
850
+ flexmock(Ruber).should_receive(:[]).with(:main_window).and_return(@mw).by_default
851
+ flexmock(Ruber).should_receive(:[]).with(:config).and_return(@config).by_default
852
+ flexmock(Ruber).should_receive(:[]).with(:docs).and_return(@docs).by_default
853
+ end
854
+
855
+ it 'calls the document list\'s close_all method' do
856
+ @docs.should_receive(:close_all).once
857
+ flexmock(@prj).should_receive(:[]).with(:state, :open_documents).once.and_return []
858
+ @ext.restore
859
+ end
860
+
861
+ it 'it calls the main_window\'s editor_for! for each entry in the project\'s state/open_documents setting from within a without_activating call' do
862
+ files = %w[/a.rb /b.rb /c.rb]
863
+ flexmock(@prj).should_receive(:[]).with(:state, :open_documents).once.and_return files
864
+ flexmock(@prj).should_receive(:[]).with(:state, :active_document).once.and_return nil
865
+ files.each{|f| @mw.should_receive(:editor_for!).with(f).once}
866
+ @mw.should_receive(:without_activating).once.with(FlexMock.on{|a| a.call || a.is_a?(Proc)})
867
+ @ext.restore
868
+ end
869
+
870
+ it 'activates the editor corresponding to the file in the project\'s state/active_document entry' do
871
+ files = %w[/a.rb /b.rb /c.rb]
872
+ flexmock(@prj).should_receive(:[]).with(:state, :open_documents).once.and_return files
873
+ flexmock(@prj).should_receive(:[]).with(:state, :active_document).once.and_return files[1]
874
+ @mw.should_receive(:without_activating).once.with(FlexMock.on{|a| a.call || a.is_a?(Proc)})
875
+ @mw.should_receive(:display_document).once.with files[1]
876
+ @ext.restore
877
+ end
878
+
879
+ it 'activates the editor corresponding to the last entry file in the project\'s state/open_documents entry if the state/active_documents entry is nil' do
880
+ files = %w[/a.rb /b.rb /c.rb]
881
+ editors = 3.times.map{|i| flexmock(i.to_s)}
882
+ flexmock(@prj).should_receive(:[]).with(:state, :open_documents).once.and_return files
883
+ flexmock(@prj).should_receive(:[]).with(:state, :active_document).once.and_return nil
884
+ @mw.should_receive(:without_activating).once.with(FlexMock.on{|a| a.call || a.is_a?(Proc)})
885
+ @mw.should_receive(:display_document).once.with files[-1]
886
+ @ext.restore
887
+ end
888
+
889
+ it 'activates the editor corresponding to the last entry file in the project\'s state/open_documents entry if the state/active_documents doesn\'t correspond to one of the open files' do
890
+ files = %w[/a.rb /b.rb /c.rb]
891
+ flexmock(@prj).should_receive(:[]).with(:state, :open_documents).once.and_return files
892
+ flexmock(@prj).should_receive(:[]).with(:state, :active_document).once.and_return '/d.rb'
893
+ @mw.should_receive(:without_activating).once.with(FlexMock.on{|a| a.call || a.is_a?(Proc)})
894
+ @mw.should_receive(:display_document).once.with files[-1]
895
+ @ext.restore
896
+ end
897
+
898
+ it 'doesn\'t open any editor if the project\'s state/open_documents entry is empty' do
899
+ files = []
900
+ flexmock(@prj).should_receive(:[]).with(:state, :open_documents).once.and_return files
901
+ flexmock(@prj).should_receive(:[]).with(:state, :active_document).and_return nil
902
+ @mw.should_receive(:editor_for!).never
903
+ @mw.should_receive(:editor_for).never
904
+ @mw.should_receive(:without_activating).never
905
+ @mw.should_receive(:activate_editor).never
906
+ @ext.restore
907
+ end
908
+
909
+ end
910
+
911
+ describe '#save_settings' do
912
+
913
+ before do
914
+ @mw = flexmock('main window'){|m| m.should_ignore_missing}
915
+ @docs = flexmock('docs'){|m| m.should_ignore_missing}
916
+ flexmock(Ruber).should_receive(:[]).with(:main_window).and_return(@mw).by_default
917
+ flexmock(Ruber).should_receive(:[]).with(:docs).and_return(@docs).by_default
918
+ end
919
+
920
+ it 'stores the paths of the open documents associated with a file in the project\'s state/open_documents entry' do
921
+ docs = %w[a b c].map{|i| flexmock(i.to_s, :path => "/#{i}")}
922
+ @docs.should_receive(:documents_with_file).once.and_return docs
923
+ flexmock(@prj).should_receive(:[]=).once.with :state, :open_documents, %w[a b c].map{|i| "/#{i}"}
924
+ flexmock(@prj).should_receive(:[]=)
925
+ @ext.save_settings
926
+ end
927
+
928
+ it 'stores an empty array in the project\'s state/open_documents entry if there\'s no open file or if none of them is associated with a document' do
929
+ @docs.should_receive(:documents_with_file).once.and_return []
930
+ flexmock(@prj).should_receive(:[]=).once.with :state, :open_documents, []
931
+ flexmock(@prj).should_receive(:[]=)
932
+ @ext.save_settings
933
+ end
934
+
935
+ it 'stores the path of the current document in the project\'s state/active_document entry' do
936
+ docs = %w[a b c].map{|i| flexmock(i.to_s, :path => "/#{i}")}
937
+ active = flexmock('doc', :path => '/b')
938
+ @docs.should_receive(:documents_with_file).once.and_return docs
939
+ @mw.should_receive(:current_document).once.and_return active
940
+ flexmock(@prj).should_receive(:[]=).once.with :state, :active_document, '/b'
941
+ flexmock(@prj).should_receive(:[]=)
942
+ @ext.save_settings
943
+ end
944
+
945
+ it 'stores nil in the project\'s state/active_document entry if there\'s no active document or the active document isn\'t associated with a file' do
946
+ docs = %w[a b c].map{|i| flexmock(i.to_s, :path => "/#{i}")}
947
+ active = flexmock('doc', :path => '')
948
+ @docs.should_receive(:documents_with_file).twice.and_return docs
949
+ @mw.should_receive(:current_document).once.and_return active
950
+ @mw.should_receive(:current_document).once.and_return nil
951
+ flexmock(@prj).should_receive(:[]=).twice.with :state, :active_document, nil
952
+ flexmock(@prj).should_receive(:[]=)
953
+ @ext.save_settings
954
+ @ext.save_settings
955
+ end
956
+
957
+ end
958
+
959
+ describe 'auto_restore' do
960
+
961
+ before do
962
+ @config = flexmock('config')
963
+ flexmock(Ruber).should_receive(:[]).with(:config).and_return(@config).by_default
964
+ @plug = Object.new
965
+ @plug.instance_variable_set :@force_restore_project_files, nil
966
+ flexmock(Ruber).should_receive(:[]).with(:state).and_return(@plug).by_default
967
+ end
968
+
969
+ it 'disconnects the project\'s activated() signal from the extension' do
970
+ flexmock(@plug).should_receive(:restore_project_files?).once.and_return false
971
+ @ext.send :auto_restore
972
+ flexmock(@ext).should_receive(:auto_restore).never
973
+ flexmock(@prj).instance_eval{emit activated}
974
+ end
975
+
976
+ it 'calls the restore method if the State plugins wants the project files restored' do
977
+ flexmock(@plug).should_receive(:restore_project_files?).once.and_return true
978
+ flexmock(@ext).should_receive(:restore).once
979
+ @ext.send :auto_restore
980
+ end
981
+
982
+ it 'does noting if the State plugins doesn\'t want the project_files restored' do
983
+ flexmock(@plug).should_receive(:restore_project_files?).once.and_return false
984
+ flexmock(@ext).should_receive(:restore).never
985
+ @ext.send :auto_restore
986
+ end
987
+
988
+
989
+ end
990
+
991
+ end