Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/registrations/experience_levels_controller_spec.rb32
-rw-r--r--spec/features/admin/admin_groups_spec.rb2
-rw-r--r--spec/features/dashboard/projects_spec.rb2
-rw-r--r--spec/frontend/alert_management/components/alert_management_list_spec.js4
-rw-r--r--spec/frontend/error_tracking/components/error_details_spec.js3
-rw-r--r--spec/graphql/resolvers/project_pipeline_resolver_spec.rb36
-rw-r--r--spec/lib/gitlab/cache/import/caching_spec.rb15
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/build/cache_spec.rb2
-rw-r--r--spec/lib/gitlab/jira_import_spec.rb25
-rw-r--r--spec/lib/gitlab/utils_spec.rb13
-rw-r--r--spec/models/ci/pipeline_spec.rb11
-rw-r--r--spec/requests/api/deploy_keys_spec.rb54
-rw-r--r--spec/requests/api/graphql/project/pipeline_spec.rb32
-rw-r--r--spec/requests/api/internal/base_spec.rb28
-rw-r--r--spec/requests/api/users_spec.rb67
-rw-r--r--spec/services/prometheus/proxy_service_spec.rb39
16 files changed, 352 insertions, 13 deletions
diff --git a/spec/controllers/registrations/experience_levels_controller_spec.rb b/spec/controllers/registrations/experience_levels_controller_spec.rb
index e67195cb932..1fc728f5de8 100644
--- a/spec/controllers/registrations/experience_levels_controller_spec.rb
+++ b/spec/controllers/registrations/experience_levels_controller_spec.rb
@@ -97,6 +97,38 @@ describe Registrations::ExperienceLevelsController do
it { is_expected.to have_gitlab_http_status(:redirect) }
it { is_expected.to redirect_to(root_path) }
end
+
+ describe 'applying the chosen level' do
+ context "when an 'onboarding_issues_settings' cookie does not exist" do
+ let(:params) { super().merge(experience_level: :novice) }
+
+ it 'does not change the cookie' do
+ expect { subject }.not_to change { cookies[:onboarding_issues_settings] }
+ end
+ end
+
+ context "when an 'onboarding_issues_settings' cookie does exist" do
+ before do
+ request.cookies[:onboarding_issues_settings] = '{}'
+ end
+
+ context 'when novice' do
+ let(:params) { super().merge(experience_level: :novice) }
+
+ it "adds a 'hideAdvanced' setting to the cookie" do
+ expect { subject }.to change { Gitlab::Json.parse(cookies[:onboarding_issues_settings])['hideAdvanced'] }.from(nil).to(true)
+ end
+ end
+
+ context 'when experienced' do
+ let(:params) { super().merge(experience_level: :experienced) }
+
+ it 'does not change the cookie' do
+ expect { subject }.not_to change { cookies[:onboarding_issues_settings] }
+ end
+ end
+ end
+ end
end
context 'when user update fails' do
diff --git a/spec/features/admin/admin_groups_spec.rb b/spec/features/admin/admin_groups_spec.rb
index 5b6c1e15917..9cd335ffb8c 100644
--- a/spec/features/admin/admin_groups_spec.rb
+++ b/spec/features/admin/admin_groups_spec.rb
@@ -181,7 +181,7 @@ RSpec.describe 'Admin Groups' do
end
end
- describe 'admin remove himself from a group', :js do
+ describe 'admin remove themself from a group', :js, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/222342' do
it 'removes admin from the group' do
group.add_user(current_user, Gitlab::Access::DEVELOPER)
diff --git a/spec/features/dashboard/projects_spec.rb b/spec/features/dashboard/projects_spec.rb
index 218cbf871a9..5201d56cc44 100644
--- a/spec/features/dashboard/projects_spec.rb
+++ b/spec/features/dashboard/projects_spec.rb
@@ -125,7 +125,7 @@ describe 'Dashboard Projects' do
end
context 'when on Starred projects tab', :js do
- it 'shows the empty state when there are no starred projects' do
+ it 'shows the empty state when there are no starred projects', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/222357' do
visit(starred_dashboard_projects_path)
element = page.find('.row.empty-state')
diff --git a/spec/frontend/alert_management/components/alert_management_list_spec.js b/spec/frontend/alert_management/components/alert_management_list_spec.js
index 39099f25150..0154e5fa112 100644
--- a/spec/frontend/alert_management/components/alert_management_list_spec.js
+++ b/spec/frontend/alert_management/components/alert_management_list_spec.js
@@ -344,11 +344,11 @@ describe('AlertManagementList', () => {
it('updates sort with new direction and column key', () => {
findSeverityColumnHeader().trigger('click');
- expect(wrapper.vm.$data.sort).toBe('SEVERITY_ASC');
+ expect(wrapper.vm.$data.sort).toBe('SEVERITY_DESC');
findSeverityColumnHeader().trigger('click');
- expect(wrapper.vm.$data.sort).toBe('SEVERITY_DESC');
+ expect(wrapper.vm.$data.sort).toBe('SEVERITY_ASC');
});
});
diff --git a/spec/frontend/error_tracking/components/error_details_spec.js b/spec/frontend/error_tracking/components/error_details_spec.js
index 9d926ca3998..fd2164d05fc 100644
--- a/spec/frontend/error_tracking/components/error_details_spec.js
+++ b/spec/frontend/error_tracking/components/error_details_spec.js
@@ -183,6 +183,9 @@ describe('ErrorDetails', () => {
count: 12,
userCount: 2,
},
+ stacktraceData: {
+ date_received: '2020-05-20',
+ },
});
});
diff --git a/spec/graphql/resolvers/project_pipeline_resolver_spec.rb b/spec/graphql/resolvers/project_pipeline_resolver_spec.rb
new file mode 100644
index 00000000000..72049f16d7d
--- /dev/null
+++ b/spec/graphql/resolvers/project_pipeline_resolver_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Resolvers::ProjectPipelineResolver do
+ include GraphqlHelpers
+
+ let_it_be(:project) { create(:project) }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project, iid: '1234') }
+ let_it_be(:other_pipeline) { create(:ci_pipeline) }
+ let(:current_user) { create(:user) }
+
+ def resolve_pipeline(project, args)
+ resolve(described_class, obj: project, args: args, ctx: { current_user: current_user })
+ end
+
+ it 'resolves pipeline for the passed iid' do
+ result = batch_sync do
+ resolve_pipeline(project, { iid: '1234' })
+ end
+
+ expect(result).to eq(pipeline)
+ end
+
+ it 'does not resolve a pipeline outside the project' do
+ result = batch_sync do
+ resolve_pipeline(other_pipeline.project, { iid: '1234' })
+ end
+
+ expect(result).to be_nil
+ end
+
+ it 'errors when no iid is passed' do
+ expect { resolve_pipeline(project, {}) }.to raise_error(ArgumentError)
+ end
+end
diff --git a/spec/lib/gitlab/cache/import/caching_spec.rb b/spec/lib/gitlab/cache/import/caching_spec.rb
index e4aec0f4dec..7b4308d32ae 100644
--- a/spec/lib/gitlab/cache/import/caching_spec.rb
+++ b/spec/lib/gitlab/cache/import/caching_spec.rb
@@ -89,7 +89,7 @@ describe Gitlab::Cache::Import::Caching, :clean_gitlab_redis_cache do
end
describe '.write_multiple' do
- it 'sets multiple keys' do
+ it 'sets multiple keys when key_prefix not set' do
mapping = { 'foo' => 10, 'bar' => 20 }
described_class.write_multiple(mapping)
@@ -101,6 +101,19 @@ describe Gitlab::Cache::Import::Caching, :clean_gitlab_redis_cache do
expect(found).to eq(value.to_s)
end
end
+
+ it 'sets multiple keys with correct prefix' do
+ mapping = { 'foo' => 10, 'bar' => 20 }
+
+ described_class.write_multiple(mapping, key_prefix: 'pref/')
+
+ mapping.each do |key, value|
+ full_key = described_class.cache_key_for("pref/#{key}")
+ found = Gitlab::Redis::Cache.with { |r| r.get(full_key) }
+
+ expect(found).to eq(value.to_s)
+ end
+ end
end
describe '.expire' do
diff --git a/spec/lib/gitlab/ci/pipeline/seed/build/cache_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/build/cache_spec.rb
index fe19244659f..f5b43b5aeab 100644
--- a/spec/lib/gitlab/ci/pipeline/seed/build/cache_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/seed/build/cache_spec.rb
@@ -134,7 +134,7 @@ describe Gitlab::Ci::Pipeline::Seed::Build::Cache do
it_behaves_like 'foo/bar directory key'
end
- context 'with directories ending in slash star' do
+ context 'with directories ending in slash star', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/222356' do
let(:files) { ['foo/bar/*'] }
it_behaves_like 'foo/bar directory key'
diff --git a/spec/lib/gitlab/jira_import_spec.rb b/spec/lib/gitlab/jira_import_spec.rb
index 6f3c8bd6ecf..5b95891c97e 100644
--- a/spec/lib/gitlab/jira_import_spec.rb
+++ b/spec/lib/gitlab/jira_import_spec.rb
@@ -107,7 +107,7 @@ describe Gitlab::JiraImport do
describe '.jira_issue_cache_key' do
it 'returns cache key for Jira issue imported to given project' do
- expect(described_class.jira_issue_cache_key(project_id, 'DEMO-123')).to eq("jira-import/items-mapper/#{project_id}/issues/DEMO-123")
+ expect(described_class.jira_item_cache_key(project_id, 'DEMO-123', :issues)).to eq("jira-import/items-mapper/#{project_id}/issues/DEMO-123")
end
end
@@ -144,6 +144,29 @@ describe Gitlab::JiraImport do
end
end
+ describe '.cache_users_mapping', :clean_gitlab_redis_cache do
+ let(:data) { { 'user1' => '456', 'user234' => '23' } }
+
+ it 'stores the data correctly' do
+ described_class.cache_users_mapping(project_id, data)
+
+ expect(Gitlab::Cache::Import::Caching.read("jira-import/items-mapper/#{project_id}/users/user1")).to eq('456')
+ expect(Gitlab::Cache::Import::Caching.read("jira-import/items-mapper/#{project_id}/users/user234")).to eq('23')
+ end
+ end
+
+ describe '.get_user_mapping', :clean_gitlab_redis_cache do
+ it 'reads the data correctly' do
+ Gitlab::Cache::Import::Caching.write("jira-import/items-mapper/#{project_id}/users/user-123", '456')
+
+ expect(described_class.get_user_mapping(project_id, 'user-123')).to eq(456)
+ end
+
+ it 'returns nil if value not found' do
+ expect(described_class.get_user_mapping(project_id, 'user-123')).to be_nil
+ end
+ end
+
describe '.store_issues_next_started_at', :clean_gitlab_redis_cache do
it 'stores nil value' do
described_class.store_issues_next_started_at(project_id, nil)
diff --git a/spec/lib/gitlab/utils_spec.rb b/spec/lib/gitlab/utils_spec.rb
index 0f0d6a93c97..3a2430d1f2d 100644
--- a/spec/lib/gitlab/utils_spec.rb
+++ b/spec/lib/gitlab/utils_spec.rb
@@ -345,4 +345,17 @@ describe Gitlab::Utils do
expect(described_class.parse_url(1)).to be nil
end
end
+
+ describe 'multiple_key_invert' do
+ it 'invert keys with array values' do
+ hash = {
+ dast: [:vulnerabilities_count, :scanned_resources_count],
+ sast: [:vulnerabilities_count]
+ }
+ expect(described_class.multiple_key_invert(hash)).to eq({
+ vulnerabilities_count: [:dast, :sast],
+ scanned_resources_count: [:dast]
+ })
+ end
+ end
end
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index 650f33b4e33..409affec5a7 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -121,6 +121,17 @@ describe Ci::Pipeline, :mailer do
end
end
+ describe '.for_iid' do
+ subject { described_class.for_iid(iid) }
+
+ let(:iid) { '1234' }
+ let!(:pipeline) { create(:ci_pipeline, iid: '1234') }
+
+ it 'returns the pipeline' do
+ is_expected.to contain_exactly(pipeline)
+ end
+ end
+
describe '.for_sha' do
subject { described_class.for_sha(sha) }
diff --git a/spec/requests/api/deploy_keys_spec.rb b/spec/requests/api/deploy_keys_spec.rb
index e8cc6bc71ae..1baa18b53ce 100644
--- a/spec/requests/api/deploy_keys_spec.rb
+++ b/spec/requests/api/deploy_keys_spec.rb
@@ -8,7 +8,7 @@ describe API::DeployKeys do
let(:admin) { create(:admin) }
let(:project) { create(:project, creator_id: user.id) }
let(:project2) { create(:project, creator_id: user.id) }
- let(:deploy_key) { create(:deploy_key, public: true) }
+ let(:deploy_key) { create(:deploy_key, public: true, user: user) }
let!(:deploy_keys_project) do
create(:deploy_keys_project, project: project, deploy_key: deploy_key)
@@ -40,6 +40,32 @@ describe API::DeployKeys do
expect(json_response).to be_an Array
expect(json_response.first['id']).to eq(deploy_keys_project.deploy_key.id)
end
+
+ it 'returns all deploy keys with comments replaced with'\
+ 'a simple identifier of username + hostname' do
+ get api('/deploy_keys', admin)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+
+ keys = json_response.map { |key_detail| key_detail['key'] }
+ expect(keys).to all(include("#{user.name} (#{Gitlab.config.gitlab.host}"))
+ end
+
+ context 'N+1 queries' do
+ before do
+ get api('/deploy_keys', admin)
+ end
+
+ it 'avoids N+1 queries', :request_store do
+ control_count = ActiveRecord::QueryRecorder.new { get api('/deploy_keys', admin) }.count
+
+ create_list(:deploy_key, 2, public: true, user: create(:user))
+
+ expect { get api('/deploy_keys', admin) }.not_to exceed_query_limit(control_count)
+ end
+ end
end
end
@@ -56,6 +82,25 @@ describe API::DeployKeys do
expect(json_response).to be_an Array
expect(json_response.first['title']).to eq(deploy_key.title)
end
+
+ context 'N+1 queries' do
+ before do
+ get api("/projects/#{project.id}/deploy_keys", admin)
+ end
+
+ it 'avoids N+1 queries', :request_store do
+ control_count = ActiveRecord::QueryRecorder.new do
+ get api("/projects/#{project.id}/deploy_keys", admin)
+ end.count
+
+ deploy_key = create(:deploy_key, user: create(:user))
+ create(:deploy_keys_project, project: project, deploy_key: deploy_key)
+
+ expect do
+ get api("/projects/#{project.id}/deploy_keys", admin)
+ end.not_to exceed_query_limit(control_count)
+ end
+ end
end
describe 'GET /projects/:id/deploy_keys/:key_id' do
@@ -66,6 +111,13 @@ describe API::DeployKeys do
expect(json_response['title']).to eq(deploy_key.title)
end
+ it 'exposes key comment as a simple identifier of username + hostname' do
+ get api("/projects/#{project.id}/deploy_keys/#{deploy_key.id}", admin)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['key']).to include("#{deploy_key.user_name} (#{Gitlab.config.gitlab.host})")
+ end
+
it 'returns 404 Not Found with invalid ID' do
get api("/projects/#{project.id}/deploy_keys/404", admin)
diff --git a/spec/requests/api/graphql/project/pipeline_spec.rb b/spec/requests/api/graphql/project/pipeline_spec.rb
new file mode 100644
index 00000000000..bed9a18577f
--- /dev/null
+++ b/spec/requests/api/graphql/project/pipeline_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'getting pipeline information nested in a project' do
+ include GraphqlHelpers
+
+ let(:project) { create(:project, :repository, :public) }
+ let(:pipeline) { create(:ci_pipeline, project: project) }
+ let(:current_user) { create(:user) }
+ let(:pipeline_graphql_data) { graphql_data['project']['pipeline'] }
+
+ let(:query) do
+ graphql_query_for(
+ 'project',
+ { 'fullPath' => project.full_path },
+ query_graphql_field('pipeline', iid: pipeline.iid.to_s)
+ )
+ end
+
+ it_behaves_like 'a working graphql query' do
+ before do
+ post_graphql(query, current_user: current_user)
+ end
+ end
+
+ it 'contains pipeline information' do
+ post_graphql(query, current_user: current_user)
+
+ expect(pipeline_graphql_data).not_to be_nil
+ end
+end
diff --git a/spec/requests/api/internal/base_spec.rb b/spec/requests/api/internal/base_spec.rb
index 403984d02f2..aa5e2367a2b 100644
--- a/spec/requests/api/internal/base_spec.rb
+++ b/spec/requests/api/internal/base_spec.rb
@@ -218,7 +218,15 @@ describe API::Internal::Base do
get(api('/internal/authorized_keys'), params: { fingerprint: key.fingerprint, secret_token: secret_token })
expect(response).to have_gitlab_http_status(:ok)
- expect(json_response["key"]).to eq(key.key)
+ expect(json_response['id']).to eq(key.id)
+ expect(json_response['key'].split[1]).to eq(key.key.split[1])
+ end
+
+ it 'exposes the comment of the key as a simple identifier of username + hostname' do
+ get(api('/internal/authorized_keys'), params: { fingerprint: key.fingerprint, secret_token: secret_token })
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['key']).to include("#{key.user_name} (#{Gitlab.config.gitlab.host})")
end
end
@@ -239,11 +247,21 @@ describe API::Internal::Base do
end
context "sending the key" do
- it "finds the key" do
- get(api('/internal/authorized_keys'), params: { key: key.key.split[1], secret_token: secret_token })
+ context "using an existing key" do
+ it "finds the key" do
+ get(api('/internal/authorized_keys'), params: { key: key.key.split[1], secret_token: secret_token })
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response["key"]).to eq(key.key)
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['id']).to eq(key.id)
+ expect(json_response['key'].split[1]).to eq(key.key.split[1])
+ end
+
+ it 'exposes the comment of the key as a simple identifier of username + hostname' do
+ get(api('/internal/authorized_keys'), params: { fingerprint: key.fingerprint, secret_token: secret_token })
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['key']).to include("#{key.user_name} (#{Gitlab.config.gitlab.host})")
+ end
end
it "returns 404 with a partial key" do
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 7c0b6ac2e45..e780f67bcab 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -1276,6 +1276,36 @@ describe API::Users, :do_not_mock_admin_mode do
expect(json_response).to be_an Array
expect(json_response.first['title']).to eq(key.title)
end
+
+ it 'returns array of ssh keys with comments replaced with'\
+ 'a simple identifier of username + hostname' do
+ get api("/users/#{user.id}/keys")
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+
+ keys = json_response.map { |key_detail| key_detail['key'] }
+ expect(keys).to all(include("#{user.name} (#{Gitlab.config.gitlab.host}"))
+ end
+
+ context 'N+1 queries' do
+ before do
+ get api("/users/#{user.id}/keys")
+ end
+
+ it 'avoids N+1 queries', :request_store do
+ control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) do
+ get api("/users/#{user.id}/keys")
+ end.count
+
+ create_list(:key, 2, user: user)
+
+ expect do
+ get api("/users/#{user.id}/keys")
+ end.not_to exceed_all_query_limit(control_count)
+ end
+ end
end
describe 'GET /user/:user_id/keys' do
@@ -1751,6 +1781,36 @@ describe API::Users, :do_not_mock_admin_mode do
expect(json_response.first["title"]).to eq(key.title)
end
+ it 'returns array of ssh keys with comments replaced with'\
+ 'a simple identifier of username + hostname' do
+ get api("/user/keys", user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+
+ keys = json_response.map { |key_detail| key_detail['key'] }
+ expect(keys).to all(include("#{user.name} (#{Gitlab.config.gitlab.host}"))
+ end
+
+ context 'N+1 queries' do
+ before do
+ get api("/user/keys", user)
+ end
+
+ it 'avoids N+1 queries', :request_store do
+ control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) do
+ get api("/user/keys", user)
+ end.count
+
+ create_list(:key, 2, user: user)
+
+ expect do
+ get api("/user/keys", user)
+ end.not_to exceed_all_query_limit(control_count)
+ end
+ end
+
context "scopes" do
let(:path) { "/user/keys" }
let(:api_call) { method(:api) }
@@ -1769,6 +1829,13 @@ describe API::Users, :do_not_mock_admin_mode do
expect(json_response["title"]).to eq(key.title)
end
+ it 'exposes SSH key comment as a simple identifier of username + hostname' do
+ get api("/user/keys/#{key.id}", user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['key']).to include("#{key.user_name} (#{Gitlab.config.gitlab.host})")
+ end
+
it "returns 404 Not Found within invalid ID" do
get api("/user/keys/#{non_existing_record_id}", user)
diff --git a/spec/services/prometheus/proxy_service_spec.rb b/spec/services/prometheus/proxy_service_spec.rb
index 656ccea10de..bd451ff00a1 100644
--- a/spec/services/prometheus/proxy_service_spec.rb
+++ b/spec/services/prometheus/proxy_service_spec.rb
@@ -41,6 +41,27 @@ describe Prometheus::ProxyService do
expect(result.params).to eq('query' => '1')
end
end
+
+ context 'with series method' do
+ let(:params) do
+ ActionController::Parameters.new(
+ match: ['1'],
+ start: "2020-06-11T10:15:51Z",
+ end: "2020-06-11T11:16:06Z",
+ unknown_param: 'val'
+ ).permit!
+ end
+
+ it 'allows match, start and end parameters' do
+ result = described_class.new(environment, 'GET', 'series', params)
+
+ expect(result.params).to eq(
+ 'match' => ['1'],
+ 'start' => "2020-06-11T10:15:51Z",
+ 'end' => "2020-06-11T11:16:06Z"
+ )
+ end
+ end
end
describe '#execute' do
@@ -182,6 +203,24 @@ describe Prometheus::ProxyService do
end
end
end
+
+ context 'with series API' do
+ let(:rest_client_response) { instance_double(RestClient::Response, code: 200, body: '') }
+
+ let(:params) do
+ ActionController::Parameters.new(match: ['1'], start: 1.hour.ago.rfc3339, end: Time.current.rfc3339).permit!
+ end
+
+ subject { described_class.new(environment, 'GET', 'series', params) }
+
+ it 'calls PrometheusClient with given parameters' do
+ expect(prometheus_client).to receive(:proxy)
+ .with('series', params.to_h)
+ .and_return(rest_client_response)
+
+ subject.execute
+ end
+ end
end
end