briefcase 0.4.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.
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