klipp 0.0.1 → 0.2.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 (73) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/.travis.yml +5 -0
  4. data/README.md +13 -26
  5. data/bin/klipp +1 -1
  6. data/klipp.gemspec +11 -6
  7. data/lib/klipp/configuration.rb +0 -4
  8. data/lib/klipp/creator.rb +78 -0
  9. data/lib/klipp/parameter_list.rb +3 -3
  10. data/lib/klipp/version.rb +1 -1
  11. data/lib/klipp.rb +148 -92
  12. data/lib/template/spec.rb +231 -0
  13. data/lib/template/token.rb +81 -0
  14. data/lib/template.rb +59 -0
  15. data/spec/fixtures/ambiguous-repo/Ambiguous/Ambiguous.klippspec +5 -0
  16. data/spec/fixtures/projects/Klippfile +26 -0
  17. data/spec/fixtures/projects/Klippfile-after-prepare +27 -0
  18. data/spec/fixtures/projects/Klippfile-ambiguous +1 -0
  19. data/spec/fixtures/projects/Klippfile-bad-ruby +3 -0
  20. data/spec/fixtures/projects/Klippfile-minimal +1 -0
  21. data/spec/fixtures/projects/Klippfile-unambiguous +1 -0
  22. data/spec/fixtures/template-repository/Ambiguous/Ambiguous.klippspec +5 -0
  23. data/spec/fixtures/template-repository/Another-Template/Another-Template.klippspec +20 -0
  24. data/spec/fixtures/template-repository/BadExample/BadExample.klippspec +35 -0
  25. data/spec/fixtures/template-repository/Empty/Empty.klippspec +20 -0
  26. data/spec/fixtures/template-repository/Example/.gitignore +10 -0
  27. data/spec/fixtures/template-repository/Example/Example.klippspec +40 -0
  28. data/spec/fixtures/template-repository/Example/Podfile +10 -0
  29. data/spec/fixtures/template-repository/Example/XXBLANKXX.hidden +10 -0
  30. data/spec/fixtures/template-repository/Example/XXPROJECT_IDXX/Config/Base.xcconfig +8 -0
  31. data/spec/fixtures/template-repository/Example/XXPROJECT_IDXX/Images/Default-568h@2x.png +0 -0
  32. data/spec/fixtures/template-repository/Example/XXPROJECT_IDXX/Images/Default.png +0 -0
  33. data/spec/fixtures/template-repository/Example/XXPROJECT_IDXX/Images/Default@2x.png +0 -0
  34. data/spec/fixtures/template-repository/Example/XXPROJECT_IDXX/Source/XXCLASS_PREFIXXXAppDelegate.h +13 -0
  35. data/spec/fixtures/template-repository/Example/XXPROJECT_IDXX/Source/XXCLASS_PREFIXXXAppDelegate.m +30 -0
  36. data/spec/fixtures/template-repository/Example/XXPROJECT_IDXX/Source/XXCLASS_PREFIXXXRootViewController.h +11 -0
  37. data/spec/fixtures/template-repository/Example/XXPROJECT_IDXX/Source/XXCLASS_PREFIXXXRootViewController.m +30 -0
  38. data/spec/fixtures/template-repository/Example/XXPROJECT_IDXX/XXPROJECT_TITLEXX-Info.plist +38 -0
  39. data/spec/fixtures/template-repository/Example/XXPROJECT_IDXX/XXPROJECT_TITLEXX-Prefix.pch +14 -0
  40. data/spec/fixtures/template-repository/Example/XXPROJECT_IDXX/en.lproj/Localizable.strings +1 -0
  41. data/spec/fixtures/template-repository/Example/XXPROJECT_IDXX/main.m +17 -0
  42. data/spec/fixtures/template-repository/Example/XXPROJECT_IDXX/nl.lproj/Localizable.strings +1 -0
  43. data/spec/fixtures/template-repository/Example/XXPROJECT_IDXX.xcodeproj/project.pbxproj +466 -0
  44. data/spec/fixtures/template-repository/Example/XXPROJECT_IDXX.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  45. data/spec/fixtures/template-repository/Example/XXPROJECT_IDXXTests/XXPROJECT_TITLEXXTests.m +22 -0
  46. data/spec/fixtures/template-repository/Interactive/Interactive.klippspec +15 -0
  47. data/spec/fixtures/template-repository/Interactive/XXSUBJECT_UNDER_TESTXXTests.m +15 -0
  48. data/spec/klipp/configuration_spec.rb +8 -0
  49. data/spec/klipp/creator_spec.rb +120 -0
  50. data/spec/klipp_spec.rb +80 -85
  51. data/spec/spec_helper.rb +8 -2
  52. data/spec/template/spec_spec.rb +225 -0
  53. data/spec/template/token_spec.rb +100 -0
  54. data/spec/template_spec.rb +82 -0
  55. metadata +118 -43
  56. data/lib/klipp/buffered_output.rb +0 -17
  57. data/lib/klipp/project.rb +0 -46
  58. data/lib/klipp/template.rb +0 -50
  59. data/lib/klipp/token.rb +0 -35
  60. data/spec/fixtures/klipps/Example.klippfile +0 -4
  61. data/spec/fixtures/klipps/ExcessiveExample.klippfile +0 -5
  62. data/spec/fixtures/klipps/Generated.klippfile +0 -11
  63. data/spec/fixtures/klipps/LackingExample.klippfile +0 -3
  64. data/spec/fixtures/klipps/MalformedExample.klippfile +0 -4
  65. data/spec/fixtures/klipps/single-token.yml +0 -5
  66. data/spec/fixtures/templates/Example/RegularFileWithContents.txt +0 -3
  67. data/spec/fixtures/templates/Example/XXCLASS_PREFIXXXPrefixedFile.txt +0 -3
  68. data/spec/fixtures/templates/Example/XXPROJECT_IDXX/BinaryFile.png +0 -0
  69. data/spec/fixtures/templates/Example/XXPROJECT_IDXX/XXCLASS_PREFIXXXPrefixedFileInDirectory.txt +0 -3
  70. data/spec/fixtures/templates/Example.yml +0 -29
  71. data/spec/klipp/project_spec.rb +0 -46
  72. data/spec/klipp/template_spec.rb +0 -80
  73. data/spec/klipp/token_spec.rb +0 -86
@@ -0,0 +1,120 @@
1
+ # coding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe Klipp::Creator do
5
+
6
+ it 'stores values for template tokens' do
7
+ creator = Klipp::Creator.new()
8
+ creator.tokens[:PROJECT_ID] = 'A project id'
9
+ creator.tokens[:PROJECT_ID].should eq 'A project id'
10
+ end
11
+
12
+ context 'concerning klippfiles' do
13
+
14
+ before do
15
+ Klipp::Configuration.stubs(:root_dir).returns(File.join(File.dirname(__dir__), 'fixtures'))
16
+ File.directory?(Klipp::Configuration.root_dir).should be true
17
+ end
18
+
19
+ context 'from file' do
20
+
21
+ context 'a minimal klippfile' do
22
+
23
+ it 'validates' do
24
+ creator = Klipp::Creator.new()
25
+ creator.expects(:invalidate).never
26
+
27
+ path = fixture_path('Klippfile-minimal')
28
+ string = read_fixture('Klippfile-minimal')
29
+ creator.eval_string(string, path)
30
+ end
31
+
32
+ end
33
+
34
+ context 'an invalid klippfile' do
35
+
36
+ it "raises an error if it's bad ruby" do
37
+ creator = Klipp::Creator.new()
38
+ creator.expects(:invalidate).never
39
+
40
+ path = fixture_path('Klippfile-bad-ruby')
41
+ string = read_fixture('Klippfile-bad-ruby')
42
+ expect { creator.eval_string(string, path) }.to raise_error RuntimeError
43
+ end
44
+
45
+ it "raises an error the Klippfile doesn't exist" do
46
+ File.stubs(:exists?).returns false
47
+ expect { Klipp::Creator.from_file ('anywhere/Klippfile') }.to raise_error RuntimeError
48
+ end
49
+
50
+ it 'warns about unambiguous templates' do
51
+ creator = Klipp::Creator.new()
52
+ path = fixture_path('Klippfile-unambiguous')
53
+ string = read_fixture('Klippfile-unambiguous')
54
+ expect { creator.eval_string(string, path) }.to raise_error Klipp::Hint
55
+ end
56
+
57
+ it 'raises an error for unknown templates' do
58
+ creator = Klipp::Creator.new()
59
+ expect { creator.eval_string("create 'Amnesia'", 'fictional-klippspec.rb') }.to raise_error RuntimeError
60
+ end
61
+
62
+ it 'raises an error for empty templates' do
63
+ creator = Klipp::Creator.new()
64
+ expect { creator.eval_string("create ''", 'fictional-klippspec.rb') }.to raise_error RuntimeError
65
+ end
66
+ end
67
+
68
+ context 'a valid klippfile' do
69
+
70
+ it 'initializes from a klippfile' do
71
+ Klipp::Creator.from_file(fixture_path('Klippfile')).should be_an_instance_of Klipp::Creator
72
+ end
73
+
74
+ it 'validates ambiguous templates' do
75
+ creator = Klipp::Creator.new()
76
+ creator.expects(:invalidate).never
77
+ path = fixture_path('Klippfile-ambiguous')
78
+ string = read_fixture('Klippfile-ambiguous')
79
+ creator.eval_string(string, path)
80
+ end
81
+
82
+ end
83
+
84
+ end
85
+
86
+ context 'from user input' do
87
+
88
+ before do
89
+ @input = StringIO.new
90
+ @output = StringIO.new
91
+ @highline = HighLine.new(@input, @output)
92
+ end
93
+
94
+ it 'validates' do
95
+ creator = Klipp::Creator.new()
96
+ creator.expects(:invalidate).never
97
+
98
+ @input << "Object\ny\n"
99
+ @input.rewind
100
+
101
+ creator.ask_user_input('Interactive', @highline)
102
+ end
103
+
104
+ it 'invalidates booleans and asks again' do
105
+ creator = Klipp::Creator.new()
106
+ creator.expects(:invalidate).never
107
+
108
+ @input << "Object\nja\ny\n"
109
+ @input.rewind
110
+
111
+ creator.ask_user_input('Interactive', @highline)
112
+ p @output.string
113
+ end
114
+
115
+ end
116
+
117
+ end
118
+
119
+
120
+ end
data/spec/klipp_spec.rb CHANGED
@@ -3,137 +3,132 @@ require 'spec_helper'
3
3
 
4
4
  describe Klipp do
5
5
 
6
- before do
7
- @output = Klipp.output = StringIO.new
8
- end
9
-
10
- describe 'when routing' do
6
+ context 'capturing stdout' do
11
7
 
12
- it 'prints help without any parameters' do
13
- expect { Klipp.route *%w[] }.to raise_error SystemExit
14
- should include 'Xcode templates for the rest of us.'
8
+ it 'matches stdout' do
9
+ capture_stdout {
10
+ puts "I'm out"
11
+ }.should eq "I'm out\n"
15
12
  end
16
13
 
17
- it 'prints warnings accordingly' do
18
- expect { Klipp.route *%w[prepare Bullshit] }.to raise_error SystemExit
19
- should include '[!]'
14
+ it 'matches formatador stdout' do
15
+ capture_stdout {
16
+ Formatador.display_line "I'm [green]green[/]"
17
+ }.should include "green"
20
18
  end
21
19
 
22
- it 'raises a warning when routing unknown commands' do
23
- expect { Klipp.route *%w[allyourbase] }.to raise_error SystemExit
24
- should include '[!]'
25
- end
20
+ end
21
+
22
+ context 'when routing commands' do
26
23
 
27
- it 'routes `prepare`' do
28
- Klipp.expects(:prepare)
29
- Klipp.route *%w[prepare Example]
24
+ it 'returns exit code 1 without any commands and displays a hint' do
25
+ (capture_stdout do
26
+ Klipp.route(*%w[]).should eq 1
27
+ end).should include '[?]'
30
28
  end
31
29
 
32
- it 'prints help when preparing without a template name' do
33
- expect { Klipp.route *%w[prepare] }.to raise_error SystemExit
34
- should include 'Add a template name to the `prepare` command.'
30
+ it 'returns exit code 1 with an unknown command and displays the error' do
31
+ (capture_stdout do
32
+ Klipp.route(*%w[magic]).should eq 1
33
+ end).should include '[!]'
35
34
  end
36
35
 
37
- it 'routes `list`' do
38
- Klipp.expects(:list)
39
- Klipp.route *%w[list]
36
+ it 'routes prepare' do
37
+ Klipp.expects(:cli_prepare).with(['Example'])
38
+ Klipp.route(*%w[prepare Example])
40
39
  end
41
40
 
42
- it 'routes `version`' do
43
- Klipp.expects(:version)
44
- Klipp.route *%w[version]
41
+ it 'routes create' do
42
+ Klipp.expects(:cli_create).with(['-f'])
43
+ Klipp.route(*%w[create -f])
45
44
  end
46
45
 
47
- it 'routes `create``' do
48
- Klipp.expects(:create)
49
- Klipp.route *%w[create]
46
+ it 'routes template with exit code 0' do
47
+ Template.expects(:route)
48
+ Klipp.route(*%w[template]).should eq 0
50
49
  end
51
50
 
52
51
  end
53
52
 
54
- describe 'when preparing' do
53
+ context 'prepare' do
55
54
 
56
55
  before do
57
- Klipp::Configuration.stubs(:root_dir).returns File.join(__dir__, 'fixtures')
56
+ Klipp::Configuration.stubs(:root_dir).returns(File.join(__dir__, 'fixtures'))
58
57
  end
59
58
 
60
- it 'raises help if the template argument is missing' do
61
- expect { Klipp.prepare nil }.to raise_error HelpRequest
59
+ it 'without template name raises error' do
60
+ expect { Klipp.cli_prepare([]) }.to raise_error Klipp::Hint
62
61
  end
63
62
 
64
- it 'saves a klippfile' do
65
- IO.expects(:write).with('Example.klippfile', anything).once
66
- Klipp.prepare 'Example'
67
- end
63
+ context 'without an existing Klippfile' do
64
+ before do
65
+ File.stubs(:exists?).returns(false)
66
+ end
68
67
 
69
- it 'raises an error when the template argument is incorrect' do
70
- expect { Klipp.prepare 'Bullshit' }.to raise_error RuntimeError
68
+ it 'write a new Klippfile' do
69
+ klippfile = read_fixture 'Klippfile-after-prepare'
70
+ File.expects(:write).with('Klippfile', klippfile)
71
+ Klipp.cli_prepare(%w[Example])
72
+ end
71
73
  end
72
74
 
73
- it 'raises an error when a .klippfile for the template already exists' do
74
- File.stubs(:exists?).with(anything).returns true
75
- expect { Klipp.prepare 'Example' }.to raise_error RuntimeError
76
- end
77
75
 
78
- end
76
+ context 'with an existing Klippfile' do
79
77
 
80
- describe 'when listing' do
78
+ before do
79
+ File.stubs(:exists?).returns(true)
80
+ end
81
81
 
82
- it 'lists templates' do
83
- Klipp::Configuration.stubs(:root_dir).returns File.join(__dir__, 'fixtures')
84
- Klipp.list
85
- should include 'Example'
86
- end
82
+ it 'will not overwrite' do
83
+ File.expects(:write).never
84
+ expect { Klipp.cli_prepare(%w[Example]) }.to raise_error RuntimeError
85
+ end
86
+
87
+ it 'will overwrite when forced' do
88
+ klippfile = read_fixture 'Klippfile-after-prepare'
89
+ File.expects(:write).with('Klippfile', klippfile)
90
+ Klipp.cli_prepare(%w[Example -f])
91
+ end
87
92
 
88
- it 'raises an error when there are no templates' do
89
- Klipp.expects(:template_files).returns([])
90
- expect { Klipp.list }.to raise_error RuntimeError
91
93
  end
92
94
 
93
95
  end
94
96
 
95
- describe 'when versioning' do
97
+ context 'create' do
96
98
 
97
- it 'displays the current version' do
98
- Klipp.version
99
- should include Klipp::VERSION
99
+ before do
100
+ Klipp::Configuration.stubs(:root_dir).returns(File.join(__dir__, 'fixtures'))
101
+ Dir.stubs(:pwd).returns(Dir.mktmpdir)
102
+
103
+ maker = Klipp::Creator.new
104
+ maker.eval_string(read_fixture('Klippfile'), fixture_path('Klippfile'))
105
+ Klipp::Creator.stubs(:from_file).returns(maker)
100
106
  end
101
107
 
102
- end
108
+ it 'creates files from a Klippfile' do
103
109
 
104
- describe 'when creating' do
110
+ Klipp.cli_create([])
111
+ File.exists?(File.join Dir.pwd, 'Podfile').should be true
112
+ File.exists?(File.join Dir.pwd, '.gitignore').should be true
113
+ File.exists?(File.join Dir.pwd, 'AmazingApp').should be true
114
+ File.exists?(File.join Dir.pwd, 'Example.klippspec').should be false
105
115
 
106
- before do
107
- Klipp::Configuration.stubs(:root_dir).returns File.join(__dir__, 'fixtures')
108
- @example_klippfile_contents = File.read(File.join(__dir__, 'fixtures', 'klipps', 'Example.klippfile'))
109
116
  end
110
117
 
111
- it 'calls create on a project with a named template' do
112
- mock_project = mock
113
- mock_project.expects(:create)
114
- Klipp::Project.expects(:new).with(is_a(Klipp::Template)).returns(mock_project)
115
- File.stubs(:read).with(anything).returns( @example_klippfile_contents )
116
- Klipp.create('Example')
117
- end
118
+ it 'creates files interactively' do
118
119
 
119
- it 'calls create on a project with an inferred template' do
120
- Dir.expects(:glob).with(anything, anything).returns %w(Example.klippfile)
121
- mock_project = mock
122
- mock_project.expects(:create)
123
- Klipp::Project.expects(:new).with(is_a(Klipp::Template)).returns(mock_project)
124
- File.stubs(:read).with(anything).returns( @example_klippfile_contents )
125
- Klipp.create nil
126
- end
120
+ input = StringIO.new
121
+ output = StringIO.new
122
+ highline = HighLine.new(input, output)
127
123
 
128
- it 'raises an error when the template name can\'t be inferred' do
129
- Dir.expects(:glob).with(anything, anything).returns []
130
- expect { Klipp.create nil }.to raise_error RuntimeError
131
- end
124
+ input << "KLPObject\nN\n"
125
+ input.rewind
132
126
 
133
- end
127
+ Klipp.cli_create(%w(Interactive), highline)
128
+ File.exists?(File.join Dir.pwd, 'KLPObjectTests.m').should be true
129
+
130
+ end
134
131
 
135
- def subject
136
- @output.string
137
132
  end
138
133
 
139
134
  end
data/spec/spec_helper.rb CHANGED
@@ -7,11 +7,17 @@ SimpleCov.formatter = SimpleCov::Formatter::HTMLFormatter
7
7
 
8
8
  require 'klipp'
9
9
 
10
+ def fixture_path fixture_name
11
+ Dir.glob(File.join(__dir__, 'fixtures', '**', fixture_name)).first
12
+ end
13
+
10
14
  def read_fixture fixture_name
11
- File.read(File.join(__dir__, 'fixtures', fixture_name))
15
+ File.read(fixture_path fixture_name)
12
16
  end
13
17
 
14
18
  RSpec.configure do |config|
15
19
  config.mock_framework = :mocha
16
20
  config.order = 'random'
17
- end
21
+ end
22
+
23
+ Klipp.env = StringInquirer.new('test')
@@ -0,0 +1,225 @@
1
+ require 'spec_helper'
2
+
3
+ describe Template::Spec do
4
+
5
+ context 'identifier methods' do
6
+
7
+ before do
8
+ Klipp::Configuration.stubs(:root_dir).returns(File.join(File.dirname(__dir__), 'fixtures'))
9
+ end
10
+
11
+ it 'finds the path to a template name' do
12
+ path = Template::Spec.spec_path_for_identifier('Example')
13
+ path.should eq File.join(File.dirname(__dir__), 'fixtures', 'template-repository', 'Example', 'Example.klippspec')
14
+ end
15
+
16
+ it 'raises error if a template doesn\'t exist' do
17
+ expect { Template::Spec.spec_path_for_identifier('Non-existing') }.to raise_error RuntimeError
18
+ end
19
+
20
+ it 'knows about unambiguous specs' do
21
+ Template::Spec.identifier_is_ambiguous('Ambiguous').should eq false
22
+ end
23
+
24
+ it 'raises error if a template is unambiguous' do
25
+ expect { Template::Spec.spec_path_for_identifier('Ambiguous') }.to raise_error RuntimeError, /Found multiple templates/
26
+ end
27
+
28
+ it 'finds the path to a template in a specific repo' do
29
+ path = Template::Spec.spec_path_for_identifier('template-repository/Ambiguous')
30
+ path.should eq File.join(File.dirname(__dir__), 'fixtures', 'template-repository', 'Ambiguous', 'Ambiguous.klippspec')
31
+ end
32
+
33
+ it 'deducts the template identifier from an unambiguous template name' do
34
+ path = Template::Spec.spec_path_for_identifier 'Example'
35
+ hash = Template::Spec.hash_for_spec_path path
36
+ Template::Spec.hash_to_identifier(hash).should eq 'template-repository/Example'
37
+ end
38
+
39
+ end
40
+
41
+ context 'with validation disabled' do
42
+ before do
43
+ Template::Spec.any_instance.stubs(:invalidate)
44
+ end
45
+
46
+ it 'yields on initialize' do
47
+ expect { |probe| Template::Spec.new().spec 'Example', &probe }.to yield_control
48
+ end
49
+
50
+ it 'passes itself as a parameter on yield' do
51
+ expect { |probe| Template::Spec.new().spec('Example', &probe) }.to yield_with_args(be_an_instance_of(Template::Spec))
52
+ end
53
+
54
+ it 'validates the spec after configuration' do
55
+ spec = Template::Spec.new
56
+ spec.expects(:validate_spec)
57
+ spec.spec('')
58
+ end
59
+
60
+ it 'raises an error when overwriting tokens, like the BLANK token' do
61
+ (expect do
62
+ Template::Spec.new().spec 'Example' do |spec|
63
+ spec.token :BLANK do |t|
64
+ t.comment = "You can't overwrite tokens"
65
+ end
66
+ end
67
+ end).to raise_error RuntimeError
68
+ end
69
+ end
70
+
71
+ context 'with an invalid spec' do
72
+
73
+ before do
74
+ @spec = Template::Spec.new
75
+ end
76
+
77
+ it 'invalidates' do
78
+ @spec.expects(:invalidate)
79
+ @spec.spec('')
80
+ end
81
+
82
+ it 'raises an error when invalidating' do
83
+ expect { @spec.spec('') }.to raise_error RuntimeError
84
+ end
85
+
86
+ it 'rescues and re-raises errors from the config block' do
87
+ expect { @spec.spec('Example') { |s| s.lala = 5 } }.to raise_error RuntimeError, /Invalid klippspec configuration/
88
+ end
89
+
90
+ it 'raises errors from klippspec string' do
91
+ expect { @spec.from_string('lalala', 'fake/path') }.to raise_error RuntimeError, /Error evaluating spec/
92
+ end
93
+
94
+ end
95
+
96
+ context 'with a valid spec' do
97
+
98
+ before do
99
+ @template = Template::Spec.new
100
+ @template.spec('Example') {}
101
+ end
102
+
103
+ it 'has a name' do
104
+ @template.identifier = 'repo/ProjectX'
105
+ @template.identifier.should eq 'repo/ProjectX'
106
+ end
107
+
108
+ it 'has a post-action setter' do
109
+ @template.post_action = 'pod install'
110
+ @template.post_actions.should eq ['pod install']
111
+ end
112
+
113
+ it 'has a post-actions setter' do
114
+ @template.post_actions = ['git init', 'git add .', 'git commit -m "Initial commit."', 'pod install']
115
+ @template.post_actions.should eq ['git init', 'git add .', 'git commit -m "Initial commit."', 'pod install']
116
+ end
117
+ it 'has a token hash' do
118
+ @template[:PROJECT_ID] = Template::Token.new
119
+ @template[:PROJECT_ID].should be_an_instance_of(Template::Token)
120
+ end
121
+
122
+ it 'creates a token' do
123
+ yielded_token = :not_a_token
124
+ @template.token(:PROJECT_ID) { |t| yielded_token = t }
125
+ yielded_token.should be_an_instance_of Template::Token
126
+ end
127
+
128
+ it 'has a blank token' do
129
+ @template[:BLANK].hidden.should eq true
130
+ @template[:BLANK].value.should eq ''
131
+ end
132
+
133
+ it 'has a date token' do
134
+ @template[:DATE].hidden.should eq true
135
+ @template[:DATE].value.should eq DateTime.now.strftime('%F')
136
+ end
137
+
138
+ it 'has a year token' do
139
+ @template[:YEAR].hidden.should eq true
140
+ @template[:YEAR].value.should eq '2013'
141
+ end
142
+
143
+ end
144
+
145
+ context 'when loading a klippspec' do
146
+
147
+ before do
148
+ Klipp::Configuration.stubs(:root_dir).returns(File.join(File.dirname(__dir__), 'fixtures'))
149
+ end
150
+
151
+ context 'with an invalid klippspec' do
152
+
153
+ it 'raises an error when loading an invalid klippspec' do
154
+ klippspec = File.join(Klipp::Configuration.root_dir, 'template-repository', 'BadExample', 'BadExample.klippspec')
155
+ File.exists?(klippspec).should be true
156
+ expect { Template::Spec.from_file(klippspec) }.to raise_error RuntimeError
157
+ end
158
+
159
+ end
160
+
161
+ context 'with a valid klippspec' do
162
+
163
+ before do
164
+ @path = File.join(Klipp::Configuration.root_dir, 'template-repository', 'Example', 'Example.klippspec')
165
+ File.exists?(@path).should be true
166
+
167
+ @spec = Template::Spec.from_file(@path)
168
+ end
169
+
170
+ it 'loads a spec from a file' do
171
+ @spec.should be_an_instance_of Template::Spec
172
+ end
173
+
174
+ it 'generates a project specific Klippfile' do
175
+ fixture = read_fixture 'Klippfile-after-prepare'
176
+ @spec.klippfile.should eq fixture
177
+ end
178
+
179
+ it 'references the repo in the Klippfile' do
180
+ @spec.klippfile.should include 'template-repository/Example'
181
+ end
182
+
183
+ context 'with a values hash' do
184
+ before do
185
+ @values = Hash.new
186
+ @values[:PROJECT_ID] = "Klipp"
187
+ @values[:PROJECT_TITLE] = "Templates for the rest of us"
188
+ @values[:BUNDLE_ID] = "com.epologee.klipp"
189
+ @values[:ORGANIZATION_NAME] = "epologee"
190
+ @values[:CLASS_PREFIX] = "KLP"
191
+ @values[:SECRET_TOGGLE] = true
192
+ end
193
+
194
+ it 'validates token values' do
195
+ @spec.set_token_values @values
196
+ end
197
+
198
+ it 'replaces delimited tokens with its values' do
199
+ @spec.set_token_values @values
200
+ source = 'XXPROJECT_IDXX - XXPROJECT_TITLEXX - XXBUNDLE_IDXX - XXORGANIZATION_NAMEXX - XXCLASS_PREFIXXX - XXSECRET_TOGGLEXX - [XXBLANKXX]'
201
+ target = 'Klipp - Templates for the rest of us - com.epologee.klipp - epologee - KLP - YES - []'
202
+ @spec.replace_tokens(source).should eq target
203
+ end
204
+ end
205
+
206
+
207
+ end
208
+
209
+ end
210
+
211
+ context 'when creating a klippspec' do
212
+
213
+ before do
214
+ Klipp::Configuration.stubs(:root_dir).returns(File.join(File.dirname(__dir__), 'fixtures'))
215
+ end
216
+
217
+ it 'generates the klippspec' do
218
+ spec = Template::Spec.new
219
+ spec.identifier = 'Another-Template'
220
+ spec.klippspec.should eq read_fixture('Another-Template.klippspec')
221
+ end
222
+
223
+ end
224
+
225
+ end
@@ -0,0 +1,100 @@
1
+ require 'spec_helper'
2
+
3
+ describe Template::Token do
4
+
5
+ before do
6
+ @token = Template::Token.new
7
+ end
8
+
9
+ it 'has a default string type' do
10
+ @token.type.should eq :string
11
+ end
12
+
13
+ it 'will not allow an unknown type' do
14
+ expect { @token.type = :invalid_type }.to raise_error RuntimeError
15
+ end
16
+
17
+ context 'with type string' do
18
+
19
+ it 'has a hidden property' do
20
+ @token.hidden = true
21
+ @token.hidden.should eq true
22
+ end
23
+
24
+ it 'is not hidden by default' do
25
+ @token.hidden.should eq false
26
+ end
27
+
28
+ it 'has a comment' do
29
+ @token.comment = 'Comment'
30
+ @token.comment.should eq 'Comment'
31
+ end
32
+
33
+ it 'has a validation' do
34
+ @token.validation = /^[A-Z][A-Za-z0-9]{2,}$/
35
+ @token.validation.should eq /^[A-Z][A-Za-z0-9]{2,}$/
36
+ end
37
+
38
+ it 'has a default validation hint' do
39
+ @token.validation = /^[A-Z][A-Za-z0-9]{2,}$/
40
+ @token.validation_hint.should include '(no custom validation_hint given)'
41
+ end
42
+
43
+ it 'accepts custom validation hints' do
44
+ @token.validation_hint = 'Hint'
45
+ @token.validation_hint.should eq 'Hint'
46
+ end
47
+
48
+ it 'invalidates booleans assigned' do
49
+ expect { @token.value = true }.to raise_error RuntimeError
50
+ end
51
+
52
+ end
53
+
54
+ context 'with type bool' do
55
+
56
+ before do
57
+ @token.type = :bool
58
+ end
59
+
60
+ it 'accepts boolean values' do
61
+ @token.value = true
62
+ @token.value.should eq true
63
+
64
+ @token.value = false
65
+ @token.value.should eq false
66
+ end
67
+
68
+ it 'accepts booleans as strings' do
69
+ @token.value = 'true'
70
+ @token.value.should eq true
71
+
72
+ @token.value = 'yes'
73
+ @token.value.should eq true
74
+
75
+ @token.value = 'Yes'
76
+ @token.value.should eq true
77
+
78
+ @token.value = 'y'
79
+ @token.value.should eq true
80
+
81
+ @token.value = 'false'
82
+ @token.value.should eq false
83
+
84
+ @token.value = 'no'
85
+ @token.value.should eq false
86
+
87
+ @token.value = 'No'
88
+ @token.value.should eq false
89
+
90
+ @token.value = 'n'
91
+ @token.value.should eq false
92
+ end
93
+
94
+ it 'invalidates other strings' do
95
+ expect { @token.value = 'ja' }.to raise_error RuntimeError
96
+ end
97
+
98
+ end
99
+
100
+ end