coverband 4.0.1.alpha → 4.0.1.beta
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +1 -1
- data/.rubocop.yml +5 -15
- data/.travis.yml +1 -0
- data/LICENSE +1 -1
- data/LICENSE.txt +1 -1
- data/README.md +19 -2
- data/Rakefile +1 -1
- data/changes.md +3 -0
- data/coverband.gemspec +7 -4
- data/lib/coverband.rb +2 -3
- data/lib/coverband/configuration.rb +5 -1
- data/lib/coverband/integrations/background.rb +19 -10
- data/lib/coverband/reporters/html_report.rb +5 -1
- data/lib/coverband/reporters/web.rb +6 -59
- data/lib/coverband/utils/html_formatter.rb +18 -2
- data/lib/coverband/utils/result.rb +1 -0
- data/lib/coverband/utils/s3_report.rb +1 -1
- data/lib/coverband/utils/source_file.rb +1 -1
- data/lib/coverband/version.rb +1 -1
- data/public/application.css +37 -3
- data/public/application.js +50 -44
- data/test/fixtures/app/controllers/sample_controller.rb +10 -0
- data/test/fixtures/app/models/user.rb +10 -0
- data/test/fixtures/never.rb +2 -0
- data/test/fixtures/sample.rb +16 -0
- data/test/fixtures/skipped.rb +4 -0
- data/test/fixtures/skipped_and_executed.rb +8 -0
- data/test/fixtures/utf-8.rb +3 -0
- data/test/rails4_dummy/config/coverband.rb +1 -1
- data/test/rails4_dummy/config/routes.rb +1 -0
- data/test/rails5_dummy/config/coverband.rb +3 -2
- data/test/rails5_dummy/config/routes.rb +1 -0
- data/test/rails_test_helper.rb +6 -6
- data/test/test_helper.rb +50 -2
- data/test/unit/adapters_base_test.rb +2 -1
- data/test/unit/adapters_file_store_test.rb +2 -1
- data/test/unit/adapters_redis_store_test.rb +2 -1
- data/test/unit/background_test.rb +12 -7
- data/test/unit/collectors_coverage_test.rb +3 -2
- data/test/unit/configuration_test.rb +2 -1
- data/test/unit/coverband_test.rb +1 -1
- data/test/unit/full_stack_test.rb +1 -1
- data/test/unit/middleware_test.rb +2 -1
- data/test/unit/rack_server_checkout_test.rb +7 -8
- data/test/unit/rails_full_stack_test.rb +26 -10
- data/test/unit/reports_base_test.rb +1 -1
- data/test/unit/reports_console_test.rb +2 -1
- data/test/unit/reports_html_test.rb +2 -1
- data/test/unit/reports_web_test.rb +3 -2
- data/test/unit/utils/file_list_test.rb +54 -0
- data/test/unit/utils/lines_classifier_test.rb +109 -0
- data/test/unit/utils/result_test.rb +104 -0
- data/test/unit/{utils_s3_report_test.rb → utils/s3_report_test.rb} +4 -4
- data/test/unit/utils/source_file_line_test.rb +165 -0
- data/test/unit/utils/source_file_test.rb +149 -0
- data/views/layout.erb +10 -1
- metadata +65 -13
- data/Gemfile.rails4.lock +0 -164
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 287311c05b4d4bc1e85d1a8cc19d9a5630551fa8
|
4
|
+
data.tar.gz: f73c312bb5c4eceff8dd48e92d9191e5c57d80e9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2fd7fa9ceae554e6dba27834be7527b2df2a8160b68079124de97f3e986a0141dea24e467832c85881dd3f6753506b1fdc060d72226a0f009daf7c3dde66500c
|
7
|
+
data.tar.gz: 55566a5fef66122bcd908b6fb1d488727f55dabff12e0dfa0d73530727555c9bd6b6d7e104b1e14d9ebf5950984c7a82aaaa011e7aba68d32c923646d3a2f071
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
@@ -10,8 +10,6 @@ Metrics/LineLength:
|
|
10
10
|
Max: 120
|
11
11
|
Metrics/BlockNesting:
|
12
12
|
Max: 5
|
13
|
-
Bundler/OrderedGems:
|
14
|
-
Enabled: false
|
15
13
|
Metrics/CyclomaticComplexity:
|
16
14
|
Enabled: false
|
17
15
|
Metrics/PerceivedComplexity:
|
@@ -20,19 +18,13 @@ Metrics/AbcSize:
|
|
20
18
|
Enabled: false
|
21
19
|
Metrics/ClassLength:
|
22
20
|
Enabled: false
|
23
|
-
Metrics/BlockLength:
|
24
|
-
Enabled: false
|
25
|
-
Metrics/BlockNesting:
|
26
|
-
Max: 10
|
27
21
|
Metrics/ModuleLength:
|
28
22
|
Enabled: false
|
29
23
|
Metrics/ParameterLists:
|
30
24
|
Max: 10
|
31
|
-
|
32
|
-
Enabled: false
|
33
|
-
Naming/PredicateName:
|
25
|
+
Style/AccessorMethodName:
|
34
26
|
Enabled: false
|
35
|
-
Style/
|
27
|
+
Style/PredicateName:
|
36
28
|
Enabled: false
|
37
29
|
Style/TernaryParentheses:
|
38
30
|
Enabled: false
|
@@ -52,11 +44,9 @@ Style/ClassAndModuleChildren:
|
|
52
44
|
Enabled: false
|
53
45
|
Performance/Casecmp:
|
54
46
|
Enabled: false
|
55
|
-
|
56
|
-
Enabled: true
|
57
|
-
Layout/MultilineMethodCallIndentation:
|
47
|
+
Style/MultilineMethodCallIndentation:
|
58
48
|
Enabled: true
|
59
|
-
|
49
|
+
Style/MultilineOperationIndentation:
|
60
50
|
Enabled: true
|
61
51
|
Lint/RescueException:
|
62
52
|
Enabled: true
|
@@ -64,6 +54,6 @@ Lint/ShadowingOuterLocalVariable:
|
|
64
54
|
Enabled: true
|
65
55
|
Style/FormatString:
|
66
56
|
Enabled: true
|
67
|
-
|
57
|
+
Lint/Eval:
|
68
58
|
Enabled: true
|
69
59
|
|
data/.travis.yml
CHANGED
data/LICENSE
CHANGED
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# Coverband
|
2
2
|
|
3
|
-
|
3
|
+
[![Build Status](https://travis-ci.org/danmayer/coverband.svg?branch=master)](https://travis-ci.org/danmayer/coverband)
|
4
|
+
[![Coverage Status](https://coveralls.io/repos/github/danmayer/coverband/badge.svg?branch=master)](https://coveralls.io/github/danmayer/coverband?branch=master)
|
4
5
|
|
5
6
|
<p align="center">
|
6
7
|
<a href="#key-features">Key Features</a> •
|
@@ -8,7 +9,6 @@ Build Status: [![Build Status](https://travis-ci.org/danmayer/coverband.svg?bran
|
|
8
9
|
<a href="#configuration">Configuration</a> •
|
9
10
|
<a href="#coverband-demo">Coverband Demo</a> •
|
10
11
|
<a href="#how-to-use">How To Use</a> •
|
11
|
-
<a href="#usage">Usage</a> •
|
12
12
|
<a href="#license">License</a> •
|
13
13
|
<a href="/changes.md">Change Log / Roadmap</a>
|
14
14
|
</p>
|
@@ -144,6 +144,23 @@ Below is my Coverband workflow, which hopefully will help other best use this li
|
|
144
144
|
* After Coverband has been verified to be working on production, I let it run for a few weeks.
|
145
145
|
* Then I view the report and start submitting PRs for the team to review delete large related sets of code that no longer are in use.
|
146
146
|
|
147
|
+
### Coverband Web Endpoint
|
148
|
+
|
149
|
+
The web endpoint is a barebones endpoint that you can either expose direct (after authentication) or you can just link to the actions you wish to expose. The index is intended as a example to showcase all the features.
|
150
|
+
|
151
|
+
![image](https://raw.github.com/danmayer/coverband/master/docs/coverband_web.png)
|
152
|
+
> The web index as available on the Coverband Demo site
|
153
|
+
|
154
|
+
* __collect data, update report, & view:__ This does everything need to view up to date Coverage
|
155
|
+
* it triggers a coverage collection on the current webserver process
|
156
|
+
* it generates a new html coverage report and pushes it to S3
|
157
|
+
* it then loads that report for you to view
|
158
|
+
* __view coverage report:__ Don't need to update the data just view the current report
|
159
|
+
* __update coverage data (collect coverage):__ This triggers coverage collection on the current webserver process
|
160
|
+
* __update coverage report (rebuild report):__ This will rebuild the HTML report from the latest available data
|
161
|
+
* __clear coverage report:__ This will clear the coverage data. This wipes out all collected data (__dangerous__)
|
162
|
+
* __reload Coverband files:__ This has Coverband reload files as configured (force reload of some files that might not capture Coverage on boot)
|
163
|
+
|
147
164
|
### Example apps
|
148
165
|
|
149
166
|
- [Rails 5.2.x App](https://github.com/danmayer/coverage_demo)
|
data/Rakefile
CHANGED
@@ -13,7 +13,7 @@ Rake::TestTask.new(:test) do |test|
|
|
13
13
|
# exclude benchmark from the tests as the way it functions resets code coverage during executions
|
14
14
|
# test.pattern = 'test/unit/*_test.rb'
|
15
15
|
# using test files opposed to pattern as it outputs which files are run
|
16
|
-
test.test_files = FileList['test/unit
|
16
|
+
test.test_files = FileList['test/unit/**/*_test.rb']
|
17
17
|
test.verbose = true
|
18
18
|
end
|
19
19
|
|
data/changes.md
CHANGED
@@ -36,6 +36,8 @@ Will be the fully modern release that drops maintenance legacy support in favor
|
|
36
36
|
- add meta data information first seen last recorded to the coverage report views (probably need to drop simplecov for that).
|
37
37
|
- more details in this issue: https://github.com/danmayer/coverband/issues/118
|
38
38
|
- Make good video on setup, install, usage
|
39
|
+
- See if we can add support for views / templates
|
40
|
+
- using this technique https://github.com/ioquatix/covered
|
39
41
|
|
40
42
|
### Coverband_jam_session
|
41
43
|
|
@@ -67,6 +69,7 @@ Feature Ideas:
|
|
67
69
|
- drops simplecov runtime dependency
|
68
70
|
- still used to measure our own code coverage ;)
|
69
71
|
- thanks SimpleCov for all the years of solid HTML reporting, and support!
|
72
|
+
- reduced the S3 dependencies to minimal set (not loading all of aws-sdk), ensured they are optional
|
70
73
|
|
71
74
|
# Released
|
72
75
|
|
data/coverband.gemspec
CHANGED
@@ -7,7 +7,7 @@ require 'coverband/version'
|
|
7
7
|
Gem::Specification.new do |spec|
|
8
8
|
spec.name = 'coverband'
|
9
9
|
spec.version = Coverband::VERSION
|
10
|
-
spec.authors = ['Dan Mayer']
|
10
|
+
spec.authors = ['Dan Mayer', 'Karl Baum']
|
11
11
|
spec.email = ['dan@mayerdan.com']
|
12
12
|
spec.description = 'Rack middleware to help measure production code usage (LOC runtime usage)'
|
13
13
|
spec.summary = 'Rack middleware to help measure production code usage (LOC runtime usage)'
|
@@ -22,21 +22,24 @@ Gem::Specification.new do |spec|
|
|
22
22
|
# to test support for sdk 1, uncomment this line
|
23
23
|
# spec.add_development_dependency 'aws-sdk', '~> 1'
|
24
24
|
# to test sdk 2 use this one
|
25
|
-
spec.add_development_dependency 'aws-sdk', '~>
|
25
|
+
spec.add_development_dependency 'aws-sdk-s3', '~> 1'
|
26
26
|
spec.add_development_dependency 'benchmark-ips'
|
27
27
|
spec.add_development_dependency 'bundler', '~> 1.3'
|
28
|
+
spec.add_development_dependency 'capybara'
|
28
29
|
spec.add_development_dependency 'm'
|
29
30
|
spec.add_development_dependency 'memory_profiler'
|
30
|
-
spec.add_development_dependency '
|
31
|
+
spec.add_development_dependency 'minitest'
|
32
|
+
spec.add_development_dependency 'mocha', '~> 1.7.0'
|
31
33
|
spec.add_development_dependency 'rack'
|
32
34
|
spec.add_development_dependency 'rack-test'
|
33
35
|
spec.add_development_dependency 'rake'
|
34
36
|
spec.add_development_dependency 'simplecov'
|
35
|
-
|
37
|
+
|
36
38
|
|
37
39
|
# TODO: used for benchmarking and tests I think we have other better benchmarking
|
38
40
|
# perhaps time to drop this and refactor.
|
39
41
|
spec.add_development_dependency 'classifier-reborn'
|
42
|
+
spec.add_development_dependency 'coveralls'
|
40
43
|
# add when debugging
|
41
44
|
# require 'byebug'; byebug
|
42
45
|
spec.add_development_dependency 'pry-byebug'
|
data/lib/coverband.rb
CHANGED
@@ -34,13 +34,12 @@ module Coverband
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def self.configure(file = nil)
|
37
|
-
configuration_file = file || CONFIG_FILE
|
38
|
-
|
37
|
+
configuration_file = file || ENV.fetch('COVERBAND_CONFIG', CONFIG_FILE)
|
39
38
|
configuration
|
40
39
|
if block_given?
|
41
40
|
yield(configuration)
|
42
41
|
elsif File.exist?(configuration_file)
|
43
|
-
|
42
|
+
load configuration_file
|
44
43
|
else
|
45
44
|
configuration.logger&.debug('using default configuration')
|
46
45
|
end
|
@@ -12,6 +12,10 @@ module Coverband
|
|
12
12
|
attr_writer :logger, :s3_region, :s3_bucket, :s3_access_key_id, :s3_secret_access_key
|
13
13
|
|
14
14
|
def initialize
|
15
|
+
reset
|
16
|
+
end
|
17
|
+
|
18
|
+
def reset
|
15
19
|
@root = Dir.pwd
|
16
20
|
@root_paths = []
|
17
21
|
@ignore = %w(vendor .erb$ .slim$)
|
@@ -35,7 +39,7 @@ module Coverband
|
|
35
39
|
end
|
36
40
|
|
37
41
|
def logger
|
38
|
-
@logger ||= if defined?(Rails)
|
42
|
+
@logger ||= if defined?(Rails.logger)
|
39
43
|
Rails.logger
|
40
44
|
else
|
41
45
|
Logger.new(STDOUT)
|
@@ -4,28 +4,37 @@ module Coverband
|
|
4
4
|
class Background
|
5
5
|
@semaphore = Mutex.new
|
6
6
|
|
7
|
+
def self.stop
|
8
|
+
@semaphore.synchronize do
|
9
|
+
if @thread
|
10
|
+
@thread.exit
|
11
|
+
@thread = nil
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
7
16
|
def self.start
|
8
|
-
return if @
|
17
|
+
return if @thread
|
9
18
|
|
10
19
|
logger = Coverband.configuration.logger
|
11
20
|
@semaphore.synchronize do
|
12
|
-
|
21
|
+
binding.pry if defined?($debug) && $debug
|
22
|
+
return if @thread
|
13
23
|
logger&.debug('Coverband: Starting background reporting')
|
14
|
-
|
15
|
-
@background_reporting_running = true
|
16
24
|
sleep_seconds = Coverband.configuration.background_reporting_sleep_seconds
|
17
|
-
Thread.new do
|
25
|
+
@thread = Thread.new do
|
18
26
|
loop do
|
19
27
|
Coverband::Collectors::Coverage.instance.report_coverage(true)
|
20
28
|
logger&.debug("Coverband: Reported coverage via thread. Sleeping #{sleep_seconds}s") if Coverband.configuration.verbose
|
21
29
|
sleep(sleep_seconds)
|
22
30
|
end
|
23
31
|
end
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
32
|
+
binding.pry if defined?($debug) && $debug
|
33
|
+
end
|
34
|
+
at_exit do
|
35
|
+
stop
|
36
|
+
Coverband::Collectors::Coverage.instance.report_coverage(true)
|
37
|
+
logger&.debug('Coverband: Reported coverage before exit')
|
29
38
|
end
|
30
39
|
end
|
31
40
|
end
|
@@ -7,6 +7,8 @@ module Coverband
|
|
7
7
|
scov_style_report = super(store, options)
|
8
8
|
open_report = options.fetch(:open_report) { true }
|
9
9
|
html = options.fetch(:html) { false }
|
10
|
+
notice = options.fetch(:notice) { nil }
|
11
|
+
base_path = options.fetch(:base_path) { nil }
|
10
12
|
|
11
13
|
# list all files, even if not tracked by Coverband (0% coverage)
|
12
14
|
tracked_glob = "#{current_root}/{app,lib,config}/**/*.{rb}"
|
@@ -19,7 +21,9 @@ module Coverband
|
|
19
21
|
end
|
20
22
|
|
21
23
|
if html
|
22
|
-
Coverband::Utils::HTMLFormatter.new(filtered_report_files
|
24
|
+
Coverband::Utils::HTMLFormatter.new(filtered_report_files,
|
25
|
+
base_path: base_path,
|
26
|
+
notice: notice).format_html!
|
23
27
|
else
|
24
28
|
Coverband::Utils::HTMLFormatter.new(filtered_report_files).format!
|
25
29
|
if open_report
|
@@ -4,7 +4,6 @@ require 'rack'
|
|
4
4
|
|
5
5
|
module Coverband
|
6
6
|
module Reporters
|
7
|
-
# TODO: move to reports and drop need for S3 allow reading from adapters?
|
8
7
|
class Web
|
9
8
|
attr_reader :request
|
10
9
|
|
@@ -20,12 +19,8 @@ module Coverband
|
|
20
19
|
|
21
20
|
if request.post?
|
22
21
|
case request.path_info
|
23
|
-
when %r{\/collect_update_and_view}
|
24
|
-
collect_update_and_view
|
25
22
|
when %r{\/clear}
|
26
23
|
clear
|
27
|
-
when %r{\/update_report}
|
28
|
-
update_report
|
29
24
|
when %r{\/collect_coverage}
|
30
25
|
collect_coverage
|
31
26
|
when %r{\/reload_files}
|
@@ -37,8 +32,6 @@ module Coverband
|
|
37
32
|
case request.path_info
|
38
33
|
when /.*\.(css|js|gif|png)/
|
39
34
|
@static.call(env)
|
40
|
-
when %r{\/show}
|
41
|
-
[200, { 'Content-Type' => 'text/html' }, [show]]
|
42
35
|
when %r{\/}
|
43
36
|
[200, { 'Content-Type' => 'text/html' }, [index]]
|
44
37
|
else
|
@@ -47,45 +40,14 @@ module Coverband
|
|
47
40
|
end
|
48
41
|
end
|
49
42
|
|
50
|
-
# TODO: move to file or template
|
51
43
|
def index
|
52
44
|
notice = "<strong>Notice:</strong> #{Rack::Utils.escape_html(request.params['notice'])}<br/>"
|
53
45
|
notice = request.params['notice'] ? notice : ''
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
<li>#{button("#{base_path}collect_update_and_view", 'collect data, update report, & view')}</li>
|
60
|
-
<li><a href='#{base_path}show'>view coverage report</a></li>
|
61
|
-
<li>#{button("#{base_path}collect_coverage", 'update coverage data (collect coverage)')}</li>
|
62
|
-
<li>#{button("#{base_path}update_report", 'update coverage report (rebuild report)')}</li>
|
63
|
-
<li>#{button("#{base_path}clear", 'clear coverage report')}</li>
|
64
|
-
<li>#{button("#{base_path}reload_files", 'reload Coverband files')}</li>
|
65
|
-
</ul>
|
66
|
-
<br/>
|
67
|
-
version: #{Coverband::VERSION}<br/>
|
68
|
-
<a href='https://github.com/danmayer/coverband'>Coverband</a>
|
69
|
-
</html>
|
70
|
-
)
|
71
|
-
end
|
72
|
-
|
73
|
-
def show
|
74
|
-
html = Coverband::Reporters::HTMLReport.report(Coverband.configuration.store,
|
75
|
-
html: true, open_report: false)
|
76
|
-
fix_html_paths(html)
|
77
|
-
end
|
78
|
-
|
79
|
-
def collect_update_and_view
|
80
|
-
collect_coverage
|
81
|
-
update_report
|
82
|
-
[301, { 'Location' => "#{base_path}show" }, []]
|
83
|
-
end
|
84
|
-
|
85
|
-
def update_report
|
86
|
-
Coverband::Reporters::HTMLReport.report(Coverband.configuration.store, open_report: false)
|
87
|
-
notice = 'coverband coverage updated'
|
88
|
-
[301, { 'Location' => "#{base_path}?notice=#{notice}" }, []]
|
46
|
+
Coverband::Reporters::HTMLReport.report(Coverband.configuration.store,
|
47
|
+
html: true,
|
48
|
+
base_path: base_path,
|
49
|
+
notice: notice,
|
50
|
+
open_report: false)
|
89
51
|
end
|
90
52
|
|
91
53
|
def collect_coverage
|
@@ -112,28 +74,13 @@ module Coverband
|
|
112
74
|
|
113
75
|
private
|
114
76
|
|
115
|
-
def fix_html_paths(html)
|
116
|
-
# HACK: the static HTML assets to link to the path where this was mounted
|
117
|
-
html = html.gsub("src='", "src='#{base_path}")
|
118
|
-
html = html.gsub("href='", "href='#{base_path}")
|
119
|
-
html = html.gsub('loading.gif', "#{base_path}loading.gif")
|
120
|
-
html = html.gsub('/images/', "#{base_path}images/")
|
121
|
-
html.gsub("./assets/#{Coverband::VERSION}/", '')
|
122
|
-
end
|
123
|
-
|
124
|
-
def button(url, title)
|
125
|
-
button = "<form action='#{url}' method='post'>"
|
126
|
-
button += "<button type='submit'>#{title}</button>"
|
127
|
-
button + '</form>'
|
128
|
-
end
|
129
|
-
|
130
77
|
# This method should get the root mounted endpoint
|
131
78
|
# for example if the app is mounted like so:
|
132
79
|
# mount Coverband::Web, at: '/coverage'
|
133
80
|
# "/coverage/collect_coverage?" become:
|
134
81
|
# /coverage/
|
135
82
|
def base_path
|
136
|
-
request.path
|
83
|
+
request.path =~ %r{\/.*\/} ? request.path.match("\/.*\/")[0] : '/'
|
137
84
|
end
|
138
85
|
end
|
139
86
|
end
|
@@ -13,7 +13,11 @@ require 'time'
|
|
13
13
|
module Coverband
|
14
14
|
module Utils
|
15
15
|
class HTMLFormatter
|
16
|
-
|
16
|
+
attr_reader :notice, :base_path
|
17
|
+
|
18
|
+
def initialize(report, options = {})
|
19
|
+
@notice = options.fetch(:notice) { nil }
|
20
|
+
@base_path = options.fetch(:base_path) { nil }
|
17
21
|
@coverage_result = Coverband::Utils::Result.new(report)
|
18
22
|
end
|
19
23
|
|
@@ -58,7 +62,19 @@ module Coverband
|
|
58
62
|
end
|
59
63
|
|
60
64
|
def assets_path(name)
|
61
|
-
|
65
|
+
if base_path
|
66
|
+
File.join(base_path, name)
|
67
|
+
else
|
68
|
+
File.join(name)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def button(url, title, opts = {})
|
73
|
+
delete = opts.fetch(:delete) { false }
|
74
|
+
button_css = delete ? 'coveraband-button del' : 'coveraband-button'
|
75
|
+
button = "<form action='#{url}' class='coverband-admin-form' method='post'>"
|
76
|
+
button += "<button class='#{button_css}' type='submit'>#{title}</button>"
|
77
|
+
button + '</form>'
|
62
78
|
end
|
63
79
|
|
64
80
|
# Returns the html for the given source_file
|