klipp 0.0.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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