dpl-connect 1.8.43

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 (105) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +8 -0
  4. data/.rspec +2 -0
  5. data/.travis.yml +36 -0
  6. data/Gemfile +100 -0
  7. data/LICENSE +22 -0
  8. data/README.md +934 -0
  9. data/Rakefile +1 -0
  10. data/TESTING.md +29 -0
  11. data/bin/dpl +5 -0
  12. data/dpl.gemspec +32 -0
  13. data/lib/dpl/cli.rb +66 -0
  14. data/lib/dpl/error.rb +3 -0
  15. data/lib/dpl/provider.rb +264 -0
  16. data/lib/dpl/provider/anynines.rb +13 -0
  17. data/lib/dpl/provider/appfog.rb +21 -0
  18. data/lib/dpl/provider/atlas.rb +108 -0
  19. data/lib/dpl/provider/azure_webapps.rb +48 -0
  20. data/lib/dpl/provider/bintray.rb +509 -0
  21. data/lib/dpl/provider/bitballoon.rb +22 -0
  22. data/lib/dpl/provider/bluemix_cloud_foundry.rb +23 -0
  23. data/lib/dpl/provider/boxfuse.rb +57 -0
  24. data/lib/dpl/provider/catalyze.rb +49 -0
  25. data/lib/dpl/provider/chef_supermarket.rb +85 -0
  26. data/lib/dpl/provider/cloud66.rb +38 -0
  27. data/lib/dpl/provider/cloud_files.rb +38 -0
  28. data/lib/dpl/provider/cloud_foundry.rb +43 -0
  29. data/lib/dpl/provider/code_deploy.rb +123 -0
  30. data/lib/dpl/provider/deis.rb +119 -0
  31. data/lib/dpl/provider/divshot.rb +23 -0
  32. data/lib/dpl/provider/elastic_beanstalk.rb +195 -0
  33. data/lib/dpl/provider/engine_yard.rb +90 -0
  34. data/lib/dpl/provider/firebase.rb +27 -0
  35. data/lib/dpl/provider/gae.rb +97 -0
  36. data/lib/dpl/provider/gcs.rb +59 -0
  37. data/lib/dpl/provider/hackage.rb +29 -0
  38. data/lib/dpl/provider/heroku.rb +18 -0
  39. data/lib/dpl/provider/heroku/api.rb +98 -0
  40. data/lib/dpl/provider/heroku/generic.rb +94 -0
  41. data/lib/dpl/provider/heroku/git.rb +28 -0
  42. data/lib/dpl/provider/lambda.rb +236 -0
  43. data/lib/dpl/provider/launchpad.rb +48 -0
  44. data/lib/dpl/provider/modulus.rb +23 -0
  45. data/lib/dpl/provider/npm.rb +64 -0
  46. data/lib/dpl/provider/openshift.rb +59 -0
  47. data/lib/dpl/provider/ops_works.rb +132 -0
  48. data/lib/dpl/provider/packagecloud.rb +144 -0
  49. data/lib/dpl/provider/pages.rb +79 -0
  50. data/lib/dpl/provider/puppet_forge.rb +43 -0
  51. data/lib/dpl/provider/pypi.rb +111 -0
  52. data/lib/dpl/provider/releases.rb +139 -0
  53. data/lib/dpl/provider/rubygems.rb +51 -0
  54. data/lib/dpl/provider/s3.rb +123 -0
  55. data/lib/dpl/provider/scalingo.rb +97 -0
  56. data/lib/dpl/provider/script.rb +29 -0
  57. data/lib/dpl/provider/surge.rb +33 -0
  58. data/lib/dpl/provider/testfairy.rb +190 -0
  59. data/lib/dpl/provider/transifex.rb +45 -0
  60. data/lib/dpl/version.rb +3 -0
  61. data/notes/engine_yard.md +1 -0
  62. data/notes/heroku.md +3 -0
  63. data/spec/cli_spec.rb +36 -0
  64. data/spec/provider/anynines_spec.rb +20 -0
  65. data/spec/provider/appfog_spec.rb +35 -0
  66. data/spec/provider/atlas_spec.rb +99 -0
  67. data/spec/provider/azure_webapps_spec.rb +95 -0
  68. data/spec/provider/bintray_spec.rb +259 -0
  69. data/spec/provider/bitballoon_spec.rb +32 -0
  70. data/spec/provider/bluemixcloudfoundry_spec.rb +23 -0
  71. data/spec/provider/boxfuse_spec.rb +16 -0
  72. data/spec/provider/catalyze_spec.rb +39 -0
  73. data/spec/provider/chef_supermarket_spec.rb +51 -0
  74. data/spec/provider/cloud66_spec.rb +44 -0
  75. data/spec/provider/cloud_files_spec.rb +88 -0
  76. data/spec/provider/cloudfoundry_spec.rb +71 -0
  77. data/spec/provider/code_deploy_spec.rb +360 -0
  78. data/spec/provider/deis_spec.rb +116 -0
  79. data/spec/provider/divshot_spec.rb +28 -0
  80. data/spec/provider/elastic_beanstalk_spec.rb +209 -0
  81. data/spec/provider/firebase_spec.rb +40 -0
  82. data/spec/provider/gae_spec.rb +26 -0
  83. data/spec/provider/gcs_spec.rb +115 -0
  84. data/spec/provider/hackage_spec.rb +47 -0
  85. data/spec/provider/heroku_spec.rb +357 -0
  86. data/spec/provider/lambda_spec.rb +432 -0
  87. data/spec/provider/launchpad_spec.rb +33 -0
  88. data/spec/provider/modulus_spec.rb +29 -0
  89. data/spec/provider/npm_spec.rb +95 -0
  90. data/spec/provider/openshift_spec.rb +91 -0
  91. data/spec/provider/ops_works_spec.rb +127 -0
  92. data/spec/provider/packagecloud_spec.rb +56 -0
  93. data/spec/provider/puppet_forge_spec.rb +60 -0
  94. data/spec/provider/pypi_spec.rb +103 -0
  95. data/spec/provider/releases_spec.rb +303 -0
  96. data/spec/provider/rubygems_spec.rb +106 -0
  97. data/spec/provider/s3_spec.rb +174 -0
  98. data/spec/provider/scalingo_spec.rb +64 -0
  99. data/spec/provider/script_spec.rb +26 -0
  100. data/spec/provider/surge_spec.rb +15 -0
  101. data/spec/provider/testfairy_spec.rb +86 -0
  102. data/spec/provider/transifex_spec.rb +110 -0
  103. data/spec/provider_spec.rb +210 -0
  104. data/spec/spec_helper.rb +20 -0
  105. metadata +279 -0
@@ -0,0 +1,174 @@
1
+ require 'spec_helper'
2
+ require 'dpl/provider/s3'
3
+
4
+ describe DPL::Provider::S3 do
5
+
6
+ subject :provider do
7
+ described_class.new(DummyContext.new, :access_key_id => 'qwertyuiopasdfghjklz', :secret_access_key => 'qwertyuiopasdfghjklzqwertyuiopasdfghjklz', :bucket => 'my-bucket')
8
+ end
9
+
10
+ describe '#s3_options' do
11
+ context 'without region' do
12
+ example do
13
+ options = provider.s3_options
14
+ expect(options[:region]).to eq('us-east-1')
15
+ end
16
+ end
17
+
18
+ context 'with region' do
19
+ example do
20
+ region = 'us-west-1'
21
+ provider.options.update(:region => region)
22
+ options = provider.s3_options
23
+ expect(options[:region]).to eq(region)
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ describe DPL::Provider::S3 do
30
+
31
+ access_key_id = 'qwertyuiopasdfghjklz'
32
+ secret_access_key = 'qwertyuiopasdfghjklzqwertyuiopasdfghjklz'
33
+ region = 'us-east-1'
34
+ bucket = 'my-bucket'
35
+
36
+ client_options = {
37
+ stub_responses: true,
38
+ region: region,
39
+ credentials: Aws::Credentials.new(access_key_id, secret_access_key)
40
+ }
41
+
42
+ subject :provider do
43
+ described_class.new(DummyContext.new, {
44
+ access_key_id: access_key_id,
45
+ secret_access_key: secret_access_key,
46
+ bucket: bucket
47
+ })
48
+ end
49
+
50
+ before :each do
51
+ provider.stub(:s3_options).and_return(client_options)
52
+ end
53
+
54
+ describe "#check_auth" do
55
+ example do
56
+ expect(provider).to receive(:log).with("Logging in with Access Key: ****************jklz")
57
+ provider.check_auth
58
+ end
59
+ end
60
+
61
+ describe "#upload_path" do
62
+ example "Without :upload_dir"do
63
+ filename = "testfile.file"
64
+
65
+ expect(provider.upload_path(filename)).to eq("testfile.file")
66
+ end
67
+
68
+ example "With :upload_dir" do
69
+ provider.options.update(:upload_dir => 'BUILD3')
70
+ filename = "testfile.file"
71
+
72
+ expect(provider.upload_path(filename)).to eq("BUILD3/testfile.file")
73
+ end
74
+ end
75
+
76
+ describe "#needs_key?" do
77
+ example do
78
+ expect(provider.needs_key?).to eq(false)
79
+ end
80
+ end
81
+
82
+ describe "#push_app" do
83
+ example "Without local_dir" do
84
+ expect(Dir).to receive(:chdir).with(Dir.pwd)
85
+ provider.push_app
86
+ end
87
+
88
+ example "With local_dir" do
89
+ provider.options.update(:local_dir => 'BUILD')
90
+
91
+ expect(Dir).to receive(:chdir).with('BUILD')
92
+ provider.push_app
93
+ end
94
+
95
+ example "Sends MIME type" do
96
+ expect(Dir).to receive(:glob).and_yield(__FILE__)
97
+ expect_any_instance_of(Aws::S3::Object).to receive(:upload_file).with(anything(), hash_including(:content_type => 'application/x-ruby'))
98
+ provider.push_app
99
+ end
100
+
101
+ example "Sets Cache and Expiration" do
102
+ provider.options.update(:cache_control => "max-age=99999999", :expires => "2012-12-21 00:00:00 -0000")
103
+ expect(Dir).to receive(:glob).and_yield(__FILE__)
104
+ expect_any_instance_of(Aws::S3::Object).to receive(:upload_file).with(anything(), hash_including(:cache_control => 'max-age=99999999', :expires => '2012-12-21 00:00:00 -0000'))
105
+ provider.push_app
106
+ end
107
+
108
+ example "Sets different Cache and Expiration" do
109
+ option_list = []
110
+ provider.options.update(:cache_control => ["max-age=99999999", "no-cache" => ["foo.html", "bar.txt"], "max-age=9999" => "*.txt"], :expires => ["2012-12-21 00:00:00 -0000", "1970-01-01 00:00:00 -0000" => "*.html"])
111
+ expect(Dir).to receive(:glob).and_yield("foo.html").and_yield("bar.txt").and_yield("baz.js")
112
+ allow_any_instance_of(Aws::S3::Object).to receive(:upload_file) do |obj, _data, options|
113
+ option_list << { key: obj.key, options: options }
114
+ end
115
+ provider.push_app
116
+ expect(option_list).to match_array([
117
+ { key: "foo.html", options: hash_including(:cache_control => "no-cache", :expires => "1970-01-01 00:00:00 -0000") },
118
+ { key: "bar.txt", options: hash_including(:cache_control => "max-age=9999", :expires => "2012-12-21 00:00:00 -0000") },
119
+ { key: "baz.js", options: hash_including(:cache_control => "max-age=99999999", :expires => "2012-12-21 00:00:00 -0000") },
120
+ ])
121
+ end
122
+
123
+ example "Sets ACL" do
124
+ provider.options.update(:acl => "public_read")
125
+ expect(Dir).to receive(:glob).and_yield(__FILE__)
126
+ expect_any_instance_of(Aws::S3::Object).to receive(:upload_file).with(anything(), hash_including(:acl => "public-read"))
127
+ provider.push_app
128
+ end
129
+
130
+ example "Sets Storage Class" do
131
+ provider.options.update(:storage_class => "STANDARD_AI")
132
+ expect(Dir).to receive(:glob).and_yield(__FILE__)
133
+ expect_any_instance_of(Aws::S3::Object).to receive(:upload_file).with(anything(), hash_including(:storage_class => "STANDARD_AI"))
134
+ provider.push_app
135
+ end
136
+
137
+ example "Sets SSE" do
138
+ provider.options.update(:server_side_encryption => true)
139
+ expect(Dir).to receive(:glob).and_yield(__FILE__)
140
+ expect_any_instance_of(Aws::S3::Object).to receive(:upload_file).with(anything(), hash_including(:server_side_encryption => "AES256"))
141
+ provider.push_app
142
+ end
143
+
144
+ example "Sets Website Index Document" do
145
+ provider.options.update(:index_document_suffix => "test/index.html")
146
+ expect(Dir).to receive(:glob).and_yield(__FILE__)
147
+ expect_any_instance_of(Aws::S3::BucketWebsite).to receive(:put).with(:website_configuration => { :index_document => { :suffix => "test/index.html" } })
148
+ provider.push_app
149
+ end
150
+
151
+ example "when detect_encoding is set" do
152
+ path = 'foo.js'
153
+ provider.options.update(:detect_encoding => true)
154
+ expect(Dir).to receive(:glob).and_yield(path)
155
+ expect(provider).to receive(:`).at_least(1).times.with("file '#{path}'").and_return('gzip compressed')
156
+ expect_any_instance_of(Aws::S3::Object).to receive(:upload_file).with(anything(), hash_including(:content_encoding => 'gzip'))
157
+ provider.push_app
158
+ end
159
+
160
+ example "when dot_match is set" do
161
+ provider.options.update(:dot_match => true)
162
+ expect(Dir).to receive(:glob).with("**/*", File::FNM_DOTMATCH)
163
+ provider.push_app
164
+ end
165
+ end
166
+
167
+ describe "#check_app" do
168
+ example "With Endpoint" do
169
+ provider.options.update(:endpoint => 's3test.com.s3-website-us-west-2.amazonaws.com')
170
+ expect(provider).to receive(:log).with('Warning: The endpoint option is no longer used and can be removed.')
171
+ provider.check_app
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+ require 'dpl/provider/scalingo'
3
+
4
+ describe DPL::Provider::Scalingo do
5
+
6
+ subject :provider do
7
+ described_class.new(DummyContext.new, :username => 'travis', :password => 'secret', :remote => 'scalingo', :branch => 'master')
8
+ end
9
+
10
+ describe "#install_deploy_dependencies" do
11
+ example do
12
+ expect(provider.context).to receive(:shell).with(
13
+ 'curl -OL https://cli-dl.scalingo.io/release/scalingo_latest_linux_amd64.tar.gz && tar -zxvf scalingo_latest_linux_amd64.tar.gz && mv scalingo_*_linux_amd64/scalingo . && rm scalingo_latest_linux_amd64.tar.gz && rm -r scalingo_*_linux_amd64'
14
+ ).and_return(true)
15
+ provider.install_deploy_dependencies
16
+ end
17
+ end
18
+
19
+ describe "#check_auth" do
20
+ example do
21
+ expect(provider.context).to receive(:shell).with(
22
+ "echo -e \"travis\nsecret\" | timeout 2 ./scalingo login 2> /dev/null > /dev/null"
23
+ ).and_return(true)
24
+ expect(provider.context).to receive(:shell).with(
25
+ 'DISABLE_INTERACTIVE=true ./scalingo login 2> /dev/null > /dev/null'
26
+ ).and_return(true)
27
+ provider.check_auth
28
+ end
29
+ end
30
+
31
+ describe "#setup_key" do
32
+ example do
33
+ expect(provider.context).to receive(:shell).with(
34
+ './scalingo keys-add dpl_tmp_key key_file'
35
+ ).and_return(true)
36
+ expect(provider.context).to receive(:shell).with(
37
+ 'DISABLE_INTERACTIVE=true ./scalingo login 2> /dev/null > /dev/null'
38
+ ).and_return(true)
39
+ provider.setup_key('key_file')
40
+ end
41
+ end
42
+
43
+ describe "#remove_key" do
44
+ example do
45
+ expect(provider.context).to receive(:shell).with(
46
+ './scalingo keys-remove dpl_tmp_key'
47
+ ).and_return(true)
48
+ expect(provider.context).to receive(:shell).with(
49
+ 'DISABLE_INTERACTIVE=true ./scalingo login 2> /dev/null > /dev/null'
50
+ ).and_return(true)
51
+ provider.remove_key
52
+ end
53
+ end
54
+
55
+ describe "#push_app" do
56
+ example do
57
+ expect(provider.context).to receive(:shell).with(
58
+ 'git push scalingo master -f'
59
+ ).and_return(true)
60
+ provider.push_app
61
+ end
62
+ end
63
+
64
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe DPL::Provider::Script do
4
+
5
+ subject :provider do
6
+ described_class.new(DummyContext.new, { script: script })
7
+ end
8
+
9
+ let(:script) { 'scripts/deploy_script' }
10
+
11
+ it 'runs command "script" given' do
12
+ expect(provider.context).to receive(:shell).with(script)
13
+ provider.push_app
14
+ end
15
+
16
+ context 'when script exits with nonzero status' do
17
+ before :each do
18
+ # TODO: Found a better way to test this
19
+ Process::Status.any_instance.stub(:exitstatus).and_return(1)
20
+ end
21
+
22
+ it 'raises error' do
23
+ expect { provider.push_app }.to raise_error(DPL::Error)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+ require 'dpl/provider/surge'
3
+
4
+ describe DPL::Provider::Surge do
5
+ subject :provider do
6
+ described_class.new(DummyContext.new, :project => './', :domain => 'mydomain')
7
+ end
8
+
9
+ describe "#push_app" do
10
+ it 'should peforme a surge command with correct project and domain set' do
11
+ expect(provider.context).to receive(:shell).with("surge " + File.expand_path('./') + " mydomain")
12
+ provider.push_app
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,86 @@
1
+ require 'spec_helper'
2
+ require 'dpl/provider/testfairy'
3
+
4
+ describe DPL::Provider::TestFairy do
5
+
6
+ before (:all) do
7
+
8
+ %x[mkdir /tmp/android/]
9
+ %x[echo 'cp $3 $4' > /tmp/android/zipalign]
10
+ %x[chmod +x /tmp/android/zipalign]
11
+
12
+ @kyestore = '/tmp/debug.keystore'
13
+ %x[curl -Lso #{@kyestore} http://www.testfairy.com/support-files/travis/dpl/debug.keystore]
14
+
15
+ @local_android_app = '/tmp/android.apk'
16
+ %x[curl -Lso #{@local_android_app} http://www.testfairy.com/support-files/travis/dpl/android.apk]
17
+
18
+ @local_ios_app = '/tmp/ios.ipa'
19
+ %x[curl -Lso #{@local_ios_app} http://www.testfairy.com/support-files/travis/dpl/Empty.ipa]
20
+
21
+ end
22
+
23
+ let :context do
24
+ DummyContext.new
25
+ end
26
+
27
+ subject :provider do
28
+ # the account is travis-test@testfairy.com
29
+ described_class.new(context, :api_key => '4b85a2c03ba6026f4e22640a0432638180e1d1ea', :storepass => "android", :alias => "androiddebugkey", :keystore_file => @kyestore, :video => "true", :video_quality => 'low')
30
+ end
31
+
32
+ describe "#check_auth" do
33
+ example "check_auth without app_file" do
34
+ lambda {provider.check_auth}.should raise_error
35
+ end
36
+
37
+ example "check_auth with app_file" do
38
+ provider.options.update(:app_file => @local_android_app)
39
+ provider.check_auth
40
+ end
41
+ end
42
+
43
+ describe "#needs_key?" do
44
+ example do
45
+ expect(provider.needs_key?).to eq(false)
46
+ end
47
+ end
48
+
49
+ describe "#push_app" do
50
+ before do
51
+ context.stub(:env) { {'ANDROID_HOME' => '/tmp/android', 'JAVA_HOME' => '/usr/bin'} }
52
+ end
53
+
54
+ example "push_app without app_file" do
55
+ lambda {provider.push_app}.should raise_error
56
+ end
57
+
58
+ xit "push_app with app_file" do
59
+ provider.options.update(:app_file => @local_android_app)
60
+ provider.push_app
61
+ end
62
+
63
+ example "push_app with wrong alias" do
64
+ provider.options.update(:app_file => @local_android_app)
65
+ provider.options.update(:alias => 'test')
66
+ lambda {provider.push_app}.should raise_error
67
+ end
68
+
69
+ example "push_app with wrong storepass" do
70
+ provider.options.update(:app_file => @local_android_app)
71
+ provider.options.update(:storepass => 'test')
72
+ lambda {provider.push_app}.should raise_error
73
+ end
74
+
75
+ example "push_app with iOS app_file" do
76
+ provider.options.update(:app_file => @local_ios_app)
77
+ provider.push_app
78
+ end
79
+
80
+ example "push_app with notifify param" do
81
+ provider.options.update(:app_file => @local_ios_app)
82
+ provider.options.update(:notify => true)
83
+ provider.push_app
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,110 @@
1
+ require 'spec_helper'
2
+ require 'dpl/provider/transifex'
3
+
4
+ describe DPL::Provider::Transifex do
5
+ let(:options) do
6
+ {
7
+ hostname: 'https://www.nottransifex.example.com',
8
+ username: 'travis',
9
+ password: 'secret',
10
+ token: 'abcd1234'
11
+ }
12
+ end
13
+
14
+ subject :provider do
15
+ described_class.new(DummyContext.new, options)
16
+ end
17
+
18
+ describe '#install_deploy_dependencies' do
19
+ context 'without version specified' do
20
+ example "installs #{described_class::DEFAULT_CLIENT_VERSION}" do
21
+ expect(provider.class).to(
22
+ receive(:pip).with('transifex', 'transifex', described_class::DEFAULT_CLIENT_VERSION)
23
+ )
24
+ provider.install_deploy_dependencies
25
+ end
26
+ end
27
+
28
+ context 'with version specified' do
29
+ before do
30
+ options[:cli_version] = '==0.12'
31
+ end
32
+
33
+ example 'installs custom version' do
34
+ expect(provider.class).to(
35
+ receive(:pip).with('transifex', 'transifex', '==0.12')
36
+ )
37
+ provider.install_deploy_dependencies
38
+ end
39
+ end
40
+ end
41
+
42
+ describe '#needs_key?' do
43
+ example do
44
+ expect(provider.needs_key?).to eq(false)
45
+ end
46
+ end
47
+
48
+ describe '#check_auth' do
49
+ before do
50
+ allow(provider).to receive(:install_deploy_dependencies)
51
+ allow(provider).to receive(:write_transifexrc)
52
+ end
53
+
54
+ example 'installs dependencies' do
55
+ expect(provider).to receive(:install_deploy_dependencies)
56
+ provider.check_auth
57
+ end
58
+
59
+ example 'writes ~/.transifexrc' do
60
+ expect(provider).to receive(:write_transifexrc)
61
+ provider.check_auth
62
+ end
63
+
64
+ example 'performs a tx status' do
65
+ expect(provider.context).to receive(:shell).with('tx status')
66
+ provider.check_auth
67
+ end
68
+ end
69
+
70
+ describe '#push_app' do
71
+ example 'delegates to the #source_push method' do
72
+ expect(provider).to receive(:source_push)
73
+ provider.push_app
74
+ end
75
+ end
76
+
77
+ describe '#source_push' do
78
+ example 'performs a tx push' do
79
+ expect(provider.context).to(
80
+ receive(:shell).with('tx push --source --no-interactive', retry: true)
81
+ )
82
+ provider.source_push
83
+ end
84
+ end
85
+
86
+ describe '#write_transifexrc' do
87
+ let(:fake_config) { StringIO.new }
88
+
89
+ before do
90
+ allow(File).to receive(:open).and_yield(fake_config)
91
+ end
92
+
93
+ example 'writes config with hostname header' do
94
+ expect(fake_config).to receive(:puts).with(/^\[#{options[:hostname]}\]/)
95
+ provider.write_transifexrc
96
+ end
97
+
98
+ %w(
99
+ hostname
100
+ username
101
+ password
102
+ token
103
+ ).map(&:to_sym).each do |key|
104
+ example "writes config with #{key} key" do
105
+ expect(fake_config).to receive(:puts).with(/^#{key} = #{options[key]}$/)
106
+ provider.write_transifexrc
107
+ end
108
+ end
109
+ end
110
+ end