blob: 7ddce74939d2f5450e0781caa8bfd242d56dc93f (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
require 'spec_helper'
describe NamespaceValidator do
let(:validator) { described_class.new(attributes: [:path]) }
# Pass in a full path to remove the format segment:
# `/ci/lint(.:format)` -> `/ci/lint`
def without_format(path)
path.split('(', 2)[0]
end
# Pass in a full path and get the last segment before a wildcard
# That's not a parameter
# `/*namespace_id/:project_id/builds/artifacts/*ref_name_and_path`
# -> 'artifacts'
def segment_before_last_wildcard(path)
path_segments = path.split('/').reject { |segment| segment.empty? }
last_wildcard_index = path_segments.rindex { |part| part.starts_with?('*') }
index_of_non_param_segment = last_wildcard_index - 1
part_before_wildcard = path_segments[index_of_non_param_segment]
while parameter?(part_before_wildcard)
index_of_non_param_segment -= 1
part_before_wildcard = path_segments[index_of_non_param_segment]
end
part_before_wildcard
end
def parameter?(path_segment)
path_segment.starts_with?(':') || path_segment.starts_with?('*')
end
let(:all_routes) do
Rails.application.routes.routes.routes.
map { |r| r.path.spec.to_s }
end
let(:routes_without_format) { all_routes.map { |path| without_format(path) } }
# Routes not starting with `/:` or `/*`
# all routes not starting with a param
let(:routes_not_starting_in_wildcard) { routes_without_format.select { |p| p !~ %r{^/[:*]} } }
# All routes that start with a namespaced path, that have 1 or more
# path-segments before having another wildcard parameter.
# - Starting with paths:
# - `/*namespace_id/:project_id/`
# - `/*namespace_id/:id/`
# - Followed by one or more path-parts not starting with `:` or `/`
# - Followed by a path-part that includes a wildcard parameter `*`
# At the time of writing these routes match: http://rubular.com/r/QDxulzZlxZ
STARTING_WITH_NAMESPACE = /^\/\*namespace_id\/:(project_)?id/
NON_PARAM_PARTS = /[^:*][a-z\-_\/]*/
ANY_OTHER_PATH_PART = /[a-z\-_\/:]*/
WILDCARD_SEGMENT = /\*/
let(:namespaced_wildcard_routes) do
routes_without_format.select do |p|
p =~ %r{#{STARTING_WITH_NAMESPACE}\/#{NON_PARAM_PARTS}\/#{ANY_OTHER_PATH_PART}#{WILDCARD_SEGMENT}}
end
end
describe 'TOP_LEVEL_ROUTES' do
it 'includes all the top level namespaces' do
top_level_words = routes_not_starting_in_wildcard.
map { |p| p.split('/')[1] }. # Get the first part of the path
compact.
uniq
expect(described_class::TOP_LEVEL_ROUTES).to include(*top_level_words)
end
end
describe 'WILDCARD_ROUTES' do
it 'includes all paths that can be used after a namespace/project path' do
all_wildcard_paths = namespaced_wildcard_routes.map do |path|
segment_before_last_wildcard(path)
end.uniq
expect(described_class::WILDCARD_ROUTES).to include(*all_wildcard_paths)
end
end
describe '#validation_type' do
it 'uses top level validation for groups without parent' do
group = build(:group)
type = validator.validation_type(group)
expect(type).to eq(:top_level)
end
it 'uses wildcard validation for groups with a parent' do
group = build(:group, parent: create(:group))
type = validator.validation_type(group)
expect(type).to eq(:wildcard)
end
it 'uses wildcard validation for a project' do
project = build(:project)
type = validator.validation_type(project)
expect(type).to eq(:wildcard)
end
it 'uses strict validation for everything else' do
type = validator.validation_type(double)
expect(type).to eq(:strict)
end
end
end
|