doc_test.rb 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. require 'test_helper'
  2. require 'docs'
  3. class DocsDocTest < MiniTest::Spec
  4. let :doc do
  5. Class.new Docs::Doc do
  6. self.name = 'name'
  7. self.type = 'type'
  8. end
  9. end
  10. let :page do
  11. { path: 'path', store_path: 'store_path', output: 'output', entries: [entry] }
  12. end
  13. let :entry do
  14. Docs::Entry.new 'name', 'path', 'type'
  15. end
  16. let :store do
  17. Docs::NullStore.new
  18. end
  19. describe ".inherited" do
  20. it "sets .type" do
  21. assert_equal doc.type, Class.new(doc).type
  22. end
  23. end
  24. describe ".name" do
  25. it "returns 'Doc' when the class is Docs::Doc" do
  26. assert_equal 'Doc', Docs::Doc.name
  27. end
  28. end
  29. describe ".name=" do
  30. it "stores .name" do
  31. doc.name = 'test'
  32. assert_equal 'test', doc.name
  33. end
  34. end
  35. describe ".slug" do
  36. it "returns 'doc' when the class is Docs::Doc" do
  37. assert_equal 'doc', Docs::Doc.slug
  38. end
  39. it "returns 'doc~4.2_lts' when the class is Docs::Doc and its #version is '42 LTS'" do
  40. stub(Docs::Doc).version { '4.2 LTS' }
  41. assert_equal 'doc~4.2_lts', Docs::Doc.slug
  42. end
  43. it "returns 'foo~42' when #slug has been set to 'foo' and #version to '42'" do
  44. doc.slug = 'foo'
  45. doc.version = '42'
  46. assert_equal 'foo~42', doc.slug
  47. end
  48. it "returns 'foobar' when #name has been set to 'FooBar'" do
  49. doc.name = 'FooBar'
  50. assert_equal 'foobar', doc.slug
  51. end
  52. it "raises error when #name has unsluggable characters" do
  53. assert_raises do
  54. doc.name = 'Foo-Bar'
  55. doc.slug
  56. end
  57. end
  58. end
  59. describe ".slug=" do
  60. it "stores .slug" do
  61. doc.slug = 'test'
  62. assert_equal 'test', doc.slug
  63. end
  64. end
  65. describe ".version=" do
  66. it "stores .version as a string" do
  67. doc.version = 4815162342
  68. assert_equal '4815162342', doc.version
  69. end
  70. end
  71. describe ".release=" do
  72. it "stores .release" do
  73. doc.release = '1'
  74. assert_equal '1', doc.release
  75. end
  76. end
  77. describe ".links=" do
  78. it "stores .links" do
  79. doc.links = { test: true }
  80. assert_equal({ test: true }, doc.links)
  81. end
  82. end
  83. describe ".abstract" do
  84. it "returns nil" do
  85. assert_nil doc.abstract
  86. end
  87. end
  88. describe ".abstract=" do
  89. it "stores .abstract" do
  90. doc.abstract = true
  91. assert doc.abstract
  92. end
  93. end
  94. describe ".path" do
  95. it "returns .slug" do
  96. doc.slug = 'slug'
  97. assert_equal 'slug', doc.path
  98. end
  99. end
  100. describe ".index_path" do
  101. it "returns .path + ::INDEX_FILENAME" do
  102. stub(doc).path { 'path' }
  103. assert_equal File.join('path', Docs::Doc::INDEX_FILENAME), doc.index_path
  104. end
  105. end
  106. describe ".db_path" do
  107. it "returns .path + ::DB_FILENAME" do
  108. stub(doc).path { 'path' }
  109. assert_equal File.join('path', Docs::Doc::DB_FILENAME), doc.db_path
  110. end
  111. end
  112. describe ".new" do
  113. it "raises an error when .abstract is true" do
  114. doc.abstract = true
  115. assert_raises NotImplementedError do
  116. doc.new
  117. end
  118. end
  119. end
  120. describe ".as_json" do
  121. it "returns a hash" do
  122. assert_instance_of Hash, doc.as_json
  123. end
  124. it "includes the doc's name, slug, type, version, and release" do
  125. assert_equal %i(name slug type), doc.as_json.keys
  126. %w(name slug type version release links).each do |attribute|
  127. eval "stub(doc).#{attribute} { attribute }"
  128. assert_equal attribute, doc.as_json[attribute.to_sym]
  129. end
  130. end
  131. it "includes the doc's version when it's defined and nil" do
  132. refute doc.as_json.key?(:version)
  133. doc.version = nil
  134. assert doc.as_json.key?(:version)
  135. end
  136. end
  137. describe ".store_page" do
  138. it "builds a page" do
  139. any_instance_of(doc) do |instance|
  140. stub(instance).build_page('id') { @called = true; nil }
  141. end
  142. doc.store_page(store, 'id') {}
  143. assert @called
  144. end
  145. context "when the page builds successfully" do
  146. before do
  147. any_instance_of(doc) do |instance|
  148. stub(instance).build_page { page }
  149. end
  150. end
  151. context "and it has :entries" do
  152. it "returns true" do
  153. assert doc.store_page(store, 'id')
  154. end
  155. it "stores a file" do
  156. mock(store).write(page[:store_path], page[:output])
  157. doc.store_page(store, 'id')
  158. end
  159. it "opens the .path directory before storing the file" do
  160. stub(doc).path { 'path' }
  161. stub(store).write { assert false }
  162. mock(store).open('path') do |_, block|
  163. stub(store).write
  164. block.call
  165. end
  166. doc.store_page(store, 'id')
  167. end
  168. end
  169. context "and it doesn't have :entries" do
  170. before do
  171. page[:entries] = []
  172. end
  173. it "returns false" do
  174. refute doc.store_page(store, 'id')
  175. end
  176. it "doesn't store a file" do
  177. dont_allow(store).write
  178. doc.store_page(store, 'id')
  179. end
  180. end
  181. end
  182. context "when the page doesn't build successfully" do
  183. before do
  184. any_instance_of(doc) do |instance|
  185. stub(instance).build_page { nil }
  186. end
  187. end
  188. it "returns false" do
  189. refute doc.store_page(store, 'id')
  190. end
  191. it "doesn't store a file" do
  192. dont_allow(store).write
  193. doc.store_page(store, 'id')
  194. end
  195. end
  196. end
  197. describe ".store_pages" do
  198. it "build the pages" do
  199. any_instance_of(doc) do |instance|
  200. stub(instance).build_pages { @called = true }
  201. end
  202. doc.store_pages(store) {}
  203. assert @called
  204. end
  205. context "when pages are built successfully" do
  206. let :pages do
  207. [
  208. page.deep_dup.tap { |p| page[:entries].first.tap { |e| e.name = 'one' } },
  209. page.deep_dup.tap { |p| page[:entries].first.tap { |e| e.name = 'two' } }
  210. ]
  211. end
  212. before do
  213. any_instance_of(doc) do |instance|
  214. stub(instance).build_pages { |block| pages.each(&block) }
  215. end
  216. end
  217. context "and at least one page has :entries" do
  218. it "returns true" do
  219. assert doc.store_pages(store)
  220. end
  221. it "stores a file for each page that has :entries" do
  222. pages.first.merge!(entries: [], output: '')
  223. mock(store).write(page[:store_path], page[:output])
  224. mock(store).write('index.json', anything)
  225. mock(store).write('db.json', anything)
  226. doc.store_pages(store)
  227. end
  228. it "stores an index that contains all the pages' entries" do
  229. stub(store).write(page[:store_path], page[:output])
  230. stub(store).write('db.json', anything)
  231. mock(store).write('index.json', anything) do |path, json|
  232. json = JSON.parse(json)
  233. assert_equal pages.length, json['entries'].length
  234. assert_includes json['entries'], Docs::Entry.new('one', 'path', 'type').as_json.stringify_keys
  235. end
  236. doc.store_pages(store)
  237. end
  238. it "stores a db that contains all the pages, indexed by path" do
  239. stub(store).write(page[:store_path], page[:output])
  240. stub(store).write('index.json', anything)
  241. mock(store).write('db.json', anything) do |path, json|
  242. json = JSON.parse(json)
  243. assert_equal page[:output], json[page[:path]]
  244. end
  245. doc.store_pages(store)
  246. end
  247. it "replaces the .path directory before storing the files" do
  248. stub(doc).path { 'path' }
  249. stub(store).write { assert false }
  250. mock(store).replace('path') do |_, block|
  251. stub(store).write
  252. block.call
  253. end
  254. doc.store_pages(store)
  255. end
  256. end
  257. context "and no pages have :entries" do
  258. before do
  259. pages.each { |page| page[:entries] = [] }
  260. end
  261. it "returns false" do
  262. refute doc.store_pages(store)
  263. end
  264. it "doesn't store files" do
  265. dont_allow(store).write
  266. doc.store_pages(store)
  267. end
  268. end
  269. end
  270. context "when no pages are built successfully" do
  271. before do
  272. any_instance_of(doc) do |instance|
  273. stub(instance).build_pages
  274. end
  275. end
  276. it "returns false" do
  277. refute doc.store_pages(store)
  278. end
  279. it "doesn't store files" do
  280. dont_allow(store).write
  281. doc.store_pages(store)
  282. end
  283. end
  284. end
  285. describe ".versions" do
  286. it "returns [self] if no versions have been created" do
  287. assert_equal [doc], doc.versions
  288. end
  289. end
  290. describe ".version" do
  291. context "with no args" do
  292. it "returns @version by default" do
  293. doc.version = 'v'
  294. assert_equal 'v', doc.version
  295. end
  296. end
  297. context "with args" do
  298. it "creates a version subclass" do
  299. version = doc.version('4') { self.release = '8'; self.links = ["https://#{self.version}"] }
  300. assert_equal [version], doc.versions
  301. assert_nil doc.version
  302. assert_nil doc.release
  303. refute doc.version?
  304. assert version.version?
  305. assert_equal '4', version.version
  306. assert_equal '8', version.release
  307. assert_equal 'name', version.name
  308. assert_equal 'type', version.type
  309. assert_equal ['https://4'], version.links
  310. end
  311. end
  312. end
  313. end