tinkit 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. data/LICENSE +176 -0
  2. data/README +11 -0
  3. data/Rakefile +75 -0
  4. data/lib/glue_envs/couchrest/couchrest_attachment_handler.rb +260 -0
  5. data/lib/glue_envs/couchrest/couchrest_files_mgr.rb +198 -0
  6. data/lib/glue_envs/couchrest_glue_env.rb +536 -0
  7. data/lib/glue_envs/files_mgr_base.rb +51 -0
  8. data/lib/glue_envs/filesystem/filesystem_files_mgr.rb +187 -0
  9. data/lib/glue_envs/filesystem_glue_env.rb +395 -0
  10. data/lib/glue_envs/mysql/mysql_files_mgr.rb +175 -0
  11. data/lib/glue_envs/mysql_glue_env.rb +428 -0
  12. data/lib/glue_envs/sdb_s3/sdb_s3_files_mgr.rb +314 -0
  13. data/lib/glue_envs/sdb_s3_glue_env.rb +248 -0
  14. data/lib/helpers/camel.rb +21 -0
  15. data/lib/helpers/filesystem_helpers.rb +27 -0
  16. data/lib/helpers/hash_helpers.rb +74 -0
  17. data/lib/helpers/log_helper.rb +34 -0
  18. data/lib/helpers/mime_types_new.rb +126 -0
  19. data/lib/helpers/old_more_open_struct.rb +28 -0
  20. data/lib/helpers/require_helper.rb +45 -0
  21. data/lib/helpers/tk_escape.rb +17 -0
  22. data/lib/midas/bufs_data_structure.rb +84 -0
  23. data/lib/midas/node_element_operations.rb +264 -0
  24. data/lib/tinkit.rb +38 -0
  25. data/lib/tinkit_base_node.rb +733 -0
  26. data/lib/tinkit_node_factory.rb +47 -0
  27. data/spec/couchrest_files_mgr_spec.rb +551 -0
  28. data/spec/couchrest_glue_spec.rb +246 -0
  29. data/spec/filesystem_files_mgr_spec.rb +236 -0
  30. data/spec/filesystem_glue_spec.rb +243 -0
  31. data/spec/filesystem_helpers_spec.rb +42 -0
  32. data/spec/helpers/bufs_node_builder.rb +17 -0
  33. data/spec/helpers/bufs_sample_dataset.rb +160 -0
  34. data/spec/helpers/bufs_test_environments.rb +81 -0
  35. data/spec/helpers/tmp_view_cleaner.rb +15 -0
  36. data/spec/lib_helpers/tk_escape_spec.rb +45 -0
  37. data/spec/mysql_files_mgr_spec.rb +250 -0
  38. data/spec/mysql_glue_spec.rb +214 -0
  39. data/spec/node_element_operations_spec.rb +392 -0
  40. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec1.rb +82 -0
  41. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec2.rb +68 -0
  42. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec3.rb +80 -0
  43. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec4.rb +110 -0
  44. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec5.rb +84 -0
  45. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec6.rb +83 -0
  46. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec7.rb +101 -0
  47. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec8.rb +92 -0
  48. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec_all.rb +266 -0
  49. data/spec/sdb_s3_glue_spec.rb +230 -0
  50. data/spec/tinkit_node_factory_spec.rb +1108 -0
  51. metadata +114 -0
@@ -0,0 +1,1108 @@
1
+ #require helper for cleaner require statements
2
+ require File.join(File.expand_path(File.dirname(__FILE__)), '../lib/helpers/require_helper')
3
+
4
+ require Tinkit.spec_helpers 'bufs_test_environments'
5
+
6
+ #Test Environments
7
+ #The test environments sets up the following:
8
+ # 4 seperate persistent layers
9
+ # - 2 CouchDB databases using CouchRest
10
+ # - 2 File Systems (just different directories) using File and FileUtils
11
+ # A data structure called Tinkit
12
+ # 2 "Glue" enviroments that bind the persistent layers to the data structure
13
+ # The 4 low level persistent layers are mapped to a common model framework
14
+ # using the glue environments to bind the datastructure and persistent layers
15
+ # to the framework
16
+
17
+ #Node Helpers
18
+ # make_doc_no_attachment - makes a common framework node without attachment
19
+ # arguments: user_class, parameters
20
+ # make_doc_w_attach_from_ile - makes a node with the file as an attachment
21
+ # arguments: user_class, filename, parameters)
22
+
23
+ module MakeUserClasses
24
+ @user1_id = "CouchUser001"
25
+ @user2_id = "CouchUser002"
26
+ @user3_id = "FileSysUser003"
27
+ @user4_id = "FileSysUser004"
28
+ @user5_id = "SDBS3User005"
29
+ @user6_id = "MysqlUser006"
30
+ node_class_id1 = "TinkitInfoNode#{@user1_id}"
31
+ node_class_id2 = "TinkitInfoNode#{@user2_id}"
32
+ node_class_id3 = "TinkitFile#{@user3_id}"
33
+ node_class_id4 = "TinkitFile#{@user4_id}"
34
+ node_class_id5 = "TinkitSdbS3#{@user5_id}"
35
+ node_class_id6 = "MysqlUser006#{@user6_id}"
36
+ node_env1 = NodeHelper.env_builder("couchrest", node_class_id1, @user1_id, CouchDB.uri, CouchDB.host)
37
+ node_env2 = NodeHelper.env_builder("couchrest", node_class_id2, @user2_id, CouchDB.uri, CouchDB.host)
38
+ node_env3 = NodeHelper.env_builder("filesystem", node_class_id3, @user3_id, FileSystem1)
39
+ node_env4 = NodeHelper.env_builder("filesystem", node_class_id4, @user4_id, FileSystem2)
40
+ node_env5 = NodeHelper.env_builder("sdb_s3", node_class_id5, @user5_id, "MyDomain")
41
+ node_env6 = NodeHelper.env_builder("mysql", node_class_id6, @user6_id, "MyTable")
42
+ #node_env2 = CouchRestNodeHelpers.env_builder(node_class_id2, CouchDB2, @user2_id)
43
+ #node_env3 = FileSystemNodeHelpers.env_builder(node_class_id3, FileSystem1, @user3_id)
44
+ #node_env4 = FileSystemNodeHelpers.env_builder(node_class_id4, FileSystem2, @user4_id)
45
+ User1Class = TinkitNodeFactory.make(node_env1)
46
+ User2Class = TinkitNodeFactory.make(node_env2)
47
+ User3Class = TinkitNodeFactory.make(node_env3)
48
+ User4Class = TinkitNodeFactory.make(node_env4)
49
+ User5Class = TinkitNodeFactory.make(node_env5)
50
+ User6Class = TinkitNodeFactory.make(node_env6)
51
+
52
+ #User5Class (AWS) is quirky and slow due to aws, add only when needed
53
+ ClassesToTest = [User1Class, User2Class, User3Class, User4Class, User6Class]
54
+ end
55
+
56
+ describe TinkitNodeFactory, "Making the Class" do
57
+ include MakeUserClasses
58
+
59
+ before(:each) do
60
+ @user_classes = ClassesToTest
61
+ end
62
+
63
+ after(:each) do
64
+ @user_classes.each do |user_class|
65
+ user_class.destroy_all
66
+ end
67
+ end
68
+
69
+ it "should initialize user docs properly" do
70
+ user_docs = {}
71
+ #test
72
+ @user_classes.each do |user_class|
73
+ #TODO: Fix Filesystem so we don't have to do this
74
+ my_cat_data = "#{user_class.name.gsub("::","_")}_data"
75
+ user_docs[user_class] = user_class.new({:my_category => my_cat_data})
76
+ end
77
+ #user2_doc = @user2_class.new({:my_category => "user2_data"})
78
+
79
+ #check results
80
+ user_docs.each do |user_class, user_node|
81
+ my_cat_data = "#{user_class.name.gsub("::","_")}_data"
82
+ user_node.my_category.should == my_cat_data
83
+ end
84
+ #user1_doc.my_category.should == "user1_data"
85
+ #user2_doc.my_category.should == "user2_data"
86
+
87
+ #users should be in different databases
88
+ #raise @user_classes.inspect
89
+ couchrest_users = @user_classes.select{|u| u.to_s =~ /TinkitInfoNode/}
90
+ couchrest_users.size.should == 2
91
+ user0_db = couchrest_users[0].myGlueEnv.moab_data[:db]
92
+ user1_db = couchrest_users[1].myGlueEnv.moab_data[:db]
93
+ user0_db.should_not == user1_db
94
+
95
+ #users should be in different directories
96
+ filesystem_users = @user_classes.select{|u| u.to_s =~ /TinkitFile/}
97
+ filesystem_users.size.should == 2
98
+ user_dirs = filesystem_users.map{|f| f.myGlueEnv.user_datastore_location}
99
+ user_dirs[0].should_not == user_dirs[1]
100
+ end
101
+ end
102
+
103
+ describe TinkitNodeFactory, "Basic Operations" do
104
+ include MakeUserClasses
105
+ include NodeHelpers
106
+
107
+ before(:each) do
108
+ @user_classes = ClassesToTest
109
+ end
110
+
111
+ after(:each) do
112
+ @user_classes.each do |user_class|
113
+ user_class.destroy_all
114
+ end
115
+ end
116
+
117
+ it "should initialize correctly with no nodes" do
118
+ #check initial conditions
119
+ @user_classes.each do |user_class|
120
+ user_class.all.size.should == 0
121
+ end
122
+ #test
123
+ default_docs = []
124
+ @user_classes.each do |user_class|
125
+ default_docs << user_class.new(get_default_params)
126
+ end
127
+ #check results
128
+ default_docs.each do |default_doc|
129
+ default_doc.my_category.should == get_default_params[:my_category]
130
+ default_doc.parent_categories.should == get_default_params[:parent_categories]
131
+ default_doc.description.should == get_default_params[:description]
132
+ end
133
+ #we haven't saved it to the database yet
134
+ @user_classes.each do |user_class|
135
+ user_class.all.size.should == 0
136
+ end
137
+ end
138
+
139
+
140
+ #TODO: Add full collections testing
141
+ #FIXME: This test is not very robust
142
+ it "should be able to retrieve all records" do
143
+ user_docs = {}
144
+
145
+ @user_classes.each do |user_class|
146
+
147
+ #TODO: fix filesystem to handle strange characters
148
+ #my_cat_data = "#{user_class.name.gsub("::","_")}_data2"
149
+ my_cat_data = "#{user_class.name}_data2"
150
+ #my_cat_data = "flat_test"
151
+ user_docs[user_class] = user_class.new({:my_category => my_cat_data})
152
+ end
153
+
154
+
155
+ #user1_doc = @user1_class.new({:my_category => "user1_data"})
156
+ #user2_doc = @user2_class.new({:my_category => "user2_data"})
157
+ user_docs.each do |user_class, node|
158
+ #p node.my_category
159
+ #raise "::'s" if node.my_category =~ /::/
160
+ node.__save
161
+ end
162
+ #user1_doc.__save
163
+ #user2_doc.__save
164
+ #@user1_class.all.first.my_category.should == "user1_data"
165
+ #@user2_class.all.first.my_category.should == "user2_data"
166
+
167
+ @user_classes.each do |user_class|
168
+ my_cat_data = "#{user_class.name}_data2"
169
+ user_class.all.first.my_category.should == my_cat_data
170
+ end
171
+ end
172
+
173
+ it "should not save if required fields don't exist" do
174
+ #set initial condition
175
+ orig_size = {}
176
+ @user_classes.each do |user_class|
177
+ orig_size[user_class] = user_class.all.size
178
+ lambda { user_class.new(:parent_categories => ['no_my_category'],
179
+ :description => 'some description',
180
+ :file_metadata => {})
181
+ }.should raise_error(ArgumentError)
182
+ end
183
+
184
+ @user_classes.each do |user_class|
185
+ user_class.all.size.should == orig_size[user_class]
186
+ end
187
+ end
188
+
189
+ it "should save" do
190
+ #set initial conditions
191
+ orig_size = {}
192
+ docs_params = {}
193
+ docs_to_save = {}
194
+ @user_classes.each do |user_class|
195
+ orig_size[user_class] = user_class.all.size
196
+ docs_params[user_class] = get_default_params.merge({:my_category => 'save_test'})
197
+ docs_to_save[user_class] = make_doc_no_attachment(user_class, docs_params[user_class].dup)
198
+ end
199
+
200
+ #test
201
+ docs_to_save.each do |user_class, doc_to_save|
202
+ doc_to_save.__save
203
+ end
204
+
205
+ #check results
206
+ @user_classes.each do |user_class|
207
+ docs_params[user_class].keys.each do |param|
208
+ persist_layer_key = user_class.myGlueEnv.persist_layer_key
209
+ doc_id = docs_to_save[user_class]._model_metadata[persist_layer_key]
210
+ #no longer just db, any persistent layer
211
+ doc_from_db = user_class.get(doc_id)
212
+ db_param = doc_from_db.__send__(param)
213
+ docs_to_save[user_class]._user_data[param].should == db_param
214
+ #test accessor method
215
+ docs_to_save[user_class].__send__(param).should == db_param
216
+ end
217
+ end
218
+
219
+ @user_classes.each do |user_class|
220
+ user_class.all.size.should == orig_size[user_class] + 1
221
+ end
222
+ end
223
+
224
+ #adding categories
225
+ it "should add a single category (and add the property :parent_categories) for an initial category setting for a new doc" do
226
+ #set initial conditions
227
+ orig_parent_cats = {}
228
+ doc_params = {}
229
+ initial_revs = {}
230
+ aftersave_revs = {}
231
+ docs_with_new_parent_cat = {}
232
+ @user_classes.each do |user_class|
233
+ orig_parent_cats[user_class] = ['old parent cat']
234
+ new_params = get_default_params.merge({:my_category => "cat_test#{(user_class.hash).to_s}", :parent_categories => orig_parent_cats[user_class]})
235
+ doc_params[user_class] = new_params
236
+ docs_with_new_parent_cat[user_class] = make_doc_no_attachment(user_class, doc_params[user_class])
237
+ initial_revs[user_class] = docs_with_new_parent_cat[user_class]._model_metadata[:_rev]
238
+ #puts "#{user_class.inspect} rev: #{initial_revs[user_class].inspect}"
239
+ end
240
+ new_cat = 'new parent cat'
241
+
242
+ #test
243
+ @user_classes.each do |user_class|
244
+ docs_with_new_parent_cat[user_class].parent_categories_add(new_cat)
245
+ aftersave_revs[user_class] = docs_with_new_parent_cat[user_class]._model_metadata[:_rev]
246
+ #puts "AS: #{user_class.inspect} rev: #{aftersave_revs[user_class].inspect}"
247
+ end
248
+
249
+ #check results
250
+ @user_classes.each do |user_class|
251
+ #check doc in memory
252
+ docs_with_new_parent_cat[user_class].parent_categories.should include new_cat
253
+ #check database
254
+ doc_params[user_class].keys.each do |param|
255
+ persist_layer_key = user_class.myGlueEnv.persist_layer_key
256
+ node = docs_with_new_parent_cat[user_class]
257
+ node_id = node._model_metadata[persist_layer_key]
258
+ model_node = node.class.get(node_id)
259
+ db_param = model_node.__send__(param.to_sym)
260
+ docs_with_new_parent_cat[user_class]._user_data[param].should == db_param
261
+ #test accessor method
262
+ docs_with_new_parent_cat[user_class].__send__(param).should == db_param
263
+ end
264
+ end
265
+ end
266
+
267
+ it "should add categories to existing categories and existing doc" do
268
+ #set initial conditions
269
+ orig_parent_cats = {}
270
+ doc_params = {}
271
+ doc_existing_new_parent_cats = {}
272
+ @user_classes.each do |user_class|
273
+ orig_parent_cats[user_class] = ["#{user_class.hash.to_s}-orig_cat1", "#{user_class.hash.to_s}-orig_cat2"]
274
+ doc_params[user_class] = get_default_params.merge({:my_category => "#{user_class.hash.to_s}-cat_test2",
275
+ :parent_categories => orig_parent_cats[user_class]})
276
+ doc_existing_new_parent_cats[user_class] = make_doc_no_attachment(user_class, doc_params[user_class])
277
+ doc_existing_new_parent_cats[user_class].__save
278
+ end
279
+ #verify initial conditions
280
+ @user_classes.each do |user_class|
281
+ persist_layer_key = user_class.myGlueEnv.persist_layer_key
282
+ doc_params[user_class].keys.each do |param|
283
+ doc_id = doc_existing_new_parent_cats[user_class]._model_metadata[persist_layer_key]
284
+ db_doc = user_class.get(doc_id)
285
+ #raise doc_id unless db_doc #._model_metadata.inspect
286
+ db_param = db_doc._user_data[param]
287
+ doc_existing_new_parent_cats[user_class]._user_data[param].should == db_param
288
+ #test accessor method
289
+ doc_existing_new_parent_cats[user_class].__send__(param).should == db_param
290
+ end
291
+ end
292
+ #continue with initial conditions
293
+ new_cats = ['new_cat1', 'new cat2', 'orig_cat2']
294
+ #test
295
+ @user_classes.each do |user_class|
296
+ doc_existing_new_parent_cats[user_class].parent_categories_add(new_cats)
297
+ end
298
+ #check results
299
+ #check doc in memory
300
+ @user_classes.each do |user_class|
301
+ new_cats.each do |new_cat|
302
+ doc_existing_new_parent_cats[user_class].parent_categories.should include new_cat
303
+ end
304
+ end
305
+ #check database
306
+ parent_cats = {}
307
+ @user_classes.each do |user_class|
308
+ persist_layer_key = user_class.myGlueEnv.persist_layer_key
309
+ parent_cats[user_class] = user_class.get(doc_existing_new_parent_cats[user_class]._model_metadata[persist_layer_key]).parent_categories
310
+ new_cats.each do |cat|
311
+ parent_cats[user_class].should include cat
312
+ end
313
+ end
314
+ #check all cats are there and are unique
315
+ @user_classes.each do |user_class|
316
+ parent_cats[user_class].sort.should == (orig_parent_cats[user_class] + new_cats).uniq.sort
317
+ end
318
+ end
319
+
320
+ it "should be able to remove parent categories" do
321
+ orig_parent_cats = {}
322
+ doc_params = {}
323
+ doc_remove_parent_cats = {}
324
+ #set initial conditions
325
+ @user_classes.each do |user_class|
326
+ orig_parent_cats[user_class] = ['orig_cat3', 'orig_cat4', 'del_this_cat1', "del_this_cat2-#{user_class.to_s}"]
327
+ doc_params[user_class] = get_default_params.merge({:my_category => 'cat_test3', :parent_categories => orig_parent_cats[user_class]})
328
+ doc_remove_parent_cats[user_class] = make_doc_no_attachment(user_class, doc_params[user_class])
329
+ doc_remove_parent_cats[user_class].__save
330
+ end
331
+ #verify initial conditions
332
+ @user_classes.each do |user_class|
333
+ doc_params[user_class].keys.each do |param|
334
+ persist_layer_key = user_class.myGlueEnv.persist_layer_key
335
+ db_param = user_class.get(doc_remove_parent_cats[user_class]._model_metadata[persist_layer_key])._user_data[param]
336
+ doc_remove_parent_cats[user_class]._user_data[param].should == db_param
337
+ #test accessor method
338
+ doc_remove_parent_cats[user_class].__send__(param).should == db_param
339
+ end
340
+ end
341
+ #continue with initial conditions
342
+ remove_multi_cats = {}
343
+ @user_classes.each do |user_class|
344
+ remove_multi_cats[user_class] = ['del_this_cat1', "del_this_cat2-#{user_class.to_s}"]
345
+ remove_multi_cats[user_class].each do |cat|
346
+ doc_remove_parent_cats[user_class].parent_categories.should include cat
347
+ end
348
+ end
349
+
350
+ #test
351
+ @user_classes.each do |user_class|
352
+ doc_remove_parent_cats[user_class].parent_categories_subtract(remove_multi_cats[user_class])
353
+ end
354
+
355
+ #verify results
356
+ @user_classes.each do |user_class|
357
+ remove_multi_cats[user_class].each do |cat|
358
+ doc_remove_parent_cats[user_class].parent_categories.should_not include cat
359
+ end
360
+ end
361
+
362
+ cats_in_db = {}
363
+ @user_classes.each do |user_class|
364
+ persist_layer_key = user_class.myGlueEnv.persist_layer_key
365
+ doc_id = doc_remove_parent_cats[user_class]._model_metadata[persist_layer_key]
366
+ db_doc = user_class.get(doc_id)
367
+ cats_in_db[user_class] = db_doc._user_data[:parent_categories].inspect
368
+ remove_multi_cats[user_class].each do |removed_cat|
369
+ cats_in_db[user_class].should_not include removed_cat
370
+ end
371
+ end
372
+ end
373
+
374
+ it "should only have unique categories" do
375
+ #verify initial state
376
+ @user_classes.each do |user_class|
377
+ user_class.all.size.should == 0
378
+ end
379
+
380
+ orig_parent_cats = {}
381
+ doc_params = {}
382
+ doc_uniq_parent_cats = {}
383
+ orig_sizes = {}
384
+ new_cats = {}
385
+ expected_sizes = {}
386
+ #set initial conditions
387
+ @user_classes.each do |user_class|
388
+ orig_parent_cats[user_class] = ['dup cat1', 'dup cat2', 'uniq cat1']
389
+ doc_params[user_class] = get_default_params.merge({:my_category => 'cat_test3', :parent_categories => orig_parent_cats[user_class]})
390
+ doc_uniq_parent_cats[user_class] = make_doc_no_attachment(user_class, doc_params[user_class])
391
+ doc_uniq_parent_cats[user_class].__save
392
+ orig_sizes[user_class] = doc_uniq_parent_cats[user_class].parent_categories.size
393
+ new_cats[user_class] = ['dup cat1', 'dup cat2', 'uniq_cat2']
394
+ expected_sizes[user_class] = orig_sizes[user_class] + 1 #uniq_cat2
395
+ end
396
+
397
+ #test
398
+ @user_classes.each do |user_class|
399
+ doc_uniq_parent_cats[user_class].parent_categories_add(new_cats[user_class])
400
+ end
401
+
402
+ #verify results
403
+ records = {}
404
+ @user_classes.each do |user_class|
405
+ expected_sizes[user_class].should == doc_uniq_parent_cats[user_class].parent_categories.size
406
+ persist_layer_key = user_class.myGlueEnv.persist_layer_key
407
+ doc_id = doc_uniq_parent_cats[user_class]._model_metadata[persist_layer_key]
408
+ db_doc = user_class.get(doc_id)
409
+ #puts "Doc ID searched: #{doc_id.inspect}"
410
+ db_doc._user_data[:parent_categories].sort.should == doc_uniq_parent_cats[user_class].parent_categories.sort
411
+ #records[user_class] = user_class.call_view(:parent_categories, 'dup cat2')
412
+ records[user_class] = user_class.find_nodes_where(:parent_categories, :contains, 'dup cat2')
413
+ records[user_class].size.should == 1
414
+ records[user_class].first.parent_categories.should include 'dup cat2'
415
+ end
416
+ end
417
+
418
+ it "should allow new data fields to be added to the data structure" do
419
+ #set initial conditions
420
+ orig_parent_cats = {}
421
+ node_params = {}
422
+ nodes = {}
423
+ @user_classes.each do |user_class|
424
+ orig_parent_cats[user_class] = ['dyn data parent cat']
425
+ new_params = get_default_params.merge({:my_category => "cat_test#{(user_class.hash).to_s}",
426
+ :parent_categories => orig_parent_cats[user_class] })
427
+ node_params[user_class] = new_params
428
+ nodes[user_class] = make_doc_no_attachment(user_class, node_params[user_class])
429
+ end
430
+ new_key_field = :links
431
+ #test for new field
432
+ @user_classes.each do |user_class|
433
+ nodes[user_class].__set_userdata_key(new_key_field, nil)
434
+ end
435
+ @user_classes.each do |user_class|
436
+ #verify new field exists and works
437
+ nodes[user_class].respond_to?(new_key_field).should == true
438
+ nodes[user_class].__send__(new_key_field).should == nil
439
+ #initial conditions for adding data
440
+ #NOTE: :links has a special operations for add and subtract
441
+ #defined in the Node Operations (see midas directory)
442
+ new_data = {:link_name => ["blah"], :link_src =>["http:\\\\to.somewhere.blah"]}
443
+ add_method = "#{new_key_field}_add".to_sym
444
+ link_add_op = DefaultOpSets::KListAddOpDef
445
+ #test adding new data
446
+ nodes[user_class].__send__(add_method, new_data)
447
+ #verify new data was added appropriately
448
+ updated_data = nodes[user_class].__send__(new_key_field)
449
+ updated_data.should == new_data #old links version it would not be equal
450
+ magically_transformed_data = link_add_op.call(nil, new_data)[:update_this]
451
+ magically_transformed_data.should == updated_data #added to a list
452
+ end
453
+ end
454
+
455
+ it "should be able to delete basic nodes" do
456
+ #set initial conditions
457
+ orig_size = {}
458
+ docs_params = {}
459
+ docs_to_save = {}
460
+ docs_to_delete = {}
461
+ @user_classes.each do |user_class|
462
+ orig_size[user_class] = user_class.all.size
463
+ docs_params[user_class] = get_default_params.merge({:my_category => 'save_test'})
464
+ docs_to_save[user_class] = make_doc_no_attachment(user_class, docs_params[user_class].dup)
465
+ docs_to_save[user_class].__save
466
+ end
467
+ @user_classes.each do |user_class|
468
+ orig_size[user_class] = user_class.all.size
469
+ docs_params[user_class] = get_default_params.merge({:my_category => 'delete_test'})
470
+ docs_to_delete[user_class] = make_doc_no_attachment(user_class, docs_params[user_class].dup)
471
+ docs_to_delete[user_class].__save
472
+ end
473
+ #verify initial conditions
474
+ @user_classes.each do |user_class|
475
+ docs = user_class.all #docs from persistent layer
476
+ docs.size.should == 2
477
+ my_cats = ['save_test', 'delete_test']
478
+ #verifies all docs exist
479
+ docs.each do |doc|
480
+ my_cats.include?(doc.my_category).should == true
481
+ my_cats.delete(doc.my_category)
482
+ end#each doc
483
+ end#each user_class
484
+
485
+ #test
486
+ @user_classes.each do |user_class|
487
+ docs_to_delete[user_class].__destroy_node
488
+ end
489
+
490
+
491
+ #verify
492
+ @user_classes.each do |user_class|
493
+ docs = user_class.all #docs from persistent layer
494
+ docs.size.should == 1
495
+
496
+ #verifies all docs exist
497
+ docs.each do |doc|
498
+ doc.my_category.should == 'save_test'
499
+ doc.my_category.should_not == 'delete_test'
500
+ end#each doc
501
+ end#each user_class
502
+ end#it
503
+
504
+ #it should distinguish between user model data and the persistence layer data
505
+ end
506
+
507
+ describe TinkitNodeFactory, "Document Operations with Attachments" do
508
+ include MakeUserClasses
509
+ include NodeHelpers
510
+ #include UserNodeSpecHelpers
511
+
512
+ before(:all) do
513
+ @test_files = TinkitFixtures.test_files
514
+ end
515
+
516
+ before(:each) do
517
+ @user_classes = ClassesToTest
518
+ end
519
+
520
+ after(:each) do
521
+ @user_classes.each do |user_class|
522
+ user_class.destroy_all
523
+ end
524
+ end
525
+
526
+ #This spec may not be needed anymore. Originally the models were defining
527
+ #the files manager's methods, but that's been moved into the base node
528
+ #so this test really only is a flag to an interface change (which may be more
529
+ #annoying than userful)
530
+ it "has a file manager associated with its nodes" do
531
+ _files_mgr_methods = [:add_files, :add_raw_data, :subtract_files,
532
+ :get_raw_data, :get_attachments_metadata]
533
+ #set initial conditions
534
+ orig_parent_cats = {}
535
+ node_params = {}
536
+ nodes = {}
537
+ @user_classes.each do |user_class|
538
+ orig_parent_cats[user_class] = ['old parent cat']
539
+ new_params = get_default_params.merge({:my_category => "cat_test#{(user_class.hash).to_s}",
540
+ :parent_categories => orig_parent_cats[user_class] })
541
+ node_params[user_class] = new_params
542
+ nodes[user_class] = make_doc_no_attachment(user_class, node_params[user_class])
543
+ end
544
+
545
+ responds_to_method = {}
546
+ should_respond_to_method = {}
547
+ @user_classes.each do |user_class|
548
+ _files_mgr_methods.each do |meth|
549
+ responds_to_method[meth] = nodes[user_class]._files_mgr.respond_to?(meth)
550
+ should_respond_to_method[meth] = true
551
+ #nodes[user_class]._files_mgr.respond_to?(meth).should == true
552
+ end
553
+ responds_to_method.should == should_respond_to_method
554
+ end
555
+ end
556
+
557
+ it "should save data files as an attachment with metadata" do
558
+ #initial conditions (attachment file)
559
+ #TODO: vary filename by user
560
+ test_filename = @test_files['binary_data_spaces_in_fname_pptx']
561
+ test_basename = File.basename(test_filename)
562
+ raise "can't find file #{test_filename.inspect}" unless File.exists?(test_filename)
563
+ #intial conditions (doc)
564
+ parent_cats = {}
565
+ doc_params = {}
566
+ basic_docs = {}
567
+ @user_classes.each do |user_class|
568
+ parent_cats[user_class] = ['docs with attachments']
569
+ doc_params[user_class] = get_default_params.merge({:my_category => 'doc_w_att1', :parent_categories => parent_cats[user_class]})
570
+ basic_docs[user_class] = make_doc_no_attachment(user_class, doc_params[user_class])
571
+ basic_docs[user_class].__save #doc must be saved before we can attach
572
+ end
573
+
574
+ #check initial conditions
575
+ @user_classes.each do |user_class|
576
+ persist_layer_key = user_class.myGlueEnv.persist_layer_key
577
+ doc_id = basic_docs[user_class]._model_metadata[persist_layer_key]
578
+ db_doc = user_class.get(doc_id)
579
+ db_doc._model_metadata['attachment_doc_id'].should == nil
580
+ #(user_class.get(basic_docs[user_class]._model_metadata['_id'])['attachment_doc_id']).should == nil
581
+ end
582
+ #test
583
+ #using just the filename
584
+ file_data = {:src_filename => test_filename}
585
+ @user_classes.each do |user_class|
586
+ basic_docs[user_class].files_add(file_data)
587
+ end
588
+
589
+ #check results
590
+ att_doc_ids = {}
591
+ att_docs = {}
592
+ @user_classes.each do |user_class|
593
+ persist_layer_key = user_class.myGlueEnv.persist_layer_key
594
+ id_of_doc_w_att = basic_docs[user_class]._model_metadata[persist_layer_key]
595
+ doc_w_att = user_class.get(id_of_doc_w_att)
596
+ doc_w_att.attached_files.size.should == 1
597
+ doc_w_att._user_data.should == basic_docs[user_class]._user_data
598
+ doc_w_att.attached_files.should == basic_docs[user_class].attached_files
599
+ end
600
+ end
601
+
602
+ it "should cleanly remove all attachments" do
603
+ #initial conditions
604
+ #TODO: vary filename by user
605
+ test_filename = @test_files['binary_data_spaces_in_fname_pptx']
606
+ parent_cats = {}
607
+ doc_params = {}
608
+ basic_docs = {}
609
+ @user_classes.each do |user_class|
610
+ parent_cats[user_class] = ['docs with attachments']
611
+ doc_params[user_class] = get_default_params.merge({:my_category => 'doc_w_att1', :parent_categories => parent_cats[user_class]})
612
+ basic_docs[user_class] = make_doc_w_attach_from_file(user_class, test_filename, doc_params[user_class])
613
+ end
614
+ #verify initial conditions
615
+ att_doc_ids = {}
616
+ att_files = {}
617
+ test_basename = File.basename(test_filename)
618
+ @user_classes.each do |user_class|
619
+ persist_layer_key = user_class.myGlueEnv.persist_layer_key
620
+ doc_id = basic_docs[user_class]._model_metadata[persist_layer_key]
621
+ db_doc = user_class.get(doc_id)
622
+ #raise db_doc.attachment_doc_id.inspect
623
+ att_files[user_class] = db_doc.attached_files
624
+ att_files[user_class].size.should == 1
625
+ att_files[user_class].first.should == TkEscape.escape(test_basename)
626
+ end
627
+ #test
628
+ attachment_name = test_basename
629
+ @user_classes.each do |user_class|
630
+ persist_layer_key = user_class.myGlueEnv.persist_layer_key
631
+ doc = user_class.get(basic_docs[user_class]._model_metadata[persist_layer_key])
632
+ doc.files_remove_all
633
+ end
634
+ #check results
635
+ #TODO: Highlight the fact that basic doc still has attachments in memory?
636
+ @user_classes.each do |user_class|
637
+ persist_layer_key = user_class.myGlueEnv.persist_layer_key
638
+ doc_id = basic_docs[user_class]._model_metadata[persist_layer_key]
639
+ db_doc = user_class.get(doc_id)
640
+ db_doc.attached_files.should == nil
641
+ end
642
+ end
643
+
644
+ it "should cleanly remove a single attachment" do
645
+ #initial conditions
646
+ #TODO: vary filename by user
647
+ test_filename1 = @test_files['binary_data_spaces_in_fname_pptx']
648
+ test_filename2 = @test_files['binary_data2_docx']
649
+ parent_cats = {}
650
+ doc_params = {}
651
+ basic_docs = {}
652
+ @user_classes.each do |user_class|
653
+ parent_cats[user_class] = ['docs with attachments']
654
+ doc_params[user_class] = get_default_params.merge({:my_category => 'doc_w_att2', :parent_categories => parent_cats[user_class]})
655
+ basic_docs[user_class] = make_doc_w_attach_from_file(user_class, test_filename1, doc_params[user_class])
656
+ basic_docs[user_class].files_add(:src_filename => test_filename2)
657
+ end
658
+
659
+ test_basename1 = File.basename(test_filename1)
660
+ test_basename2 = File.basename(test_filename2)
661
+ @user_classes.each do |user_class|
662
+ persist_layer_key = user_class.myGlueEnv.persist_layer_key
663
+ doc_id = basic_docs[user_class]._model_metadata[persist_layer_key]
664
+ db_doc = user_class.get(doc_id)
665
+ db_doc.attached_files.size.should == 2
666
+ end
667
+ #test
668
+ attachment_name1 = TkEscape.escape(test_basename1)
669
+ attachment_name2 = TkEscape.escape(test_basename2)
670
+ @user_classes.each do |user_class|
671
+ persist_layer_key = user_class.myGlueEnv.persist_layer_key
672
+ doc = user_class.get(basic_docs[user_class]._model_metadata[persist_layer_key])
673
+ doc.files_subtract(attachment_name1)
674
+ end
675
+ #check results
676
+ @user_classes.each do |user_class|
677
+ persist_layer_key = user_class.myGlueEnv.persist_layer_key
678
+ doc_id = basic_docs[user_class]._model_metadata[persist_layer_key]
679
+ db_doc = user_class.get(doc_id)
680
+ db_doc.attached_files.size.should == 1
681
+ db_doc.attached_files.first.should == TkEscape.escape(attachment_name2)
682
+ end
683
+ #delete again so that all attachments are deleted
684
+ @user_classes.each do |user_class|
685
+ persist_layer_key = user_class.myGlueEnv.persist_layer_key
686
+ doc = user_class.get(basic_docs[user_class]._model_metadata[persist_layer_key])
687
+ doc.files_subtract(attachment_name2)
688
+ end
689
+ #check results
690
+ @user_classes.each do |user_class|
691
+ persist_layer_key = user_class.myGlueEnv.persist_layer_key
692
+ doc_id = basic_docs[user_class]._model_metadata[persist_layer_key]
693
+ db_doc = user_class.get(doc_id)
694
+ db_doc.attached_files.size.should == 0
695
+ end
696
+ end
697
+
698
+ it "should list attachment list" do
699
+ #initial conditions
700
+ #TODO: vary filename by user, support multiple attachments
701
+ test_filename = @test_files['binary_data_spaces_in_fname_pptx']
702
+ parent_cats = {}
703
+ doc_params = {}
704
+ basic_docs = {}
705
+ @user_classes.each do |user_class|
706
+ parent_cats[user_class] = ['docs with attachments']
707
+ doc_params[user_class] = get_default_params.merge({:my_category => 'doc_w_att1', :parent_categories => parent_cats[user_class]})
708
+
709
+ basic_docs[user_class] = make_doc_w_attach_from_file(user_class, test_filename, doc_params[user_class])
710
+ end
711
+ #verify initial conditions
712
+ att_doc_ids = {}
713
+ att_docs = {}
714
+ test_basename = File.basename(test_filename)
715
+ @user_classes.each do |user_class|
716
+ persist_layer_key = user_class.myGlueEnv.persist_layer_key
717
+ doc_id = basic_docs[user_class]._model_metadata[persist_layer_key]
718
+ db_doc = user_class.get(doc_id)
719
+ db_doc.attached_files.size.should == 1
720
+ db_doc.attached_files.first.should == TkEscape.escape(test_basename)
721
+ end
722
+ #test
723
+ attachment_names = {}
724
+ @user_classes.each do |user_class|
725
+ persist_layer_key = user_class.myGlueEnv.persist_layer_key
726
+ doc_id = basic_docs[user_class]._model_metadata[persist_layer_key]
727
+ db_doc = user_class.get(doc_id)
728
+ attachment_names[user_class] = db_doc.attached_files
729
+ end
730
+ #check results
731
+ @user_classes.each do |user_class|
732
+ attachment_names[user_class].size.should == 1
733
+ attachment_names[user_class].first.should == TkEscape.escape(test_basename)
734
+ end
735
+ end
736
+
737
+ it "should avoid creating hellish names when escaping and unescaping" do
738
+ #initial conditions (attachment file)
739
+ #this file has spaces in the file name
740
+ test_filename = @test_files['strange_characters_in_file_name']
741
+ test_basename = File.basename(test_filename)
742
+ raise "can't find file #{test_filename.inspect}" unless File.exists?(test_filename)
743
+ #intial conditions (doc)
744
+ parent_cats = {}
745
+ doc_params = {}
746
+ basic_docs = {}
747
+ @user_classes.each do |user_class|
748
+ parent_cats[user_class] = ['text file', 'test file']
749
+ doc_params[user_class] = get_default_params.merge({:my_category => 'strange_characters', :parent_categories => parent_cats[user_class]})
750
+ basic_docs[user_class] = make_doc_no_attachment(user_class, doc_params[user_class])
751
+ basic_docs[user_class].__save #doc must be saved before we can attach
752
+ end
753
+ #test
754
+ @user_classes.each do |user_class|
755
+ basic_docs[user_class].files_add(:src_filename => test_filename)
756
+ end
757
+ #check results
758
+ @user_classes.each do |user_class|
759
+ persist_layer_key = user_class.myGlueEnv.persist_layer_key
760
+ doc_id = basic_docs[user_class]._model_metadata[persist_layer_key]
761
+ db_doc = user_class.get(doc_id)
762
+ db_doc.attached_files.first.should == TkEscape.escape(test_basename)
763
+ end
764
+ end
765
+
766
+ it "should create an attachment from raw data" do
767
+ #TODO organize the test and chekcing results sections
768
+ #set initial conditions
769
+ data_file = @test_files['binary_data3_pptx'] #@test_files['strange_characters_in_file_name']
770
+ binary_data = File.open(data_file, 'rb'){|f| f.read}
771
+ binary_data_content_type = "application/vnd.openxmlformats-officedocument.presentationml.presentation"
772
+ attach_name = File.basename(data_file)
773
+ #intial conditions (doc)
774
+ parent_cats = {}
775
+ doc_params = {}
776
+ basic_docs = {}
777
+ metadata = {}
778
+ att_doc_ids = {}
779
+ att_docs = {}
780
+ @user_classes.each do |user_class|
781
+ parent_cats[user_class] = ['docs with attachments']
782
+ doc_params[user_class] = get_default_params.merge({:my_category => 'doc_w_raw_data_att', :parent_categories => parent_cats[user_class]})
783
+ basic_docs[user_class] = make_doc_no_attachment(user_class, doc_params[user_class])
784
+ basic_docs[user_class].__save
785
+ #test
786
+ #metadata[user_class] = basic_docs[user_class].add_raw_data(attach_name, binary_data_content_type, binary_data)
787
+ #metadata[user_class].should == ["should be the metadata for that user"]
788
+ basic_docs[user_class].add_raw_data(attach_name, binary_data_content_type, binary_data)
789
+ #verify results
790
+ persist_layer_key = user_class.myGlueEnv.persist_layer_key
791
+ doc_id = basic_docs[user_class]._model_metadata[persist_layer_key]
792
+ db_doc = user_class.get(doc_id)
793
+ db_doc.attached_files.size.should == 1
794
+ att_file = db_doc.attached_files.first
795
+ att_file.should == TkEscape.escape(attach_name)
796
+ #TODO: More rigorous testing of attached data from raw data
797
+ end
798
+ end
799
+
800
+ it "should be able to retrieve the metadata for a single attachment" do
801
+ test_filename = @test_files['simple_text_file']
802
+ test_basename = File.basename(test_filename)
803
+ parent_cats = {}
804
+ node_params = {}
805
+ basic_nodes = {}
806
+ attached_basenames = {}
807
+ raise "can't find file #{test_filename.inspect}" unless File.exists?(test_filename)
808
+ #set initial conditions
809
+ @user_classes.each do |user_class|
810
+ parent_cats[user_class] = ['nodes with attachments']
811
+ my_cat = 'doc_w_att1'
812
+ params = {:my_category => my_cat, :parent_categories => parent_cats[user_class]}
813
+ node_params[user_class] = get_default_params.merge(params)
814
+ basic_nodes[user_class] = make_doc_no_attachment(user_class, node_params[user_class])
815
+ basic_nodes[user_class].__save
816
+ basic_nodes[user_class].files_add(:src_filename => test_filename)
817
+ end
818
+ #check initial conditions
819
+ @user_classes.each do |user_class|
820
+ attached_basenames[user_class] = basic_nodes[user_class].attached_files
821
+ attached_basenames[user_class].size.should == 1
822
+ attached_basename= attached_basenames[user_class].first
823
+ attached_basename.should == TkEscape.escape(test_basename)
824
+ #test
825
+ moab_att_metadata = basic_nodes[user_class].__get_attachment_metadata(attached_basename)
826
+ md = moab_att_metadata
827
+ md[:file_modified].should == File.mtime(test_filename).to_s
828
+ md[:content_type].should =~ /text\/plain/
829
+ #TODO Test for content type match too
830
+ end
831
+ end
832
+
833
+ it "should be able to retrieve the metadata for an attachment" do
834
+ test_filename = @test_files['simple_text_file']
835
+ test_basename = File.basename(test_filename)
836
+ parent_cats = {}
837
+ node_params = {}
838
+ basic_nodes = {}
839
+ attached_basenames = {}
840
+ raise "can't find file #{test_filename.inspect}" unless File.exists?(test_filename)
841
+ #set initial conditions
842
+ @user_classes.each do |user_class|
843
+ parent_cats[user_class] = ['nodes with attachments']
844
+ my_cat = 'doc_w_att1'
845
+ params = {:my_category => my_cat, :parent_categories => parent_cats[user_class]}
846
+ node_params[user_class] = get_default_params.merge(params)
847
+ basic_nodes[user_class] = make_doc_no_attachment(user_class, node_params[user_class])
848
+ basic_nodes[user_class].__save
849
+ basic_nodes[user_class].files_add(:src_filename => test_filename)
850
+ end
851
+ #check initial conditions
852
+ @user_classes.each do |user_class|
853
+ attached_basenames[user_class] = basic_nodes[user_class].attached_files
854
+ attached_basenames[user_class].size.should == 1
855
+ attached_basename= attached_basenames[user_class].first
856
+ attached_basename.should == TkEscape.escape(test_basename)
857
+ #test
858
+ moab_att_metadata = basic_nodes[user_class].__get_attachments_metadata
859
+ md = moab_att_metadata[test_basename.to_sym]
860
+ md[:file_modified].should == File.mtime(test_filename).to_s
861
+ #TODO Test for content type match too
862
+ end
863
+ end
864
+
865
+ it "should be able to retrieve the raw data for an attachment" do
866
+ test_filename = @test_files['simple_text_file']
867
+ test_basename = File.basename(test_filename)
868
+ parent_cats = {}
869
+ node_params = {}
870
+ basic_nodes = {}
871
+ attached_basenames = {}
872
+ raise "can't find file #{test_filename.inspect}" unless File.exists?(test_filename)
873
+ #set initial conditions
874
+ @user_classes.each do |user_class|
875
+ parent_cats[user_class] = ['nodes with attachments']
876
+ my_cat = 'doc_w_att1'
877
+ params = {:my_category => my_cat, :parent_categories => parent_cats[user_class]}
878
+ node_params[user_class] = get_default_params.merge(params)
879
+ basic_nodes[user_class] = make_doc_no_attachment(user_class, node_params[user_class])
880
+ basic_nodes[user_class].__save
881
+ basic_nodes[user_class].files_add(:src_filename => test_filename)
882
+ end
883
+ #check initial conditions
884
+ @user_classes.each do |user_class|
885
+ attached_basenames[user_class] = basic_nodes[user_class].attached_files
886
+ attached_basenames[user_class].size.should == 1
887
+ attached_basename = attached_basenames[user_class].first
888
+ attached_basename.should == TkEscape.escape(test_basename)
889
+ #test
890
+ moab_raw_data = basic_nodes[user_class].get_raw_data(attached_basename)
891
+ file_raw_data = File.open(test_filename, "r"){|f| f.read}
892
+ moab_raw_data.should == file_raw_data
893
+ end
894
+ end
895
+
896
+ it "should have an export function for attachments" do
897
+ test_filename = @test_files['simple_text_file']
898
+ test_basename = File.basename(test_filename)
899
+ parent_cats = {}
900
+ node_params = {}
901
+ basic_nodes = {}
902
+ attached_basenames = {}
903
+ raise "can't find file #{test_filename.inspect}" unless File.exists?(test_filename)
904
+ #set initial conditions
905
+ @user_classes.each do |user_class|
906
+ parent_cats[user_class] = ['nodes with attachments']
907
+ my_cat = 'doc_w_att1'
908
+ params = {:my_category => my_cat, :parent_categories => parent_cats[user_class]}
909
+ node_params[user_class] = get_default_params.merge(params)
910
+ basic_nodes[user_class] = make_doc_no_attachment(user_class, node_params[user_class])
911
+ basic_nodes[user_class].__save
912
+ basic_nodes[user_class].files_add(:src_filename => test_filename)
913
+ end
914
+ #check initial conditions
915
+ @user_classes.each do |user_class|
916
+ attached_basenames[user_class] = basic_nodes[user_class].attached_files
917
+ attached_basenames[user_class].size.should == 1
918
+ attached_basename = attached_basenames[user_class].first
919
+ attached_basename.should == TkEscape.escape(test_basename)
920
+ #test
921
+ exported_att_data = basic_nodes[user_class].__export_attachment(attached_basename)
922
+ exported_att_data[:metadata].should == basic_nodes[user_class].__get_attachment_metadata(attached_basename)
923
+ exported_att_data[:raw_data].should == basic_nodes[user_class].get_raw_data(attached_basename)
924
+ end
925
+ end
926
+
927
+ it "should have an import function for attachments" do
928
+ test_filename = @test_files['simple_text_file']
929
+ test_basename = File.basename(test_filename)
930
+ parent_cats = {}
931
+ node_params = {}
932
+ basic_nodes = {}
933
+ attached_basenames = {}
934
+ att_names = {}
935
+ raise "can't find file #{test_filename.inspect}" unless File.exists?(test_filename)
936
+ #set initial conditions
937
+ @user_classes.each do |user_class|
938
+ parent_cats[user_class] = ['nodes with attachments']
939
+ my_cat = 'doc_w_att1'
940
+ params = {:my_category => my_cat, :parent_categories => parent_cats[user_class]}
941
+ node_params[user_class] = get_default_params.merge(params)
942
+ basic_nodes[user_class] = make_doc_no_attachment(user_class, node_params[user_class])
943
+ basic_nodes[user_class].__save
944
+ file_modified = File.mtime(test_filename).to_s
945
+ content_type = MimeNew.for_ofc_x(test_filename)
946
+ metadata = {:file_modified => file_modified, :content_type => content_type}
947
+ raw_data = File.open(test_filename, "r"){|f| f.read}
948
+ import_format = {:raw_data => raw_data, :metadata => metadata}
949
+ att_names[user_class] = TkEscape.escape(test_basename)
950
+ #test
951
+ basic_nodes[user_class].__import_attachment(att_names[user_class], import_format)
952
+ end
953
+ #verify results
954
+ @user_classes.each do |user_class|
955
+ basic_nodes[user_class].attached_files.size.should == 1
956
+ basic_nodes[user_class].attached_files.first.should == att_names[user_class]
957
+ end
958
+ end
959
+
960
+
961
+ it "should be able to create a node from another node" do
962
+ #other node is from the first user class
963
+ test_filename = @test_files['simple_text_file']
964
+ test_basename = File.basename(test_filename)
965
+ raise "can't find file #{test_filename.inspect}" unless File.exists?(test_filename)
966
+ #set initial conditions
967
+ parent_cats = ['nodes from other nodes']
968
+ my_cat1 = 'doc_w_att_xfer1'
969
+ my_cat2 = 'doc_w_att_xfer2'
970
+ params1 = {:my_category => my_cat1, :parent_categories => parent_cats}
971
+ params2 = {:my_category => my_cat2, :parent_categories => parent_cats}
972
+ node_params1 = get_default_params.merge(params1)
973
+ node_params2 = get_default_params.merge(params2)
974
+ #here is where we create the node from the first user class
975
+ user_class1 = @user_classes[0]
976
+ #TODO: Figure out better way that doesn't break when reconfiguring user classes
977
+ user_class2 = @user_classes[2] #||@user_classes[0]
978
+ raise "User Class is nil" unless (user_class1 && user_class2)
979
+ other_node1 = make_doc_no_attachment(user_class1, node_params1)
980
+ #plus one from a different class
981
+ other_node2 = make_doc_no_attachment(user_class2, node_params2)
982
+ other_node1.__save
983
+ other_node2.__save
984
+ other_node1.files_add(:src_filename => test_filename)
985
+ other_node2.files_add(:src_filename => test_filename)
986
+ #check initial conditions
987
+ other_node1.my_category.should == my_cat1
988
+ other_node1.attached_files.first.should == TkEscape.escape(test_basename)
989
+ other_node2.my_category.should == my_cat2
990
+ other_node2.attached_files.first.should == TkEscape.escape(test_basename)
991
+ #test
992
+ this_node = user_class2.__create_from_other_node(other_node1)
993
+ #test_inverse
994
+ this_other_node = user_class1.__create_from_other_node(other_node2)
995
+ #verify results
996
+ this_node.class.should == other_node2.class
997
+ this_node.class.should_not == other_node1.class
998
+ this_node.my_category.should == my_cat1
999
+ this_node.attached_files.first.should == TkEscape.escape(test_basename)
1000
+ #verify inverse
1001
+ this_other_node.class.should == other_node1.class
1002
+ this_other_node.class.should_not == other_node2.class
1003
+ this_other_node.my_category.should == my_cat2
1004
+ this_other_node.attached_files.first.should == TkEscape.escape(test_basename)
1005
+ end
1006
+ end
1007
+
1008
+ #Note these tests use the default categories, rather than the buf categories
1009
+ describe TinkitNodeFactory, "Portable Views" do
1010
+ include MakeUserClasses
1011
+ include NodeHelpers
1012
+
1013
+ before(:each) do
1014
+ @user_classes = [User1Class, User2Class, User3Class, User4Class]
1015
+ end
1016
+
1017
+ after(:each) do
1018
+ @user_classes.each do |user_class|
1019
+ user_class.destroy_all
1020
+ end
1021
+ end
1022
+
1023
+ it "should be able to query all records in the persitence layer" do
1024
+ user_docs = {}
1025
+ @user_classes.each do |user_class|
1026
+ node_list = [user_class.new({:my_category => "#{user_class.name}_data1"}),
1027
+ user_class.new({:my_category => "#{user_class.name}_data2"}),
1028
+ user_class.new({:my_category => "#{user_class.name}_data3"})]
1029
+ node_list.each {|n| n.__save}
1030
+ user_docs[user_class] = node_list
1031
+ #user_docs[user_class] = user_class.new({:my_category => "#{user_class.name}_data2"})
1032
+ #user_docs[user_class].__save
1033
+ end
1034
+
1035
+ #tests the "all" class method to return all fields
1036
+ @user_classes.each do |user_class|
1037
+ user_nodes = user_class.all
1038
+ user_nodes.size.should == 3
1039
+ my_categories = user_nodes.map{|n| n.my_category}
1040
+ my_categories.should include "#{user_class.name}_data1"
1041
+ my_categories.should include "#{user_class.name}_data2"
1042
+ #user_class.all.first.my_category.should == "blah" #"#{user_class.name}_data1"
1043
+ end
1044
+ end
1045
+
1046
+ =begin
1047
+ it "should be able to select certain data" do
1048
+ user_docs = {}
1049
+ @user_classes.each do |user_class|
1050
+ node_list = [user_class.new({:my_category => "#{user_class.name}_cat1", :label =>"#{user_class.name}_label"}),
1051
+ user_class.new({:my_category => "#{user_class.name}_cat2", :label =>"#{user_class.name}_label"}),
1052
+ user_class.new({:my_category => "#{user_class.name}_cat3", :other => "some other"})]
1053
+ node_list.each {|n| n.__save}
1054
+ user_docs[user_class] = node_list
1055
+ end
1056
+
1057
+ @user_classes.each do |user_class|
1058
+ user_nodes = user_class.call_view
1059
+ user_nodes.size.should == 2
1060
+ my_categories = user_nodes.map{|n| n.my_category}
1061
+ my_categories.should include "#{user_class.name}_data1"
1062
+ my_categories.should include "#{user_class.name}_data2"
1063
+ #user_class.all.first.my_category.should == "blah" #"#{user_class.name}_data1"
1064
+ end
1065
+ end
1066
+ =end
1067
+ end
1068
+
1069
+
1070
+
1071
+ describe "Cleanup" do
1072
+ include MakeUserClasses
1073
+ before(:all) do
1074
+ @test_files = TinkitFixtures.test_files
1075
+ end
1076
+
1077
+ before(:each) do
1078
+ @user_classes = [User1Class, User2Class, User3Class, User4Class]
1079
+ end
1080
+
1081
+ after(:each) do
1082
+ @user_classes.each do |user_class|
1083
+ user_class.destroy_all
1084
+ end
1085
+ end
1086
+
1087
+ #TODO: update for other persist layers
1088
+ it "should leave underlying persistence models empty" do
1089
+ #initial conditions
1090
+ #check initial conditions
1091
+ #persistence models used in specs
1092
+ CouchDB.class.should == CouchRest::Database
1093
+ File.exist?(FileSystem1).should == true
1094
+ File.exist?(FileSystem2).should == true
1095
+ #test
1096
+ @user_classes.each do |user_class|
1097
+ user_class.destroy_all
1098
+ end
1099
+ doc_ids_in_db = CouchDB.documents['rows'].map{|i| i['id'] unless i['id'] =~ /^_design/ }.compact!
1100
+ doc_ids_in_db.should == []
1101
+ Dir.glob("#{FileSystem1}/#{@user_id3}/.model/**", File::FNM_DOTMATCH).should == []
1102
+ Dir.glob("#{FileSystem2}/#{@user_id4}/.model/**", File::FNM_DOTMATCH).should == []
1103
+ #note: A failure may mean changes were made to primary keys
1104
+ end
1105
+
1106
+ end
1107
+
1108
+ #TODO: Need to test boundary conditions