Commit 354b69dd authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge remote-tracking branch 'origin/release-notes'

Signed-off-by: default avatarDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
parents 2ee3f838 b7619dad
...@@ -32,6 +32,7 @@ v 8.2.0 (unreleased) ...@@ -32,6 +32,7 @@ v 8.2.0 (unreleased)
v 8.1.4 v 8.1.4
- Fix bug where manually merged branches in a MR would end up with an empty diff (Stan Hu) - Fix bug where manually merged branches in a MR would end up with an empty diff (Stan Hu)
- Prevent redirect loop when home_page_url is set to the root URL - Prevent redirect loop when home_page_url is set to the root URL
- Ability to add release notes (markdown text and attachments) to git tags
v 8.1.3 v 8.1.3
- Force update refs/merge-requests/X/head upon a push to the source branch of a merge request (Stan Hu) - Force update refs/merge-requests/X/head upon a push to the source branch of a merge request (Stan Hu)
......
...@@ -39,6 +39,12 @@ class Dispatcher ...@@ -39,6 +39,12 @@ class Dispatcher
shortcut_handler = new ShortcutsNavigation() shortcut_handler = new ShortcutsNavigation()
new DropzoneInput($('.merge-request-form')) new DropzoneInput($('.merge-request-form'))
new IssuableForm($('.merge-request-form')) new IssuableForm($('.merge-request-form'))
when 'projects:tags:new'
new ZenMode()
new DropzoneInput($('.tag-form'))
when 'projects:releases:edit'
new ZenMode()
new DropzoneInput($('.release-form'))
when 'projects:merge_requests:show' when 'projects:merge_requests:show'
new Diff() new Diff()
shortcut_handler = new ShortcutsIssuable() shortcut_handler = new ShortcutsIssuable()
......
...@@ -9,9 +9,9 @@ ...@@ -9,9 +9,9 @@
.bs-callout { .bs-callout {
margin: 20px 0; margin: 20px 0;
padding: 20px; padding: 20px;
border-left: 3px solid #eee; border-left: 3px solid $border-color;
color: #666; color: $text-color;
background: #f9f9f9; background: $background-color;
} }
.bs-callout h4 { .bs-callout h4 {
margin-top: 0; margin-top: 0;
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
.append-bottom-10 { margin-bottom:10px } .append-bottom-10 { margin-bottom:10px }
.append-bottom-15 { margin-bottom:15px } .append-bottom-15 { margin-bottom:15px }
.append-bottom-20 { margin-bottom:20px } .append-bottom-20 { margin-bottom:20px }
.append-bottom-default { margin-bottom: $gl-padding; }
.inline { display: inline-block } .inline { display: inline-block }
.center { text-align: center } .center { text-align: center }
......
...@@ -117,7 +117,7 @@ ul.content-list { ...@@ -117,7 +117,7 @@ ul.content-list {
} }
.controls { .controls {
padding-top: 4px; padding-top: 1px;
float: right; float: right;
.btn { .btn {
......
...@@ -72,9 +72,10 @@ ...@@ -72,9 +72,10 @@
list-style: none; list-style: none;
> li { > li {
@include clearfix;
padding: 10px 0; padding: 10px 0;
border-bottom: 1px solid #EEE; border-bottom: 1px solid #EEE;
overflow: hidden;
display: block; display: block;
margin: 0px; margin: 0px;
......
...@@ -115,3 +115,10 @@ li.commit { ...@@ -115,3 +115,10 @@ li.commit {
} }
} }
} }
.branch-commit {
color: $gl-gray;
.commit-id, .commit-row-message {
color: $gl-gray;
}
}
class Projects::ReleasesController < Projects::ApplicationController
# Authorize
before_action :require_non_empty_project
before_action :authorize_download_code!
before_action :authorize_push_code!
before_action :tag
before_action :release
def edit
end
def update
release.update_attributes(release_params)
redirect_to namespace_project_tag_path(@project.namespace, @project, @tag.name)
end
private
def tag
@tag ||= @repository.find_tag(params[:tag_id])
end
def release
@release ||= @project.releases.find_or_initialize_by(tag: @tag.name)
end
def release_params
params.require(:release).permit(:description)
end
end
...@@ -8,15 +8,23 @@ class Projects::TagsController < Projects::ApplicationController ...@@ -8,15 +8,23 @@ class Projects::TagsController < Projects::ApplicationController
def index def index
sorted = VersionSorter.rsort(@repository.tag_names) sorted = VersionSorter.rsort(@repository.tag_names)
@tags = Kaminari.paginate_array(sorted).page(params[:page]).per(PER_PAGE) @tags = Kaminari.paginate_array(sorted).page(params[:page]).per(PER_PAGE)
@releases = project.releases.where(tag: @tags)
end
def show
@tag = @repository.find_tag(params[:id])
@release = @project.releases.find_or_initialize_by(tag: @tag.name)
@commit = @repository.commit(@tag.target)
end end
def create def create
result = CreateTagService.new(@project, current_user). result = CreateTagService.new(@project, current_user).
execute(params[:tag_name], params[:ref], params[:message]) execute(params[:tag_name], params[:ref], params[:message], params[:release_description])
if result[:status] == :success if result[:status] == :success
@tag = result[:tag] @tag = result[:tag]
redirect_to namespace_project_tags_path(@project.namespace, @project)
redirect_to namespace_project_tag_path(@project.namespace, @project, @tag.name)
else else
@error = result[:message] @error = result[:message]
render action: 'new' render action: 'new'
...@@ -26,12 +34,6 @@ class Projects::TagsController < Projects::ApplicationController ...@@ -26,12 +34,6 @@ class Projects::TagsController < Projects::ApplicationController
def destroy def destroy
DeleteTagService.new(project, current_user).execute(params[:id]) DeleteTagService.new(project, current_user).execute(params[:id])
respond_to do |format| redirect_to namespace_project_tags_path(@project.namespace, @project)
format.html do
redirect_to namespace_project_tags_path(@project.namespace,
@project)
end
format.js
end
end end
end end
...@@ -122,6 +122,7 @@ class Project < ActiveRecord::Base ...@@ -122,6 +122,7 @@ class Project < ActiveRecord::Base
has_many :starrers, through: :users_star_projects, source: :user has_many :starrers, through: :users_star_projects, source: :user
has_many :ci_commits, dependent: :destroy, class_name: 'Ci::Commit', foreign_key: :gl_project_id has_many :ci_commits, dependent: :destroy, class_name: 'Ci::Commit', foreign_key: :gl_project_id
has_many :ci_builds, through: :ci_commits, source: :builds, dependent: :destroy, class_name: 'Ci::Build' has_many :ci_builds, through: :ci_commits, source: :builds, dependent: :destroy, class_name: 'Ci::Build'
has_many :releases, dependent: :destroy
has_one :import_data, dependent: :destroy, class_name: "ProjectImportData" has_one :import_data, dependent: :destroy, class_name: "ProjectImportData"
has_one :gitlab_ci_project, dependent: :destroy, class_name: "Ci::Project", foreign_key: :gitlab_id has_one :gitlab_ci_project, dependent: :destroy, class_name: "Ci::Project", foreign_key: :gitlab_id
......
class Release < ActiveRecord::Base
belongs_to :project
validates :description, :project, :tag, presence: true
end
require_relative 'base_service' require_relative 'base_service'
class CreateTagService < BaseService class CreateTagService < BaseService
def execute(tag_name, ref, message) def execute(tag_name, ref, message, release_description = nil)
valid_tag = Gitlab::GitRefValidator.validate(tag_name) valid_tag = Gitlab::GitRefValidator.validate(tag_name)
if valid_tag == false if valid_tag == false
return error('Tag name invalid') return error('Tag name invalid')
...@@ -19,8 +19,12 @@ class CreateTagService < BaseService ...@@ -19,8 +19,12 @@ class CreateTagService < BaseService
new_tag = repository.find_tag(tag_name) new_tag = repository.find_tag(tag_name)
if new_tag if new_tag
push_data = create_push_data(project, current_user, new_tag) if release_description
release = project.releases.find_or_initialize_by(tag: tag_name)
release.update_attributes(description: release_description)
end
push_data = create_push_data(project, current_user, new_tag)
EventCreateService.new.push(project, current_user, push_data) EventCreateService.new.push(project, current_user, push_data)
project.execute_hooks(push_data.dup, :tag_push_hooks) project.execute_hooks(push_data.dup, :tag_push_hooks)
project.execute_services(push_data.dup, :tag_push_hooks) project.execute_services(push_data.dup, :tag_push_hooks)
......
...@@ -11,8 +11,10 @@ class DeleteTagService < BaseService ...@@ -11,8 +11,10 @@ class DeleteTagService < BaseService
end end
if repository.rm_tag(tag_name) if repository.rm_tag(tag_name)
push_data = build_push_data(tag) release = project.releases.find_by(tag: tag_name)
release.destroy if release
push_data = build_push_data(tag)
EventCreateService.new.push(project, current_user, push_data) EventCreateService.new.push(project, current_user, push_data)
project.execute_hooks(push_data.dup, :tag_push_hooks) project.execute_hooks(push_data.dup, :tag_push_hooks)
project.execute_services(push_data.dup, :tag_push_hooks) project.execute_services(push_data.dup, :tag_push_hooks)
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
Files Files
- if project_nav_tab? :commits - if project_nav_tab? :commits
= nav_link(controller: %w(commit commits compare repositories tags branches)) do = nav_link(controller: %w(commit commits compare repositories tags branches releases)) do
= link_to project_commits_path(@project), title: 'Commits', class: 'shortcuts-commits', data: {placement: 'right'} do = link_to project_commits_path(@project), title: 'Commits', class: 'shortcuts-commits', data: {placement: 'right'} do
= icon('history fw') = icon('history fw')
%span %span
......
.branch-commit.light .branch-commit
= link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit_short_id" = link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit-id"
&middot; &middot;
%span.str-truncated %span.str-truncated
= link_to_gfm commit.title, namespace_project_commit_path(project.namespace, project, commit.id), class: "commit-row-message" = link_to_gfm commit.title, namespace_project_commit_path(project.namespace, project, commit.id), class: "commit-row-message"
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
Branches Branches
%span.badge.js-totalbranch-count= @repository.branches.size %span.badge.js-totalbranch-count= @repository.branches.size
= nav_link(controller: :tags) do = nav_link(controller: [:tags, :releases]) do
= link_to namespace_project_tags_path(@project.namespace, @project) do = link_to namespace_project_tags_path(@project.namespace, @project) do
Tags Tags
%span.badge.js-totaltags-count= @repository.tags.length %span.badge.js-totaltags-count= @repository.tags.length
- page_title "Edit", @tag.name, "Tags"
= render "projects/commits/header_title"
= render "projects/commits/head"
.gray-content-block
.oneline
.title
Release notes for tag
%strong #{@tag.name}
.prepend-top-default
= form_for(@release, method: :put, url: namespace_project_tag_release_path(@project.namespace, @project, @tag.name), html: { class: 'form-horizontal gfm-form release-form' }) do |f|
= render layout: 'projects/md_preview', locals: { preview_class: "md-preview", referenced_users: true } do
= render 'projects/zen', f: f, attr: :description, classes: 'description js-quick-submit'
= render 'projects/notes/hints'
.error-alert
.prepend-top-default
= f.submit 'Save changes', class: 'btn btn-save'
= link_to "Cancel", namespace_project_tag_path(@project.namespace, @project, @tag.name), class: "btn btn-default btn-cancel"
%span.btn-group.btn-grouped
= link_to archive_namespace_project_repository_path(project.namespace, project, ref: ref, format: 'zip'), class: 'btn btn-default', rel: 'nofollow' do
%i.fa.fa-download
%span source code
%a.btn.btn-default.dropdown-toggle{ 'data-toggle' => 'dropdown' }
%span.caret
%span.sr-only
Select Archive Format
%ul.col-xs-10.dropdown-menu{ role: 'menu' }
%li
= link_to archive_namespace_project_repository_path(project.namespace, project, ref: ref, format: 'zip'), rel: 'nofollow' do
%i.fa.fa-download
%span Download zip
%li
= link_to archive_namespace_project_repository_path(project.namespace, project, ref: ref, format: 'tar.gz'), rel: 'nofollow' do
%i.fa.fa-download
%span Download tar.gz
- commit = @repository.commit(tag.target) - commit = @repository.commit(tag.target)
- release = @releases.find { |release| release.tag == tag.name }
%li %li
%div %div
= link_to namespace_project_commits_path(@project.namespace, @project, tag.name), class: "" do = link_to namespace_project_tag_path(@project.namespace, @project, tag.name) do
%strong %strong
%i.fa.fa-tag = icon('tag')
= tag.name = tag.name
- if tag.message.present? - if tag.message.present?
&nbsp; &nbsp;
= strip_gpg_signature(tag.message) = strip_gpg_signature(tag.message)
.controls .controls
= link_to edit_namespace_project_tag_release_path(@project.namespace, @project, tag.name), class: 'btn-grouped btn' do
= icon("pencil")
- if can? current_user, :download_code, @project - if can? current_user, :download_code, @project
= render 'projects/repositories/download_archive', ref: tag.name, btn_class: 'btn-grouped btn-group-xs' = render 'projects/tags/download', ref: tag.name, project: @project
- if can?(current_user, :admin_project, @project)
= link_to namespace_project_tag_path(@project.namespace, @project, tag.name), class: 'btn btn-xs btn-remove remove-row grouped', method: :delete, data: { confirm: 'Removed tag cannot be restored. Are you sure?'}, remote: true do
%i.fa.fa-trash-o
- if commit - if commit
= render 'projects/branches/commit', commit: commit, project: @project = render 'projects/branches/commit', commit: commit, project: @project
- else - else
%p %p
Cant find HEAD commit for this tag Cant find HEAD commit for this tag
- if release && release.description.present?
.description.prepend-top-default
.wiki
= preserve do
= markdown release.description
$('.js-totaltags-count').html("#{@repository.tags.size}")
- if @repository.tags.size == 0
$('.tags').load(document.URL + ' .nothing-here-block').hide().fadeIn(1000)
...@@ -5,10 +5,12 @@ ...@@ -5,10 +5,12 @@
.alert.alert-danger .alert.alert-danger
%button{ type: "button", class: "close", "data-dismiss" => "alert"} &times; %button{ type: "button", class: "close", "data-dismiss" => "alert"} &times;
= @error = @error
%h3.page-title %h3.page-title
%i.fa.fa-code-fork New git tag
New tag %hr
= form_tag namespace_project_tags_path, method: :post, id: "new-tag-form", class: "form-horizontal" do
= form_tag namespace_project_tags_path, method: :post, id: "new-tag-form", class: "form-horizontal tag-form" do
.form-group .form-group
= label_tag :tag_name, 'Name for new tag', class: 'control-label' = label_tag :tag_name, 'Name for new tag', class: 'control-label'
.col-sm-10 .col-sm-10
...@@ -17,12 +19,29 @@ ...@@ -17,12 +19,29 @@
= label_tag :ref, 'Create from', class: 'control-label' = label_tag :ref, 'Create from', class: 'control-label'
.col-sm-10 .col-sm-10
= text_field_tag :ref, params[:ref], placeholder: 'master', required: true, tabindex: 2, class: 'form-control' = text_field_tag :ref, params[:ref], placeholder: 'master', required: true, tabindex: 2, class: 'form-control'
.light Branch name or commit SHA .help-block Branch name or commit SHA
.form-group .form-group
= label_tag :message, 'Message', class: 'control-label' = label_tag :message, 'Message', class: 'control-label'
.col-sm-10 .col-sm-10
= text_field_tag :message, nil, placeholder: 'Enter message.', required: false, tabindex: 3, class: 'form-control' = text_field_tag :message, nil, placeholder: 'Enter message.', required: false, tabindex: 3, class: 'form-control'
.light (Optional) Entering a message will create an annotated tag. .help-block (Optional) Entering a message will create an annotated tag.
%hr
.form-group
= label_tag :release_description, 'Release notes', class: 'control-label'
.col-sm-10
= render layout: 'projects/md_preview', locals: { preview_class: "md-preview", referenced_users: true } do
.zennable
%input#zen-toggle-comment.zen-toggle-comment(tabindex="-1" type="checkbox")
.zen-backdrop
= text_area_tag :release_description, nil, class: 'js-gfm-input markdown-area description js-quick-submit form-control', placeholder: ''
%a.zen-enter-link(tabindex="-1" href="#")
= icon('expand')
Edit in fullscreen
%a.zen-leave-link(href="#")
= icon('compress')
= render 'projects/notes/hints'
.help-block (Optional) You can add release notes to your tag. It will be stored in the GitLab database and shown on the tags page
.form-actions .form-actions
= button_tag 'Create tag', class: 'btn btn-create', tabindex: 3 = button_tag 'Create tag', class: 'btn btn-create', tabindex: 3
= link_to 'Cancel', namespace_project_tags_path(@project.namespace, @project), class: 'btn btn-cancel' = link_to 'Cancel', namespace_project_tags_path(@project.namespace, @project), class: 'btn btn-cancel'
......
- page_title @tag.name, "Tags"
= render "projects/commits/header_title"
= render "projects/commits/head"
.gray-content-block
.pull-right
- if can?(current_user, :push_code, @project)
= link_to edit_namespace_project_tag_release_path(@project.namespace, @project, @tag.name), class: 'btn-grouped btn', title: 'Edit release notes' do
= icon("pencil")
= link_to namespace_project_tree_path(@project.namespace, @project, @tag.name), class: 'btn btn-grouped', title: 'Browse source code' do
= icon('files-o')
= link_to namespace_project_commits_path(@project.namespace, @project, @tag.name), class: 'btn btn-grouped', title: 'Browse commits' do
= icon('history')
- if can? current_user, :download_code, @project
= render 'projects/tags/download', ref: @tag.name, project: @project
- if can?(current_user, :admin_project, @project)
.pull-right
= link_to namespace_project_tag_path(@project.namespace, @project, @tag.name), class: 'btn btn-remove remove-row grouped', method: :delete, data: { confirm: 'Removed tag cannot be restored. Are you sure?'} do
%i.fa.fa-trash-o
.title
%strong= @tag.name
- if @tag.message.present?
%span.light
&nbsp;
= strip_gpg_signature(@tag.message)
- if @commit
= render 'projects/branches/commit', commit: @commit, project: @project
- else
Cant find HEAD commit for this tag
.append-bottom-default.prepend-top-default
- if @release.description.present?
.description
.wiki
= preserve do
= markdown @release.description
- else
This tag has no release notes.
...@@ -583,7 +583,10 @@ Gitlab::Application.routes.draw do ...@@ -583,7 +583,10 @@ Gitlab::Application.routes.draw do
end end
resources :branches, only: [:index, :new, :create, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex } resources :branches, only: [:index, :new, :create, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex }
resources :tags, only: [:index, :new, :create, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex } resources :tags, only: [:index, :show, :new, :create, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex } do
resource :release, only: [:edit, :update]
end
resources :protected_branches, only: [:index, :create, :update, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex } resources :protected_branches, only: [:index, :create, :update, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex }
resource :variables, only: [:show, :update] resource :variables, only: [:show, :update]
resources :triggers, only: [:index, :create, :destroy] resources :triggers, only: [:index, :create, :destroy]
......
class CreateReleases < ActiveRecord::Migration
def change
create_table :releases do |t|
t.string :tag
t.text :description
t.integer :project_id
t.timestamps
end
add_index :releases, :project_id
add_index :releases, [:project_id, :tag]
end
end
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20151103133339) do ActiveRecord::Schema.define(version: 20151105094515) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
...@@ -639,6 +639,17 @@ ActiveRecord::Schema.define(version: 20151103133339) do ...@@ -639,6 +639,17 @@ ActiveRecord::Schema.define(version: 20151103133339) do
add_index "protected_branches", ["project_id"], name: "index_protected_branches_on_project_id", using: :btree add_index "protected_branches", ["project_id"], name: "index_protected_branches_on_project_id", using: :btree
create_table "releases", force: true do |t|
t.string "tag"
t.text "description"
t.integer "project_id"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "releases", ["project_id", "tag"], name: "index_releases_on_project_id_and_tag", using: :btree
add_index "releases", ["project_id"], name: "index_releases_on_project_id", using: :btree
create_table "sent_notifications", force: true do |t| create_table "sent_notifications", force: true do |t|
t.integer "project_id" t.integer "project_id"
t.integer "noteable_id" t.integer "noteable_id"
......
...@@ -12,6 +12,12 @@ Feature: Project Commits Tags ...@@ -12,6 +12,12 @@ Feature: Project Commits Tags
And I submit new tag form And I submit new tag form
Then I should see new tag created Then I should see new tag created
Scenario: I create a tag with release notes
Given I click new tag link
And I submit new tag form with release notes
Then I should see new tag created
And I should see tag release notes
Scenario: I create a tag with invalid name Scenario: I create a tag with invalid name
And I click new tag link And I click new tag link
And I submit new tag form with invalid name And I submit new tag form with invalid name
...@@ -27,15 +33,13 @@ Feature: Project Commits Tags ...@@ -27,15 +33,13 @@ Feature: Project Commits Tags
And I submit new tag form with tag that already exists And I submit new tag form with tag that already exists
Then I should see new an error that tag already exists Then I should see new an error that tag already exists
@javascript
Scenario: I delete a tag Scenario: I delete a tag
Given I visit tag 'v1.1.0' page
Given I delete tag 'v1.1.0' Given I delete tag 'v1.1.0'
Then I should not see tag 'v1.1.0' Then I should not see tag 'v1.1.0'
@javascript Scenario: I add release notes to the tag
Scenario: I delete all tags and see info message Given I visit tag 'v1.1.0' page
Given I delete all tags When I click edit tag link
Then I should see tags info message And I fill release notes and submit form
Then I should see tag release notes
# @wip
# Scenario: I can download project by tag
...@@ -18,6 +18,18 @@ class Spinach::Features::ProjectCommitsTags < Spinach::FeatureSteps ...@@ -18,6 +18,18 @@ class Spinach::Features::ProjectCommitsTags < Spinach::FeatureSteps
click_button 'Create tag' click_button 'Create tag'
end end
step 'I submit new tag form with release notes' do
fill_in 'tag_name', with: 'v7.0'
fill_in 'ref', with: 'master'
fill_in 'release_description', with: 'Awesome release notes'
click_button 'Create tag'
end
step 'I fill release notes and submit form' do
fill_in 'release_description', with: 'Awesome release notes'
click_button 'Save changes'
end
step 'I submit new tag form with invalid name' do step 'I submit new tag form with invalid name' do
fill_in 'tag_name', with: 'v 1.0' fill_in 'tag_name', with: 'v 1.0'
fill_in 'ref', with: 'master' fill_in 'ref', with: 'master'
...@@ -52,31 +64,27 @@ class Spinach::Features::ProjectCommitsTags < Spinach::FeatureSteps ...@@ -52,31 +64,27 @@ class Spinach::Features::ProjectCommitsTags < Spinach::FeatureSteps
expect(page).to have_content 'Tag already exists' expect(page).to have_content 'Tag already exists'
end end
step "I visit tag 'v1.1.0' page" do
click_link 'v1.1.0'
end
step "I delete tag 'v1.1.0'" do step "I delete tag 'v1.1.0'" do
page.within '.tags' do page.within('.content') do
first('.btn-remove').click first('.btn-remove').click
sleep 0.05
end end
end end
step "I should not see tag 'v1.1.0'" do step "I should not see tag 'v1.1.0'" do
page.within '.tags' do page.within '.tags' do
expect(page.all(visible: true)).not_to have_content 'v1.1.0' expect(page).not_to have_link 'v1.1.0'
end end
end end
step 'I delete all tags' do step 'I click edit tag link' do
page.within '.tags' do click_link 'Edit release notes'
page.all('.btn-remove').each do |remove|
remove.click
sleep 0.05
end
end
end end
step 'I should see tags info message' do step 'I should see tag release notes' do
page.within '.tags' do expect(page).to have_content 'Awesome release notes'
expect(page).to have_content 'Repository has no tags yet.'
end
end end
end end
# Read about factories at https://github.com/thoughtbot/factory_girl
FactoryGirl.define do
factory :release do
tag "v1.1.0"
description "Awesome release"
project
end
end
require 'rails_helper'
RSpec.describe Release, type: :model do
let(:release) { create(:release) }
it { expect(release).to be_valid }
describe 'associations' do
it { is_expected.to belong_to(:project) }
end
describe 'validation' do
it { is_expected.to validate_presence_of(:project) }
it { is_expected.to validate_presence_of(:description) }
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment