Merge branch 'master' into go-go-gadget-webpack
* master: (24 commits) Allow to use + symbol in filenames Use string for class_name option for lazy autoload class change how pagination component is loaded revise sortable_name test formatting fix pagination component handling different header styles from different server proxies Improve disabled state select Fix Rubocop offense in build specs Add Changelog for commit links fix on pipelines page Remove empty build spec file from invalid location Merge build specs into file that has valid location Fixed spacing of labels in issuable row on milestone#show Update commit entity to point to valid commit page Allow to use ENV variables in redis config Check for env[Grape::Env::GRAPE_ROUTING_ARGS] instead of endpoint.route Mutate the attribute instead of issuing a write operation to the DB Remove useless permission checks in Gitlab::Checks::ChangeAccess Fix broken link in docs prefer unit test on model over view test rename sort method add CHANGELOG.md entry for !8277 ...
This commit is contained in:
commit
76a4f1e61d
37 changed files with 1524 additions and 1385 deletions
|
@ -2,6 +2,7 @@
|
|||
window.Vue = require('vue');
|
||||
window.Vue.use(require('vue-resource'));
|
||||
require('../vue_common_component/commit');
|
||||
require('../vue_pagination/index');
|
||||
require('../boards/vue_resource_interceptor');
|
||||
require('./status');
|
||||
require('./store');
|
||||
|
|
|
@ -3,15 +3,25 @@
|
|||
require('../vue_realtime_listener');
|
||||
|
||||
((gl) => {
|
||||
const pageValues = headers => ({
|
||||
perPage: +headers['X-Per-Page'],
|
||||
page: +headers['X-Page'],
|
||||
total: +headers['X-Total'],
|
||||
totalPages: +headers['X-Total-Pages'],
|
||||
nextPage: +headers['X-Next-Page'],
|
||||
previousPage: +headers['X-Prev-Page'],
|
||||
const pageValues = (headers) => {
|
||||
const normalizedHeaders = {};
|
||||
|
||||
Object.keys(headers).forEach((e) => {
|
||||
normalizedHeaders[e.toUpperCase()] = headers[e];
|
||||
});
|
||||
|
||||
const paginationInfo = {
|
||||
perPage: +normalizedHeaders['X-PER-PAGE'],
|
||||
page: +normalizedHeaders['X-PAGE'],
|
||||
total: +normalizedHeaders['X-TOTAL'],
|
||||
totalPages: +normalizedHeaders['X-TOTAL-PAGES'],
|
||||
nextPage: +normalizedHeaders['X-NEXT-PAGE'],
|
||||
previousPage: +normalizedHeaders['X-PREV-PAGE'],
|
||||
};
|
||||
|
||||
return paginationInfo;
|
||||
};
|
||||
|
||||
gl.PipelineStore = class {
|
||||
fetchDataLoop(Vue, pageNum, url, apiScope) {
|
||||
const updatePipelineNums = (count) => {
|
||||
|
|
|
@ -109,6 +109,10 @@
|
|||
.avatar {
|
||||
float: none;
|
||||
}
|
||||
|
||||
> a:not(:last-of-type) {
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -137,4 +137,10 @@ class CommitStatus < ActiveRecord::Base
|
|||
.new(self, current_user)
|
||||
.fabricate!
|
||||
end
|
||||
|
||||
def sortable_name
|
||||
name.split(/(\d+)/).map do |v|
|
||||
v =~ /\d+/ ? v.to_i : v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -32,6 +32,6 @@ module ProjectFeaturesCompatibility
|
|||
build_project_feature unless project_feature
|
||||
|
||||
access_level = Gitlab::Utils.to_boolean(value) ? ProjectFeature::ENABLED : ProjectFeature::DISABLED
|
||||
project_feature.update_attribute(field, access_level)
|
||||
project_feature.send(:write_attribute, field, access_level)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
class ForkedProjectLink < ActiveRecord::Base
|
||||
belongs_to :forked_to_project, class_name: Project
|
||||
belongs_to :forked_from_project, class_name: Project
|
||||
belongs_to :forked_to_project, class_name: 'Project'
|
||||
belongs_to :forked_from_project, class_name: 'Project'
|
||||
end
|
||||
|
|
|
@ -122,7 +122,7 @@ class Project < ActiveRecord::Base
|
|||
# Merge Requests for target project should be removed with it
|
||||
has_many :merge_requests, dependent: :destroy, foreign_key: 'target_project_id'
|
||||
# Merge requests from source project should be kept when source project was removed
|
||||
has_many :fork_merge_requests, foreign_key: 'source_project_id', class_name: MergeRequest
|
||||
has_many :fork_merge_requests, foreign_key: 'source_project_id', class_name: 'MergeRequest'
|
||||
has_many :issues, dependent: :destroy
|
||||
has_many :labels, dependent: :destroy, class_name: 'ProjectLabel'
|
||||
has_many :services, dependent: :destroy
|
||||
|
|
|
@ -8,16 +8,16 @@ class CommitEntity < API::Entities::RepoCommit
|
|||
end
|
||||
|
||||
expose :commit_url do |commit|
|
||||
namespace_project_tree_url(
|
||||
namespace_project_commit_url(
|
||||
request.project.namespace,
|
||||
request.project,
|
||||
id: commit.id)
|
||||
commit)
|
||||
end
|
||||
|
||||
expose :commit_path do |commit|
|
||||
namespace_project_tree_path(
|
||||
namespace_project_commit_path(
|
||||
request.project.namespace,
|
||||
request.project,
|
||||
id: commit.id)
|
||||
commit)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
git push -u origin master
|
||||
|
||||
%fieldset
|
||||
%h5 Existing folder or Git repository
|
||||
%h5 Existing folder
|
||||
%pre.light-well
|
||||
:preserve
|
||||
cd existing_folder
|
||||
|
@ -62,6 +62,15 @@
|
|||
git commit
|
||||
git push -u origin master
|
||||
|
||||
%fieldset
|
||||
%h5 Existing Git repository
|
||||
%pre.light-well
|
||||
:preserve
|
||||
cd existing_repo
|
||||
git remote add origin #{ content_tag(:span, default_url_to_repo, class: 'clone')}
|
||||
git push -u origin --all
|
||||
git push -u origin --tags
|
||||
|
||||
- if can? current_user, :remove_project, @project
|
||||
.prepend-top-20
|
||||
= link_to 'Remove project', [@project.namespace.becomes(Namespace), @project], data: { confirm: remove_project_message(@project)}, method: :delete, class: "btn btn-remove pull-right"
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
- content_for :page_specific_javascripts do
|
||||
= stylesheet_link_tag "xterm/xterm"
|
||||
= page_specific_javascript_tag("terminal/terminal_bundle.js")
|
||||
= page_specific_javascript_bundle_tag("terminal")
|
||||
|
||||
%div{ class: container_class }
|
||||
.top-area
|
||||
|
|
|
@ -7,20 +7,21 @@
|
|||
%p
|
||||
= @teams.one? ? 'The team' : 'Select the team'
|
||||
where the slash commands will be used in
|
||||
- selected_id = @teams.keys.first if @teams.one?
|
||||
- selected_id = @teams.one? ? @teams.keys.first : 0
|
||||
- options = mattermost_teams_options(@teams)
|
||||
- options = options_for_select(options, selected_id)
|
||||
= f.select(:team_id, options, {}, { class: 'form-control', selected: "#{selected_id}" })
|
||||
= f.select(:team_id, options, {}, { class: 'form-control', disabled: @teams.one?, selected: selected_id })
|
||||
= f.hidden_field(:team_id, value: selected_id) if @teams.one?
|
||||
.help-block
|
||||
- if @teams.one?
|
||||
This is the only team where you are an administrator.
|
||||
This is the only available team.
|
||||
- else
|
||||
The list shows teams where you are administrator
|
||||
To create a team, ask your Mattermost system administrator.
|
||||
The list shows all available teams.
|
||||
To create a team,
|
||||
= link_to "#{Gitlab.config.mattermost.host}/create_team" do
|
||||
use Mattermost's interface
|
||||
= icon('external-link')
|
||||
or ask your Mattermost system administrator.
|
||||
%hr
|
||||
%h4 Command trigger word
|
||||
%p Choose the word that will trigger commands
|
||||
|
|
|
@ -64,5 +64,4 @@
|
|||
|
||||
.vue-pipelines-index
|
||||
|
||||
= page_specific_javascript_bundle_tag('vue_pagination')
|
||||
= page_specific_javascript_bundle_tag('vue_pipelines')
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
- stage = local_assigns.fetch(:stage)
|
||||
- statuses = stage.statuses.latest
|
||||
- status_groups = statuses.sort_by(&:name).group_by(&:group_name)
|
||||
- status_groups = statuses.sort_by(&:sortable_name).group_by(&:group_name)
|
||||
%li.stage-column
|
||||
.stage-name
|
||||
%a{ name: stage.name }
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Check for env[Grape::Env::GRAPE_ROUTING_ARGS] instead of endpoint.route
|
||||
merge_request: 8544
|
||||
author:
|
4
changelogs/unreleased/allow_plus_sign_for_snippets.yml
Normal file
4
changelogs/unreleased/allow_plus_sign_for_snippets.yml
Normal file
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Allow to use + symbol in filenames
|
||||
merge_request: 6644
|
||||
author: blackst0ne
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Mutate the attribute instead of issuing a write operation to the DB in `ProjectFeaturesCompatibility`
|
||||
concern.
|
||||
merge_request: 8552
|
||||
author:
|
4
changelogs/unreleased/env-var-in-redis-config.yml
Normal file
4
changelogs/unreleased/env-var-in-redis-config.yml
Normal file
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Allow to use ENV variables in redis config
|
||||
merge_request: 8073
|
||||
author: Semyon Pupkov
|
4
changelogs/unreleased/fix-build-sort-order.yml
Normal file
4
changelogs/unreleased/fix-build-sort-order.yml
Normal file
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Sort numbers in build names more intelligently
|
||||
merge_request: 8277
|
||||
author:
|
4
changelogs/unreleased/fix-serialized-commit-path.yml
Normal file
4
changelogs/unreleased/fix-serialized-commit-path.yml
Normal file
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Fix links to commits pages on pipelines list page
|
||||
merge_request: 8558
|
||||
author:
|
|
@ -34,7 +34,6 @@ var config = {
|
|||
users: './users/users_bundle.js',
|
||||
lib_chart: './lib/chart.js',
|
||||
lib_d3: './lib/d3.js',
|
||||
vue_pagination: './vue_pagination/index.js',
|
||||
vue_pipelines: './vue_pipelines_index/index.js',
|
||||
},
|
||||
|
||||
|
|
|
@ -601,6 +601,12 @@ If you want to connect the Redis server via socket, then use the "unix:" URL sch
|
|||
production:
|
||||
url: unix:/path/to/redis/socket
|
||||
|
||||
Also you can use environment variables in the `config/resque.yml` file:
|
||||
|
||||
# example
|
||||
production:
|
||||
url: <%= ENV.fetch('GITLAB_REDIS_URL') %>
|
||||
|
||||
### Custom SSH Connection
|
||||
|
||||
If you are running SSH on a non-standard port, you must change the GitLab user's SSH config.
|
||||
|
|
|
@ -6,7 +6,7 @@ Slack commands give users an extra interface to perform common operations
|
|||
from the chat environment. This allows one to, for example, create an issue as
|
||||
soon as the idea was discussed in chat.
|
||||
For all available commands try the help subcommand, for example: `/gitlab help`,
|
||||
all review the [full list of commands](../integrations/chat_commands.md).
|
||||
all review the [full list of commands](../integration/chat_commands.md).
|
||||
|
||||
## Prerequisites
|
||||
|
||||
|
|
|
@ -30,9 +30,9 @@ module Gitlab
|
|||
return unless @branch_name
|
||||
return unless project.protected_branch?(@branch_name)
|
||||
|
||||
if forced_push? && user_access.cannot_do_action?(:force_push_code_to_protected_branches)
|
||||
if forced_push?
|
||||
return "You are not allowed to force push code to a protected branch on this project."
|
||||
elsif Gitlab::Git.blank_ref?(@newrev) && user_access.cannot_do_action?(:remove_protected_branches)
|
||||
elsif Gitlab::Git.blank_ref?(@newrev)
|
||||
return "You are not allowed to delete protected branches from this project."
|
||||
end
|
||||
|
||||
|
|
|
@ -71,10 +71,17 @@ module Gitlab
|
|||
def tag_endpoint(trans, env)
|
||||
endpoint = env[ENDPOINT_KEY]
|
||||
|
||||
# endpoint.route is nil in the case of a 405 response
|
||||
if endpoint.route
|
||||
path = endpoint_paths_cache[endpoint.route.request_method][endpoint.route.path]
|
||||
trans.action = "Grape##{endpoint.route.request_method} #{path}"
|
||||
begin
|
||||
route = endpoint.route
|
||||
rescue
|
||||
# endpoint.route is calling env[Grape::Env::GRAPE_ROUTING_ARGS][:route_info]
|
||||
# but env[Grape::Env::GRAPE_ROUTING_ARGS] is nil in the case of a 405 response
|
||||
# so we're rescuing exceptions and bailing out
|
||||
end
|
||||
|
||||
if route
|
||||
path = endpoint_paths_cache[route.request_method][route.path]
|
||||
trans.action = "Grape##{route.request_method} #{path}"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ module Gitlab
|
|||
return @_raw_config if defined?(@_raw_config)
|
||||
|
||||
begin
|
||||
@_raw_config = File.read(CONFIG_FILE).freeze
|
||||
@_raw_config = ERB.new(File.read(CONFIG_FILE)).result.freeze
|
||||
rescue Errno::ENOENT
|
||||
@_raw_config = false
|
||||
end
|
||||
|
|
|
@ -61,11 +61,11 @@ module Gitlab
|
|||
end
|
||||
|
||||
def file_name_regex
|
||||
@file_name_regex ||= /\A[[[:alnum:]]_\-\.\@]*\z/.freeze
|
||||
@file_name_regex ||= /\A[[[:alnum:]]_\-\.\@\+]*\z/.freeze
|
||||
end
|
||||
|
||||
def file_name_regex_message
|
||||
"can contain only letters, digits, '_', '-', '@' and '.'."
|
||||
"can contain only letters, digits, '_', '-', '@', '+' and '.'."
|
||||
end
|
||||
|
||||
def file_path_regex
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/bash
|
||||
#!/bin/sh
|
||||
# Sends Slack notification ERROR_MSG to CHANNEL
|
||||
# An env. variable CI_SLACK_WEBHOOK_URL needs to be set.
|
||||
|
||||
|
|
|
@ -33,10 +33,89 @@ feature 'Setup Mattermost slash commands', feature: true do
|
|||
expect(value).to eq(token)
|
||||
end
|
||||
|
||||
describe 'mattermost service is enabled' do
|
||||
it 'shows the add to mattermost button' do
|
||||
expect(page).to have_link 'Add to Mattermost'
|
||||
expect(page).to have_link('Add to Mattermost')
|
||||
end
|
||||
|
||||
it 'shows an explanation if user is a member of no teams' do
|
||||
stub_teams(count: 0)
|
||||
|
||||
click_link 'Add to Mattermost'
|
||||
|
||||
expect(page).to have_content('You aren’t a member of any team on the Mattermost instance')
|
||||
expect(page).to have_link('join a team', href: "#{Gitlab.config.mattermost.host}/select_team")
|
||||
end
|
||||
|
||||
it 'shows an explanation if user is a member of 1 team' do
|
||||
stub_teams(count: 1)
|
||||
|
||||
click_link 'Add to Mattermost'
|
||||
|
||||
expect(page).to have_content('The team where the slash commands will be used in')
|
||||
expect(page).to have_content('This is the only available team.')
|
||||
end
|
||||
|
||||
it 'shows a disabled prefilled select if user is a member of 1 team' do
|
||||
teams = stub_teams(count: 1)
|
||||
|
||||
click_link 'Add to Mattermost'
|
||||
|
||||
team_name = teams.first[1]['display_name']
|
||||
select_element = find('select#mattermost_team_id')
|
||||
selected_option = select_element.find('option[selected]')
|
||||
|
||||
expect(select_element['disabled']).to be(true)
|
||||
expect(selected_option).to have_content(team_name.to_s)
|
||||
end
|
||||
|
||||
it 'has a hidden input for the prefilled value if user is a member of 1 team' do
|
||||
teams = stub_teams(count: 1)
|
||||
|
||||
click_link 'Add to Mattermost'
|
||||
|
||||
expect(find('input#mattermost_team_id', visible: false).value).to eq(teams.first[0].to_s)
|
||||
end
|
||||
|
||||
it 'shows an explanation user is a member of multiple teams' do
|
||||
stub_teams(count: 2)
|
||||
|
||||
click_link 'Add to Mattermost'
|
||||
|
||||
expect(page).to have_content('Select the team where the slash commands will be used in')
|
||||
expect(page).to have_content('The list shows all available teams.')
|
||||
end
|
||||
|
||||
it 'shows a select with team options user is a member of multiple teams' do
|
||||
stub_teams(count: 2)
|
||||
|
||||
click_link 'Add to Mattermost'
|
||||
|
||||
select_element = find('select#mattermost_team_id')
|
||||
selected_option = select_element.find('option[selected]')
|
||||
|
||||
expect(select_element['disabled']).to be(false)
|
||||
expect(selected_option).to have_content('Select team...')
|
||||
# The 'Select team...' placeholder is item `0`.
|
||||
expect(select_element.all('option').count).to eq(3)
|
||||
end
|
||||
|
||||
def stub_teams(count: 0)
|
||||
teams = create_teams(count)
|
||||
|
||||
allow_any_instance_of(MattermostSlashCommandsService).to receive(:list_teams) { teams }
|
||||
|
||||
teams
|
||||
end
|
||||
|
||||
def create_teams(count = 0)
|
||||
teams = {}
|
||||
|
||||
count.times do |i|
|
||||
i += 1
|
||||
teams[i] = { id: i, display_name: i }
|
||||
end
|
||||
|
||||
teams
|
||||
end
|
||||
|
||||
describe 'mattermost service is not enabled' do
|
||||
|
|
|
@ -17,4 +17,18 @@ feature 'Create Snippet', feature: true do
|
|||
expect(page).to have_content('My Snippet Title')
|
||||
expect(page).to have_content('Hello World!')
|
||||
end
|
||||
|
||||
scenario 'Authenticated user creates a snippet with + in filename' do
|
||||
fill_in 'personal_snippet_title', with: 'My Snippet Title'
|
||||
page.within('.file-editor') do
|
||||
find(:xpath, "//input[@id='personal_snippet_file_name']").set 'snippet+file+name'
|
||||
find(:xpath, "//input[@id='personal_snippet_content']").set 'Hello World!'
|
||||
end
|
||||
|
||||
click_button 'Create snippet'
|
||||
|
||||
expect(page).to have_content('My Snippet Title')
|
||||
expect(page).to have_content('snippet+file+name')
|
||||
expect(page).to have_content('Hello World!')
|
||||
end
|
||||
end
|
||||
|
|
2
spec/fixtures/config/redis_config_with_env.yml
vendored
Normal file
2
spec/fixtures/config/redis_config_with_env.yml
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
test:
|
||||
url: <%= ENV['TEST_GITLAB_REDIS_URL'] %>
|
|
@ -56,7 +56,6 @@ describe Gitlab::Checks::ChangeAccess, lib: true do
|
|||
|
||||
it 'returns an error if the user is not allowed to do forced pushes to protected branches' do
|
||||
expect(Gitlab::Checks::ForcePush).to receive(:force_push?).and_return(true)
|
||||
expect(user_access).to receive(:can_do_action?).with(:force_push_code_to_protected_branches).and_return(false)
|
||||
|
||||
expect(subject.status).to be(false)
|
||||
expect(subject.message).to eq('You are not allowed to force push code to a protected branch on this project.')
|
||||
|
@ -88,8 +87,6 @@ describe Gitlab::Checks::ChangeAccess, lib: true do
|
|||
end
|
||||
|
||||
it 'returns an error if the user is not allowed to delete protected branches' do
|
||||
expect(user_access).to receive(:can_do_action?).with(:remove_protected_branches).and_return(false)
|
||||
|
||||
expect(subject.status).to be(false)
|
||||
expect(subject.message).to eq('You are not allowed to delete protected branches from this project.')
|
||||
end
|
||||
|
|
|
@ -126,5 +126,16 @@ describe Gitlab::Metrics::RackMiddleware do
|
|||
|
||||
expect(transaction.action).to eq('Grape#GET /projects/:id/archive')
|
||||
end
|
||||
|
||||
it 'does not tag a transaction if route infos are missing' do
|
||||
endpoint = double(:endpoint)
|
||||
allow(endpoint).to receive(:route).and_raise
|
||||
|
||||
env['api.endpoint'] = endpoint
|
||||
|
||||
middleware.tag_endpoint(transaction, env)
|
||||
|
||||
expect(transaction.action).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Redis do
|
||||
let(:redis_config) { Rails.root.join('config', 'resque.yml').to_s }
|
||||
include StubENV
|
||||
|
||||
before(:each) { clear_raw_config }
|
||||
after(:each) { clear_raw_config }
|
||||
|
@ -72,6 +72,20 @@ describe Gitlab::Redis do
|
|||
|
||||
expect(url2).not_to end_with('foobar')
|
||||
end
|
||||
|
||||
context 'when yml file with env variable' do
|
||||
let(:redis_config) { Rails.root.join('spec/fixtures/config/redis_config_with_env.yml') }
|
||||
|
||||
before do
|
||||
stub_env('TEST_GITLAB_REDIS_URL', 'redis://redishost:6379')
|
||||
end
|
||||
|
||||
it 'reads redis url from env variable' do
|
||||
stub_const("#{described_class}::CONFIG_FILE", redis_config)
|
||||
|
||||
expect(described_class.url).to eq 'redis://redishost:6379'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '._raw_config' do
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -243,4 +243,23 @@ describe CommitStatus, models: true do
|
|||
.to be_a Gitlab::Ci::Status::Success
|
||||
end
|
||||
end
|
||||
|
||||
describe '#sortable_name' do
|
||||
tests = {
|
||||
'karma' => ['karma'],
|
||||
'karma 0 20' => ['karma ', 0, ' ', 20],
|
||||
'karma 10 20' => ['karma ', 10, ' ', 20],
|
||||
'karma 50:100' => ['karma ', 50, ':', 100],
|
||||
'karma 1.10' => ['karma ', 1, '.', 10],
|
||||
'karma 1.5.1' => ['karma ', 1, '.', 5, '.', 1],
|
||||
'karma 1 a' => ['karma ', 1, ' a']
|
||||
}
|
||||
|
||||
tests.each do |name, sortable_name|
|
||||
it "'#{name}' sorts as '#{sortable_name}'" do
|
||||
commit_status.name = name
|
||||
expect(commit_status.sortable_name).to eq(sortable_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -33,10 +33,12 @@ describe CommitEntity do
|
|||
|
||||
it 'contains path to commit' do
|
||||
expect(subject).to include(:commit_path)
|
||||
expect(subject[:commit_path]).to include "commit/#{commit.id}"
|
||||
end
|
||||
|
||||
it 'contains URL to commit' do
|
||||
expect(subject).to include(:commit_url)
|
||||
expect(subject[:commit_path]).to include "commit/#{commit.id}"
|
||||
end
|
||||
|
||||
it 'needs to receive project in the request' do
|
||||
|
|
Loading…
Reference in a new issue