spreadsheet_architect 2.1.2 → 3.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 (243) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +17 -2
  3. data/README.md +149 -129
  4. data/lib/spreadsheet_architect/class_methods/csv.rb +2 -2
  5. data/lib/spreadsheet_architect/class_methods/ods.rb +2 -2
  6. data/lib/spreadsheet_architect/class_methods/xlsx.rb +26 -30
  7. data/lib/spreadsheet_architect/exceptions.rb +32 -30
  8. data/lib/spreadsheet_architect/utils/xlsx.rb +46 -25
  9. data/lib/spreadsheet_architect/utils.rb +116 -121
  10. data/lib/spreadsheet_architect/version.rb +1 -1
  11. data/lib/spreadsheet_architect.rb +5 -1
  12. data/test/dummy_app/app/models/active_model_object.rb +1 -0
  13. data/test/dummy_app/app/models/custom_post.rb +1 -0
  14. data/test/dummy_app/app/models/legacy_plain_ruby_object.rb +14 -0
  15. data/test/dummy_app/app/models/plain_ruby_object.rb +2 -9
  16. data/test/dummy_app/app/models/post.rb +3 -0
  17. data/test/dummy_app/config/routes.rb +4 -5
  18. data/test/dummy_app/db/test.sqlite3 +0 -0
  19. data/test/dummy_app/log/test.log +26911 -21739
  20. data/test/dummy_app/tmp/2.0.1/integration/alt_xlsx.xlsx +0 -0
  21. data/test/dummy_app/tmp/2.0.1/integration/csv.csv +6 -0
  22. data/test/dummy_app/tmp/2.0.1/integration/ods.ods +0 -0
  23. data/test/dummy_app/tmp/2.0.1/integration/xlsx.xlsx +0 -0
  24. data/test/dummy_app/tmp/2.0.1/kitchen_sink.ods +0 -0
  25. data/test/dummy_app/tmp/2.0.1/kitchen_sink.xlsx +0 -0
  26. data/test/dummy_app/tmp/2.0.1/models/ActiveModelObject/data.csv +3 -0
  27. data/test/dummy_app/tmp/2.0.1/models/ActiveModelObject/data.ods +0 -0
  28. data/test/dummy_app/tmp/2.0.1/models/ActiveModelObject/data.xlsx +0 -0
  29. data/test/dummy_app/tmp/{empty_sa.csv → 2.0.1/models/ActiveModelObject/empty.csv} +0 -0
  30. data/test/dummy_app/tmp/{ods/empty_model.ods → 2.0.1/models/ActiveModelObject/empty.ods} +0 -0
  31. data/test/dummy_app/tmp/2.0.1/models/ActiveModelObject/empty.xlsx +0 -0
  32. data/test/dummy_app/tmp/2.0.1/models/ActiveModelObject/instances.csv +6 -0
  33. data/test/dummy_app/tmp/2.0.1/models/ActiveModelObject/instances.ods +0 -0
  34. data/test/dummy_app/tmp/2.0.1/models/ActiveModelObject/instances.xlsx +0 -0
  35. data/test/dummy_app/tmp/2.0.1/models/CustomPost/data.csv +3 -0
  36. data/test/dummy_app/tmp/2.0.1/models/CustomPost/data.ods +0 -0
  37. data/test/dummy_app/tmp/2.0.1/models/CustomPost/data.xlsx +0 -0
  38. data/test/dummy_app/tmp/2.0.1/models/CustomPost/empty.csv +1 -0
  39. data/test/dummy_app/tmp/2.0.1/models/CustomPost/empty.ods +0 -0
  40. data/test/dummy_app/tmp/2.0.1/models/CustomPost/empty.xlsx +0 -0
  41. data/test/dummy_app/tmp/2.0.1/models/CustomPost/instances.csv +6 -0
  42. data/test/dummy_app/tmp/2.0.1/models/CustomPost/instances.ods +0 -0
  43. data/test/dummy_app/tmp/2.0.1/models/CustomPost/instances.xlsx +0 -0
  44. data/test/dummy_app/tmp/2.0.1/models/LegacyPlainRubyObject/data.csv +3 -0
  45. data/test/dummy_app/tmp/2.0.1/models/LegacyPlainRubyObject/data.ods +0 -0
  46. data/test/dummy_app/tmp/2.0.1/models/LegacyPlainRubyObject/data.xlsx +0 -0
  47. data/test/dummy_app/tmp/2.0.1/models/LegacyPlainRubyObject/empty.csv +1 -0
  48. data/test/dummy_app/tmp/2.0.1/models/LegacyPlainRubyObject/empty.ods +0 -0
  49. data/test/dummy_app/tmp/2.0.1/models/LegacyPlainRubyObject/empty.xlsx +0 -0
  50. data/test/dummy_app/tmp/2.0.1/models/LegacyPlainRubyObject/instances.csv +6 -0
  51. data/test/dummy_app/tmp/2.0.1/models/LegacyPlainRubyObject/instances.ods +0 -0
  52. data/test/dummy_app/tmp/2.0.1/models/LegacyPlainRubyObject/instances.xlsx +0 -0
  53. data/test/dummy_app/tmp/2.0.1/models/PlainRubyObject/data.csv +3 -0
  54. data/test/dummy_app/tmp/2.0.1/models/PlainRubyObject/data.ods +0 -0
  55. data/test/dummy_app/tmp/2.0.1/models/PlainRubyObject/data.xlsx +0 -0
  56. data/test/dummy_app/tmp/2.0.1/models/PlainRubyObject/empty.csv +0 -0
  57. data/test/dummy_app/tmp/2.0.1/models/PlainRubyObject/empty.ods +0 -0
  58. data/test/dummy_app/tmp/2.0.1/models/PlainRubyObject/empty.xlsx +0 -0
  59. data/test/dummy_app/tmp/2.0.1/models/PlainRubyObject/instances.csv +6 -0
  60. data/test/dummy_app/tmp/2.0.1/models/PlainRubyObject/instances.ods +0 -0
  61. data/test/dummy_app/tmp/2.0.1/models/PlainRubyObject/instances.xlsx +0 -0
  62. data/test/dummy_app/tmp/2.0.1/models/Post/data.csv +3 -0
  63. data/test/dummy_app/tmp/2.0.1/models/Post/data.ods +0 -0
  64. data/test/dummy_app/tmp/2.0.1/models/Post/data.xlsx +0 -0
  65. data/test/dummy_app/tmp/2.0.1/models/Post/empty.csv +0 -0
  66. data/test/dummy_app/tmp/2.0.1/models/Post/empty.ods +0 -0
  67. data/test/dummy_app/tmp/2.0.1/models/Post/empty.xlsx +0 -0
  68. data/test/dummy_app/tmp/2.0.1/models/SpreadsheetArchitect/data.csv +3 -0
  69. data/test/dummy_app/tmp/2.0.1/models/SpreadsheetArchitect/data.ods +0 -0
  70. data/test/dummy_app/tmp/2.0.1/models/SpreadsheetArchitect/data.xlsx +0 -0
  71. data/test/dummy_app/tmp/2.0.1/models/SpreadsheetArchitect/empty.csv +0 -0
  72. data/test/dummy_app/tmp/2.0.1/models/SpreadsheetArchitect/empty.ods +0 -0
  73. data/test/dummy_app/tmp/2.0.1/models/SpreadsheetArchitect/empty.xlsx +0 -0
  74. data/test/dummy_app/tmp/2.0.1/multi_sheet.ods +0 -0
  75. data/test/dummy_app/tmp/2.0.1/multi_sheet.xlsx +0 -0
  76. data/test/dummy_app/tmp/3.0.0.pre/integration/alt_xlsx.xlsx +0 -0
  77. data/test/dummy_app/tmp/3.0.0.pre/integration/csv.csv +6 -0
  78. data/test/dummy_app/tmp/3.0.0.pre/integration/ods.ods +0 -0
  79. data/test/dummy_app/tmp/3.0.0.pre/integration/xlsx.xlsx +0 -0
  80. data/test/dummy_app/tmp/3.0.0.pre/kitchen_sink.ods +0 -0
  81. data/test/dummy_app/tmp/3.0.0.pre/kitchen_sink.xlsx +0 -0
  82. data/test/dummy_app/tmp/3.0.0.pre/models/ActiveModelObject/data.csv +3 -0
  83. data/test/dummy_app/tmp/3.0.0.pre/models/ActiveModelObject/data.ods +0 -0
  84. data/test/dummy_app/tmp/3.0.0.pre/models/ActiveModelObject/data.xlsx +0 -0
  85. data/test/dummy_app/tmp/3.0.0.pre/models/ActiveModelObject/empty.csv +0 -0
  86. data/test/dummy_app/tmp/3.0.0.pre/models/ActiveModelObject/empty.ods +0 -0
  87. data/test/dummy_app/tmp/3.0.0.pre/models/ActiveModelObject/empty.xlsx +0 -0
  88. data/test/dummy_app/tmp/3.0.0.pre/models/ActiveModelObject/instances.csv +6 -0
  89. data/test/dummy_app/tmp/3.0.0.pre/models/ActiveModelObject/instances.ods +0 -0
  90. data/test/dummy_app/tmp/3.0.0.pre/models/ActiveModelObject/instances.xlsx +0 -0
  91. data/test/dummy_app/tmp/3.0.0.pre/models/CustomPost/data.csv +3 -0
  92. data/test/dummy_app/tmp/3.0.0.pre/models/CustomPost/data.ods +0 -0
  93. data/test/dummy_app/tmp/3.0.0.pre/models/CustomPost/data.xlsx +0 -0
  94. data/test/dummy_app/tmp/3.0.0.pre/models/CustomPost/empty.csv +1 -0
  95. data/test/dummy_app/tmp/3.0.0.pre/models/CustomPost/empty.ods +0 -0
  96. data/test/dummy_app/tmp/3.0.0.pre/models/CustomPost/empty.xlsx +0 -0
  97. data/test/dummy_app/tmp/3.0.0.pre/models/CustomPost/instances.csv +6 -0
  98. data/test/dummy_app/tmp/3.0.0.pre/models/CustomPost/instances.ods +0 -0
  99. data/test/dummy_app/tmp/3.0.0.pre/models/CustomPost/instances.xlsx +0 -0
  100. data/test/dummy_app/tmp/3.0.0.pre/models/LegacyPlainRubyObject/data.csv +3 -0
  101. data/test/dummy_app/tmp/3.0.0.pre/models/LegacyPlainRubyObject/data.ods +0 -0
  102. data/test/dummy_app/tmp/3.0.0.pre/models/LegacyPlainRubyObject/data.xlsx +0 -0
  103. data/test/dummy_app/tmp/3.0.0.pre/models/LegacyPlainRubyObject/empty.csv +0 -0
  104. data/test/dummy_app/tmp/3.0.0.pre/models/LegacyPlainRubyObject/empty.ods +0 -0
  105. data/test/dummy_app/tmp/3.0.0.pre/models/LegacyPlainRubyObject/empty.xlsx +0 -0
  106. data/test/dummy_app/tmp/3.0.0.pre/models/LegacyPlainRubyObject/instances.csv +6 -0
  107. data/test/dummy_app/tmp/3.0.0.pre/models/LegacyPlainRubyObject/instances.ods +0 -0
  108. data/test/dummy_app/tmp/3.0.0.pre/models/LegacyPlainRubyObject/instances.xlsx +0 -0
  109. data/test/dummy_app/tmp/3.0.0.pre/models/PlainRubyObject/data.csv +3 -0
  110. data/test/dummy_app/tmp/3.0.0.pre/models/PlainRubyObject/data.ods +0 -0
  111. data/test/dummy_app/tmp/3.0.0.pre/models/PlainRubyObject/data.xlsx +0 -0
  112. data/test/dummy_app/tmp/3.0.0.pre/models/PlainRubyObject/empty.csv +1 -0
  113. data/test/dummy_app/tmp/3.0.0.pre/models/PlainRubyObject/empty.ods +0 -0
  114. data/test/dummy_app/tmp/3.0.0.pre/models/PlainRubyObject/empty.xlsx +0 -0
  115. data/test/dummy_app/tmp/3.0.0.pre/models/PlainRubyObject/instances.csv +6 -0
  116. data/test/dummy_app/tmp/3.0.0.pre/models/PlainRubyObject/instances.ods +0 -0
  117. data/test/dummy_app/tmp/3.0.0.pre/models/PlainRubyObject/instances.xlsx +0 -0
  118. data/test/dummy_app/tmp/3.0.0.pre/models/Post/data.csv +3 -0
  119. data/test/dummy_app/tmp/3.0.0.pre/models/Post/data.ods +0 -0
  120. data/test/dummy_app/tmp/3.0.0.pre/models/Post/data.xlsx +0 -0
  121. data/test/dummy_app/tmp/3.0.0.pre/models/Post/empty.csv +0 -0
  122. data/test/dummy_app/tmp/3.0.0.pre/models/Post/empty.ods +0 -0
  123. data/test/dummy_app/tmp/3.0.0.pre/models/Post/empty.xlsx +0 -0
  124. data/test/dummy_app/tmp/3.0.0.pre/models/SpreadsheetArchitect/data.csv +3 -0
  125. data/test/dummy_app/tmp/3.0.0.pre/models/SpreadsheetArchitect/data.ods +0 -0
  126. data/test/dummy_app/tmp/3.0.0.pre/models/SpreadsheetArchitect/data.xlsx +0 -0
  127. data/test/dummy_app/tmp/3.0.0.pre/models/SpreadsheetArchitect/empty.csv +0 -0
  128. data/test/dummy_app/tmp/3.0.0.pre/models/SpreadsheetArchitect/empty.ods +0 -0
  129. data/test/dummy_app/tmp/3.0.0.pre/models/SpreadsheetArchitect/empty.xlsx +0 -0
  130. data/test/dummy_app/tmp/3.0.0.pre/multi_sheet.ods +0 -0
  131. data/test/dummy_app/tmp/3.0.0.pre/multi_sheet.xlsx +0 -0
  132. data/test/dummy_app/tmp/axlsx-master/integration/alt_xlsx.xlsx +0 -0
  133. data/test/dummy_app/tmp/axlsx-master/integration/csv.csv +6 -0
  134. data/test/dummy_app/tmp/axlsx-master/integration/ods.ods +0 -0
  135. data/test/dummy_app/tmp/axlsx-master/integration/xlsx.xlsx +0 -0
  136. data/test/dummy_app/tmp/axlsx-master/kitchen_sink.ods +0 -0
  137. data/test/dummy_app/tmp/axlsx-master/kitchen_sink.xlsx +0 -0
  138. data/test/dummy_app/tmp/axlsx-master/models/ActiveModelObject/data.csv +3 -0
  139. data/test/dummy_app/tmp/axlsx-master/models/ActiveModelObject/data.ods +0 -0
  140. data/test/dummy_app/tmp/axlsx-master/models/ActiveModelObject/data.xlsx +0 -0
  141. data/test/dummy_app/tmp/axlsx-master/models/ActiveModelObject/empty.csv +0 -0
  142. data/test/dummy_app/tmp/axlsx-master/models/ActiveModelObject/empty.ods +0 -0
  143. data/test/dummy_app/tmp/axlsx-master/models/ActiveModelObject/empty.xlsx +0 -0
  144. data/test/dummy_app/tmp/axlsx-master/models/ActiveModelObject/instances.csv +6 -0
  145. data/test/dummy_app/tmp/axlsx-master/models/ActiveModelObject/instances.ods +0 -0
  146. data/test/dummy_app/tmp/axlsx-master/models/ActiveModelObject/instances.xlsx +0 -0
  147. data/test/dummy_app/tmp/axlsx-master/models/CustomPost/data.csv +3 -0
  148. data/test/dummy_app/tmp/axlsx-master/models/CustomPost/data.ods +0 -0
  149. data/test/dummy_app/tmp/axlsx-master/models/CustomPost/data.xlsx +0 -0
  150. data/test/dummy_app/tmp/axlsx-master/models/CustomPost/empty.csv +0 -0
  151. data/test/dummy_app/tmp/axlsx-master/models/CustomPost/empty.ods +0 -0
  152. data/test/dummy_app/tmp/axlsx-master/models/CustomPost/empty.xlsx +0 -0
  153. data/test/dummy_app/tmp/axlsx-master/models/CustomPost/instances.csv +6 -0
  154. data/test/dummy_app/tmp/axlsx-master/models/CustomPost/instances.ods +0 -0
  155. data/test/dummy_app/tmp/axlsx-master/models/CustomPost/instances.xlsx +0 -0
  156. data/test/dummy_app/tmp/axlsx-master/models/LegacyPlainRubyObject/data.csv +3 -0
  157. data/test/dummy_app/tmp/axlsx-master/models/LegacyPlainRubyObject/data.ods +0 -0
  158. data/test/dummy_app/tmp/axlsx-master/models/LegacyPlainRubyObject/data.xlsx +0 -0
  159. data/test/dummy_app/tmp/axlsx-master/models/LegacyPlainRubyObject/empty.csv +1 -0
  160. data/test/dummy_app/tmp/axlsx-master/models/LegacyPlainRubyObject/empty.ods +0 -0
  161. data/test/dummy_app/tmp/axlsx-master/models/LegacyPlainRubyObject/empty.xlsx +0 -0
  162. data/test/dummy_app/tmp/axlsx-master/models/LegacyPlainRubyObject/instances.csv +6 -0
  163. data/test/dummy_app/tmp/axlsx-master/models/LegacyPlainRubyObject/instances.ods +0 -0
  164. data/test/dummy_app/tmp/axlsx-master/models/LegacyPlainRubyObject/instances.xlsx +0 -0
  165. data/test/dummy_app/tmp/axlsx-master/models/PlainRubyObject/data.csv +3 -0
  166. data/test/dummy_app/tmp/axlsx-master/models/PlainRubyObject/data.ods +0 -0
  167. data/test/dummy_app/tmp/axlsx-master/models/PlainRubyObject/data.xlsx +0 -0
  168. data/test/dummy_app/tmp/axlsx-master/models/PlainRubyObject/empty.csv +1 -0
  169. data/test/dummy_app/tmp/axlsx-master/models/PlainRubyObject/empty.ods +0 -0
  170. data/test/dummy_app/tmp/axlsx-master/models/PlainRubyObject/empty.xlsx +0 -0
  171. data/test/dummy_app/tmp/axlsx-master/models/PlainRubyObject/instances.csv +6 -0
  172. data/test/dummy_app/tmp/axlsx-master/models/PlainRubyObject/instances.ods +0 -0
  173. data/test/dummy_app/tmp/axlsx-master/models/PlainRubyObject/instances.xlsx +0 -0
  174. data/test/dummy_app/tmp/axlsx-master/models/Post/data.csv +3 -0
  175. data/test/dummy_app/tmp/axlsx-master/models/Post/data.ods +0 -0
  176. data/test/dummy_app/tmp/axlsx-master/models/Post/data.xlsx +0 -0
  177. data/test/dummy_app/tmp/axlsx-master/models/Post/empty.csv +0 -0
  178. data/test/dummy_app/tmp/axlsx-master/models/Post/empty.ods +0 -0
  179. data/test/dummy_app/tmp/axlsx-master/models/Post/empty.xlsx +0 -0
  180. data/test/dummy_app/tmp/axlsx-master/models/SpreadsheetArchitect/data.csv +3 -0
  181. data/test/dummy_app/tmp/axlsx-master/models/SpreadsheetArchitect/data.ods +0 -0
  182. data/test/dummy_app/tmp/axlsx-master/models/SpreadsheetArchitect/data.xlsx +0 -0
  183. data/test/dummy_app/tmp/axlsx-master/models/SpreadsheetArchitect/empty.csv +0 -0
  184. data/test/dummy_app/tmp/axlsx-master/models/SpreadsheetArchitect/empty.ods +0 -0
  185. data/test/dummy_app/tmp/axlsx-master/models/SpreadsheetArchitect/empty.xlsx +0 -0
  186. data/test/dummy_app/tmp/axlsx-master/multi_sheet.ods +0 -0
  187. data/test/dummy_app/tmp/axlsx-master/multi_sheet.xlsx +0 -0
  188. data/test/integration/application_test.rb +8 -11
  189. data/test/models/all_models_test.rb +107 -0
  190. data/test/test_helper.rb +13 -4
  191. data/test/unit/exceptions_test.rb +168 -0
  192. data/test/unit/formats_test.rb +15 -0
  193. data/test/unit/general_test.rb +15 -0
  194. data/test/unit/kitchen_sink_test.rb +87 -0
  195. data/test/unit/multi_sheet_test.rb +29 -0
  196. data/test/unit/utils_test.rb +179 -0
  197. data/test/unit/xlsx_utils_test.rb +143 -0
  198. metadata +409 -116
  199. data/lib/generators/spreadsheet_architect/add_project_defaults_generator.rb +0 -20
  200. data/test/dummy_app/app/models/bad_plain_ruby_object.rb +0 -3
  201. data/test/dummy_app/app/views/reports/sample.html.erb +0 -1
  202. data/test/dummy_app/log/development.log +0 -28
  203. data/test/dummy_app/tmp/active_model_object/csv.csv +0 -21
  204. data/test/dummy_app/tmp/active_model_object/ods.ods +0 -0
  205. data/test/dummy_app/tmp/active_model_object/xlsx.xlsx +0 -0
  206. data/test/dummy_app/tmp/custom_posts/csv.csv +0 -6
  207. data/test/dummy_app/tmp/custom_posts/empty.xlsx +0 -0
  208. data/test/dummy_app/tmp/custom_posts/ods.ods +0 -0
  209. data/test/dummy_app/tmp/custom_posts/xlsx.xlsx +0 -0
  210. data/test/dummy_app/tmp/empty_model.csv +0 -1
  211. data/test/dummy_app/tmp/empty_model.xlsx +0 -0
  212. data/test/dummy_app/tmp/empty_sa.xlsx +0 -0
  213. data/test/dummy_app/tmp/extreme.xlsx +0 -0
  214. data/test/dummy_app/tmp/integration_tests/alt_xlsx.xlsx +0 -0
  215. data/test/dummy_app/tmp/integration_tests/csv.csv +0 -6
  216. data/test/dummy_app/tmp/integration_tests/ods.ods +0 -0
  217. data/test/dummy_app/tmp/integration_tests/xlsx.xlsx +0 -0
  218. data/test/dummy_app/tmp/model.csv +0 -6
  219. data/test/dummy_app/tmp/model.xlsx +0 -0
  220. data/test/dummy_app/tmp/ods/empty_sa.ods +0 -0
  221. data/test/dummy_app/tmp/ods/model.ods +0 -0
  222. data/test/dummy_app/tmp/ods/model_options.ods +0 -0
  223. data/test/dummy_app/tmp/ods/sa.ods +0 -0
  224. data/test/dummy_app/tmp/options.csv +0 -6
  225. data/test/dummy_app/tmp/plain_ruby_object/csv.csv +0 -4
  226. data/test/dummy_app/tmp/plain_ruby_object/ods.ods +0 -0
  227. data/test/dummy_app/tmp/plain_ruby_object/xlsx.xlsx +0 -0
  228. data/test/dummy_app/tmp/posts/csv.csv +0 -6
  229. data/test/dummy_app/tmp/posts/empty.xlsx +0 -0
  230. data/test/dummy_app/tmp/posts/ods.ods +0 -0
  231. data/test/dummy_app/tmp/posts/xlsx.xlsx +0 -0
  232. data/test/dummy_app/tmp/sa.csv +0 -4
  233. data/test/dummy_app/tmp/sa.xlsx +0 -0
  234. data/test/models/active_model_object_test.rb +0 -51
  235. data/test/models/bad_plain_ruby_object_test.rb +0 -28
  236. data/test/models/csv_test.rb +0 -59
  237. data/test/models/custom_post_test.rb +0 -51
  238. data/test/models/ods_test.rb +0 -65
  239. data/test/models/plain_ruby_object_test.rb +0 -51
  240. data/test/models/post_test.rb +0 -44
  241. data/test/models/spreadsheet_architect_utils_test.rb +0 -73
  242. data/test/models/xlsx_test.rb +0 -98
  243. data/test/spreadsheet_architect_test.rb +0 -11
@@ -4,26 +4,21 @@ require 'test_helper'
4
4
 
5
5
  class ApplicationTest < ActionDispatch::IntegrationTest
6
6
  def setup
7
- @path = Rails.root.join('tmp/integration_tests')
7
+ @path = VERSIONED_BASE_PATH.join("integration")
8
8
  FileUtils.mkdir_p(@path)
9
9
  end
10
10
 
11
- test "Renders sample xlsx action" do
12
- get '/spreadsheet/xlsx', params: {format: :xlsx}
13
- assert_response :success
14
- assert_not @response.body.include?("<h1>Hello World!</h1>")
15
- end
16
-
17
11
  def test_csv
18
- get '/spreadsheet/csv'
12
+ get '/spreadsheets/csv', params: {format: :csv}
19
13
  assert_response :success
14
+
20
15
  File.open(File.join(@path, 'csv.csv'), 'w+b') do |f|
21
16
  f.write @response.body
22
17
  end
23
18
  end
24
19
 
25
20
  def test_ods
26
- get '/spreadsheet/ods'
21
+ get '/spreadsheets/ods'
27
22
  assert_response :success
28
23
 
29
24
  File.open(File.join(@path, 'ods.ods'), 'w+b') do |f|
@@ -32,16 +27,18 @@ class ApplicationTest < ActionDispatch::IntegrationTest
32
27
  end
33
28
 
34
29
  def test_xlsx
35
- get '/spreadsheet/xlsx'
30
+ get '/spreadsheets/xlsx'
36
31
  assert_response :success
32
+
37
33
  File.open(File.join(@path, 'xlsx.xlsx'), 'w+b') do |f|
38
34
  f.write @response.body
39
35
  end
40
36
  end
41
37
 
42
38
  def test_alt_xlsx
43
- get '/spreadsheet/alt_xlsx', params: {format: :xlsx}
39
+ get '/spreadsheets/alt_xlsx', params: {format: :xlsx}
44
40
  assert_response :success
41
+
45
42
  File.open(File.join(@path, 'alt_xlsx.xlsx'), 'w+b') do |f|
46
43
  f.write @response.body
47
44
  end
@@ -0,0 +1,107 @@
1
+ require "test_helper"
2
+
3
+ class AllModelsTest < ActiveSupport::TestCase
4
+
5
+ def setup
6
+ @data = [
7
+ ['row1', 'test1'],
8
+ [123.456, nil, '123'],
9
+ [123, Date.today, Time.now]
10
+ ]
11
+ end
12
+
13
+ def teardown
14
+ end
15
+
16
+ def set_path(klass)
17
+ @path = VERSIONED_BASE_PATH.join("models/#{klass}")
18
+ FileUtils.mkdir_p(@path)
19
+ end
20
+
21
+ models = [SpreadsheetArchitect, ActiveModelObject, PlainRubyObject, LegacyPlainRubyObject, Post, CustomPost]
22
+
23
+ models.each do |klass|
24
+ instances = 5.times.map{|i|
25
+ x = (klass == SpreadsheetArchitect ? Post : klass).new
26
+ x.name = i
27
+ x.content = i+2
28
+ x.created_at = Time.now
29
+ x
30
+ }
31
+
32
+ ['csv', 'ods', 'xlsx'].each do |format|
33
+
34
+ if klass.instance_methods.include?(:spreadsheet_columns) || klass.instance_methods.include?(:column_names)
35
+
36
+ test ":instances #{klass} #{format}" do
37
+ set_path(klass)
38
+
39
+ method = "to_#{format}"
40
+ which = klass.respond_to?(method) ? klass : SpreadsheetArchitect
41
+
42
+ data = which.send(method, instances: instances)
43
+
44
+ File.open(File.join(@path, "instances.#{format}"), 'w+b') do |f|
45
+ f.write data
46
+ end
47
+ end
48
+
49
+ test "Empty :instances #{klass} #{format}" do
50
+ set_path(klass)
51
+
52
+ method = "to_#{format}"
53
+ which = klass.respond_to?(method) ? klass : SpreadsheetArchitect
54
+
55
+ File.open(File.join(@path, "empty.#{format}"),'w+b') do |f|
56
+ f.write which.send(method, instances: [])
57
+ end
58
+ end
59
+ end
60
+
61
+ test ":data #{klass} #{format}" do
62
+ set_path(klass)
63
+
64
+ method = "to_#{format}"
65
+ which = klass.respond_to?(method) ? klass : SpreadsheetArchitect
66
+
67
+ data = which.send(method, data: @data)
68
+
69
+ File.open(File.join(@path, "data.#{format}"), 'w+b') do |f|
70
+ f.write data
71
+ end
72
+ end
73
+
74
+ test "Empty :data #{klass} #{format}" do
75
+ set_path(klass)
76
+
77
+ method = "to_#{format}"
78
+ which = klass.respond_to?(method) ? klass : SpreadsheetArchitect
79
+
80
+ File.open(File.join(@path, "empty.#{format}"),'w+b') do |f|
81
+ f.write which.send(method, data: [])
82
+ end
83
+ end
84
+
85
+ if klass.is_a?(ActiveRecord::Base)
86
+ test "ActiveRecord::Relation" do
87
+ method = "to_#{format}"
88
+
89
+ File.open(File.join(@path, "active_record_relation.#{format}"),'w+b') do |f|
90
+ f.write klass.all.send(method)
91
+ end
92
+ end
93
+
94
+ test "Empty ActiveRecord::Relation" do
95
+ method = "to_#{format}"
96
+
97
+ File.open(File.join(@path, "empty_active_record_relation.#{format}"),'w+b') do |f|
98
+ f.write klass.limit(0).send(method)
99
+ end
100
+ end
101
+ end
102
+
103
+ end
104
+
105
+ end
106
+
107
+ end
data/test/test_helper.rb CHANGED
@@ -23,13 +23,22 @@ Minitest::Reporters.use!
23
23
 
24
24
  require 'custom_assertions'
25
25
 
26
- ### Cleanup old test spreadsheets
27
- FileUtils.remove_dir(Rails.root.join('tmp/'), true)
28
- FileUtils.mkdir(Rails.root.join('tmp/'))
29
-
30
26
  post_count = Post.count
31
27
  if post_count < 5
32
28
  (5 - post_count).times do |i|
33
29
  Post.create!(name: "foo #{i}", content: "bar #{i}", age: i)
34
30
  end
35
31
  end
32
+
33
+ axlsx_spec = Gem.loaded_specs['axlsx']
34
+ if !axlsx_spec.source.is_a?(Bundler::Source::Rubygems)
35
+ axlsx_version = 'axlsx-master'
36
+ else
37
+ axlsx_version = axlsx_spec.version.to_s
38
+ end
39
+
40
+ VERSIONED_BASE_PATH = Rails.root.join("tmp/#{axlsx_version}")
41
+
42
+ ### Cleanup old test spreadsheets
43
+ FileUtils.remove_dir(VERSIONED_BASE_PATH, true)
44
+ FileUtils.mkdir_p(VERSIONED_BASE_PATH)
@@ -0,0 +1,168 @@
1
+ require 'test_helper'
2
+
3
+ class ExceptionsTest < ActiveSupport::TestCase
4
+
5
+ test "NoDataError" do
6
+ error = SpreadsheetArchitect::Exceptions::NoDataError
7
+
8
+ assert error.new
9
+
10
+ assert_raise error do
11
+ SpreadsheetArchitect.to_csv(foo: :bar)
12
+ end
13
+ end
14
+
15
+ test "MultipleDataSourcesError" do
16
+ error = SpreadsheetArchitect::Exceptions::MultipleDataSourcesError
17
+
18
+ assert error.new
19
+
20
+ assert_raise error do
21
+ SpreadsheetArchitect.to_csv(data: [], instances: [])
22
+ end
23
+ end
24
+
25
+ test "InvalidTypeError" do
26
+ error = SpreadsheetArchitect::Exceptions::InvalidTypeError
27
+
28
+ assert error.new(:foobar_option).message
29
+
30
+ assert_raise error do
31
+ SpreadsheetArchitect.to_csv(spreadsheet_columns: :foo)
32
+ end
33
+ assert_raise error do
34
+ SpreadsheetArchitect.to_csv(data: :foo)
35
+ end
36
+ assert_raise error do
37
+ SpreadsheetArchitect.to_csv(instances: :foo)
38
+ end
39
+ assert_raise error do
40
+ SpreadsheetArchitect.to_csv(headers: :foo)
41
+ end
42
+ assert_raise error do
43
+ SpreadsheetArchitect.to_csv(header_style: :foo)
44
+ end
45
+ assert_raise error do
46
+ SpreadsheetArchitect.to_csv(row_style: :foo)
47
+ end
48
+ assert_raise error do
49
+ SpreadsheetArchitect.to_csv(column_styles: :foo)
50
+ end
51
+ assert_raise error do
52
+ SpreadsheetArchitect.to_csv(range_styles: :foo)
53
+ end
54
+ assert_raise error do
55
+ SpreadsheetArchitect.to_csv(merges: :foo)
56
+ end
57
+ assert_raise error do
58
+ SpreadsheetArchitect.to_csv(borders: :foo)
59
+ end
60
+ assert_raise error do
61
+ SpreadsheetArchitect.to_csv(column_widths: :foo)
62
+ end
63
+ end
64
+
65
+ test "SpreadsheetColumnsNotDefinedError" do
66
+ error = SpreadsheetArchitect::Exceptions::SpreadsheetColumnsNotDefinedError
67
+
68
+ assert_raise ArgumentError do
69
+ error.new
70
+ end
71
+
72
+ assert error.new(SpreadsheetArchitect)
73
+
74
+ class QuickBadClass
75
+ include SpreadsheetArchitect
76
+ end
77
+
78
+ assert_raise error do
79
+ QuickBadClass.to_csv(instances: [])
80
+ end
81
+ end
82
+
83
+ test "InvalidColumnError" do
84
+ error = SpreadsheetArchitect::Exceptions::InvalidColumnError
85
+
86
+ assert_raise ArgumentError do
87
+ error.new
88
+ end
89
+
90
+ assert error.new(:foobar_column)
91
+
92
+ assert_raise error do
93
+ SpreadsheetArchitect.to_xlsx(data: [[1]], column_styles: [{columns: 999}])
94
+ end
95
+
96
+ assert_raise error do
97
+ SpreadsheetArchitect.to_xlsx(data: [[1]], column_styles: [{columns: 'ZZZ'}])
98
+ end
99
+
100
+ assert_raise error do
101
+ SpreadsheetArchitect.to_xlsx(data: [[1]], column_styles: [{columns: [999]}])
102
+ end
103
+
104
+ assert_raise error do
105
+ SpreadsheetArchitect.to_xlsx(data: [[1]], column_styles: [{columns: ('ZZX'..'ZZZ')}])
106
+ end
107
+ end
108
+
109
+ test "InvalidRangeStylesOptionError" do
110
+ error = SpreadsheetArchitect::Exceptions::InvalidRangeStylesOptionError
111
+
112
+ assert_raise ArgumentError do
113
+ error.new
114
+ end
115
+
116
+ assert error.new(:columns, :bar_opt)
117
+ assert error.new(:row, :bar_opt)
118
+ assert error.new(:foo, :bar_opt)
119
+
120
+ assert_raise error do
121
+ SpreadsheetArchitect::Utils::XLSX.range_hash_to_str({columns: :foo}, 1, 1)
122
+ end
123
+
124
+ assert_raise error do
125
+ SpreadsheetArchitect::Utils::XLSX.range_hash_to_str({rows: :foo}, 1, 1)
126
+ end
127
+ end
128
+
129
+ test "InvalidRangeError" do
130
+ error = SpreadsheetArchitect::Exceptions::InvalidRangeError
131
+
132
+ assert_raise ArgumentError do
133
+ error.new
134
+ end
135
+
136
+ errors = []
137
+ errors.push error.new(:foo_type, :bar_opt)
138
+ errors.push error.new(:columns, :bar_opt)
139
+ errors.push error.new(:rows, :bar_opt)
140
+ errors.push error.new(:format, :bar_opt)
141
+ errors.push error.new(:type, :bar_opt)
142
+ errors.push error.new(:foo_type, :bar_opt)
143
+
144
+ assert_equal errors.count, errors.uniq.count
145
+ assert error.new(:foo_type, :bar_opt)
146
+
147
+ assert_raise error do
148
+ SpreadsheetArchitect::Utils::XLSX.verify_range(:foo, 1)
149
+ end
150
+
151
+ assert_raise error do
152
+ SpreadsheetArchitect::Utils::XLSX.verify_range("foo", 1)
153
+ end
154
+
155
+ assert_raise error do
156
+ SpreadsheetArchitect::Utils::XLSX.verify_range("foo:foo", 1)
157
+ end
158
+
159
+ assert_raise error do
160
+ SpreadsheetArchitect::Utils::XLSX.verify_range("A1:A2", 1)
161
+ end
162
+
163
+ assert_raise error do
164
+ SpreadsheetArchitect::Utils::XLSX.verify_range("@1:A2", 1)
165
+ end
166
+ end
167
+
168
+ end
@@ -0,0 +1,15 @@
1
+ require 'test_helper'
2
+
3
+ class FormatsTest < ActiveSupport::TestCase
4
+
5
+ [:xlsx, :ods, :csv].each do |format|
6
+ test "Registers :#{format} mime type" do
7
+ assert Mime::Type.lookup_by_extension(format)
8
+ end
9
+
10
+ test "Registers :#{format} template handler" do
11
+ assert ActionController::Renderers::RENDERERS.include?(format.to_sym)
12
+ end
13
+ end
14
+
15
+ end
@@ -0,0 +1,15 @@
1
+ require 'test_helper'
2
+
3
+ class GeneralTest < ActiveSupport::TestCase
4
+
5
+ test "Version accessible by default" do
6
+ assert_not_nil SpreadsheetArchitect::VERSION
7
+ end
8
+
9
+ test "Constants dont change" do
10
+ x = SpreadsheetArchitect.default_options.to_s
11
+ SpreadsheetArchitect.to_xlsx(headers: [[1]], data: [[1]], header_style: {b: false}, row_style: {background_color: '000000'})
12
+ assert_equal(x, SpreadsheetArchitect.default_options.to_s)
13
+ end
14
+
15
+ end
@@ -0,0 +1,87 @@
1
+ require "test_helper"
2
+
3
+ class KitchenSinkTest < ActiveSupport::TestCase
4
+
5
+ def setup
6
+ @options = {
7
+ headers: [
8
+ ['Latest Posts'],
9
+ ['Title','Category','Author','Posted on','Earnings']
10
+ ],
11
+ data: 50.times.map{|i| [i, i*2, i*3, i*4, i*5, i*6, i*7, i*8]},
12
+ header_style: {background_color: "000000", color: "FFFFFF", align: :center, font_size: 12, bold: true, italic: true},
13
+ row_style: {background_color: nil, color: "000000", align: :left, font_size: 12},
14
+ sheet_name: 'Kitchen Sink'
15
+ }
16
+ end
17
+
18
+ def teardown
19
+ end
20
+
21
+ def test_xlsx
22
+ @options.merge!({
23
+ column_styles: [
24
+ {columns: 0, styles: {bold: true}},
25
+ {columns: (1..3), styles: {format_code: "$#,##0.00"}},
26
+ {columns: [4], include_header: true, styles: {italic: true}}
27
+ ],
28
+
29
+ range_styles: [
30
+ {range: "B2:C4", styles: {background_color: "CCCCCC"}},
31
+ {range: {rows: 1, columns: :all}, styles: {bold: true}},
32
+ {range: {rows: (0..5), columns: (1..4)}, styles: {italic: true}},
33
+ {range: {rows: :all, columns: (3..4)}, styles: {color: "999999"}}
34
+ ],
35
+
36
+ borders: [
37
+ {range: "B2:C4"},
38
+ {range: "D6:D7", border_styles: {style: :dashDot, color: "333333"}},
39
+ {range: {rows: (2..11), columns: :all}, border_styles: {edges: [:top,:bottom]}},
40
+ {range: {rows: 3, columns: 4}, border_styles: {edges: [:top,:bottom]}}
41
+ ],
42
+
43
+ merges: [
44
+ {range: "A1:C1"},
45
+ {range: {rows: 2, columns: :all}},
46
+ {range: {rows: (3..4), columns: (0..3)}}
47
+ ],
48
+
49
+ column_types: [
50
+ :string,
51
+ :integer,
52
+ :float,
53
+ :boolean,
54
+ nil,
55
+ ],
56
+ })
57
+
58
+ # Using Array Data
59
+ file_data = SpreadsheetArchitect.to_xlsx(@options)
60
+
61
+ File.open(VERSIONED_BASE_PATH.join("kitchen_sink.xlsx"),'w+b') do |f|
62
+ f.write file_data
63
+ end
64
+ end
65
+
66
+ def test_ods
67
+ @options.merge!({
68
+ column_types: [
69
+ :string,
70
+ :float,
71
+ :percent,
72
+ :currency,
73
+ :date,
74
+ :time,
75
+ nil
76
+ ],
77
+ })
78
+
79
+ # Using Array Data
80
+ file_data = SpreadsheetArchitect.to_ods(@options)
81
+
82
+ File.open(VERSIONED_BASE_PATH.join("kitchen_sink.ods"),'w+b') do |f|
83
+ f.write file_data
84
+ end
85
+ end
86
+
87
+ end
@@ -0,0 +1,29 @@
1
+ require 'test_helper'
2
+
3
+ class MultiSheetTest < ActiveSupport::TestCase
4
+
5
+ def setup
6
+ @test_data = [[1,2,3], [4,5,6], [7,8,9]]
7
+ end
8
+
9
+ test "xlsx" do
10
+ package = Post.to_axlsx_package
11
+ package = CustomPost.to_axlsx_package({sheet_name: 'Latest Projects'}, package)
12
+ package = SpreadsheetArchitect.to_axlsx_package({data: @test_data, sheet_name: 'Another Sheet'}, package)
13
+
14
+ File.open(VERSIONED_BASE_PATH.join("multi_sheet.xlsx"),'w+b') do |f|
15
+ f.write package.to_stream.read
16
+ end
17
+ end
18
+
19
+ test "ods" do
20
+ spreadsheet = Post.to_rodf_spreadsheet
21
+ spreadsheet = CustomPost.to_rodf_spreadsheet({sheet_name: 'Latest Projects'}, spreadsheet)
22
+ spreadsheet = SpreadsheetArchitect.to_rodf_spreadsheet({data: @test_data, sheet_name: 'Another Sheet'}, spreadsheet)
23
+
24
+ File.open(VERSIONED_BASE_PATH.join("multi_sheet.ods"),'w+b') do |f|
25
+ f.write spreadsheet.bytes
26
+ end
27
+ end
28
+
29
+ end
@@ -0,0 +1,179 @@
1
+ require 'test_helper'
2
+
3
+ class UtilsTest < ActiveSupport::TestCase
4
+ klass = SpreadsheetArchitect::Utils
5
+
6
+ def setup
7
+ @options = {
8
+ header_style: {background_color: 'AAAAAA', color: 'FFFFFF', align: :center, font_name: 'Arial', font_size: 10, bold: false, italic: false, underline: false},
9
+ row_style: {background_color: nil, color: '000000', align: :left, font_name: 'Arial', font_size: 10, bold: false, italic: false, underline: false},
10
+ sheet_name: 'My Project Export',
11
+ column_styles: [],
12
+ range_styles: [],
13
+ merges: [],
14
+ borders: [],
15
+ column_types: [],
16
+ column_widths: [],
17
+
18
+ headers: ['test1', 'test2','test3'],
19
+ data: [
20
+ ['row1'],
21
+ ['row2 c1', 'row2 c2'],
22
+ ['the','data']
23
+ ]
24
+ }
25
+ end
26
+
27
+ def teardown
28
+ end
29
+
30
+ test "get_cell_data" do
31
+ assert klass.get_cell_data(@options, SpreadsheetArchitect)
32
+
33
+ assert klass.get_cell_data(@options, Post)
34
+
35
+ assert klass.get_options({}, SpreadsheetArchitect)
36
+
37
+ assert_raise SpreadsheetArchitect::Exceptions::MultipleDataSourcesError do
38
+ klass.get_cell_data(@options.merge(instances: []), SpreadsheetArchitect)
39
+ end
40
+
41
+ ### using Data option
42
+ output = klass.get_cell_data(@options.merge(headers: true), SpreadsheetArchitect)
43
+ assert_equal false, output[:headers]
44
+
45
+ output = klass.get_cell_data(@options.merge(column_types: nil), SpreadsheetArchitect)
46
+ assert_nil output[:column_types]
47
+
48
+ output = klass.get_cell_data(@options.merge(column_types: []), SpreadsheetArchitect)
49
+ assert_nil output[:column_types]
50
+
51
+ output = klass.get_cell_data(@options.merge(column_types: [:string]), SpreadsheetArchitect)
52
+ assert_equal output[:column_types], [:string]
53
+
54
+ headers = [[1,2,3], [3,4,5]]
55
+ output = klass.get_cell_data(@options.merge(headers: headers), SpreadsheetArchitect)
56
+ assert_equal headers, output[:headers]
57
+
58
+ ### Using instances option
59
+ output = klass.get_cell_data(@options.merge(data: nil), Post.all)
60
+ assert output[:instances].is_a?(Array)
61
+
62
+ output = klass.get_cell_data(@options.merge(data: nil), Post.limit(0))
63
+ assert output[:instances].is_a?(Array)
64
+
65
+ assert_raise SpreadsheetArchitect::Exceptions::NoDataError do
66
+ klass.get_cell_data(@options.merge(data: nil, instances: nil), SpreadsheetArchitect)
67
+ end
68
+
69
+ output = klass.get_cell_data(@options.merge(data: nil, instances: [PlainRubyObject.new]), SpreadsheetArchitect)
70
+ assert output[:instances].count == 1
71
+ end
72
+
73
+ test "get_options" do
74
+ ### Empty
75
+ assert_not_empty klass.get_options({}, SpreadsheetArchitect)
76
+
77
+ ### using SpreadsheetArchitect
78
+ assert_not_empty klass.get_options(@options, SpreadsheetArchitect)
79
+
80
+ ### with model defaults via SPREADSHEET_OPTIONS
81
+ assert defined?(CustomPost::SPREADSHEET_OPTIONS)
82
+ assert klass.get_options(@options, CustomPost)
83
+
84
+ ### without model defaults via SPREADSHEET_OPTIONS
85
+ assert_not_empty klass.get_options(@options, Post)
86
+
87
+ ### without :headers removes :header_style
88
+ assert_equal klass.get_options({header_style: false, headers: false}, SpreadsheetArchitect)[:header_style], false
89
+
90
+ ### sets :sheet_name if needed
91
+ assert_equal klass.get_options({sheet_name: false}, SpreadsheetArchitect)[:sheet_name], 'Sheet1'
92
+
93
+ ### sets :sheet_name if needed, using pluralized only when using Rails
94
+ assert_equal klass.get_options({sheet_name: false}, Post)[:sheet_name], 'Posts'
95
+ end
96
+
97
+ test "convert_styles_to_ods" do
98
+ ods_styles = klass.convert_styles_to_ods({
99
+ background_color: '333333',
100
+ color: '000000',
101
+ align: true,
102
+ bold: true,
103
+ font_size: 14,
104
+ italic: true,
105
+ underline: true,
106
+ test: true
107
+ })
108
+
109
+ assert_equal(ods_styles, {
110
+ 'cell' => {
111
+ 'background-color' => '#333333'
112
+ },
113
+ 'text' => {
114
+ 'color' => '#000000',
115
+ 'align' => true,
116
+ 'font-weight' => 'bold',
117
+ 'font-size' => 14,
118
+ 'font-style' => 'italic',
119
+ 'text-underline-type' => 'single',
120
+ 'text-underline-style' => 'solid'
121
+ }
122
+ })
123
+ end
124
+
125
+ test "is_ar_model" do
126
+ assert klass.is_ar_model?(Post)
127
+
128
+ assert_not klass.is_ar_model?(SpreadsheetArchitect)
129
+ end
130
+
131
+ test "str_titleize" do
132
+ assert_equal(klass.str_titleize('my_project_export'), 'My Project Export')
133
+ assert_equal(klass.str_titleize('My Project Export'), 'My Project Export')
134
+ assert_equal(klass.str_titleize('TBS report'), 'TBS Report')
135
+ end
136
+
137
+ test "check_option_type" do
138
+ klass.check_option_type(@options, :data, Array)
139
+
140
+ klass.check_option_type(@options, :foo, Array)
141
+
142
+ assert_raise SpreadsheetArchitect::Exceptions::InvalidTypeError do
143
+ klass.check_option_type({foo: :bar}, :foo, Array)
144
+ end
145
+ end
146
+
147
+ test "verify_option_types" do
148
+ klass.verify_option_types(@options)
149
+
150
+ assert_raise SpreadsheetArchitect::Exceptions::InvalidTypeError do
151
+ klass.verify_option_types(@options.merge({column_widths: :foobar}))
152
+ end
153
+ end
154
+
155
+ test "stringify_keys" do
156
+ hash = klass.stringify_keys
157
+ assert_empty hash
158
+
159
+ hash = klass.stringify_keys({foo: :bar})
160
+ assert_nil hash[:foo]
161
+ assert_equal hash['foo'], :bar
162
+
163
+ hash = klass.stringify_keys({foo: :bar, 'bar' => :foo})
164
+ assert_nil hash[:foo]
165
+ assert_equal hash['foo'], :bar
166
+
167
+ hash = klass.stringify_keys({foo: {foo: :bar}})
168
+ assert_nil hash[:foo]
169
+ assert_equal hash['foo']['foo'], :bar
170
+
171
+ hash = klass.stringify_keys({foo: {foo: {foo: :bar}}})
172
+ assert_nil hash[:foo]
173
+ assert_equal hash['foo']['foo']['foo'], :bar
174
+
175
+ hash = klass.stringify_keys({foo: {foo: {foo: {foo: :bar}}}})
176
+ assert_nil hash[:foo]
177
+ assert_equal hash['foo']['foo']['foo']['foo'], :bar
178
+ end
179
+ end