BigW Consortium Gitlab

issues_spec.rb 13.3 KB
Newer Older
gitlabhq committed
1 2
require 'spec_helper'

3
describe 'Issues', feature: true do
Dmitriy Zaporozhets committed
4 5
  include SortingHelper

6
  let(:project) { create(:project) }
gitlabhq committed
7

Nihad Abbasov committed
8
  before do
gitlabhq committed
9
    login_as :user
Riyad Preukschas committed
10
    user2 = create(:user)
gitlabhq committed
11

12
    project.team << [[@user, user2], :developer]
gitlabhq committed
13 14
  end

15
  describe 'Edit issue' do
Riyad Preukschas committed
16 17 18 19 20 21 22
    let!(:issue) do
      create(:issue,
             author: @user,
             assignee: @user,
             project: project)
    end

Nihad Abbasov committed
23
    before do
24
      visit edit_namespace_project_issue_path(project.namespace, project, issue)
Phil Hughes committed
25
      click_button "Go full screen"
gitlabhq committed
26 27
    end

28
    it 'should open new issue popup' do
29
      expect(page).to have_content("Issue ##{issue.iid}")
gitlabhq committed
30 31
    end

32
    describe 'fill in' do
gitlabhq committed
33
      before do
34 35
        fill_in 'issue_title', with: 'bug 345'
        fill_in 'issue_description', with: 'bug description'
gitlabhq committed
36 37
      end
    end
38 39
  end

40
  describe 'Editing issue assignee' do
41 42 43 44 45 46 47
    let!(:issue) do
      create(:issue,
             author: @user,
             assignee: @user,
             project: project)
    end

48
    it 'allows user to select unassigned', js: true do
Vinnie Okada committed
49
      visit edit_namespace_project_issue_path(project.namespace, project, issue)
50

51
      expect(page).to have_content "Assignee #{@user.name}"
52

53
      first('#s2id_issue_assignee_id').click
54
      sleep 2 # wait for ajax stuff to complete
55
      first('.user-result').click
56

57
      click_button 'Save changes'
58

59
      page.within('.assignee') do
60
        expect(page).to have_content 'No assignee - assign yourself'
61 62
      end

63
      expect(issue.reload.assignee).to be_nil
64
    end
gitlabhq committed
65
  end
66

67 68 69 70 71 72 73 74 75 76 77 78
  describe 'Issue info' do
    it 'excludes award_emoji from comment count' do
      issue = create(:issue, author: @user, assignee: @user, project: project, title: 'foobar')
      create(:upvote_note, noteable: issue)

      visit namespace_project_issues_path(project.namespace, project, assignee_id: @user.id)

      expect(page).to have_content 'foobar'
      expect(page.all('.issue-no-comments').first.text).to eq "0"
    end
  end

79
  describe 'Filter issue' do
80 81
    before do
      ['foobar', 'barbaz', 'gitlab'].each do |title|
Riyad Preukschas committed
82 83 84 85 86
        create(:issue,
               author: @user,
               assignee: @user,
               project: project,
               title: title)
87 88
      end

Dmitriy Zaporozhets committed
89
      @issue = Issue.find_by(title: 'foobar')
90 91 92
      @issue.milestone = create(:milestone, project: project)
      @issue.assignee = nil
      @issue.save
93 94
    end

95
    let(:issue) { @issue }
Riyad Preukschas committed
96

97
    it 'should allow filtering by issues with no specified assignee' do
98
      visit namespace_project_issues_path(project.namespace, project, assignee_id: IssuableFinder::NONE)
99

100 101 102
      expect(page).to have_content 'foobar'
      expect(page).not_to have_content 'barbaz'
      expect(page).not_to have_content 'gitlab'
103 104
    end

105
    it 'should allow filtering by a specified assignee' do
Vinnie Okada committed
106
      visit namespace_project_issues_path(project.namespace, project, assignee_id: @user.id)
107

108 109 110
      expect(page).not_to have_content 'foobar'
      expect(page).to have_content 'barbaz'
      expect(page).to have_content 'gitlab'
111
    end
112
  end
113 114

  describe 'filter issue' do
Rémy Coutable committed
115
    titles = %w[foo bar baz]
116
    titles.each_with_index do |title, index|
117 118 119 120 121
      let!(title.to_sym) do
        create(:issue, title: title,
                       project: project,
                       created_at: Time.now - (index * 60))
      end
122
    end
123 124
    let(:newer_due_milestone) { create(:milestone, due_date: '2013-12-11') }
    let(:later_due_milestone) { create(:milestone, due_date: '2013-12-12') }
125 126

    it 'sorts by newest' do
Vinnie Okada committed
127
      visit namespace_project_issues_path(project.namespace, project, sort: sort_value_recently_created)
128

129 130
      expect(first_issue).to include('baz')
      expect(last_issue).to include('foo')
131 132 133
    end

    it 'sorts by oldest' do
Vinnie Okada committed
134
      visit namespace_project_issues_path(project.namespace, project, sort: sort_value_oldest_created)
135

136 137
      expect(first_issue).to include('foo')
      expect(last_issue).to include('baz')
138 139 140 141 142
    end

    it 'sorts by most recently updated' do
      baz.updated_at = Time.now + 100
      baz.save
Vinnie Okada committed
143
      visit namespace_project_issues_path(project.namespace, project, sort: sort_value_recently_updated)
144

145
      expect(first_issue).to include('baz')
146 147 148 149 150
    end

    it 'sorts by least recently updated' do
      baz.updated_at = Time.now - 100
      baz.save
Vinnie Okada committed
151
      visit namespace_project_issues_path(project.namespace, project, sort: sort_value_oldest_updated)
152

153
      expect(first_issue).to include('baz')
154 155
    end

156
    describe 'sorting by due date' do
157
      before do
Rémy Coutable committed
158 159
        foo.update(due_date: 1.day.from_now)
        bar.update(due_date: 6.days.from_now)
160 161 162 163
      end

      it 'sorts by recently due date' do
        visit namespace_project_issues_path(project.namespace, project, sort: sort_value_due_date_soon)
Rémy Coutable committed
164

165 166 167 168 169
        expect(first_issue).to include('foo')
      end

      it 'sorts by least recently due date' do
        visit namespace_project_issues_path(project.namespace, project, sort: sort_value_due_date_later)
Rémy Coutable committed
170

171 172 173 174 175
        expect(first_issue).to include('bar')
      end

      it 'sorts by least recently due date by excluding nil due dates' do
        bar.update(due_date: nil)
Rémy Coutable committed
176

177
        visit namespace_project_issues_path(project.namespace, project, sort: sort_value_due_date_later)
Rémy Coutable committed
178

179 180
        expect(first_issue).to include('foo')
      end
181 182 183 184 185 186 187 188 189 190 191 192 193

      context 'with a filter on labels' do
        let(:label) { create(:label, project: project) }
        before { create(:label_link, label: label, target: foo) }

        it 'sorts by least recently due date by excluding nil due dates' do
          bar.update(due_date: nil)

          visit namespace_project_issues_path(project.namespace, project, label_names: [label.name], sort: sort_value_due_date_later)

          expect(first_issue).to include('foo')
        end
      end
194 195 196
    end

    describe 'filtering by due date' do
Rémy Coutable committed
197 198 199
      before do
        foo.update(due_date: 1.day.from_now)
        bar.update(due_date: 6.days.from_now)
200 201 202
      end

      it 'filters by none' do
203
        visit namespace_project_issues_path(project.namespace, project, due_date: Issue::NoDueDate.name)
Rémy Coutable committed
204 205 206 207

        expect(page).not_to have_content('foo')
        expect(page).not_to have_content('bar')
        expect(page).to have_content('baz')
208 209 210
      end

      it 'filters by any' do
211
        visit namespace_project_issues_path(project.namespace, project, due_date: Issue::AnyDueDate.name)
Rémy Coutable committed
212 213 214 215

        expect(page).to have_content('foo')
        expect(page).to have_content('bar')
        expect(page).to have_content('baz')
216 217
      end

218 219 220 221
      it 'filters by due this week' do
        foo.update(due_date: Date.today.beginning_of_week + 2.days)
        bar.update(due_date: Date.today.end_of_week)
        baz.update(due_date: Date.today - 8.days)
Rémy Coutable committed
222

223
        visit namespace_project_issues_path(project.namespace, project, due_date: Issue::DueThisWeek.name)
Rémy Coutable committed
224 225 226 227

        expect(page).to have_content('foo')
        expect(page).to have_content('bar')
        expect(page).not_to have_content('baz')
228 229
      end

230 231 232 233
      it 'filters by due this month' do
        foo.update(due_date: Date.today.beginning_of_month + 2.days)
        bar.update(due_date: Date.today.end_of_month)
        baz.update(due_date: Date.today - 50.days)
Rémy Coutable committed
234

235
        visit namespace_project_issues_path(project.namespace, project, due_date: Issue::DueThisMonth.name)
Rémy Coutable committed
236 237 238 239

        expect(page).to have_content('foo')
        expect(page).to have_content('bar')
        expect(page).not_to have_content('baz')
240 241
      end

242 243 244 245 246
      it 'filters by overdue' do
        foo.update(due_date: Date.today + 2.days)
        bar.update(due_date: Date.today + 20.days)
        baz.update(due_date: Date.yesterday)

Rémy Coutable committed
247 248 249 250 251 252
        visit namespace_project_issues_path(project.namespace, project, due_date: Issue::Overdue.name)

        expect(page).not_to have_content('foo')
        expect(page).not_to have_content('bar')
        expect(page).to have_content('baz')
      end
253 254
    end

255
    describe 'sorting by milestone' do
Rémy Coutable committed
256
      before do
257 258 259 260 261 262 263
        foo.milestone = newer_due_milestone
        foo.save
        bar.milestone = later_due_milestone
        bar.save
      end

      it 'sorts by recently due milestone' do
Vinnie Okada committed
264
        visit namespace_project_issues_path(project.namespace, project, sort: sort_value_milestone_soon)
265

266
        expect(first_issue).to include('foo')
267
        expect(last_issue).to include('baz')
268 269 270
      end

      it 'sorts by least recently due milestone' do
Vinnie Okada committed
271
        visit namespace_project_issues_path(project.namespace, project, sort: sort_value_milestone_later)
272

273
        expect(first_issue).to include('bar')
274
        expect(last_issue).to include('baz')
275 276 277 278 279 280
      end
    end

    describe 'combine filter and sort' do
      let(:user2) { create(:user) }

Rémy Coutable committed
281
      before do
282 283 284 285 286 287 288
        foo.assignee = user2
        foo.save
        bar.assignee = user2
        bar.save
      end

      it 'sorts with a filter applied' do
Vinnie Okada committed
289 290 291
        visit namespace_project_issues_path(project.namespace, project,
                                            sort: sort_value_oldest_created,
                                            assignee_id: user2.id)
292

293 294
        expect(first_issue).to include('foo')
        expect(last_issue).to include('bar')
295
        expect(page).not_to have_content 'baz'
296 297 298
      end
    end
  end
299

300
  describe 'update assignee from issue#show' do
301
    let(:issue) { create(:issue, project: project, author: @user, assignee: @user) }
302

303
    context 'by authorized user' do
304

305
      it 'allows user to select unassigned', js: true do
Vinnie Okada committed
306
        visit namespace_project_issue_path(project.namespace, project, issue)
307

308 309 310 311 312 313 314 315 316 317 318
        page.within('.assignee') do
          expect(page).to have_content "#{@user.name}"
        end

        find('.block.assignee .edit-link').click
        sleep 2 # wait for ajax stuff to complete
        first('.dropdown-menu-user-link').click
        sleep 2
        page.within('.assignee') do
          expect(page).to have_content 'No assignee'
        end
319

320
        expect(issue.reload.assignee).to be_nil
321
      end
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342

      it 'allows user to select an assignee', js: true do
        issue2 = create(:issue, project: project, author: @user)
        visit namespace_project_issue_path(project.namespace, project, issue2)

        page.within('.assignee') do
          expect(page).to have_content "No assignee"
        end

        page.within '.assignee' do
          click_link 'Edit'
        end
        
        page.within '.dropdown-menu-user' do
          click_link @user.name
        end

        page.within('.assignee') do
          expect(page).to have_content @user.name
        end
      end
343 344 345
    end

    context 'by unauthorized user' do
Dmitriy Zaporozhets committed
346

347
      let(:guest) { create(:user) }
Dmitriy Zaporozhets committed
348

Rémy Coutable committed
349
      before do
350 351 352
        project.team << [[guest], :guest]
      end

353
      it 'shows assignee text', js: true do
354 355 356
        logout
        login_with guest

Vinnie Okada committed
357
        visit namespace_project_issue_path(project.namespace, project, issue)
358
        expect(page).to have_content issue.assignee.name
359 360 361 362 363 364 365 366 367 368 369
      end
    end
  end

  describe 'update milestone from issue#show' do
    let!(:issue) { create(:issue, project: project, author: @user) }
    let!(:milestone) { create(:milestone, project: project) }

    context 'by authorized user' do


370 371
      it 'allows user to select unassigned', js: true do
        visit namespace_project_issue_path(project.namespace, project, issue)
372

373 374 375
        page.within('.milestone') do
          expect(page).to have_content "None"
        end
376

377 378 379 380
        find('.block.milestone .edit-link').click
        sleep 2 # wait for ajax stuff to complete
        first('.dropdown-content li').click
        sleep 2
381
        page.within('.milestone') do
382
          expect(page).to have_content 'None'
383 384
        end

385
        expect(issue.reload.milestone).to be_nil
386 387 388 389 390
      end
    end

    context 'by unauthorized user' do
      let(:guest) { create(:user) }
Dmitriy Zaporozhets committed
391

Rémy Coutable committed
392
      before do
Dmitriy Zaporozhets committed
393
        project.team << [guest, :guest]
394 395 396 397
        issue.milestone = milestone
        issue.save
      end

398
      it 'shows milestone text', js: true do
399 400 401
        logout
        login_with guest

Vinnie Okada committed
402
        visit namespace_project_issue_path(project.namespace, project, issue)
403
        expect(page).to have_content milestone.title
404 405
      end
    end
406 407 408 409

    describe 'removing assignee' do
      let(:user2) { create(:user) }

Rémy Coutable committed
410
      before do
411 412 413 414
        issue.assignee = user2
        issue.save
      end
    end
415 416
  end

417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433
  describe 'new issue' do
    context 'dropzone upload file', js: true do
      before do
        visit new_namespace_project_issue_path(project.namespace, project)
      end

      it 'should upload file when dragging into textarea' do
        drop_in_dropzone test_image_file

        # Wait for the file to upload
        sleep 1

        expect(page.find_field("issue_description").value).to have_content 'banana_sample'
      end
    end
  end

434
  def first_issue
Douwe Maan committed
435
    page.all('ul.issues-list > li').first.text
436 437 438
  end

  def last_issue
Douwe Maan committed
439
    page.all('ul.issues-list > li').last.text
440
  end
441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461

  def drop_in_dropzone(file_path)
    # Generate a fake input selector
    page.execute_script <<-JS
      var fakeFileInput = window.$('<input/>').attr(
        {id: 'fakeFileInput', type: 'file'}
      ).appendTo('body');
    JS
    # Attach the file to the fake input selector with Capybara
    attach_file("fakeFileInput", file_path)
    # Add the file to a fileList array and trigger the fake drop event
    page.execute_script <<-JS
      var fileList = [$('#fakeFileInput')[0].files[0]];
      var e = jQuery.Event('drop', { dataTransfer : { files : fileList } });
      $('.div-dropzone')[0].dropzone.listeners[0].events.drop(e);
    JS
  end

  def test_image_file
    File.join(Rails.root, 'spec', 'fixtures', 'banana_sample.gif')
  end
Dmitriy Zaporozhets committed
462
end