sufia 6.0.0 → 6.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (290) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -5
  3. data/CONTRIBUTING.md +4 -4
  4. data/Gemfile +2 -1
  5. data/History.md +69 -0
  6. data/README.md +84 -4
  7. data/SUFIA_VERSION +1 -1
  8. data/app/assets/images/zotero.png +0 -0
  9. data/app/assets/javascripts/sufia/featured_works.js +20 -3
  10. data/app/assets/stylesheets/generic_files.css.erb +2 -2
  11. data/app/assets/stylesheets/sufia.css.scss +2 -2
  12. data/app/assets/stylesheets/sufia/_buttons.scss +2 -2
  13. data/app/assets/stylesheets/sufia/_collections.scss +4 -4
  14. data/app/assets/stylesheets/sufia/_dashboard.scss +1 -1
  15. data/app/assets/stylesheets/sufia/_file-listing.scss +3 -0
  16. data/app/assets/stylesheets/sufia/_modal.scss +4 -0
  17. data/app/assets/stylesheets/sufia/_settings.scss +4 -3
  18. data/app/assets/stylesheets/sufia/_styles.scss +4 -0
  19. data/app/controllers/admin/stats_controller.rb +68 -0
  20. data/app/controllers/api/items_controller.rb +78 -0
  21. data/app/controllers/api/zotero_controller.rb +70 -0
  22. data/app/controllers/authorities_controller.rb +6 -5
  23. data/app/controllers/concerns/sufia/batch_edits_controller_behavior.rb +2 -1
  24. data/app/controllers/concerns/sufia/breadcrumbs.rb +1 -1
  25. data/app/controllers/concerns/sufia/depositors_controller_behavior.rb +11 -0
  26. data/app/controllers/concerns/sufia/files_controller/browse_everything.rb +1 -1
  27. data/app/controllers/concerns/sufia/files_controller/local_ingest_behavior.rb +1 -1
  28. data/app/controllers/concerns/sufia/files_controller_behavior.rb +23 -11
  29. data/app/controllers/concerns/sufia/my_controller_behavior.rb +1 -7
  30. data/app/controllers/concerns/sufia/users_controller_behavior.rb +1 -2
  31. data/app/controllers/my/collections_controller.rb +1 -0
  32. data/app/controllers/my/files_controller.rb +1 -1
  33. data/app/helpers/sufia/sufia_helper_behavior.rb +28 -16
  34. data/app/models/my_search_builder.rb +4 -0
  35. data/app/search_builders/sufia/my_search_builder_behavior.rb +20 -0
  36. data/app/search_builders/sufia/search_builder.rb +1 -1
  37. data/app/views/admin/stats/index.html.erb +68 -0
  38. data/app/views/collections/_action_menu.html.erb +22 -20
  39. data/app/views/collections/_collection.html.erb +1 -1
  40. data/app/views/collections/_form_for_select_collection.html.erb +5 -3
  41. data/app/views/generic_files/_show_actions.html.erb +4 -2
  42. data/app/views/generic_files/show.html.erb +1 -1
  43. data/app/views/layouts/sufia-dashboard.html.erb +5 -4
  44. data/app/views/layouts/sufia-one-column.html.erb +2 -0
  45. data/app/views/layouts/sufia-two-column.html.erb +6 -4
  46. data/app/views/my/_facet_layout.html.erb +2 -2
  47. data/app/views/my/_facets.html.erb +4 -6
  48. data/app/views/my/index.html.erb +4 -3
  49. data/app/views/users/_edit_primary.html.erb +18 -17
  50. data/app/views/users/_follower_modal.html.erb +5 -1
  51. data/app/views/users/_following_modal.html.erb +5 -1
  52. data/app/views/users/_user_info.html.erb +6 -1
  53. data/app/views/users/_zotero.html.erb +12 -0
  54. data/config/locales/sufia.en.yml +10 -1
  55. data/config/routes.rb +23 -1
  56. data/lib/generators/sufia/admin_stat_generator.rb +17 -0
  57. data/lib/generators/sufia/install_generator.rb +8 -3
  58. data/{sufia-models/lib/generators/sufia/models/templates/config/resque_admin.rb → lib/generators/sufia/templates/sufia/stats_admin.rb} +3 -3
  59. data/lib/generators/sufia/upgrade400_generator.rb +2 -2
  60. data/lib/sufia.rb +3 -0
  61. data/lib/sufia/arkivo.rb +11 -0
  62. data/lib/sufia/arkivo/actor.rb +95 -0
  63. data/lib/sufia/arkivo/config.rb +11 -0
  64. data/lib/sufia/arkivo/create_subscription_job.rb +67 -0
  65. data/lib/sufia/arkivo/metadata_munger.rb +51 -0
  66. data/lib/sufia/arkivo/schema_validator.rb +55 -0
  67. data/lib/sufia/form_builder.rb +1 -1
  68. data/lib/sufia/inflections.rb +3 -0
  69. data/lib/sufia/version.rb +1 -1
  70. data/lib/sufia/zotero.rb +6 -0
  71. data/lib/sufia/zotero/config.rb +15 -0
  72. data/solr_conf/conf/solrconfig.xml +11 -0
  73. data/spec/controllers/admin_stats_controller_spec.rb +73 -0
  74. data/spec/controllers/api/items_controller_spec.rb +476 -0
  75. data/spec/controllers/api/zotero_controller_spec.rb +178 -0
  76. data/spec/controllers/batch_edits_controller_spec.rb +7 -0
  77. data/spec/controllers/collections_controller_spec.rb +1 -1
  78. data/spec/controllers/dashboard_controller_spec.rb +1 -1
  79. data/spec/controllers/depositors_controller_spec.rb +9 -5
  80. data/spec/controllers/generic_files_controller_spec.rb +5 -4
  81. data/spec/controllers/mailbox_controller_spec.rb +2 -2
  82. data/spec/controllers/my/collections_controller_spec.rb +1 -2
  83. data/spec/controllers/my/files_controller_spec.rb +5 -5
  84. data/spec/controllers/my/shares_controller_spec.rb +15 -3
  85. data/spec/controllers/pages_controller_spec.rb +1 -1
  86. data/spec/controllers/users_controller_spec.rb +10 -9
  87. data/spec/factories/api_items.rb +91 -0
  88. data/spec/factories/generic_files.rb +4 -0
  89. data/spec/factories/users.rb +4 -4
  90. data/spec/features/featured_item_spec.rb +26 -0
  91. data/spec/features/ingest_upload_files_spec.rb +2 -3
  92. data/spec/features/proxy_spec.rb +0 -1
  93. data/spec/helpers/permissions_helper_spec.rb +2 -2
  94. data/spec/helpers/sufia_helper_spec.rb +11 -5
  95. data/spec/inputs/select_with_help_input_spec.rb +2 -2
  96. data/spec/javascripts/helpers/.gitkeep +0 -0
  97. data/spec/javascripts/helpers/jasmine-jquery.js +832 -0
  98. data/spec/javascripts/jasmine_spec.rb +31 -0
  99. data/spec/javascripts/notify_update_link_spec.js +8 -0
  100. data/spec/javascripts/single_use_link_spec.js.coffee +23 -0
  101. data/spec/javascripts/support/jasmine.yml +124 -0
  102. data/spec/javascripts/support/jasmine_helper.rb +15 -0
  103. data/spec/javascripts/terms_of_service_spec.js.coffee +32 -0
  104. data/spec/javascripts/toggle_icon_spec.js +11 -0
  105. data/spec/jobs/active_fedora_id_based_job_spec.rb +3 -3
  106. data/spec/jobs/import_url_job_spec.rb +0 -2
  107. data/spec/lib/sufia/arkivo/actor_spec.rb +139 -0
  108. data/spec/lib/sufia/arkivo/create_subscription_job_spec.rb +54 -0
  109. data/spec/lib/sufia/arkivo/metadata_munger_spec.rb +48 -0
  110. data/spec/lib/sufia/arkivo/schema_validator_spec.rb +65 -0
  111. data/spec/lib/sufia/upload_complete_behavior_spec.rb +1 -1
  112. data/spec/lib/sufia/user_stat_importer_spec.rb +60 -0
  113. data/spec/lib/sufia/zotero/config_spec.rb +30 -0
  114. data/spec/models/collection_spec.rb +36 -7
  115. data/spec/models/file_download_stat_spec.rb +5 -5
  116. data/spec/models/file_usage_spec.rb +23 -0
  117. data/spec/models/file_view_stat_spec.rb +6 -6
  118. data/spec/models/fits_datastream_spec.rb +0 -5
  119. data/spec/models/generic_file_spec.rb +49 -14
  120. data/spec/models/local_authority_spec.rb +1 -1
  121. data/spec/models/proxy_deposit_request_spec.rb +1 -1
  122. data/spec/models/trophy_spec.rb +8 -8
  123. data/spec/models/user_spec.rb +33 -0
  124. data/spec/presenters/sufia/collection_presenter_spec.rb +1 -1
  125. data/spec/routing/api_route_spec.rb +91 -0
  126. data/spec/routing/route_spec.rb +1 -1
  127. data/spec/services/generic_file_audit_service_spec.rb +44 -8
  128. data/spec/spec_helper.rb +18 -3
  129. data/spec/support/features.rb +0 -2
  130. data/spec/support/locations.rb +0 -21
  131. data/spec/support/rake.rb +41 -0
  132. data/spec/support/selectors.rb +0 -50
  133. data/spec/tasks/rake_spec.rb +33 -12
  134. data/spec/test_app_templates/lib/generators/test_app_generator.rb +12 -0
  135. data/spec/views/admin/stats/index.html.erb_spec.rb +45 -0
  136. data/spec/views/catalog/sort_and_per_page.html.erb_spec.rb +0 -1
  137. data/spec/views/dashboard/index_spec.rb +1 -1
  138. data/spec/views/generic_file/edit.html.erb_spec.rb +1 -1
  139. data/spec/views/generic_file/show.html.erb_spec.rb +1 -3
  140. data/spec/views/users/_follower_modal.html.erb_spec.rb +44 -7
  141. data/spec/views/users/_following_modal.html.erb_spec.rb +49 -7
  142. data/spec/views/users/edit.html.erb_spec.rb +72 -0
  143. data/spec/views/users/show.html.erb_spec.rb +1 -1
  144. data/sufia.gemspec +6 -2
  145. data/tasks/sufia-user.rake +14 -0
  146. metadata +130 -156
  147. data/spec/lib/sufia/id_service_spec.rb +0 -32
  148. data/spec/services/noid_spec.rb +0 -9
  149. data/spec/support/poltergeist.rb +0 -11
  150. data/spec/support/rake_output.rb +0 -20
  151. data/sufia-models/.gitignore +0 -17
  152. data/sufia-models/Gemfile +0 -4
  153. data/sufia-models/LICENSE.md +0 -177
  154. data/sufia-models/README.md +0 -39
  155. data/sufia-models/Rakefile +0 -1
  156. data/sufia-models/app/actors/sufia/generic_file/actor.rb +0 -137
  157. data/sufia-models/app/jobs/active_fedora_id_based_job.rb +0 -22
  158. data/sufia-models/app/jobs/active_fedora_pid_based_job.rb +0 -7
  159. data/sufia-models/app/jobs/audit_job.rb +0 -62
  160. data/sufia-models/app/jobs/batch_update_job.rb +0 -72
  161. data/sufia-models/app/jobs/characterize_job.rb +0 -10
  162. data/sufia-models/app/jobs/create_derivatives_job.rb +0 -14
  163. data/sufia-models/app/jobs/import_url_job.rb +0 -52
  164. data/sufia-models/app/jobs/ingest_local_file_job.rb +0 -46
  165. data/sufia-models/app/jobs/resolrize_job.rb +0 -9
  166. data/sufia-models/app/models/batch.rb +0 -36
  167. data/sufia-models/app/models/checksum_audit_log.rb +0 -21
  168. data/sufia-models/app/models/concerns/sufia/ability.rb +0 -61
  169. data/sufia-models/app/models/concerns/sufia/collection_behavior.rb +0 -24
  170. data/sufia-models/app/models/concerns/sufia/file_stat_utils.rb +0 -35
  171. data/sufia-models/app/models/concerns/sufia/generic_file.rb +0 -25
  172. data/sufia-models/app/models/concerns/sufia/generic_file/batches.rb +0 -28
  173. data/sufia-models/app/models/concerns/sufia/generic_file/characterization.rb +0 -89
  174. data/sufia-models/app/models/concerns/sufia/generic_file/content.rb +0 -13
  175. data/sufia-models/app/models/concerns/sufia/generic_file/derivatives.rb +0 -26
  176. data/sufia-models/app/models/concerns/sufia/generic_file/export.rb +0 -343
  177. data/sufia-models/app/models/concerns/sufia/generic_file/featured.rb +0 -11
  178. data/sufia-models/app/models/concerns/sufia/generic_file/full_text_indexing.rb +0 -43
  179. data/sufia-models/app/models/concerns/sufia/generic_file/indexing.rb +0 -14
  180. data/sufia-models/app/models/concerns/sufia/generic_file/metadata.rb +0 -98
  181. data/sufia-models/app/models/concerns/sufia/generic_file/mime_types.rb +0 -69
  182. data/sufia-models/app/models/concerns/sufia/generic_file/permissions.rb +0 -11
  183. data/sufia-models/app/models/concerns/sufia/generic_file/proxy_deposit.rb +0 -31
  184. data/sufia-models/app/models/concerns/sufia/generic_file/trophies.rb +0 -14
  185. data/sufia-models/app/models/concerns/sufia/generic_file/versions.rb +0 -16
  186. data/sufia-models/app/models/concerns/sufia/generic_file/virus_check.rb +0 -37
  187. data/sufia-models/app/models/concerns/sufia/model_methods.rb +0 -20
  188. data/sufia-models/app/models/concerns/sufia/user.rb +0 -137
  189. data/sufia-models/app/models/concerns/sufia/user_usage_stats.rb +0 -15
  190. data/sufia-models/app/models/datastreams/file_content_datastream.rb +0 -4
  191. data/sufia-models/app/models/datastreams/fits_datastream.rb +0 -152
  192. data/sufia-models/app/models/domain_term.rb +0 -5
  193. data/sufia-models/app/models/featured_work.rb +0 -22
  194. data/sufia-models/app/models/file_download_stat.rb +0 -18
  195. data/sufia-models/app/models/file_usage.rb +0 -34
  196. data/sufia-models/app/models/file_view_stat.rb +0 -18
  197. data/sufia-models/app/models/follow.rb +0 -12
  198. data/sufia-models/app/models/generic_file.rb +0 -3
  199. data/sufia-models/app/models/geo_names_resource.rb +0 -18
  200. data/sufia-models/app/models/group.rb +0 -8
  201. data/sufia-models/app/models/local_authority.rb +0 -86
  202. data/sufia-models/app/models/local_authority_entry.rb +0 -3
  203. data/sufia-models/app/models/proxy_deposit_request.rb +0 -85
  204. data/sufia-models/app/models/proxy_deposit_rights.rb +0 -4
  205. data/sufia-models/app/models/single_use_link.rb +0 -42
  206. data/sufia-models/app/models/subject_local_authority_entry.rb +0 -2
  207. data/sufia-models/app/models/sufia/avatar_uploader.rb +0 -20
  208. data/sufia-models/app/models/sufia/avatar_validator.rb +0 -8
  209. data/sufia-models/app/models/sufia/collection.rb +0 -5
  210. data/sufia-models/app/models/sufia/download.rb +0 -9
  211. data/sufia-models/app/models/sufia/orcid_validator.rb +0 -12
  212. data/sufia-models/app/models/sufia/pageview.rb +0 -9
  213. data/sufia-models/app/models/trophy.rb +0 -10
  214. data/sufia-models/app/models/user_stat.rb +0 -2
  215. data/sufia-models/app/models/version_committer.rb +0 -2
  216. data/sufia-models/app/services/sufia/analytics.rb +0 -50
  217. data/sufia-models/app/services/sufia/generic_file_audit_service.rb +0 -83
  218. data/sufia-models/app/services/sufia/generic_file_indexing_service.rb +0 -12
  219. data/sufia-models/app/services/sufia/id_service.rb +0 -45
  220. data/sufia-models/app/services/sufia/noid.rb +0 -22
  221. data/sufia-models/app/services/sufia/repository_audit_service.rb +0 -9
  222. data/sufia-models/config/locales/sufia.en.yml +0 -6
  223. data/sufia-models/lib/generators/sufia/models/abstract_migration_generator.rb +0 -30
  224. data/sufia-models/lib/generators/sufia/models/cached_stats_generator.rb +0 -24
  225. data/sufia-models/lib/generators/sufia/models/fulltext_generator.rb +0 -27
  226. data/sufia-models/lib/generators/sufia/models/install_generator.rb +0 -106
  227. data/sufia-models/lib/generators/sufia/models/orcid_field_generator.rb +0 -19
  228. data/sufia-models/lib/generators/sufia/models/proxies_generator.rb +0 -24
  229. data/sufia-models/lib/generators/sufia/models/templates/app/models/collection.rb +0 -2
  230. data/sufia-models/lib/generators/sufia/models/templates/config/analytics.yml +0 -9
  231. data/sufia-models/lib/generators/sufia/models/templates/config/clamav.rb +0 -1
  232. data/sufia-models/lib/generators/sufia/models/templates/config/mailboxer.rb +0 -17
  233. data/sufia-models/lib/generators/sufia/models/templates/config/mime_types.rb +0 -6
  234. data/sufia-models/lib/generators/sufia/models/templates/config/redis.yml +0 -9
  235. data/sufia-models/lib/generators/sufia/models/templates/config/redis_config.rb +0 -32
  236. data/sufia-models/lib/generators/sufia/models/templates/config/resque-pool.yml +0 -1
  237. data/sufia-models/lib/generators/sufia/models/templates/config/resque_config.rb +0 -5
  238. data/sufia-models/lib/generators/sufia/models/templates/config/setup_mail.rb +0 -3
  239. data/sufia-models/lib/generators/sufia/models/templates/config/solrconfig.xml +0 -223
  240. data/sufia-models/lib/generators/sufia/models/templates/config/sufia.rb +0 -144
  241. data/sufia-models/lib/generators/sufia/models/templates/migrations/acts_as_follower_migration.rb +0 -17
  242. data/sufia-models/lib/generators/sufia/models/templates/migrations/add_avatars_to_users.rb +0 -15
  243. data/sufia-models/lib/generators/sufia/models/templates/migrations/add_external_key_to_content_blocks.rb +0 -6
  244. data/sufia-models/lib/generators/sufia/models/templates/migrations/add_groups_to_users.rb +0 -11
  245. data/sufia-models/lib/generators/sufia/models/templates/migrations/add_ldap_attrs_to_user.rb +0 -27
  246. data/sufia-models/lib/generators/sufia/models/templates/migrations/add_linkedin_to_users.rb +0 -5
  247. data/sufia-models/lib/generators/sufia/models/templates/migrations/add_orcid_to_users.rb +0 -5
  248. data/sufia-models/lib/generators/sufia/models/templates/migrations/add_social_to_users.rb +0 -13
  249. data/sufia-models/lib/generators/sufia/models/templates/migrations/change_audit_log_pid_to_generic_file_id.rb +0 -5
  250. data/sufia-models/lib/generators/sufia/models/templates/migrations/change_proxy_deposit_request_pid_to_generic_file_id.rb +0 -5
  251. data/sufia-models/lib/generators/sufia/models/templates/migrations/create_checksum_audit_logs.rb +0 -19
  252. data/sufia-models/lib/generators/sufia/models/templates/migrations/create_content_blocks.rb +0 -10
  253. data/sufia-models/lib/generators/sufia/models/templates/migrations/create_featured_works.rb +0 -12
  254. data/sufia-models/lib/generators/sufia/models/templates/migrations/create_file_download_stats.rb +0 -12
  255. data/sufia-models/lib/generators/sufia/models/templates/migrations/create_file_view_stats.rb +0 -12
  256. data/sufia-models/lib/generators/sufia/models/templates/migrations/create_local_authorities.rb +0 -50
  257. data/sufia-models/lib/generators/sufia/models/templates/migrations/create_proxy_deposit_requests.rb +0 -16
  258. data/sufia-models/lib/generators/sufia/models/templates/migrations/create_proxy_deposit_rights.rb +0 -11
  259. data/sufia-models/lib/generators/sufia/models/templates/migrations/create_single_use_links.rb +0 -12
  260. data/sufia-models/lib/generators/sufia/models/templates/migrations/create_tinymce_assets.rb +0 -8
  261. data/sufia-models/lib/generators/sufia/models/templates/migrations/create_trophies.rb +0 -10
  262. data/sufia-models/lib/generators/sufia/models/templates/migrations/create_user_stats.rb +0 -19
  263. data/sufia-models/lib/generators/sufia/models/templates/migrations/create_version_committers.rb +0 -15
  264. data/sufia-models/lib/generators/sufia/models/update_content_blocks_generator.rb +0 -18
  265. data/sufia-models/lib/generators/sufia/models/upgrade400_generator.rb +0 -54
  266. data/sufia-models/lib/generators/sufia/models/upgrade600_generator.rb +0 -21
  267. data/sufia-models/lib/generators/sufia/models/usagestats_generator.rb +0 -19
  268. data/sufia-models/lib/generators/sufia/models/user_stats_generator.rb +0 -31
  269. data/sufia-models/lib/sufia/messages.rb +0 -66
  270. data/sufia-models/lib/sufia/models.rb +0 -34
  271. data/sufia-models/lib/sufia/models/active_fedora/redis.rb +0 -43
  272. data/sufia-models/lib/sufia/models/active_record/redis.rb +0 -56
  273. data/sufia-models/lib/sufia/models/engine.rb +0 -79
  274. data/sufia-models/lib/sufia/models/file_content.rb +0 -6
  275. data/sufia-models/lib/sufia/models/file_content/versions.rb +0 -21
  276. data/sufia-models/lib/sufia/models/resque.rb +0 -36
  277. data/sufia-models/lib/sufia/models/stats/user_stat_importer.rb +0 -108
  278. data/sufia-models/lib/sufia/models/user_local_directory_behavior.rb +0 -29
  279. data/sufia-models/lib/sufia/models/utils.rb +0 -22
  280. data/sufia-models/lib/sufia/models/version.rb +0 -5
  281. data/sufia-models/lib/sufia/models/virus_found_error.rb +0 -4
  282. data/sufia-models/lib/sufia/permissions.rb +0 -9
  283. data/sufia-models/lib/sufia/permissions/readable.rb +0 -20
  284. data/sufia-models/lib/sufia/permissions/writable.rb +0 -74
  285. data/sufia-models/lib/tasks/batch_cleanup.rake +0 -19
  286. data/sufia-models/lib/tasks/migrate.rake +0 -21
  287. data/sufia-models/lib/tasks/resque.rake +0 -13
  288. data/sufia-models/lib/tasks/stats_tasks.rake +0 -12
  289. data/sufia-models/lib/tasks/sufia-models_tasks.rake +0 -80
  290. data/sufia-models/sufia-models.gemspec +0 -52
@@ -11,6 +11,10 @@ FactoryGirl.define do
11
11
  read_groups ["public"]
12
12
  end
13
13
 
14
+ factory :registered_file do
15
+ read_groups ["registered"]
16
+ end
17
+
14
18
  factory :fixture do
15
19
  factory :public_pdf do
16
20
  transient do
@@ -20,8 +20,8 @@ FactoryGirl.define do
20
20
  # Create examples of single file successes and failures
21
21
  (1..10).each do |number|
22
22
  file = MockFile.new(number.to_s, "Single File #{number.to_s}")
23
- User.batchuser().send_message(user, message.single_success("single-batch-success", file), message.success_subject, sanitize_text = false)
24
- User.batchuser().send_message(user, message.single_failure("single-batch-failure", file), message.failure_subject, sanitize_text = false)
23
+ User.batchuser().send_message(user, message.single_success("single-batch-success", file), message.success_subject, false)
24
+ User.batchuser().send_message(user, message.single_failure("single-batch-failure", file), message.failure_subject, false)
25
25
  end
26
26
 
27
27
  # Create examples of mulitple file successes and failures
@@ -29,8 +29,8 @@ FactoryGirl.define do
29
29
  (1..50).each do |number|
30
30
  files << MockFile.new(number.to_s, "File #{number.to_s}")
31
31
  end
32
- User.batchuser().send_message(user, message.multiple_success("multiple-batch-success", files), message.success_subject, sanitize_text = false)
33
- User.batchuser().send_message(user, message.multiple_failure("multiple-batch-failure", files), message.failure_subject, sanitize_text = false)
32
+ User.batchuser().send_message(user, message.multiple_success("multiple-batch-success", files), message.success_subject, false)
33
+ User.batchuser().send_message(user, message.multiple_failure("multiple-batch-failure", files), message.failure_subject, false)
34
34
  end
35
35
  end
36
36
 
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe "featuring items" do
4
+ context "when viewing a featured item" do
5
+ let(:user) do
6
+ u = FactoryGirl.build(:user)
7
+ u.group_list = "admin"
8
+ u.save
9
+ u
10
+ end
11
+ it "should have a working unfeature link", :js => true do
12
+ sign_in user
13
+ file = create(:public_file)
14
+ create(:featured_work, generic_file_id: file.id)
15
+ visit sufia.generic_file_path(id: file.id)
16
+
17
+ expect(page).to have_link "Unfeature"
18
+ click_link "Unfeature"
19
+
20
+ expect(page).to have_link("Feature")
21
+ expect(GenericFile.find(file.id)).not_to be_featured
22
+ click_link "Feature"
23
+ expect(page).to have_link "Unfeature"
24
+ end
25
+ end
26
+ end
@@ -18,9 +18,8 @@ describe "Uploading files via web form", :type => :feature do
18
18
  attach_file("files[]", File.dirname(__FILE__)+"/../../spec/fixtures/image.jp2")
19
19
  attach_file("files[]", File.dirname(__FILE__)+"/../../spec/fixtures/jp2_fits.xml")
20
20
  expect(page).to have_css("button#main_upload_start[disabled]")
21
- find('#main_upload_start_span').hover do
22
- expect(page).to have_content "Please accept Deposit Agreement before you can upload."
23
- end
21
+ find('#main_upload_start_span').hover
22
+ expect(page).to have_content "Please accept Deposit Agreement before you can upload."
24
23
  end
25
24
  end
26
25
  end
@@ -35,7 +35,6 @@ describe 'proxy', :type => :feature do
35
35
  test_file_path = File.expand_path('../../fixtures/small_file.txt', __FILE__)
36
36
  page.execute_script(%Q{$("input[type=file]").first().css("opacity", "1").css("-moz-transform", "none");$("input[type=file]").first().attr('id',"fileselect");})
37
37
  attach_file("fileselect", test_file_path)
38
- redirect_url = find("#redirect-loc", visible: false).text
39
38
  click_button('Start upload')
40
39
  expect(page).to have_content('Apply Metadata')
41
40
  fill_in('generic_file_title', with: 'MY Title for the World')
@@ -5,7 +5,7 @@ describe Sufia::PermissionsHelper do
5
5
  subject { helper.visibility_help }
6
6
 
7
7
  it "draws help_icon" do
8
- expect(subject).to match /data-content="<p>This setting will determine who can view your file/
8
+ expect(subject).to match(/data-content="<p>This setting will determine who can view your file/)
9
9
  expect(subject).to have_selector 'a i.help-icon'
10
10
  end
11
11
  end
@@ -14,7 +14,7 @@ describe Sufia::PermissionsHelper do
14
14
  subject { helper.share_with_help }
15
15
 
16
16
  it "draws help_icon" do
17
- expect(subject).to match /data-content="<p>You may grant &quot;View\/Download/
17
+ expect(subject).to match(/data-content="<p>You may grant &quot;View\/Download/)
18
18
  expect(subject).to have_selector 'a i.help-icon'
19
19
  end
20
20
  end
@@ -45,23 +45,23 @@ describe SufiaHelper, :type => :helper do
45
45
  let(:document) { SolrDocument.new( mime_type_tesim: 'image/jpeg', id: '1234' ) }
46
46
  it "should show the audio thumbnail" do
47
47
  rendered = helper.sufia_thumbnail_tag(document, { width: 90 })
48
- expect(rendered).to match /src="\/downloads\/1234\?file=thumbnail"/
49
- expect(rendered).to match /width="90"/
48
+ expect(rendered).to match(/src="\/downloads\/1234\?file=thumbnail"/)
49
+ expect(rendered).to match(/width="90"/)
50
50
  end
51
51
  end
52
52
  context "for an audio object" do
53
53
  let(:document) { SolrDocument.new( mime_type_tesim: 'audio/x-wave', id: '1234') }
54
54
  it "should show the audio thumbnail" do
55
55
  rendered = helper.sufia_thumbnail_tag(document, {})
56
- expect(rendered).to match /src="\/assets\/audio.png"/
56
+ expect(rendered).to match(/src="\/assets\/audio.png"/)
57
57
  end
58
58
  end
59
59
  context "for an document object" do
60
60
  let(:document) { SolrDocument.new( mime_type_tesim: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', id: '1234') }
61
61
  it "should show the default thumbnail" do
62
62
  rendered = helper.sufia_thumbnail_tag(document, { width: 90 })
63
- expect(rendered).to match /src="\/downloads\/1234\?file=thumbnail"/
64
- expect(rendered).to match /width="90"/
63
+ expect(rendered).to match(/src="\/downloads\/1234\?file=thumbnail"/)
64
+ expect(rendered).to match(/width="90"/)
65
65
  end
66
66
  end
67
67
  end
@@ -164,6 +164,12 @@ describe SufiaHelper, :type => :helper do
164
164
 
165
165
  end
166
166
 
167
+ describe '#zotero_label' do
168
+ subject { helper }
169
+
170
+ it { is_expected.to respond_to(:zotero_label) }
171
+ end
172
+
167
173
  describe "#number_of_deposits" do
168
174
  let(:conn) { ActiveFedora::SolrService.instance.conn }
169
175
  let(:user1) { User.new(email: "abc@test") }
@@ -10,7 +10,7 @@ describe 'SelectWithHelpInput', type: :input do
10
10
 
11
11
  it "should not be required by default" do
12
12
  expect(subject).to have_selector 'select'
13
- expect(subject).not_to match /required/
13
+ expect(subject).not_to match(/required/)
14
14
  end
15
15
  end
16
16
 
@@ -26,6 +26,6 @@ describe 'SelectWithHelpInput File Edit', type: :input do
26
26
 
27
27
  it "should not be required by default" do
28
28
  expect(subject).to have_selector 'select'
29
- expect(subject).not_to match /required/
29
+ expect(subject).not_to match(/required/)
30
30
  end
31
31
  end
File without changes
@@ -0,0 +1,832 @@
1
+ /*!
2
+ Jasmine-jQuery: a set of jQuery helpers for Jasmine tests.
3
+
4
+ Version 2.0.7
5
+
6
+ https://github.com/velesin/jasmine-jquery
7
+
8
+ Copyright (c) 2010-2014 Wojciech Zawistowski, Travis Jeffery
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining
11
+ a copy of this software and associated documentation files (the
12
+ "Software"), to deal in the Software without restriction, including
13
+ without limitation the rights to use, copy, modify, merge, publish,
14
+ distribute, sublicense, and/or sell copies of the Software, and to
15
+ permit persons to whom the Software is furnished to do so, subject to
16
+ the following conditions:
17
+
18
+ The above copyright notice and this permission notice shall be
19
+ included in all copies or substantial portions of the Software.
20
+
21
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
+ */
29
+
30
+ +function (window, jasmine, $) { "use strict";
31
+
32
+ jasmine.spiedEventsKey = function (selector, eventName) {
33
+ return [$(selector).selector, eventName].toString()
34
+ }
35
+
36
+ jasmine.getFixtures = function () {
37
+ return jasmine.currentFixtures_ = jasmine.currentFixtures_ || new jasmine.Fixtures()
38
+ }
39
+
40
+ jasmine.getStyleFixtures = function () {
41
+ return jasmine.currentStyleFixtures_ = jasmine.currentStyleFixtures_ || new jasmine.StyleFixtures()
42
+ }
43
+
44
+ jasmine.Fixtures = function () {
45
+ this.containerId = 'jasmine-fixtures'
46
+ this.fixturesCache_ = {}
47
+ this.fixturesPath = 'spec/javascripts/fixtures'
48
+ }
49
+
50
+ jasmine.Fixtures.prototype.set = function (html) {
51
+ this.cleanUp()
52
+ return this.createContainer_(html)
53
+ }
54
+
55
+ jasmine.Fixtures.prototype.appendSet= function (html) {
56
+ this.addToContainer_(html)
57
+ }
58
+
59
+ jasmine.Fixtures.prototype.preload = function () {
60
+ this.read.apply(this, arguments)
61
+ }
62
+
63
+ jasmine.Fixtures.prototype.load = function () {
64
+ this.cleanUp()
65
+ this.createContainer_(this.read.apply(this, arguments))
66
+ }
67
+
68
+ jasmine.Fixtures.prototype.appendLoad = function () {
69
+ this.addToContainer_(this.read.apply(this, arguments))
70
+ }
71
+
72
+ jasmine.Fixtures.prototype.read = function () {
73
+ var htmlChunks = []
74
+ , fixtureUrls = arguments
75
+
76
+ for(var urlCount = fixtureUrls.length, urlIndex = 0; urlIndex < urlCount; urlIndex++) {
77
+ htmlChunks.push(this.getFixtureHtml_(fixtureUrls[urlIndex]))
78
+ }
79
+
80
+ return htmlChunks.join('')
81
+ }
82
+
83
+ jasmine.Fixtures.prototype.clearCache = function () {
84
+ this.fixturesCache_ = {}
85
+ }
86
+
87
+ jasmine.Fixtures.prototype.cleanUp = function () {
88
+ $('#' + this.containerId).remove()
89
+ }
90
+
91
+ jasmine.Fixtures.prototype.sandbox = function (attributes) {
92
+ var attributesToSet = attributes || {}
93
+ return $('<div id="sandbox" />').attr(attributesToSet)
94
+ }
95
+
96
+ jasmine.Fixtures.prototype.createContainer_ = function (html) {
97
+ var container = $('<div>')
98
+ .attr('id', this.containerId)
99
+ .html(html)
100
+
101
+ $(document.body).append(container)
102
+ return container
103
+ }
104
+
105
+ jasmine.Fixtures.prototype.addToContainer_ = function (html){
106
+ var container = $(document.body).find('#'+this.containerId).append(html)
107
+
108
+ if (!container.length) {
109
+ this.createContainer_(html)
110
+ }
111
+ }
112
+
113
+ jasmine.Fixtures.prototype.getFixtureHtml_ = function (url) {
114
+ if (typeof this.fixturesCache_[url] === 'undefined') {
115
+ this.loadFixtureIntoCache_(url)
116
+ }
117
+ return this.fixturesCache_[url]
118
+ }
119
+
120
+ jasmine.Fixtures.prototype.loadFixtureIntoCache_ = function (relativeUrl) {
121
+ var self = this
122
+ , url = this.makeFixtureUrl_(relativeUrl)
123
+ , htmlText = ''
124
+ , request = $.ajax({
125
+ async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded
126
+ cache: false,
127
+ url: url,
128
+ dataType: 'html',
129
+ success: function (data, status, $xhr) {
130
+ htmlText = $xhr.responseText
131
+ }
132
+ }).fail(function ($xhr, status, err) {
133
+ throw new Error('Fixture could not be loaded: ' + url + ' (status: ' + status + ', message: ' + err.message + ')')
134
+ })
135
+
136
+ var scripts = $($.parseHTML(htmlText, true)).find('script[src]') || [];
137
+
138
+ scripts.each(function(){
139
+ $.ajax({
140
+ async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded
141
+ cache: false,
142
+ dataType: 'script',
143
+ url: $(this).attr('src'),
144
+ success: function (data, status, $xhr) {
145
+ htmlText += '<script>' + $xhr.responseText + '</script>'
146
+ },
147
+ error: function ($xhr, status, err) {
148
+ throw new Error('Script could not be loaded: ' + url + ' (status: ' + status + ', message: ' + err.message + ')')
149
+ }
150
+ });
151
+ })
152
+
153
+ self.fixturesCache_[relativeUrl] = htmlText;
154
+ }
155
+
156
+ jasmine.Fixtures.prototype.makeFixtureUrl_ = function (relativeUrl){
157
+ return this.fixturesPath.match('/$') ? this.fixturesPath + relativeUrl : this.fixturesPath + '/' + relativeUrl
158
+ }
159
+
160
+ jasmine.Fixtures.prototype.proxyCallTo_ = function (methodName, passedArguments) {
161
+ return this[methodName].apply(this, passedArguments)
162
+ }
163
+
164
+
165
+ jasmine.StyleFixtures = function () {
166
+ this.fixturesCache_ = {}
167
+ this.fixturesNodes_ = []
168
+ this.fixturesPath = 'spec/javascripts/fixtures'
169
+ }
170
+
171
+ jasmine.StyleFixtures.prototype.set = function (css) {
172
+ this.cleanUp()
173
+ this.createStyle_(css)
174
+ }
175
+
176
+ jasmine.StyleFixtures.prototype.appendSet = function (css) {
177
+ this.createStyle_(css)
178
+ }
179
+
180
+ jasmine.StyleFixtures.prototype.preload = function () {
181
+ this.read_.apply(this, arguments)
182
+ }
183
+
184
+ jasmine.StyleFixtures.prototype.load = function () {
185
+ this.cleanUp()
186
+ this.createStyle_(this.read_.apply(this, arguments))
187
+ }
188
+
189
+ jasmine.StyleFixtures.prototype.appendLoad = function () {
190
+ this.createStyle_(this.read_.apply(this, arguments))
191
+ }
192
+
193
+ jasmine.StyleFixtures.prototype.cleanUp = function () {
194
+ while(this.fixturesNodes_.length) {
195
+ this.fixturesNodes_.pop().remove()
196
+ }
197
+ }
198
+
199
+ jasmine.StyleFixtures.prototype.createStyle_ = function (html) {
200
+ var styleText = $('<div></div>').html(html).text()
201
+ , style = $('<style>' + styleText + '</style>')
202
+
203
+ this.fixturesNodes_.push(style)
204
+ $('head').append(style)
205
+ }
206
+
207
+ jasmine.StyleFixtures.prototype.clearCache = jasmine.Fixtures.prototype.clearCache
208
+ jasmine.StyleFixtures.prototype.read_ = jasmine.Fixtures.prototype.read
209
+ jasmine.StyleFixtures.prototype.getFixtureHtml_ = jasmine.Fixtures.prototype.getFixtureHtml_
210
+ jasmine.StyleFixtures.prototype.loadFixtureIntoCache_ = jasmine.Fixtures.prototype.loadFixtureIntoCache_
211
+ jasmine.StyleFixtures.prototype.makeFixtureUrl_ = jasmine.Fixtures.prototype.makeFixtureUrl_
212
+ jasmine.StyleFixtures.prototype.proxyCallTo_ = jasmine.Fixtures.prototype.proxyCallTo_
213
+
214
+ jasmine.getJSONFixtures = function () {
215
+ return jasmine.currentJSONFixtures_ = jasmine.currentJSONFixtures_ || new jasmine.JSONFixtures()
216
+ }
217
+
218
+ jasmine.JSONFixtures = function () {
219
+ this.fixturesCache_ = {}
220
+ this.fixturesPath = 'spec/javascripts/fixtures/json'
221
+ }
222
+
223
+ jasmine.JSONFixtures.prototype.load = function () {
224
+ this.read.apply(this, arguments)
225
+ return this.fixturesCache_
226
+ }
227
+
228
+ jasmine.JSONFixtures.prototype.read = function () {
229
+ var fixtureUrls = arguments
230
+
231
+ for(var urlCount = fixtureUrls.length, urlIndex = 0; urlIndex < urlCount; urlIndex++) {
232
+ this.getFixtureData_(fixtureUrls[urlIndex])
233
+ }
234
+
235
+ return this.fixturesCache_
236
+ }
237
+
238
+ jasmine.JSONFixtures.prototype.clearCache = function () {
239
+ this.fixturesCache_ = {}
240
+ }
241
+
242
+ jasmine.JSONFixtures.prototype.getFixtureData_ = function (url) {
243
+ if (!this.fixturesCache_[url]) this.loadFixtureIntoCache_(url)
244
+ return this.fixturesCache_[url]
245
+ }
246
+
247
+ jasmine.JSONFixtures.prototype.loadFixtureIntoCache_ = function (relativeUrl) {
248
+ var self = this
249
+ , url = this.fixturesPath.match('/$') ? this.fixturesPath + relativeUrl : this.fixturesPath + '/' + relativeUrl
250
+
251
+ $.ajax({
252
+ async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded
253
+ cache: false,
254
+ dataType: 'json',
255
+ url: url,
256
+ success: function (data) {
257
+ self.fixturesCache_[relativeUrl] = data
258
+ },
259
+ error: function ($xhr, status, err) {
260
+ throw new Error('JSONFixture could not be loaded: ' + url + ' (status: ' + status + ', message: ' + err.message + ')')
261
+ }
262
+ })
263
+ }
264
+
265
+ jasmine.JSONFixtures.prototype.proxyCallTo_ = function (methodName, passedArguments) {
266
+ return this[methodName].apply(this, passedArguments)
267
+ }
268
+
269
+ jasmine.jQuery = function () {}
270
+
271
+ jasmine.jQuery.browserTagCaseIndependentHtml = function (html) {
272
+ return $('<div/>').append(html).html()
273
+ }
274
+
275
+ jasmine.jQuery.elementToString = function (element) {
276
+ return $(element).map(function () { return this.outerHTML; }).toArray().join(', ')
277
+ }
278
+
279
+ var data = {
280
+ spiedEvents: {}
281
+ , handlers: []
282
+ }
283
+
284
+ jasmine.jQuery.events = {
285
+ spyOn: function (selector, eventName) {
286
+ var handler = function (e) {
287
+ var calls = (typeof data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] !== 'undefined') ? data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)].calls : 0
288
+ data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] = {
289
+ args: jasmine.util.argsToArray(arguments),
290
+ calls: ++calls
291
+ }
292
+ }
293
+
294
+ $(selector).on(eventName, handler)
295
+ data.handlers.push(handler)
296
+
297
+ return {
298
+ selector: selector,
299
+ eventName: eventName,
300
+ handler: handler,
301
+ reset: function (){
302
+ delete data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)]
303
+ },
304
+ calls: {
305
+ count: function () {
306
+ return data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] ?
307
+ data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)].calls : 0;
308
+ },
309
+ any: function () {
310
+ return data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] ?
311
+ !!data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)].calls : false;
312
+ }
313
+ }
314
+ }
315
+ },
316
+
317
+ args: function (selector, eventName) {
318
+ var actualArgs = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)].args
319
+
320
+ if (!actualArgs) {
321
+ throw "There is no spy for " + eventName + " on " + selector.toString() + ". Make sure to create a spy using spyOnEvent."
322
+ }
323
+
324
+ return actualArgs
325
+ },
326
+
327
+ wasTriggered: function (selector, eventName) {
328
+ return !!(data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)])
329
+ },
330
+
331
+ wasTriggeredWith: function (selector, eventName, expectedArgs, util, customEqualityTesters) {
332
+ var actualArgs = jasmine.jQuery.events.args(selector, eventName).slice(1)
333
+
334
+ if (Object.prototype.toString.call(expectedArgs) !== '[object Array]')
335
+ actualArgs = actualArgs[0]
336
+
337
+ return util.equals(actualArgs, expectedArgs, customEqualityTesters)
338
+ },
339
+
340
+ wasPrevented: function (selector, eventName) {
341
+ var spiedEvent = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)]
342
+ , args = (jasmine.util.isUndefined(spiedEvent)) ? {} : spiedEvent.args
343
+ , e = args ? args[0] : undefined
344
+
345
+ return e && e.isDefaultPrevented()
346
+ },
347
+
348
+ wasStopped: function (selector, eventName) {
349
+ var spiedEvent = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)]
350
+ , args = (jasmine.util.isUndefined(spiedEvent)) ? {} : spiedEvent.args
351
+ , e = args ? args[0] : undefined
352
+
353
+ return e && e.isPropagationStopped()
354
+ },
355
+
356
+ cleanUp: function () {
357
+ data.spiedEvents = {}
358
+ data.handlers = []
359
+ }
360
+ }
361
+
362
+ var hasProperty = function (actualValue, expectedValue) {
363
+ if (expectedValue === undefined)
364
+ return actualValue !== undefined
365
+
366
+ return actualValue === expectedValue
367
+ }
368
+
369
+ beforeEach(function () {
370
+ jasmine.addMatchers({
371
+ toHaveClass: function () {
372
+ return {
373
+ compare: function (actual, className) {
374
+ return { pass: $(actual).hasClass(className) }
375
+ }
376
+ }
377
+ },
378
+
379
+ toHaveCss: function () {
380
+ return {
381
+ compare: function (actual, css) {
382
+ for (var prop in css){
383
+ var value = css[prop]
384
+ // see issue #147 on gh
385
+ ;if (value === 'auto' && $(actual).get(0).style[prop] === 'auto') continue
386
+ if ($(actual).css(prop) !== value) return { pass: false }
387
+ }
388
+ return { pass: true }
389
+ }
390
+ }
391
+ },
392
+
393
+ toBeVisible: function () {
394
+ return {
395
+ compare: function (actual) {
396
+ return { pass: $(actual).is(':visible') }
397
+ }
398
+ }
399
+ },
400
+
401
+ toBeHidden: function () {
402
+ return {
403
+ compare: function (actual) {
404
+ return { pass: $(actual).is(':hidden') }
405
+ }
406
+ }
407
+ },
408
+
409
+ toBeSelected: function () {
410
+ return {
411
+ compare: function (actual) {
412
+ return { pass: $(actual).is(':selected') }
413
+ }
414
+ }
415
+ },
416
+
417
+ toBeChecked: function () {
418
+ return {
419
+ compare: function (actual) {
420
+ return { pass: $(actual).is(':checked') }
421
+ }
422
+ }
423
+ },
424
+
425
+ toBeEmpty: function () {
426
+ return {
427
+ compare: function (actual) {
428
+ return { pass: $(actual).is(':empty') }
429
+ }
430
+ }
431
+ },
432
+
433
+ toBeInDOM: function () {
434
+ return {
435
+ compare: function (actual) {
436
+ return { pass: $.contains(document.documentElement, $(actual)[0]) }
437
+ }
438
+ }
439
+ },
440
+
441
+ toExist: function () {
442
+ return {
443
+ compare: function (actual) {
444
+ return { pass: $(actual).length }
445
+ }
446
+ }
447
+ },
448
+
449
+ toHaveLength: function () {
450
+ return {
451
+ compare: function (actual, length) {
452
+ return { pass: $(actual).length === length }
453
+ }
454
+ }
455
+ },
456
+
457
+ toHaveAttr: function () {
458
+ return {
459
+ compare: function (actual, attributeName, expectedAttributeValue) {
460
+ return { pass: hasProperty($(actual).attr(attributeName), expectedAttributeValue) }
461
+ }
462
+ }
463
+ },
464
+
465
+ toHaveProp: function () {
466
+ return {
467
+ compare: function (actual, propertyName, expectedPropertyValue) {
468
+ return { pass: hasProperty($(actual).prop(propertyName), expectedPropertyValue) }
469
+ }
470
+ }
471
+ },
472
+
473
+ toHaveId: function () {
474
+ return {
475
+ compare: function (actual, id) {
476
+ return { pass: $(actual).attr('id') == id }
477
+ }
478
+ }
479
+ },
480
+
481
+ toHaveHtml: function () {
482
+ return {
483
+ compare: function (actual, html) {
484
+ return { pass: $(actual).html() == jasmine.jQuery.browserTagCaseIndependentHtml(html) }
485
+ }
486
+ }
487
+ },
488
+
489
+ toContainHtml: function () {
490
+ return {
491
+ compare: function (actual, html) {
492
+ var actualHtml = $(actual).html()
493
+ , expectedHtml = jasmine.jQuery.browserTagCaseIndependentHtml(html)
494
+
495
+ return { pass: (actualHtml.indexOf(expectedHtml) >= 0) }
496
+ }
497
+ }
498
+ },
499
+
500
+ toHaveText: function () {
501
+ return {
502
+ compare: function (actual, text) {
503
+ var actualText = $(actual).text()
504
+ var trimmedText = $.trim(actualText)
505
+
506
+ if (text && $.isFunction(text.test)) {
507
+ return { pass: text.test(actualText) || text.test(trimmedText) }
508
+ } else {
509
+ return { pass: (actualText == text || trimmedText == text) }
510
+ }
511
+ }
512
+ }
513
+ },
514
+
515
+ toContainText: function () {
516
+ return {
517
+ compare: function (actual, text) {
518
+ var trimmedText = $.trim($(actual).text())
519
+
520
+ if (text && $.isFunction(text.test)) {
521
+ return { pass: text.test(trimmedText) }
522
+ } else {
523
+ return { pass: trimmedText.indexOf(text) != -1 }
524
+ }
525
+ }
526
+ }
527
+ },
528
+
529
+ toHaveValue: function () {
530
+ return {
531
+ compare: function (actual, value) {
532
+ return { pass: $(actual).val() === value }
533
+ }
534
+ }
535
+ },
536
+
537
+ toHaveData: function () {
538
+ return {
539
+ compare: function (actual, key, expectedValue) {
540
+ return { pass: hasProperty($(actual).data(key), expectedValue) }
541
+ }
542
+ }
543
+ },
544
+
545
+ toContainElement: function () {
546
+ return {
547
+ compare: function (actual, selector) {
548
+ return { pass: $(actual).find(selector).length }
549
+ }
550
+ }
551
+ },
552
+
553
+ toBeMatchedBy: function () {
554
+ return {
555
+ compare: function (actual, selector) {
556
+ return { pass: $(actual).filter(selector).length }
557
+ }
558
+ }
559
+ },
560
+
561
+ toBeDisabled: function () {
562
+ return {
563
+ compare: function (actual, selector) {
564
+ return { pass: $(actual).is(':disabled') }
565
+ }
566
+ }
567
+ },
568
+
569
+ toBeFocused: function (selector) {
570
+ return {
571
+ compare: function (actual, selector) {
572
+ return { pass: $(actual)[0] === $(actual)[0].ownerDocument.activeElement }
573
+ }
574
+ }
575
+ },
576
+
577
+ toHandle: function () {
578
+ return {
579
+ compare: function (actual, event) {
580
+ if ( !actual || actual.length === 0 ) return { pass: false };
581
+ var events = $._data($(actual).get(0), "events")
582
+
583
+ if (!events || !event || typeof event !== "string") {
584
+ return { pass: false }
585
+ }
586
+
587
+ var namespaces = event.split(".")
588
+ , eventType = namespaces.shift()
589
+ , sortedNamespaces = namespaces.slice(0).sort()
590
+ , namespaceRegExp = new RegExp("(^|\\.)" + sortedNamespaces.join("\\.(?:.*\\.)?") + "(\\.|$)")
591
+
592
+ if (events[eventType] && namespaces.length) {
593
+ for (var i = 0; i < events[eventType].length; i++) {
594
+ var namespace = events[eventType][i].namespace
595
+
596
+ if (namespaceRegExp.test(namespace))
597
+ return { pass: true }
598
+ }
599
+ } else {
600
+ return { pass: (events[eventType] && events[eventType].length > 0) }
601
+ }
602
+
603
+ return { pass: false }
604
+ }
605
+ }
606
+ },
607
+
608
+ toHandleWith: function () {
609
+ return {
610
+ compare: function (actual, eventName, eventHandler) {
611
+ if ( !actual || actual.length === 0 ) return { pass: false };
612
+ var normalizedEventName = eventName.split('.')[0]
613
+ , stack = $._data($(actual).get(0), "events")[normalizedEventName]
614
+
615
+ for (var i = 0; i < stack.length; i++) {
616
+ if (stack[i].handler == eventHandler) return { pass: true }
617
+ }
618
+
619
+ return { pass: false }
620
+ }
621
+ }
622
+ },
623
+
624
+ toHaveBeenTriggeredOn: function () {
625
+ return {
626
+ compare: function (actual, selector) {
627
+ var result = { pass: jasmine.jQuery.events.wasTriggered(selector, actual) }
628
+
629
+ result.message = result.pass ?
630
+ "Expected event " + $(actual) + " not to have been triggered on " + selector :
631
+ "Expected event " + $(actual) + " to have been triggered on " + selector
632
+
633
+ return result;
634
+ }
635
+ }
636
+ },
637
+
638
+ toHaveBeenTriggered: function (){
639
+ return {
640
+ compare: function (actual) {
641
+ var eventName = actual.eventName
642
+ , selector = actual.selector
643
+ , result = { pass: jasmine.jQuery.events.wasTriggered(selector, eventName) }
644
+
645
+ result.message = result.pass ?
646
+ "Expected event " + eventName + " not to have been triggered on " + selector :
647
+ "Expected event " + eventName + " to have been triggered on " + selector
648
+
649
+ return result
650
+ }
651
+ }
652
+ },
653
+
654
+ toHaveBeenTriggeredOnAndWith: function (j$, customEqualityTesters) {
655
+ return {
656
+ compare: function (actual, selector, expectedArgs) {
657
+ var wasTriggered = jasmine.jQuery.events.wasTriggered(selector, actual)
658
+ , result = { pass: wasTriggered && jasmine.jQuery.events.wasTriggeredWith(selector, actual, expectedArgs, j$, customEqualityTesters) }
659
+
660
+ if (wasTriggered) {
661
+ var actualArgs = jasmine.jQuery.events.args(selector, actual, expectedArgs)[1]
662
+ result.message = result.pass ?
663
+ "Expected event " + actual + " not to have been triggered with " + jasmine.pp(expectedArgs) + " but it was triggered with " + jasmine.pp(actualArgs) :
664
+ "Expected event " + actual + " to have been triggered with " + jasmine.pp(expectedArgs) + " but it was triggered with " + jasmine.pp(actualArgs)
665
+
666
+ } else {
667
+ // todo check on this
668
+ result.message = result.pass ?
669
+ "Expected event " + actual + " not to have been triggered on " + selector :
670
+ "Expected event " + actual + " to have been triggered on " + selector
671
+ }
672
+
673
+ return result
674
+ }
675
+ }
676
+ },
677
+
678
+ toHaveBeenPreventedOn: function () {
679
+ return {
680
+ compare: function (actual, selector) {
681
+ var result = { pass: jasmine.jQuery.events.wasPrevented(selector, actual) }
682
+
683
+ result.message = result.pass ?
684
+ "Expected event " + actual + " not to have been prevented on " + selector :
685
+ "Expected event " + actual + " to have been prevented on " + selector
686
+
687
+ return result
688
+ }
689
+ }
690
+ },
691
+
692
+ toHaveBeenPrevented: function () {
693
+ return {
694
+ compare: function (actual) {
695
+ var eventName = actual.eventName
696
+ , selector = actual.selector
697
+ , result = { pass: jasmine.jQuery.events.wasPrevented(selector, eventName) }
698
+
699
+ result.message = result.pass ?
700
+ "Expected event " + eventName + " not to have been prevented on " + selector :
701
+ "Expected event " + eventName + " to have been prevented on " + selector
702
+
703
+ return result
704
+ }
705
+ }
706
+ },
707
+
708
+ toHaveBeenStoppedOn: function () {
709
+ return {
710
+ compare: function (actual, selector) {
711
+ var result = { pass: jasmine.jQuery.events.wasStopped(selector, actual) }
712
+
713
+ result.message = result.pass ?
714
+ "Expected event " + actual + " not to have been stopped on " + selector :
715
+ "Expected event " + actual + " to have been stopped on " + selector
716
+
717
+ return result;
718
+ }
719
+ }
720
+ },
721
+
722
+ toHaveBeenStopped: function () {
723
+ return {
724
+ compare: function (actual) {
725
+ var eventName = actual.eventName
726
+ , selector = actual.selector
727
+ , result = { pass: jasmine.jQuery.events.wasStopped(selector, eventName) }
728
+
729
+ result.message = result.pass ?
730
+ "Expected event " + eventName + " not to have been stopped on " + selector :
731
+ "Expected event " + eventName + " to have been stopped on " + selector
732
+
733
+ return result
734
+ }
735
+ }
736
+ }
737
+ })
738
+
739
+ jasmine.getEnv().addCustomEqualityTester(function(a, b) {
740
+ if (a && b) {
741
+ if (a instanceof $ || jasmine.isDomNode(a)) {
742
+ var $a = $(a)
743
+
744
+ if (b instanceof $)
745
+ return $a.length == b.length && a.is(b)
746
+
747
+ return $a.is(b);
748
+ }
749
+
750
+ if (b instanceof $ || jasmine.isDomNode(b)) {
751
+ var $b = $(b)
752
+
753
+ if (a instanceof $)
754
+ return a.length == $b.length && $b.is(a)
755
+
756
+ return $(b).is(a);
757
+ }
758
+ }
759
+ })
760
+
761
+ jasmine.getEnv().addCustomEqualityTester(function (a, b) {
762
+ if (a instanceof $ && b instanceof $ && a.size() == b.size())
763
+ return a.is(b)
764
+ })
765
+ })
766
+
767
+ afterEach(function () {
768
+ jasmine.getFixtures().cleanUp()
769
+ jasmine.getStyleFixtures().cleanUp()
770
+ jasmine.jQuery.events.cleanUp()
771
+ })
772
+
773
+ window.readFixtures = function () {
774
+ return jasmine.getFixtures().proxyCallTo_('read', arguments)
775
+ }
776
+
777
+ window.preloadFixtures = function () {
778
+ jasmine.getFixtures().proxyCallTo_('preload', arguments)
779
+ }
780
+
781
+ window.loadFixtures = function () {
782
+ jasmine.getFixtures().proxyCallTo_('load', arguments)
783
+ }
784
+
785
+ window.appendLoadFixtures = function () {
786
+ jasmine.getFixtures().proxyCallTo_('appendLoad', arguments)
787
+ }
788
+
789
+ window.setFixtures = function (html) {
790
+ return jasmine.getFixtures().proxyCallTo_('set', arguments)
791
+ }
792
+
793
+ window.appendSetFixtures = function () {
794
+ jasmine.getFixtures().proxyCallTo_('appendSet', arguments)
795
+ }
796
+
797
+ window.sandbox = function (attributes) {
798
+ return jasmine.getFixtures().sandbox(attributes)
799
+ }
800
+
801
+ window.spyOnEvent = function (selector, eventName) {
802
+ return jasmine.jQuery.events.spyOn(selector, eventName)
803
+ }
804
+
805
+ window.preloadStyleFixtures = function () {
806
+ jasmine.getStyleFixtures().proxyCallTo_('preload', arguments)
807
+ }
808
+
809
+ window.loadStyleFixtures = function () {
810
+ jasmine.getStyleFixtures().proxyCallTo_('load', arguments)
811
+ }
812
+
813
+ window.appendLoadStyleFixtures = function () {
814
+ jasmine.getStyleFixtures().proxyCallTo_('appendLoad', arguments)
815
+ }
816
+
817
+ window.setStyleFixtures = function (html) {
818
+ jasmine.getStyleFixtures().proxyCallTo_('set', arguments)
819
+ }
820
+
821
+ window.appendSetStyleFixtures = function (html) {
822
+ jasmine.getStyleFixtures().proxyCallTo_('appendSet', arguments)
823
+ }
824
+
825
+ window.loadJSONFixtures = function () {
826
+ return jasmine.getJSONFixtures().proxyCallTo_('load', arguments)
827
+ }
828
+
829
+ window.getJSONFixture = function (url) {
830
+ return jasmine.getJSONFixtures().proxyCallTo_('read', arguments)[url]
831
+ }
832
+ }(window, window.jasmine, window.jQuery);