Skip to content

Commit 3ca551a

Browse files
committed
Split routes_spec.rb into 6 smaller files for better parallelization
Original file: spec/request/routes_spec.rb (3,748 lines, 401 examples) Split into: - list_spec.rb (GET /v3/routes) - 937 lines - show_spec.rb (GET /v3/routes/:guid) - 171 lines - create_spec.rb (POST /v3/routes) - 1289 lines - update_and_delete_spec.rb - 277 lines - sharing_spec.rb (shared_spaces relationships) - 917 lines - apps_routes_spec.rb (GET /v3/apps/:app_guid/routes) - 173 lines Shared test setup extracted to shared_context.rb This split enables better parallel test distribution.
1 parent 870056e commit 3ca551a

7 files changed

Lines changed: 3800 additions & 0 deletions

File tree

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
require 'spec_helper'
2+
require 'request_spec_shared_examples'
3+
require_relative 'shared_context'
4+
5+
# Split from spec/request/routes_spec.rb for better test parallelization
6+
7+
RSpec.describe 'Routes Request' do
8+
include_context 'routes request spec'
9+
10+
describe 'GET /v3/apps/:app_guid/routes' do
11+
let(:app_model) { VCAP::CloudController::AppModel.make(space:) }
12+
let(:route1) { VCAP::CloudController::Route.make(space:) }
13+
let(:route2) { VCAP::CloudController::Route.make(space:) }
14+
let!(:route3) { VCAP::CloudController::Route.make(space:) }
15+
let!(:route_mapping1) { VCAP::CloudController::RouteMappingModel.make(app: app_model, route: route1, process_type: 'web') }
16+
let!(:route_mapping2) { VCAP::CloudController::RouteMappingModel.make(app: app_model, route: route2, process_type: 'admin') }
17+
let(:api_call) { ->(user_headers) { get "/v3/apps/#{app_model.guid}/routes", nil, user_headers } }
18+
19+
let(:route1_json) do
20+
{
21+
guid: route1.guid,
22+
protocol: route1.domain.protocols[0],
23+
host: route1.host,
24+
path: route1.path,
25+
port: nil,
26+
url: "#{route1.host}.#{route1.domain.name}#{route1.path}",
27+
created_at: iso8601,
28+
updated_at: iso8601,
29+
destinations: contain_exactly({
30+
guid: route_mapping1.guid,
31+
app: {
32+
guid: app_model.guid,
33+
process: {
34+
type: route_mapping1.process_type
35+
}
36+
},
37+
weight: route_mapping1.weight,
38+
port: route_mapping1.presented_port,
39+
protocol: 'http1',
40+
created_at: iso8601,
41+
updated_at: iso8601
42+
}),
43+
relationships: {
44+
space: {
45+
data: { guid: route1.space.guid }
46+
},
47+
domain: {
48+
data: { guid: route1.domain.guid }
49+
}
50+
},
51+
metadata: {
52+
labels: {},
53+
annotations: {}
54+
},
55+
links: {
56+
self: { href: %r{#{Regexp.escape(link_prefix)}/v3/routes/#{route1.guid}} },
57+
space: { href: %r{#{Regexp.escape(link_prefix)}/v3/spaces/#{route1.space.guid}} },
58+
destinations: { href: %r{#{Regexp.escape(link_prefix)}/v3/routes/#{route1.guid}/destinations} },
59+
domain: { href: %r{#{Regexp.escape(link_prefix)}/v3/domains/#{route1.domain.guid}} }
60+
},
61+
options: {}
62+
}
63+
end
64+
65+
let(:route2_json) do
66+
{
67+
guid: route2.guid,
68+
protocol: route2.domain.protocols[0],
69+
host: route2.host,
70+
path: route2.path,
71+
port: nil,
72+
url: "#{route2.host}.#{route2.domain.name}#{route2.path}",
73+
created_at: iso8601,
74+
updated_at: iso8601,
75+
destinations: contain_exactly({
76+
guid: route_mapping2.guid,
77+
app: {
78+
guid: app_model.guid,
79+
process: {
80+
type: route_mapping2.process_type
81+
}
82+
},
83+
weight: route_mapping2.weight,
84+
port: route_mapping2.presented_port,
85+
protocol: 'http1',
86+
created_at: iso8601,
87+
updated_at: iso8601
88+
}),
89+
relationships: {
90+
space: {
91+
data: { guid: route2.space.guid }
92+
},
93+
domain: {
94+
data: { guid: route2.domain.guid }
95+
}
96+
},
97+
metadata: {
98+
labels: {},
99+
annotations: {}
100+
},
101+
links: {
102+
self: { href: %r{#{Regexp.escape(link_prefix)}/v3/routes/#{route2.guid}} },
103+
space: { href: %r{#{Regexp.escape(link_prefix)}/v3/spaces/#{route2.space.guid}} },
104+
destinations: { href: %r{#{Regexp.escape(link_prefix)}/v3/routes/#{route2.guid}/destinations} },
105+
domain: { href: %r{#{Regexp.escape(link_prefix)}/v3/domains/#{route2.domain.guid}} }
106+
},
107+
options: {}
108+
}
109+
end
110+
111+
context 'when the user is a member in the app space' do
112+
let(:expected_codes_and_responses) do
113+
h = Hash.new(
114+
{ code: 200,
115+
response_objects: [route1_json, route2_json] }.freeze
116+
)
117+
118+
h['org_auditor'] = { code: 404 }
119+
h['org_billing_manager'] = { code: 404 }
120+
h['no_role'] = { code: 404 }
121+
h
122+
end
123+
124+
it_behaves_like 'permissions for list endpoint', ALL_PERMISSIONS
125+
end
126+
127+
context 'ports filter' do
128+
# Don't even think of converting the following hash to symbols ('type' => 'tcp' NOT type: 'tcp'), and you need to set the GUID
129+
let(:router_group) { VCAP::CloudController::RoutingApi::RouterGroup.new({ 'type' => 'tcp', 'reservable_ports' => '7777,8888,9999', 'guid' => 'some-guid' }) }
130+
let(:routing_api_client) { instance_double(VCAP::CloudController::RoutingApi::Client) }
131+
132+
before do
133+
allow_any_instance_of(CloudController::DependencyLocator).to receive(:routing_api_client).and_return(routing_api_client)
134+
allow(routing_api_client).to receive_messages(enabled?: true, router_group: router_group)
135+
end
136+
137+
context 'when there are multiple TCP routes with different ports' do
138+
# The following `let`s depend on the above `before do`
139+
let(:domain_tcp) { VCAP::CloudController::SharedDomain.make(router_group_guid: router_group.guid, name: 'my.domain') }
140+
let!(:route_with_ports_0) do
141+
VCAP::CloudController::Route.make(host: '', space: space, domain: domain_tcp, guid: 'route-with-port-0', port: 7777)
142+
end
143+
let!(:route_with_ports_1) do
144+
VCAP::CloudController::Route.make(host: '', space: space, domain: domain_tcp, guid: 'route-with-port-1', port: 8888)
145+
end
146+
let!(:route_with_ports_2) do
147+
VCAP::CloudController::Route.make(host: '', space: space, domain: domain_tcp, guid: 'route-with-port-2', port: 9999)
148+
end
149+
let!(:route_mapping_1) { VCAP::CloudController::RouteMappingModel.make(app: app_model, route: route_with_ports_1, process_type: 'web') }
150+
let!(:route_mapping_2) { VCAP::CloudController::RouteMappingModel.make(app: app_model, route: route_with_ports_2, process_type: 'web') }
151+
152+
it 'returns routes filtered by ports' do
153+
get "/v3/apps/#{app_model.guid}/routes?ports=7777,8888", nil, admin_header
154+
expect(last_response).to have_status_code(200)
155+
expect(parsed_response['resources'].size).to eq(1)
156+
expect(parsed_response['resources'].first['port']).to eq(route_with_ports_1.port)
157+
end
158+
end
159+
end
160+
161+
describe 'eager loading' do
162+
it 'eager loads associated resources that the presenter specifies' do
163+
expect(VCAP::CloudController::RouteFetcher).to receive(:fetch).with(
164+
anything,
165+
hash_including(eager_loaded_associations: %i[domain space route_mappings labels annotations])
166+
).and_call_original
167+
168+
get "/v3/apps/#{app_model.guid}/routes", nil, admin_header
169+
expect(last_response).to have_status_code(200)
170+
end
171+
end
172+
end
173+
end

0 commit comments

Comments
 (0)