briefcase 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/spec/git_spec.rb ADDED
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe Briefcase::Commands::Git do
4
+
5
+ before do
6
+ create_dotfiles_directory
7
+ create_git_repo
8
+ end
9
+
10
+ after do
11
+ cleanup_dotfiles_directory
12
+ end
13
+
14
+ it "creates links to existing files" do
15
+ create_file(dotfiles_path + '/test.txt', 'testing git integration')
16
+ run_command("git status")
17
+
18
+ output_must_contain(/Running git status/)
19
+ end
20
+
21
+ end
@@ -0,0 +1,84 @@
1
+ def directory_must_exist(path)
2
+ File.directory?(path).must_equal(true, "Expected directory to exist at #{path}")
3
+ end
4
+
5
+ def directory_must_not_exist(path)
6
+ File.directory?(path).must_equal(false, "Did not expect directory to exist at #{path}")
7
+ end
8
+
9
+ def file_must_exist(path)
10
+ File.file?(path).must_equal(true, "Expected file to exist at #{path}")
11
+ end
12
+
13
+ def file_must_contain(path, text)
14
+ file_must_exist(path)
15
+ # strip trailing whitespace to make it easier to use multiline strings
16
+ File.read(path).strip.must_equal(text.strip)
17
+ end
18
+
19
+ def file_must_not_match(path, regex)
20
+ file_must_exist(path)
21
+ File.read(path).strip.wont_match(regex)
22
+ end
23
+
24
+ def file_must_not_exist(path)
25
+ File.file?(path).must_equal(false, "Expected file to not exist at #{path}")
26
+ end
27
+
28
+ def symlink_must_exist(path, target)
29
+ File.exist?(path).must_equal(true, "Expected symlink to exist at #{path}")
30
+ actual = File.readlink(path)
31
+ actual.must_equal(target, "Expected symlink to #{target}, was #{actual}")
32
+ end
33
+
34
+ def symlink_must_not_exist(path)
35
+ if File.exist?(path)
36
+ File.file?(path).must_equal true
37
+ end
38
+ end
39
+
40
+ def file_must_have_moved(original_path, new_path)
41
+ file_must_exist(new_path)
42
+ birthplace = File.open(new_path) do |file|
43
+ file.read
44
+ end
45
+ birthplace.must_equal(original_path, "Expected file at #{new_path} to have been moved from #{original_path}")
46
+ end
47
+
48
+ def file_must_not_have_moved(path)
49
+ file_must_exist(path)
50
+ birthplace = File.open(path) { |file| file.read }
51
+ birthplace.must_equal(path, "Did not expect file at #{path} to have been moved from #{birthplace}")
52
+ end
53
+
54
+ def git_ignore_must_include(path)
55
+ git_ignore_path = File.join(dotfiles_path, '.gitignore')
56
+ file_must_exist(git_ignore_path)
57
+ ignore_contents = File.open(git_ignore_path) { |file| file.read }
58
+ ignore_contents.must_match %r{^#{File.basename(path)}$}
59
+ end
60
+
61
+ def secret_must_be_stored(yaml_key, key, value)
62
+ file_must_exist(secrets_path)
63
+ @secrets = YAML.load_file(secrets_path)
64
+ @secrets[yaml_key].wont_equal(nil, "Expected YAML secrets file to contain value for key '#{yaml_key}'")
65
+ @secrets[yaml_key][key].must_equal(value)
66
+ end
67
+
68
+ def array_matches_regex(array, regex)
69
+ array.any? do |element|
70
+ element.gsub(/\e\[\d+m/, '') =~ regex
71
+ end
72
+ end
73
+
74
+ def output_must_contain(*regexes)
75
+ regexes.all? do |regex|
76
+ array_matches_regex(@output.lines, regex).must_equal(true, "Could not find #{regex} in: \n#{@output}")
77
+ end
78
+ end
79
+
80
+ def output_must_not_contain(*regexes)
81
+ regexes.any? do |regex|
82
+ array_matches_regex(@output.lines, regex).must_equal(false, "Found #{regex} in: \n#{@output}")
83
+ end
84
+ end
@@ -0,0 +1,42 @@
1
+ require "open4"
2
+
3
+ def run_command(command, expected_status=0, &block)
4
+ @output = ''
5
+
6
+ responses = []
7
+ def responses.response(regex, text)
8
+ push([regex, text])
9
+ end
10
+
11
+ if block_given?
12
+ block.call(responses)
13
+ end
14
+
15
+ ENV['BRIEFCASE_DOTFILES_PATH'] = dotfiles_path
16
+ ENV['BRIEFCASE_HOME_PATH'] = home_path
17
+ ENV['BRIEFCASE_SECRETS_PATH'] = secrets_path
18
+ ENV['BRIEFCASE_TESTING'] = 'true'
19
+ ENV['RUBYOPT'] = 'rubygems'
20
+ ENV['BRIEFCASE_EDITOR'] = File.expand_path('../bin/editor', File.dirname(__FILE__))
21
+
22
+ full_command = "./bin/briefcase #{command}"
23
+ full_command << " --trace" if ENV['BRIEFCASE_TEST_TRACE']
24
+
25
+ status = Open4.popen4(full_command) do |pid, stdin, stdout, stderr|
26
+ while output = stdout.gets() || stderr.gets()
27
+ puts output if ENV['BRIEFCASE_VERBOSE_TEST']
28
+ @output << output
29
+ responses.each do |response|
30
+ regex, text = response
31
+ stdin.write(text + "\n") if output =~ regex
32
+ end
33
+ end
34
+ end
35
+
36
+ exit_status = status.exitstatus
37
+ unless exit_status == expected_status
38
+ puts "\n" + @output + "\n" if ENV['BRIEFCASE_TEST_TRACE']
39
+ fail("Expected exist status of #{expected_status}, got #{exit_status}")
40
+ end
41
+
42
+ end
@@ -0,0 +1,56 @@
1
+ require 'fileutils'
2
+ include FileUtils
3
+
4
+ SPEC_ROOT = "/tmp/briefcase_spec_work"
5
+
6
+ def home_path
7
+ File.expand_path('briefcase_home', SPEC_ROOT)
8
+ end
9
+
10
+ def dotfiles_path
11
+ File.expand_path('briefcase_dotfiles', SPEC_ROOT)
12
+ end
13
+
14
+ def secrets_path
15
+ File.expand_path('.briefcase_secrets', home_path)
16
+ end
17
+
18
+ def editor_responses_path
19
+ File.expand_path('briefcase_editor_responses', SPEC_ROOT)
20
+ end
21
+
22
+ def create_home_directory
23
+ mkdir_p(home_path)
24
+ end
25
+
26
+ def cleanup_home_directory
27
+ rm_rf(home_path)
28
+ end
29
+
30
+ def create_git_repo
31
+ mkdir_p(File.join(dotfiles_path, '.git'))
32
+ end
33
+
34
+ def create_dotfiles_directory
35
+ mkdir_p(dotfiles_path)
36
+ end
37
+
38
+ def create_secrets(hash={})
39
+ File.open(secrets_path, "w") do |file|
40
+ file.write(hash.to_yaml)
41
+ end
42
+ end
43
+
44
+ def cleanup_dotfiles_directory
45
+ rm_rf(dotfiles_path)
46
+ end
47
+
48
+ def create_file(path, text='')
49
+ File.open(path, "w") do |file|
50
+ file.write(text)
51
+ end
52
+ end
53
+
54
+ def create_trackable_file(path)
55
+ create_file(path, path)
56
+ end
@@ -0,0 +1,25 @@
1
+ def stub_editor_response(file, text)
2
+ response_file = file.gsub(/\//, '_')
3
+ mkdir_p(editor_responses_path)
4
+ File.open(File.join(editor_responses_path, response_file), 'w') do |file|
5
+ file.write(text)
6
+ end
7
+ end
8
+
9
+ def cleanup_editor_responses
10
+ rm_rf(editor_responses_path)
11
+ end
12
+
13
+ class Object
14
+ def stub(method_name, return_value=nil, &block)
15
+ (class << self; self; end).class_eval do
16
+ define_method method_name do |*args|
17
+ if block_given?
18
+ block.call(*args)
19
+ else
20
+ return_value
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,145 @@
1
+ require 'spec_helper'
2
+
3
+ describe Briefcase::Commands::Import do
4
+
5
+ before do
6
+ create_home_directory
7
+
8
+ @original_path = File.join(home_path, '.test')
9
+ @destination_path = File.join(dotfiles_path, 'test')
10
+ end
11
+
12
+ after do
13
+ cleanup_home_directory
14
+ cleanup_dotfiles_directory
15
+ cleanup_editor_responses
16
+ end
17
+
18
+ it "creates a .dotfiles directory if it doesn't exist" do
19
+ create_trackable_file(@original_path)
20
+
21
+ run_command("import #{@original_path}") do |c|
22
+ c.response(/create one now?/, 'create')
23
+ end
24
+
25
+ output_must_contain(/Creating/)
26
+ output_must_contain(/Initialized/)
27
+ directory_must_exist(dotfiles_path)
28
+
29
+ directory_must_exist(File.join(dotfiles_path, '.git'))
30
+ end
31
+
32
+ it "does not create a .dotfiles directory when a users cancels" do
33
+ create_trackable_file(@original_path)
34
+
35
+ run_command("import #{@original_path}", 255) do |c|
36
+ c.response(/create one now?/, 'abort')
37
+ end
38
+
39
+ output_must_not_contain(/Creating/)
40
+ output_must_not_contain(/Initializing/)
41
+ directory_must_not_exist(dotfiles_path)
42
+ end
43
+
44
+ describe "with an existing dotfiles directory" do
45
+
46
+ before do
47
+ create_dotfiles_directory
48
+ create_git_repo
49
+ end
50
+
51
+ after do
52
+ cleanup_dotfiles_directory
53
+ end
54
+
55
+ it "does not import a nonexistent dotfile" do
56
+ run_command("import .test", 255)
57
+ output_must_contain(/does not exist/)
58
+ end
59
+
60
+ it "imports a dotfile" do
61
+ create_trackable_file(@original_path)
62
+
63
+ run_command("import #{@original_path}")
64
+
65
+ output_must_contain(/Importing/, /Moving/)
66
+ file_must_have_moved(@original_path, @destination_path)
67
+ symlink_must_exist(@original_path, @destination_path)
68
+ end
69
+
70
+ it "imports a redacted dotfile" do
71
+ redacted_path = File.join(dotfiles_path, 'test.redacted')
72
+ create_file @original_path, <<-TEXT
73
+ setting: ABCDEFG
74
+ TEXT
75
+
76
+ stub_editor_response redacted_path, <<-TEXT
77
+ # Edit the file below, replacing and sensitive information to turn this:
78
+ #
79
+ # password: superSecretPassword
80
+ #
81
+ # Into:
82
+ #
83
+ # password: # briefcase(password)
84
+ #
85
+ ########################################################################
86
+ setting: # briefcase(token)
87
+ TEXT
88
+
89
+ run_command("redact #{@original_path}")
90
+
91
+ output_must_contain(/Importing/, /Moving/, /Creating redacted version at/, /Storing secret value for key: token/)
92
+ secret_must_be_stored('test', 'token', 'ABCDEFG')
93
+ symlink_must_exist(@original_path, @destination_path)
94
+ file_must_not_match(redacted_path, 'replacing and sensitive information')
95
+ git_ignore_must_include(@destination_path)
96
+ end
97
+
98
+ describe "collision handling" do
99
+
100
+ before do
101
+ @relocated_path = File.join(dotfiles_path, 'test.old.1')
102
+ create_trackable_file(@original_path)
103
+ create_trackable_file(@destination_path)
104
+ end
105
+
106
+ it "renames an existing dotfile when importing a duplicate and instructed to replace it" do
107
+ run_command("import #{@original_path}") do |c|
108
+ c.response(/Do you want to replace it\?/, 'replace')
109
+ end
110
+
111
+ output_must_contain(/Moving/, /Symlinking/, /already exists as a dotfile/)
112
+ file_must_exist(@destination_path)
113
+ file_must_exist(@relocated_path)
114
+ symlink_must_exist(@original_path, @destination_path)
115
+ end
116
+
117
+ it "renames an existing duplicate dotfile when importing a duplicate and instructed to replace it" do
118
+ duplicate_path = File.join(dotfiles_path, 'test.old.2')
119
+ create_trackable_file(@relocated_path)
120
+
121
+ run_command("import #{@original_path}") do |c|
122
+ c.response(/Do you want to replace it\?/, 'replace')
123
+ end
124
+
125
+ file_must_have_moved(@destination_path, duplicate_path)
126
+ file_must_not_have_moved(@relocated_path)
127
+ end
128
+
129
+ it "does not modify an existing dotfile when instructed not to" do
130
+ run_command("import #{@original_path}", 255) do |c|
131
+ c.response(/Do you want to replace it\?/, 'abort')
132
+ end
133
+
134
+ output_must_contain(/already exists as a dotfile/)
135
+ output_must_not_contain(/Moving/, /Symlinking/)
136
+ file_must_not_have_moved(@original_path)
137
+ file_must_not_have_moved(@destination_path)
138
+ file_must_not_exist(@relocated_path)
139
+ symlink_must_not_exist(@original_path)
140
+ end
141
+
142
+ end
143
+
144
+ end
145
+ end
@@ -0,0 +1,17 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ require 'minitest/spec'
5
+ # require 'turn/autorun/minitest'
6
+ require 'minitest/mock'
7
+
8
+ MiniTest::Unit.autorun
9
+
10
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
11
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
12
+ require 'briefcase'
13
+
14
+ require 'helpers/assertions'
15
+ require 'helpers/files'
16
+ require 'helpers/stubbing'
17
+ require 'helpers/commands'
data/spec/sync_spec.rb ADDED
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+
3
+ describe Briefcase::Commands::Sync do
4
+
5
+ before do
6
+ create_home_directory
7
+ create_dotfiles_directory
8
+
9
+ @file_path = File.join(dotfiles_path, 'test')
10
+ @link_path = File.join(home_path, '.test')
11
+ end
12
+
13
+ after do
14
+ cleanup_home_directory
15
+ cleanup_dotfiles_directory
16
+ end
17
+
18
+ it "creates links to existing files" do
19
+ create_file(@file_path)
20
+
21
+ run_command("sync")
22
+
23
+ output_must_contain(/Synchronizing dotfiles/, /Symlinking/)
24
+
25
+ file_must_exist(@file_path)
26
+ symlink_must_exist(@link_path, @file_path)
27
+ end
28
+
29
+ it "does not create links to existing dynamic files" do
30
+ redacted_path = File.join(dotfiles_path, 'test.redacted')
31
+ dynamic_link_path = File.join(home_path, '.test.redacted')
32
+ create_file(redacted_path)
33
+
34
+ run_command("sync")
35
+
36
+ output_must_not_contain(/Symlinking/)
37
+ file_must_not_exist(dynamic_link_path)
38
+ end
39
+
40
+ it "handles finding real dotfiles where symlinks would be" do
41
+ file_path = File.join(home_path, '.test')
42
+ link_path = File.join(dotfiles_path, 'test')
43
+ create_file(file_path)
44
+ create_file(link_path)
45
+
46
+ run_command("sync")
47
+
48
+ output_must_not_contain(/Symlinking/)
49
+ output_must_contain(/skipping/)
50
+ end
51
+
52
+ end