PageRenderTime 47ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/test/unit/generator_test.rb

https://github.com/amacdougall/project-sprouts
Ruby | 387 lines | 313 code | 55 blank | 19 comment | 9 complexity | e40ec17f82c2095ecab2443eec401868 MD5 | raw file
  1. require 'test_helper'
  2. class GeneratorTest < Test::Unit::TestCase
  3. include Sprout::TestHelper
  4. context "The Sprout::Generator" do
  5. should "identify a default set of search paths" do
  6. File.stubs(:directory?).returns true
  7. ENV['SPROUT_GENERATORS'] = Dir.pwd
  8. paths = Sprout::Generator.search_paths
  9. assert_equal File.join('config', 'generators'), paths.shift
  10. assert_equal File.join('vendor', 'generators'), paths.shift
  11. assert_equal Sprout.generator_cache, paths.shift
  12. assert_equal Dir.pwd, paths.shift
  13. end
  14. should "return empty search paths if no defaults are found" do
  15. File.stubs(:directory?).returns false
  16. paths = Sprout::Generator.search_paths
  17. assert_equal [], paths
  18. end
  19. end
  20. context "A new application generator" do
  21. setup do
  22. @fixture = File.join fixtures, 'generators', 'fake'
  23. @templates = File.join fixtures, 'generators', 'templates'
  24. @string_io = StringIO.new
  25. @generator = configure_generator FakeGenerator.new
  26. Sprout::Generator.register OtherFakeGenerator
  27. FileUtils.mkdir_p @fixture
  28. end
  29. teardown do
  30. remove_file @fixture
  31. end
  32. context "that is asked to execute/create" do
  33. should "default path to pwd" do
  34. generator = FakeGenerator.new
  35. assert_equal Dir.pwd, generator.path
  36. end
  37. should "create outer directory and file" do
  38. @generator.input = 'some_project'
  39. @generator.execute
  40. project = File.join(@fixture, 'some_project')
  41. assert_directory project
  42. assert_file File.join(project, 'SomeFile')
  43. assert_directory File.join(project, 'src')
  44. assert_file File.join(project, 'src', 'SomeProject.as') do |content|
  45. assert_matches /public class SomeProject/, content
  46. assert_matches /public function SomeProject/, content
  47. end
  48. end
  49. should "show template paths and nothing else" do
  50. @generator.parse! ['--show-template-paths']
  51. output = @generator.execute
  52. assert_equal 7, output.split("\n").size
  53. end
  54. should "not clobber existing files" do
  55. dir = File.join(@fixture, 'some_project', 'src')
  56. FileUtils.mkdir_p dir
  57. File.open File.join(dir, 'SomeProject.as'), 'w+' do |f|
  58. f.write "Hello World"
  59. end
  60. @generator.input = 'some_project'
  61. @generator.execute
  62. assert_matches /Hello World/, File.read(File.join(dir, 'SomeProject.as'))
  63. end
  64. should "clobber existing files if --force" do
  65. dir = File.join(@fixture, 'some_project', 'src')
  66. FileUtils.mkdir_p dir
  67. File.open File.join(dir, 'SomeProject.as'), 'w+' do |f|
  68. f.write "Hello World"
  69. end
  70. @generator.input = 'some_project'
  71. @generator.force = true
  72. @generator.execute
  73. assert_matches /public function SomeProject/, File.read(File.join(dir, 'SomeProject.as'))
  74. end
  75. should "call another generator" do
  76. @generator.external = true
  77. @generator.execute
  78. assert_file File.join(@fixture, 'some_project', 'SomeOtherOtherFile') do |content|
  79. assert_matches /We are agents of the free?/, content
  80. end
  81. end
  82. should "copy templates from the first found template path" do
  83. @generator.input = 'some_project'
  84. @generator.band_name = 'R.E.M.'
  85. @generator.execute
  86. assert_file File.join(@fixture, 'some_project', 'SomeFile') do |content|
  87. assert_matches /got my Orange Crush - R.E.M./, content
  88. end
  89. end
  90. should "respect updates from subclasses" do
  91. @generator = configure_generator SubclassedGenerator.new
  92. @generator.input = 'some_project'
  93. @generator.force = true
  94. @generator.execute
  95. assert_file File.join(@fixture, 'some_project', 'SomeFile') do |content|
  96. assert_matches /Living Jest enough for the City and SomeProject/, content
  97. end
  98. end
  99. should "use concrete template when provided" do
  100. @generator.input = 'some_project'
  101. @generator.execute
  102. assert_file File.join(@fixture, 'some_project', 'SomeOtherFile') do |content|
  103. assert_matches /I've had my fun/, content
  104. end
  105. end
  106. should "raise missing template error if expected template is not found" do
  107. @generator = configure_generator MissingTemplateGenerator.new
  108. assert_raises Sprout::Errors::MissingTemplateError do
  109. @generator.execute
  110. end
  111. assert !File.exists?(File.join(@fixture, 'some_project')), "Shouldn't leave half-generated files around"
  112. end
  113. should "notify user of all files created" do
  114. @generator.input = 'some_project'
  115. @string_io.expects(:puts).with('Skipped directory: .')
  116. @string_io.expects(:puts).with('Created directory: ./some_project')
  117. @string_io.expects(:puts).with('Created file: ./some_project/SomeFile')
  118. @string_io.expects(:puts).with('Created file: ./some_project/SomeOtherFile')
  119. @string_io.expects(:puts).with('Created directory: ./some_project/src')
  120. @string_io.expects(:puts).with('Created file: ./some_project/src/SomeProject.as')
  121. @generator.execute
  122. end
  123. should "not notify if quiet is true" do
  124. @generator.input = 'some_project'
  125. @generator.quiet = true
  126. @string_io.expects(:puts).never
  127. @generator.execute
  128. end
  129. should "only have one param in class definition" do
  130. assert_equal 3, FakeGenerator.static_parameter_collection.size
  131. assert_equal 2, FakeGenerator.static_default_value_collection.size
  132. end
  133. should "not update superclass parameter collection" do
  134. assert_equal 7, Sprout::Generator::Base.static_parameter_collection.size
  135. assert_equal 1, Sprout::Generator::Base.static_default_value_collection.size
  136. end
  137. ##
  138. # TODO: Add ability to prompt the user if requested files already exist,
  139. # and force != true
  140. end
  141. context "that is asked to unexecute/delete" do
  142. setup do
  143. @generator.input = 'some_project'
  144. @generator.execute
  145. @project = File.join @fixture, 'some_project'
  146. @file = File.join @project, 'SomeFile'
  147. assert_file File.join(@fixture, 'some_project')
  148. end
  149. should "remove the expected files" do
  150. @generator.unexecute
  151. assert !File.exists?(@project), "Project should be deleted"
  152. end
  153. should "remove the expected files if destroy == true" do
  154. @generator.destroy = true
  155. @generator.execute
  156. assert !File.exists?(@project), "Project should be deleted"
  157. end
  158. should "not remove files (or their parents) that have been edited" do
  159. # Edit the file:
  160. File.open @file, 'w+' do |f|
  161. f.write "New Content"
  162. end
  163. @generator.unexecute
  164. assert !File.exists?(File.join(@project, 'src')), "src dir should be removed"
  165. assert_file @file, "Edited files should not be removed"
  166. end
  167. should "remove edited files if force is true" do
  168. # Edit the file:
  169. File.open @file, 'w+' do |f|
  170. f.write "New Content"
  171. end
  172. @generator.force = true
  173. @generator.unexecute
  174. assert !File.exists?(@project), "Project dir should be removed"
  175. end
  176. should "not remove directories that have files in them" do
  177. @file = File.join(@project, 'SomeNewFile.as')
  178. File.open(@file, 'w+') do |f|
  179. f.write 'New Content'
  180. end
  181. @generator.unexecute
  182. assert_file @file, 'New file should not be removed'
  183. end
  184. end
  185. end
  186. private
  187. def configure_generator generator
  188. generator.input = 'some_project'
  189. generator.logger = @string_io
  190. generator.path = @fixture
  191. generator.templates << @templates
  192. generator
  193. end
  194. ##
  195. # This is a fake Generator that should
  196. # exercise the inputs.
  197. class FakeGenerator < Sprout::Generator::Base
  198. add_param :external, Boolean
  199. ##
  200. # Register this generator by input, type and version
  201. #register :application, :fake, '1.0.pre'
  202. ##
  203. # Some argument for the Fake Generator
  204. add_param :band_name, String, { :default => 'Styx' }
  205. ##
  206. # Source path
  207. add_param :src, String, { :default => 'src' }
  208. ##
  209. # The package (usually Gem) name
  210. set :pkg_name, 'generator_test'
  211. ##
  212. # The package version
  213. set :pkg_version, '1.0.pre'
  214. def class_name
  215. @class_name ||= input.camel_case
  216. end
  217. def manifest
  218. directory input do
  219. template 'SomeFile'
  220. template 'SomeOtherFile', 'OtherFileTemplate'
  221. generator :other_fake if external
  222. directory src do
  223. template "#{class_name}.as", 'Main.as'
  224. end
  225. end
  226. end
  227. end
  228. class OtherFakeGenerator < Sprout::Generator::Base
  229. add_param :band_name, String, { :default => 'Barf' }
  230. def manifest
  231. directory input do
  232. template 'SomeOtherOtherFile', 'OtherFileTemplate'
  233. end
  234. end
  235. end
  236. context "an unregistered generator" do
  237. setup do
  238. @generators = File.join fixtures, 'generators'
  239. @path = File.join @generators, 'fake'
  240. @project = File.join @path, 'SomeProject'
  241. $:.unshift @generators
  242. end
  243. teardown do
  244. $:.shift
  245. remove_file @path
  246. end
  247. should "fail to find unknown generator" do
  248. assert_raises Sprout::Errors::LoadError do
  249. generator = Sprout::Generator.load :demo, 'unknown_file', '>= 1.0.pre'
  250. end
  251. end
  252. should "be loadable if it's in the load path" do
  253. generator = Sprout::Generator.load :application, 'temp_generator', '>= 1.0.pre'
  254. assert_not_nil generator
  255. generator.logger = StringIO.new
  256. generator.path = @path
  257. generator.input = 'SomeProject'
  258. generator.execute
  259. assert_file @project, "Should have created project folder"
  260. end
  261. end
  262. context "a generator that is a subclass of another" do
  263. # Require the source files for this context
  264. require 'fixtures/generators/song_generator'
  265. require 'fixtures/generators/song_subclass/least_favorite'
  266. setup do
  267. @path = File.join(fixtures, 'generators', 'tmp')
  268. FileUtils.mkdir_p @path
  269. @song_generator = SongGenerator.new
  270. @song_generator.logger = StringIO.new
  271. @song_generator.path = @path
  272. @least_favorite = LeastFavorite.new
  273. @least_favorite.logger = StringIO.new
  274. @least_favorite.path = @path
  275. end
  276. teardown do
  277. remove_file @path
  278. end
  279. should "select templates from where it's defined - not it's superclass" do
  280. @song_generator.favorite = 'I Feel Better'
  281. @song_generator.execute
  282. assert_file File.join(@path, 'i_feel_better.txt') do |content|
  283. assert_matches /Your favorite song is 'I Feel Better'/, content
  284. end
  285. @least_favorite.favorite = 'I Feel Better'
  286. @least_favorite.execute
  287. assert_file File.join(@path, 'sucky', 'i_feel_better.txt') do |content|
  288. assert_matches /Your LEAST favorite song is 'I Feel Better'/, content
  289. end
  290. end
  291. end
  292. class SubclassedGenerator < FakeGenerator
  293. add_param :new_param, String, { :default => 'Other' }
  294. def manifest
  295. super
  296. directory input do
  297. template 'SomeFile', 'SomeSubclassFile'
  298. end
  299. end
  300. end
  301. ##
  302. # This is a broken generator that should fail
  303. # with a MissingTemplateError
  304. class MissingTemplateGenerator < Sprout::Generator::Base
  305. def manifest
  306. directory input do
  307. template 'FileWithNoTemplate'
  308. end
  309. end
  310. end
  311. end