danger-dangermattic 1.2.2 → 1.2.3
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +6 -0
- data/Gemfile.lock +95 -57
- data/lib/dangermattic/gem_version.rb +1 -1
- data/lib/dangermattic/plugins/android_unit_test_checker.rb +7 -4
- data/lib/dangermattic/plugins/manifest_pr_checker.rb +13 -1
- data/lib/dangermattic/plugins/podfile_checker.rb +2 -0
- data/rakelib/console.rake +1 -1
- data/rakelib/git_helpers.rake +1 -1
- data/spec/android_unit_test_checker_spec.rb +93 -3
- data/spec/fixtures/android_unit_test_checker/MixDataPlusNormalClass.kt +14 -0
- data/spec/fixtures/android_unit_test_checker/src/main/java/com/dayoneapp/dayone/api/ApiResult.kt +69 -0
- data/spec/fixtures/android_unit_test_checker/src/main/java/com/dayoneapp/dayone/api/WebRecordApi.kt +49 -0
- data/spec/fixtures/android_unit_test_checker/src/main/java/com/dayoneapp/dayone/domain/drive/UiStates.kt +13 -0
- data/spec/fixtures/android_unit_test_checker/src/main/java/com/dayoneapp/dayone/main/settings/integrations/connect/AppIntegrationModule.kt +29 -0
- data/spec/fixtures/android_unit_test_checker/src/main/java/com/dayoneapp/dayone/main/streaks/StreaksViewModel.kt +377 -0
- data/spec/fixtures/android_unit_test_checker/src/main/java/com/dayoneapp/dayone/mediastorage/MediaStorageConfiguration.kt +31 -0
- data/spec/fixtures/android_unit_test_checker/src/main/java/com/dayoneapp/dayone/utils/AccountType.kt +15 -0
- data/spec/fixtures/android_unit_test_checker/src/main/java/com/dayoneapp/dayone/utils/usecase/SelectPhotoUseCase.kt +76 -0
- data/spec/pr_size_checker_spec.rb +14 -14
- data/spec/spec_helper.rb +8 -2
- data/spec/view_changes_checker_spec.rb +15 -15
- metadata +11 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 20a5e57d91cc796def3533c72a3a674ea494356982fa78015ccc016ce19b61c9
|
4
|
+
data.tar.gz: 376d14c60ba7aadc6107b4a6de9a40dc968a658a0fe326aaad208866bf4583e9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 10ed4e5e5772cc7631470fe591c79004a5a237ddaffb6c708204d4823a204f15cc068530c5e8b05bc0f150577037f93bcb675a93ae47eb4c71a5d1b245e658fe
|
7
|
+
data.tar.gz: 06c85ea386f290706300db05c3a07439859bda94d025a6dd9bab9068786a2040b247c09c8d1314c31f44c09d07e5aded50434d3092c55aeca1ff9fce2aad78d2
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
danger-dangermattic (1.2.
|
4
|
+
danger-dangermattic (1.2.3)
|
5
5
|
danger (~> 9.4)
|
6
6
|
danger-plugin-api (~> 1.0)
|
7
7
|
danger-rubocop (~> 0.13)
|
@@ -10,10 +10,25 @@ PATH
|
|
10
10
|
GEM
|
11
11
|
remote: https://rubygems.org/
|
12
12
|
specs:
|
13
|
+
activesupport (8.0.2)
|
14
|
+
base64
|
15
|
+
benchmark (>= 0.3)
|
16
|
+
bigdecimal
|
17
|
+
concurrent-ruby (~> 1.0, >= 1.3.1)
|
18
|
+
connection_pool (>= 2.2.5)
|
19
|
+
drb
|
20
|
+
i18n (>= 1.6, < 2)
|
21
|
+
logger (>= 1.4.2)
|
22
|
+
minitest (>= 5.1)
|
23
|
+
securerandom (>= 0.3)
|
24
|
+
tzinfo (~> 2.0, >= 2.0.5)
|
25
|
+
uri (>= 0.13.1)
|
13
26
|
addressable (2.8.7)
|
14
27
|
public_suffix (>= 2.0.2, < 7.0)
|
15
|
-
ast (2.4.
|
16
|
-
base64 (0.
|
28
|
+
ast (2.4.3)
|
29
|
+
base64 (0.3.0)
|
30
|
+
benchmark (0.4.1)
|
31
|
+
bigdecimal (3.2.2)
|
17
32
|
claide (1.1.0)
|
18
33
|
claide-plugins (0.9.2)
|
19
34
|
cork
|
@@ -21,48 +36,55 @@ GEM
|
|
21
36
|
open4 (~> 1.3)
|
22
37
|
coderay (1.1.3)
|
23
38
|
colored2 (3.1.2)
|
39
|
+
concurrent-ruby (1.3.5)
|
40
|
+
connection_pool (2.5.3)
|
24
41
|
cork (0.3.0)
|
25
42
|
colored2 (~> 3.1)
|
26
|
-
danger (9.5.
|
43
|
+
danger (9.5.3)
|
27
44
|
base64 (~> 0.2)
|
28
45
|
claide (~> 1.0)
|
29
46
|
claide-plugins (>= 0.9.2)
|
30
|
-
colored2 (
|
47
|
+
colored2 (>= 3.1, < 5)
|
31
48
|
cork (~> 0.1)
|
32
49
|
faraday (>= 0.9.0, < 3.0)
|
33
50
|
faraday-http-cache (~> 2.0)
|
34
|
-
git (
|
35
|
-
kramdown (
|
51
|
+
git (>= 1.13, < 3.0)
|
52
|
+
kramdown (>= 2.5.1, < 3.0)
|
36
53
|
kramdown-parser-gfm (~> 1.0)
|
37
54
|
octokit (>= 4.0)
|
38
55
|
pstore (~> 0.1)
|
39
|
-
terminal-table (>= 1, <
|
56
|
+
terminal-table (>= 1, < 5)
|
40
57
|
danger-plugin-api (1.0.0)
|
41
58
|
danger (> 2.0)
|
42
59
|
danger-rubocop (0.13.0)
|
43
60
|
danger
|
44
61
|
rubocop (~> 1.0)
|
45
|
-
diff-lcs (1.
|
46
|
-
|
47
|
-
|
62
|
+
diff-lcs (1.6.2)
|
63
|
+
drb (2.2.3)
|
64
|
+
faraday (2.13.4)
|
65
|
+
faraday-net_http (>= 2.0, < 3.5)
|
48
66
|
json
|
49
67
|
logger
|
50
68
|
faraday-http-cache (2.5.1)
|
51
69
|
faraday (>= 0.8)
|
52
|
-
faraday-net_http (3.
|
53
|
-
net-http
|
54
|
-
ffi (1.17.
|
55
|
-
ffi (1.17.
|
56
|
-
formatador (1.1.
|
57
|
-
git (
|
70
|
+
faraday-net_http (3.4.1)
|
71
|
+
net-http (>= 0.5.0)
|
72
|
+
ffi (1.17.2)
|
73
|
+
ffi (1.17.2-arm64-darwin)
|
74
|
+
formatador (1.1.1)
|
75
|
+
git (2.3.3)
|
76
|
+
activesupport (>= 5.0)
|
58
77
|
addressable (~> 2.8)
|
78
|
+
process_executer (~> 1.1)
|
59
79
|
rchardet (~> 1.8)
|
60
|
-
guard (2.19.
|
80
|
+
guard (2.19.1)
|
61
81
|
formatador (>= 0.2.4)
|
62
82
|
listen (>= 2.7, < 4.0)
|
83
|
+
logger (~> 1.6)
|
63
84
|
lumberjack (>= 1.0.12, < 2.0)
|
64
85
|
nenv (~> 0.1)
|
65
86
|
notiffany (~> 0.0)
|
87
|
+
ostruct (~> 0.6)
|
66
88
|
pry (>= 0.13.0)
|
67
89
|
shellany (~> 0.0)
|
68
90
|
thor (>= 0.18.1)
|
@@ -71,86 +93,102 @@ GEM
|
|
71
93
|
guard (~> 2.1)
|
72
94
|
guard-compat (~> 1.1)
|
73
95
|
rspec (>= 2.99.0, < 4.0)
|
74
|
-
|
75
|
-
|
76
|
-
|
96
|
+
i18n (1.14.7)
|
97
|
+
concurrent-ruby (~> 1.0)
|
98
|
+
json (2.13.2)
|
99
|
+
kramdown (2.5.1)
|
100
|
+
rexml (>= 3.3.9)
|
77
101
|
kramdown-parser-gfm (1.1.0)
|
78
102
|
kramdown (~> 2.0)
|
79
|
-
language_server-protocol (3.17.0.
|
103
|
+
language_server-protocol (3.17.0.5)
|
104
|
+
lint_roller (1.1.0)
|
80
105
|
listen (3.9.0)
|
81
106
|
rb-fsevent (~> 0.10, >= 0.10.3)
|
82
107
|
rb-inotify (~> 0.9, >= 0.9.10)
|
83
|
-
logger (1.
|
84
|
-
lumberjack (1.
|
108
|
+
logger (1.7.0)
|
109
|
+
lumberjack (1.4.0)
|
85
110
|
method_source (1.1.0)
|
111
|
+
minitest (5.25.5)
|
86
112
|
nap (1.1.0)
|
87
113
|
nenv (0.3.0)
|
88
|
-
net-http (0.
|
114
|
+
net-http (0.6.0)
|
89
115
|
uri
|
90
116
|
notiffany (0.1.3)
|
91
117
|
nenv (~> 0.1)
|
92
118
|
shellany (~> 0.0)
|
93
|
-
octokit (
|
119
|
+
octokit (10.0.0)
|
94
120
|
faraday (>= 1, < 3)
|
95
121
|
sawyer (~> 0.9)
|
96
122
|
open4 (1.3.4)
|
97
|
-
|
98
|
-
|
123
|
+
ostruct (0.6.3)
|
124
|
+
parallel (1.27.0)
|
125
|
+
parser (3.3.9.0)
|
99
126
|
ast (~> 2.4.1)
|
100
127
|
racc
|
101
|
-
|
128
|
+
prism (1.4.0)
|
129
|
+
process_executer (1.3.0)
|
130
|
+
pry (0.15.2)
|
102
131
|
coderay (~> 1.1)
|
103
132
|
method_source (~> 1.0)
|
104
|
-
pstore (0.
|
105
|
-
public_suffix (6.0.
|
133
|
+
pstore (0.2.0)
|
134
|
+
public_suffix (6.0.2)
|
106
135
|
racc (1.8.1)
|
107
136
|
rainbow (3.1.1)
|
108
|
-
rake (13.
|
137
|
+
rake (13.3.0)
|
109
138
|
rb-fsevent (0.11.2)
|
110
139
|
rb-inotify (0.11.1)
|
111
140
|
ffi (~> 1.0)
|
112
|
-
rchardet (1.
|
113
|
-
regexp_parser (2.
|
114
|
-
rexml (3.
|
115
|
-
rspec (3.13.
|
141
|
+
rchardet (1.9.0)
|
142
|
+
regexp_parser (2.11.0)
|
143
|
+
rexml (3.4.2)
|
144
|
+
rspec (3.13.1)
|
116
145
|
rspec-core (~> 3.13.0)
|
117
146
|
rspec-expectations (~> 3.13.0)
|
118
147
|
rspec-mocks (~> 3.13.0)
|
119
|
-
rspec-core (3.13.
|
148
|
+
rspec-core (3.13.5)
|
120
149
|
rspec-support (~> 3.13.0)
|
121
|
-
rspec-expectations (3.13.
|
150
|
+
rspec-expectations (3.13.5)
|
122
151
|
diff-lcs (>= 1.2.0, < 2.0)
|
123
152
|
rspec-support (~> 3.13.0)
|
124
|
-
rspec-mocks (3.13.
|
153
|
+
rspec-mocks (3.13.5)
|
125
154
|
diff-lcs (>= 1.2.0, < 2.0)
|
126
155
|
rspec-support (~> 3.13.0)
|
127
|
-
rspec-support (3.13.
|
128
|
-
rubocop (1.
|
156
|
+
rspec-support (3.13.4)
|
157
|
+
rubocop (1.79.2)
|
129
158
|
json (~> 2.3)
|
130
|
-
language_server-protocol (
|
159
|
+
language_server-protocol (~> 3.17.0.2)
|
160
|
+
lint_roller (~> 1.1.0)
|
131
161
|
parallel (~> 1.10)
|
132
162
|
parser (>= 3.3.0.2)
|
133
163
|
rainbow (>= 2.2.2, < 4.0)
|
134
|
-
regexp_parser (>= 2.
|
135
|
-
rubocop-ast (>= 1.
|
164
|
+
regexp_parser (>= 2.9.3, < 3.0)
|
165
|
+
rubocop-ast (>= 1.46.0, < 2.0)
|
136
166
|
ruby-progressbar (~> 1.7)
|
137
|
-
unicode-display_width (>= 2.4.0, <
|
138
|
-
rubocop-ast (1.
|
139
|
-
parser (>= 3.3.
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
rubocop (
|
167
|
+
unicode-display_width (>= 2.4.0, < 4.0)
|
168
|
+
rubocop-ast (1.46.0)
|
169
|
+
parser (>= 3.3.7.2)
|
170
|
+
prism (~> 1.4)
|
171
|
+
rubocop-rake (0.7.1)
|
172
|
+
lint_roller (~> 1.1)
|
173
|
+
rubocop (>= 1.72.1)
|
174
|
+
rubocop-rspec (3.6.0)
|
175
|
+
lint_roller (~> 1.1)
|
176
|
+
rubocop (~> 1.72, >= 1.72.1)
|
144
177
|
ruby-progressbar (1.13.0)
|
145
178
|
sawyer (0.9.2)
|
146
179
|
addressable (>= 2.3.5)
|
147
180
|
faraday (>= 0.17.3, < 3)
|
181
|
+
securerandom (0.4.1)
|
148
182
|
shellany (0.0.1)
|
149
|
-
terminal-table (
|
150
|
-
unicode-display_width (>= 1.1.1, <
|
151
|
-
thor (1.
|
152
|
-
|
153
|
-
|
183
|
+
terminal-table (4.0.0)
|
184
|
+
unicode-display_width (>= 1.1.1, < 4)
|
185
|
+
thor (1.4.0)
|
186
|
+
tzinfo (2.0.6)
|
187
|
+
concurrent-ruby (~> 1.0)
|
188
|
+
unicode-display_width (3.1.4)
|
189
|
+
unicode-emoji (~> 4.0, >= 4.0.4)
|
190
|
+
unicode-emoji (4.0.4)
|
191
|
+
uri (1.0.3)
|
154
192
|
yard (0.9.37)
|
155
193
|
|
156
194
|
PLATFORMS
|
@@ -170,4 +208,4 @@ DEPENDENCIES
|
|
170
208
|
yard
|
171
209
|
|
172
210
|
BUNDLED WITH
|
173
|
-
2.
|
211
|
+
2.6.8
|
@@ -24,14 +24,15 @@ module Danger
|
|
24
24
|
#
|
25
25
|
class AndroidUnitTestChecker < Plugin
|
26
26
|
ANY_CLASS_DETECTOR = /class\s+([A-Z]\w+)\s*(.*?)\s*{/m
|
27
|
-
CLASS_MODIFIER_DETECTOR = /((?:\s|public|internal|protected|private|final|abstract|static|data|enum|sealed|value)*)class\s+([A-Z]\w+)\s*(.*?)\s*{/m
|
27
|
+
CLASS_MODIFIER_DETECTOR = /((?:\s|public|internal|protected|private|final|abstract|static|data|enum|sealed|value|annotation)*)class\s+([A-Z]\w+)\s*(.*?)\s*({|\n\n)/m
|
28
28
|
|
29
29
|
CLASS_MODIFIER_EXCEPTIONS = [
|
30
30
|
/\s*data\s*/,
|
31
31
|
/\s*private\s*/,
|
32
32
|
/\s*enum\s*/,
|
33
33
|
/\s*sealed\s*/,
|
34
|
-
/\s*value\s
|
34
|
+
/\s*value\s*/,
|
35
|
+
/\s*annotation\s*/
|
35
36
|
].freeze
|
36
37
|
|
37
38
|
DEFAULT_CLASSES_EXCEPTIONS = [
|
@@ -95,6 +96,7 @@ module Danger
|
|
95
96
|
private
|
96
97
|
|
97
98
|
ClassViolation = Struct.new(:classname, :file)
|
99
|
+
private_constant :ClassViolation
|
98
100
|
|
99
101
|
# @param git_diff [Git::Diff] the git diff object
|
100
102
|
# @param classes_exceptions [Array<String>] Regexes matching class names to exclude from the check.
|
@@ -151,7 +153,7 @@ module Danger
|
|
151
153
|
# @return [Array<ClassViolation>] An array of ClassViolation objects representing the violations found.
|
152
154
|
def find_violations(path:, diff_patch:, classes_exceptions:, subclasses_exceptions:)
|
153
155
|
added_lines = git_utils.added_lines(diff_patch: diff_patch)
|
154
|
-
matches = added_lines.scan(CLASS_MODIFIER_DETECTOR)
|
156
|
+
matches = "#{added_lines}\n".scan(CLASS_MODIFIER_DETECTOR) # add a newline to ensure the regex matches the last class in the file
|
155
157
|
matches.reject! do |m|
|
156
158
|
class_match_is_exception?(
|
157
159
|
m,
|
@@ -180,10 +182,11 @@ module Danger
|
|
180
182
|
# @param classes_exceptions [Array<String>] Regexes matching class names to exclude from the check.
|
181
183
|
# @param subclasses_exceptions [Array<String>] Regexes matching base class names to exclude from the check
|
182
184
|
#
|
183
|
-
# @return [
|
185
|
+
# @return [Boolean]
|
184
186
|
def class_match_is_exception?(match, file, classes_exceptions, subclasses_exceptions)
|
185
187
|
return true if classes_exceptions.any? { |re| match[1] =~ re }
|
186
188
|
return true if CLASS_MODIFIER_EXCEPTIONS.any? { |re| match[0] =~ re }
|
189
|
+
return true unless match[3].include?('{') # Ignore classes that don't have a body
|
187
190
|
|
188
191
|
subclass_regexp = File.extname(file) == '.java' ? /extends\s+([A-Z]\w+)/m : /\s*:\s*([A-Z]\w+)/m
|
189
192
|
subclass = match[2].scan(subclass_regexp)&.last&.last
|
@@ -29,7 +29,17 @@ module Danger
|
|
29
29
|
#
|
30
30
|
class ManifestPRChecker < Plugin
|
31
31
|
MESSAGE = '`%s` was changed without updating its corresponding `%s`. %s.'
|
32
|
-
|
32
|
+
|
33
|
+
# The two new lines at the start are intentional.
|
34
|
+
# This will be interpolated in MESSAGE into the final %s.
|
35
|
+
# The first new line moves it to a new line, the second adds visual padding.
|
36
|
+
SWIFT_INSTRUCTION = <<~INSTRUCTION
|
37
|
+
|
38
|
+
|
39
|
+
If the change includes adding, removing, or editing a dependency please resolve the Swift packages as appropriate to your project setup (e.g. in Xcode or by running `swift package resolve`).
|
40
|
+
|
41
|
+
If the change to the `Package.swift` did not modify dependencies, ignoring this warning should be safe, but we recommend double checking and running the package resolution just in case.
|
42
|
+
INSTRUCTION
|
33
43
|
|
34
44
|
# Performs all the checks, asserting that changes on `Gemfile`, `Podfile` and `Package.swift` must have corresponding
|
35
45
|
# lock file changes.
|
@@ -88,6 +98,8 @@ module Danger
|
|
88
98
|
# Check if the `Package.swift` file was modified without a corresponding `Package.resolved` update,
|
89
99
|
# checking for exact path matches
|
90
100
|
#
|
101
|
+
# @param manifest_path [String] The path to the `Package.swift` file.
|
102
|
+
# @param manifest_lock_path [String] The path to the `Package.resolved` file.
|
91
103
|
# @param report_type [Symbol] (optional) The type of report for the message. Types: :error, :warning (default), :message.
|
92
104
|
#
|
93
105
|
# @return [void]
|
@@ -86,7 +86,9 @@ module Danger
|
|
86
86
|
private
|
87
87
|
|
88
88
|
COMMIT_REFERENCE_REGEXP = /\(from `\S+`, commit `\S+`\)/
|
89
|
+
private_constant :COMMIT_REFERENCE_REGEXP
|
89
90
|
BRANCH_REFERENCE_REGEXP = /\(from `\S+`, branch `\S+`\)/
|
91
|
+
private_constant :BRANCH_REFERENCE_REGEXP
|
90
92
|
|
91
93
|
def check_podfile_does_not_match(
|
92
94
|
regexp:,
|
data/rakelib/console.rake
CHANGED
data/rakelib/git_helpers.rake
CHANGED
@@ -17,7 +17,7 @@ module GitHelper
|
|
17
17
|
elsif branch_exists
|
18
18
|
Rake.sh('git', 'checkout', release_branch)
|
19
19
|
else # create it
|
20
|
-
abort('Aborted, as not run from trunk nor release branch') unless current_branch == 'trunk' || Console.confirm("You are not on 'trunk', nor already on '#{release_branch}'. Do you really want to cut the release branch from #{current_branch}?")
|
20
|
+
abort('Aborted, as not run from trunk nor release branch') unless current_branch == 'trunk' || Console.confirm?("You are not on 'trunk', nor already on '#{release_branch}'. Do you really want to cut the release branch from #{current_branch}?")
|
21
21
|
|
22
22
|
Rake.sh('git', 'checkout', '-b', release_branch)
|
23
23
|
end
|
@@ -144,6 +144,93 @@ module Danger
|
|
144
144
|
expect(@dangerfile).to not_report
|
145
145
|
end
|
146
146
|
|
147
|
+
it 'ensures data classes with no {…} body don\'t mess up detection of subsequent classes in the same file' do
|
148
|
+
# Ensure the CLASS_MODIFIER_DETECTOR regex doesn't assume class declaration always ends with `{` marking the class body
|
149
|
+
# (which would lead the regex to either miss the data class or extend the regex to the next `{`… that potentially belongs to the next class)
|
150
|
+
# This is especially important given data classes might not have a body at all
|
151
|
+
|
152
|
+
mix_data_plus_normal_class_file = 'MixDataPlusNormalClass.kt'
|
153
|
+
data_and_normal_class_diff = generate_add_diff_from_fixtures([mix_data_plus_normal_class_file])
|
154
|
+
|
155
|
+
allow(@dangerfile.git).to receive(:diff).and_return(data_and_normal_class_diff)
|
156
|
+
|
157
|
+
@plugin.check_missing_tests
|
158
|
+
|
159
|
+
expect_class_names_match_report(class_names: ['DummyClassMissingTest'], error_report: @dangerfile.status_report[:errors])
|
160
|
+
end
|
161
|
+
|
162
|
+
context 'when detecting classes and class modifiers' do
|
163
|
+
let(:added_files) do
|
164
|
+
dayone_source_fixtures_subdir = %w[src main java com dayoneapp dayone]
|
165
|
+
Dir.glob('**/*.kt', base: fixture_path('android_unit_test_checker', dayone_source_fixtures_subdir))
|
166
|
+
.map { |file| File.join(dayone_source_fixtures_subdir, file) }
|
167
|
+
end
|
168
|
+
let(:diff) { generate_add_diff_from_fixtures(added_files) }
|
169
|
+
|
170
|
+
# ClassName => Expected to be detected (true) or ignored (false)
|
171
|
+
let(:expected_detected_classes) do
|
172
|
+
{
|
173
|
+
# ApiResult.kt
|
174
|
+
'ApiResult' => false, # `sealed class ApiResult<T>`
|
175
|
+
'Success' => false, # `data class Success<T>`
|
176
|
+
'Empty' => false, # `class Empty<T> : ApiResult<T>()` (but no body)
|
177
|
+
'Failure' => false, # `data class Failure<T>(…)`
|
178
|
+
'FailureType' => false, # `enum class FailureType`
|
179
|
+
|
180
|
+
# WebRecordApi.kt
|
181
|
+
'CursorTime' => false, # `value class CursorTime`
|
182
|
+
'WebRecordChanges' => false, # `data class WebRecordChanges`
|
183
|
+
|
184
|
+
# UiStates.kt
|
185
|
+
'LoadKeyUiState' => false, # `sealed class LoadKeyUiState`
|
186
|
+
|
187
|
+
# AppIntegrationModule.kt
|
188
|
+
'AppIntegrationHandlers' => false, # `annotation class AppIntegrationHandlers`
|
189
|
+
|
190
|
+
# StreaksViewModel.kt
|
191
|
+
'StreaksViewModel' => true, # `class StreaksViewModel`
|
192
|
+
'Streaks' => false, # `data class Streaks`
|
193
|
+
'JournalOptionsState' => false, # `class JournalOptionsState` (but no body)
|
194
|
+
'StreakWeekDay' => false, # `data class StreakWeekDay`
|
195
|
+
'DayJournaled' => false, # `value class DayJournaled`
|
196
|
+
'StreakJournal' => false, # `data class StreakJournal`
|
197
|
+
'DaysOfWeekList' => false, # `private class DaysOfWeekList`
|
198
|
+
'PreviousDays' => false, # `class PreviousDays` (but no body)
|
199
|
+
|
200
|
+
# MediaStorageConfiguration.kt
|
201
|
+
'CompressQuality' => false, # `value class CompressQuality`
|
202
|
+
'MediaStorageConfiguration' => false, # `class MediaStorageConfiguration` (but no body)
|
203
|
+
'ThumbnailsConfiguration' => false, # `class ThumbnailsConfiguration` (but no body)
|
204
|
+
|
205
|
+
# AccountType.kt
|
206
|
+
'AccountType' => false, # `enum class AccountType`
|
207
|
+
|
208
|
+
# SelectPhotoUseCase.kt
|
209
|
+
'SelectPhotoUseCase' => true, # `class SelectPhotoUseCase`
|
210
|
+
'GetMultipleImages' => false, # `private class GetMultipleImages`
|
211
|
+
'GetSingleImage' => false # `private class GetSingleImage`
|
212
|
+
}
|
213
|
+
end
|
214
|
+
|
215
|
+
before do
|
216
|
+
allow(@dangerfile.git).to receive(:diff).and_return(diff)
|
217
|
+
end
|
218
|
+
|
219
|
+
it 'reports only classes that don\'t have a modifier that is part of modifier exceptions' do
|
220
|
+
@plugin.check_missing_tests
|
221
|
+
expected_violating_classes = expected_detected_classes.filter_map { |k, v| k if v } # only keys whose value is true
|
222
|
+
expect_class_names_match_report(class_names: expected_violating_classes, error_report: @dangerfile.status_report[:errors])
|
223
|
+
end
|
224
|
+
|
225
|
+
it 'validates that the RegEx matches all classes from source code' do
|
226
|
+
# Mock detection of exceptions in order to make `check_missing_tests` report all classes regardless of modifiers
|
227
|
+
# This allows us to validate that our RegEx matches all classes from the source code in the first place
|
228
|
+
allow(@plugin).to receive(:class_match_is_exception?).and_return(false)
|
229
|
+
@plugin.check_missing_tests
|
230
|
+
expect_class_names_match_report(class_names: expected_detected_classes.keys, error_report: @dangerfile.status_report[:errors])
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
147
234
|
it 'does not report that a PR with the tests bypass label is missing tests' do
|
148
235
|
added_files = %w[
|
149
236
|
Abc.java
|
@@ -301,7 +388,7 @@ module Danger
|
|
301
388
|
|
302
389
|
def generate_add_diff_from_fixtures(paths)
|
303
390
|
paths.map do |path|
|
304
|
-
content = fixture(
|
391
|
+
content = fixture('android_unit_test_checker', path)
|
305
392
|
diff_str = generate_add_diff(file_path: path, content: content)
|
306
393
|
|
307
394
|
GitDiffStruct.new('new', path, diff_str)
|
@@ -310,7 +397,7 @@ module Danger
|
|
310
397
|
|
311
398
|
def generate_delete_diff_from_fixtures(paths)
|
312
399
|
paths.map do |path|
|
313
|
-
content = fixture(
|
400
|
+
content = fixture('android_unit_test_checker', path)
|
314
401
|
diff_str = generate_delete_diff(file_path: path, content: content)
|
315
402
|
|
316
403
|
GitDiffStruct.new('deleted', path, diff_str)
|
@@ -348,7 +435,10 @@ module Danger
|
|
348
435
|
end
|
349
436
|
|
350
437
|
def expect_class_names_match_report(class_names:, error_report:)
|
351
|
-
|
438
|
+
if error_report.length != class_names.length
|
439
|
+
reported_class_names = error_report.map { |e| e.match(/class `(.*?)`/)[1] }
|
440
|
+
expect(reported_class_names).to eq(class_names)
|
441
|
+
end
|
352
442
|
class_names.zip(error_report).each do |cls, error|
|
353
443
|
expect(error).to include "Please add tests for class `#{cls}`"
|
354
444
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import javax.inject.Inject
|
2
|
+
import javax.inject.Singleton
|
3
|
+
|
4
|
+
internal data class DummyDataClassNotNeedingTests(
|
5
|
+
val title: String,
|
6
|
+
val id: String
|
7
|
+
)
|
8
|
+
|
9
|
+
@Singleton
|
10
|
+
internal class DummyClassMissingTest @Inject constructor(
|
11
|
+
private val name: String,
|
12
|
+
) : ParentClass {
|
13
|
+
private val loggingTag = 'mylogging'
|
14
|
+
}
|
data/spec/fixtures/android_unit_test_checker/src/main/java/com/dayoneapp/dayone/api/ApiResult.kt
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
package com.dayoneapp.dayone.api
|
2
|
+
|
3
|
+
import com.dayoneapp.dayone.api.ApiResult.Failure
|
4
|
+
import com.dayoneapp.dayone.api.ApiResult.FailureType.GENERIC
|
5
|
+
import com.dayoneapp.dayone.api.ApiResult.FailureType.SERVER_ERROR
|
6
|
+
import com.dayoneapp.dayone.api.ApiResult.FailureType.TIMEOUT
|
7
|
+
import com.dayoneapp.dayone.api.ApiResult.FailureType.UNAUTHORIZED
|
8
|
+
import com.dayoneapp.syncservice.NetworkErrorType
|
9
|
+
import com.google.api.client.http.HttpStatusCodes
|
10
|
+
import retrofit2.Response
|
11
|
+
import java.io.IOException
|
12
|
+
|
13
|
+
sealed class ApiResult<T> {
|
14
|
+
data class Success<T>(
|
15
|
+
val data: T,
|
16
|
+
) : ApiResult<T>()
|
17
|
+
|
18
|
+
class Empty<T> : ApiResult<T>()
|
19
|
+
|
20
|
+
data class Failure<T>(
|
21
|
+
val type: FailureType,
|
22
|
+
val errorCode: Int? = null,
|
23
|
+
val errorMessage: String? = null,
|
24
|
+
) : ApiResult<T>()
|
25
|
+
|
26
|
+
enum class FailureType {
|
27
|
+
SERVER_ERROR,
|
28
|
+
UNAUTHORIZED,
|
29
|
+
TIMEOUT,
|
30
|
+
GENERIC,
|
31
|
+
NOT_CONNECTED,
|
32
|
+
;
|
33
|
+
|
34
|
+
companion object {
|
35
|
+
fun fromNetworkErrorType(networkErrorType: NetworkErrorType): FailureType =
|
36
|
+
when (networkErrorType) {
|
37
|
+
NetworkErrorType.SERVER_ERROR -> SERVER_ERROR
|
38
|
+
NetworkErrorType.UNAUTHORIZED -> UNAUTHORIZED
|
39
|
+
NetworkErrorType.TIMEOUT -> TIMEOUT
|
40
|
+
NetworkErrorType.GENERIC -> GENERIC
|
41
|
+
else -> {
|
42
|
+
GENERIC
|
43
|
+
}
|
44
|
+
}
|
45
|
+
}
|
46
|
+
}
|
47
|
+
}
|
48
|
+
|
49
|
+
suspend fun <T> apiCall(apiCall: suspend () -> Response<T>): ApiResult<T> =
|
50
|
+
try {
|
51
|
+
with(apiCall()) {
|
52
|
+
if (this.isSuccessful) {
|
53
|
+
this.body()?.let {
|
54
|
+
ApiResult.Success(it)
|
55
|
+
} ?: ApiResult.Empty()
|
56
|
+
} else {
|
57
|
+
val type =
|
58
|
+
when (this.code()) {
|
59
|
+
HttpStatusCodes.STATUS_CODE_UNAUTHORIZED, HttpStatusCodes.STATUS_CODE_FORBIDDEN -> UNAUTHORIZED
|
60
|
+
HttpStatusCodes.STATUS_CODE_SERVER_ERROR -> SERVER_ERROR
|
61
|
+
else -> GENERIC
|
62
|
+
}
|
63
|
+
Failure(type, this.code(), this.message())
|
64
|
+
}
|
65
|
+
}
|
66
|
+
} catch (e: IOException) {
|
67
|
+
Failure(TIMEOUT)
|
68
|
+
}
|
69
|
+
|
data/spec/fixtures/android_unit_test_checker/src/main/java/com/dayoneapp/dayone/api/WebRecordApi.kt
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
package com.dayoneapp.dayone.api
|
2
|
+
|
3
|
+
import com.dayoneapp.dayone.domain.sync.WebRecordRemote
|
4
|
+
import com.google.gson.annotations.SerializedName
|
5
|
+
import retrofit2.Response
|
6
|
+
import retrofit2.http.*
|
7
|
+
|
8
|
+
@JvmInline
|
9
|
+
value class CursorTime(
|
10
|
+
val time: String,
|
11
|
+
)
|
12
|
+
|
13
|
+
val ZeroCursorTime = CursorTime("0")
|
14
|
+
|
15
|
+
data class WebRecordChanges(
|
16
|
+
@SerializedName("changes")
|
17
|
+
val changes: List<WebRecordRemote>,
|
18
|
+
@SerializedName("cursor")
|
19
|
+
val cursor: String,
|
20
|
+
)
|
21
|
+
|
22
|
+
interface WebRecordApi {
|
23
|
+
@POST("$SYNC/named/{name}")
|
24
|
+
suspend fun createRecord(
|
25
|
+
@Path("name") name: String,
|
26
|
+
@Body record: WebRecordRemote,
|
27
|
+
): Response<WebRecordRemote>
|
28
|
+
|
29
|
+
@PUT("$SYNC/{syncId}")
|
30
|
+
suspend fun updateRecord(
|
31
|
+
@Path("syncId") syncId: String,
|
32
|
+
@Body record: WebRecordRemote,
|
33
|
+
): Response<WebRecordRemote>
|
34
|
+
|
35
|
+
@GET("$SYNC/named/{name}")
|
36
|
+
suspend fun fetchRecord(
|
37
|
+
@Path("name") name: String,
|
38
|
+
): Response<WebRecordRemote>
|
39
|
+
|
40
|
+
@GET("$SYNC/changes/{kind}")
|
41
|
+
suspend fun fetchRecordChanges(
|
42
|
+
@Path("kind") kind: String,
|
43
|
+
@Query("cursor") cursor: CursorTime,
|
44
|
+
): Response<WebRecordChanges>
|
45
|
+
|
46
|
+
companion object {
|
47
|
+
const val SYNC = "/api/v4/sync"
|
48
|
+
}
|
49
|
+
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
package com.dayoneapp.dayone.domain.drive
|
2
|
+
|
3
|
+
sealed class LoadKeyUiState(
|
4
|
+
val buttonEnabled: Boolean,
|
5
|
+
) {
|
6
|
+
object Init : LoadKeyUiState(buttonEnabled = true)
|
7
|
+
|
8
|
+
object Loading : LoadKeyUiState(buttonEnabled = false)
|
9
|
+
|
10
|
+
object KeyLoaded : LoadKeyUiState(buttonEnabled = false)
|
11
|
+
|
12
|
+
object KeyNotFound : LoadKeyUiState(buttonEnabled = true)
|
13
|
+
}
|