task_lists_spec.rb 11 KB
Newer Older
1 2
require 'spec_helper'

3
describe 'Task Lists' do
4 5
  include Warden::Test::Helpers

6
  let(:project) { create(:project, :repository) }
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
  let(:user)    { create(:user) }
  let(:user2)   { create(:user) }

  let(:markdown) do
    <<-MARKDOWN.strip_heredoc
    This is a task list:

    - [ ] Incomplete entry 1
    - [x] Complete entry 1
    - [ ] Incomplete entry 2
    - [x] Complete entry 2
    - [ ] Incomplete entry 3
    - [ ] Incomplete entry 4
    MARKDOWN
  end

Clement Ho's avatar
Clement Ho committed
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
  let(:singleIncompleteMarkdown) do
    <<-MARKDOWN.strip_heredoc
    This is a task list:

    - [ ] Incomplete entry 1
    MARKDOWN
  end

  let(:singleCompleteMarkdown) do
    <<-MARKDOWN.strip_heredoc
    This is a task list:

    - [x] Incomplete entry 1
    MARKDOWN
  end

39
  let(:nested_tasks_markdown_redcarpet) do
40 41 42 43 44 45 46 47 48 49 50 51
    <<-EOT.strip_heredoc
    - [ ] Task a
      - [x] Task a.1
      - [ ] Task a.2
    - [ ] Task b

    1. [ ] Task 1
      1. [ ] Task 1.1
      1. [x] Task 1.2
    EOT
  end

52 53 54 55 56 57 58 59 60 61 62 63 64
  let(:nested_tasks_markdown) do
    <<-EOT.strip_heredoc
    - [ ] Task a
      - [x] Task a.1
      - [ ] Task a.2
    - [ ] Task b

    1. [ ] Task 1
       1. [ ] Task 1.1
       1. [x] Task 1.2
    EOT
  end

65 66 67
  before do
    Warden.test_mode!

68
    project.add_maintainer(user)
69
    project.add_guest(user2)
70 71 72 73 74

    login_as(user)
  end

  def visit_issue(project, issue)
75
    visit project_issue_path(project, issue)
76 77
  end

78
  describe 'for Issues' do
79
    describe 'multiple tasks', :js do
Clement Ho's avatar
Clement Ho committed
80
      let!(:issue) { create(:issue, description: markdown, author: user, project: project) }
81

Clement Ho's avatar
Clement Ho committed
82 83
      it 'renders' do
        visit_issue(project, issue)
84
        wait_for_requests
85

Clement Ho's avatar
Clement Ho committed
86 87 88 89 90 91 92
        expect(page).to have_selector('ul.task-list',      count: 1)
        expect(page).to have_selector('li.task-list-item', count: 6)
        expect(page).to have_selector('ul input[checked]', count: 2)
      end

      it 'contains the required selectors' do
        visit_issue(project, issue)
93
        wait_for_requests
Clement Ho's avatar
Clement Ho committed
94

Regis's avatar
Regis committed
95
        expect(page).to have_selector(".wiki .task-list .task-list-item .task-list-item-checkbox")
Clement Ho's avatar
Clement Ho committed
96 97
        expect(page).to have_selector('a.btn-close')
      end
98

Clement Ho's avatar
Clement Ho committed
99 100
      it 'is only editable by author' do
        visit_issue(project, issue)
101
        wait_for_requests
102

Regis's avatar
Regis committed
103
        expect(page).to have_selector(".wiki .task-list .task-list-item .task-list-item-checkbox")
104

Clement Ho's avatar
Clement Ho committed
105 106 107
        logout(:user)
        login_as(user2)
        visit current_path
108
        wait_for_requests
Regis's avatar
Regis committed
109 110

        expect(page).to have_selector(".wiki .task-list .task-list-item .task-list-item-checkbox")
Clement Ho's avatar
Clement Ho committed
111 112 113
      end

      it 'provides a summary on Issues#index' do
114
        visit project_issues_path(project)
Clement Ho's avatar
Clement Ho committed
115 116
        expect(page).to have_content("2 of 6 tasks completed")
      end
117 118
    end

119
    describe 'single incomplete task', :js do
Clement Ho's avatar
Clement Ho committed
120
      let!(:issue) { create(:issue, description: singleIncompleteMarkdown, author: user, project: project) }
121

Clement Ho's avatar
Clement Ho committed
122 123
      it 'renders' do
        visit_issue(project, issue)
124
        wait_for_requests
125

Clement Ho's avatar
Clement Ho committed
126 127 128 129 130 131
        expect(page).to have_selector('ul.task-list',      count: 1)
        expect(page).to have_selector('li.task-list-item', count: 1)
        expect(page).to have_selector('ul input[checked]', count: 0)
      end

      it 'provides a summary on Issues#index' do
132
        visit project_issues_path(project)
Regis's avatar
Regis committed
133

Clement Ho's avatar
Clement Ho committed
134 135
        expect(page).to have_content("0 of 1 task completed")
      end
136 137
    end

138
    describe 'single complete task', :js do
Clement Ho's avatar
Clement Ho committed
139 140 141 142
      let!(:issue) { create(:issue, description: singleCompleteMarkdown, author: user, project: project) }

      it 'renders' do
        visit_issue(project, issue)
143
        wait_for_requests
144

Clement Ho's avatar
Clement Ho committed
145 146 147 148 149 150
        expect(page).to have_selector('ul.task-list',      count: 1)
        expect(page).to have_selector('li.task-list-item', count: 1)
        expect(page).to have_selector('ul input[checked]', count: 1)
      end

      it 'provides a summary on Issues#index' do
151
        visit project_issues_path(project)
Regis's avatar
Regis committed
152

Clement Ho's avatar
Clement Ho committed
153 154
        expect(page).to have_content("1 of 1 task completed")
      end
155
    end
156

157
    shared_examples 'shared nested tasks' do
158
      before do
159
        allow(Banzai::Filter::MarkdownFilter).to receive(:engine).and_return('Redcarpet')
160 161
        visit_issue(project, issue)
      end
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
      it 'renders' do
        expect(page).to have_selector('ul.task-list',      count: 2)
        expect(page).to have_selector('li.task-list-item', count: 7)
        expect(page).to have_selector('ul input[checked]', count: 1)
        expect(page).to have_selector('ol input[checked]', count: 1)
      end

      it 'solves tasks' do
        expect(page).to have_content("2 of 7 tasks completed")

        page.find('li.task-list-item', text: 'Task b').find('input').click
        page.find('li.task-list-item ul li.task-list-item', text: 'Task a.2').find('input').click
        page.find('li.task-list-item ol li.task-list-item', text: 'Task 1.1').find('input').click

        expect(page).to have_content("5 of 7 tasks completed")

        visit_issue(project, issue) # reload to see new system notes

        expect(page).to have_content('marked the task Task b as complete')
        expect(page).to have_content('marked the task Task a.2 as complete')
        expect(page).to have_content('marked the task Task 1.1 as complete')
      end
    end
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208

    describe 'nested tasks', :js do
      context 'with Redcarpet' do
        let(:issue) { create(:issue, description: nested_tasks_markdown_redcarpet, author: user, project: project) }

        before do
          allow_any_instance_of(Banzai::Filter::MarkdownFilter).to receive(:engine).and_return('Redcarpet')
          visit_issue(project, issue)
        end

        it_behaves_like 'shared nested tasks'
      end

      context 'with CommonMark' do
        let(:issue) { create(:issue, description: nested_tasks_markdown, author: user, project: project) }

        before do
          allow_any_instance_of(Banzai::Filter::MarkdownFilter).to receive(:engine).and_return('CommonMark')
          visit_issue(project, issue)
        end

        it_behaves_like 'shared nested tasks'
      end
    end
209 210 211 212
  end

  describe 'for Notes' do
    let!(:issue) { create(:issue, author: user, project: project) }
Clement Ho's avatar
Clement Ho committed
213 214 215 216 217 218
    describe 'multiple tasks' do
      let!(:note) do
        create(:note, note: markdown, noteable: issue,
                      project: project, author: user)
      end

Filipa Lacerda's avatar
Filipa Lacerda committed
219
      it 'renders for note body', :js do
Clement Ho's avatar
Clement Ho committed
220 221 222 223 224 225 226
        visit_issue(project, issue)

        expect(page).to have_selector('.note ul.task-list',      count: 1)
        expect(page).to have_selector('.note li.task-list-item', count: 6)
        expect(page).to have_selector('.note ul input[checked]', count: 2)
      end

Filipa Lacerda's avatar
Filipa Lacerda committed
227
      it 'contains the required selectors', :js do
Clement Ho's avatar
Clement Ho committed
228 229 230 231 232 233
        visit_issue(project, issue)

        expect(page).to have_selector('.note .js-task-list-container')
        expect(page).to have_selector('.note .js-task-list-container .task-list .task-list-item .task-list-item-checkbox')
      end

Filipa Lacerda's avatar
Filipa Lacerda committed
234
      it 'is only editable by author', :js do
Clement Ho's avatar
Clement Ho committed
235 236 237
        visit_issue(project, issue)
        expect(page).to have_selector('.js-task-list-container')

238
        gitlab_sign_out
Clement Ho's avatar
Clement Ho committed
239

240
        gitlab_sign_in(user2)
Clement Ho's avatar
Clement Ho committed
241 242 243
        visit current_path
        expect(page).not_to have_selector('.js-task-list-container')
      end
244
    end
245

Clement Ho's avatar
Clement Ho committed
246 247 248 249 250
    describe 'single incomplete task' do
      let!(:note) do
        create(:note, note: singleIncompleteMarkdown, noteable: issue,
                      project: project, author: user)
      end
251

Filipa Lacerda's avatar
Filipa Lacerda committed
252
      it 'renders for note body', :js do
Clement Ho's avatar
Clement Ho committed
253
        visit_issue(project, issue)
254

Clement Ho's avatar
Clement Ho committed
255 256 257 258
        expect(page).to have_selector('.note ul.task-list',      count: 1)
        expect(page).to have_selector('.note li.task-list-item', count: 1)
        expect(page).to have_selector('.note ul input[checked]', count: 0)
      end
259 260
    end

Clement Ho's avatar
Clement Ho committed
261 262 263 264 265
    describe 'single complete task' do
      let!(:note) do
        create(:note, note: singleCompleteMarkdown, noteable: issue,
                      project: project, author: user)
      end
266

Filipa Lacerda's avatar
Filipa Lacerda committed
267
      it 'renders for note body', :js do
Clement Ho's avatar
Clement Ho committed
268
        visit_issue(project, issue)
269

Clement Ho's avatar
Clement Ho committed
270 271 272 273
        expect(page).to have_selector('.note ul.task-list',      count: 1)
        expect(page).to have_selector('.note li.task-list-item', count: 1)
        expect(page).to have_selector('.note ul input[checked]', count: 1)
      end
274 275 276 277 278
    end
  end

  describe 'for Merge Requests' do
    def visit_merge_request(project, merge)
279
      visit project_merge_request_path(project, merge)
280 281
    end

Clement Ho's avatar
Clement Ho committed
282
    describe 'multiple tasks' do
283
      let(:project) { create(:project, :repository) }
Clement Ho's avatar
Clement Ho committed
284
      let!(:merge) { create(:merge_request, :simple, description: markdown, author: user, source_project: project) }
285

Clement Ho's avatar
Clement Ho committed
286 287
      it 'renders for description' do
        visit_merge_request(project, merge)
288

Clement Ho's avatar
Clement Ho committed
289 290 291 292
        expect(page).to have_selector('ul.task-list',      count: 1)
        expect(page).to have_selector('li.task-list-item', count: 6)
        expect(page).to have_selector('ul input[checked]', count: 2)
      end
293

Clement Ho's avatar
Clement Ho committed
294 295
      it 'contains the required selectors' do
        visit_merge_request(project, merge)
296

Clement Ho's avatar
Clement Ho committed
297
        container = '.detail-page-description .description.js-task-list-container'
298

Clement Ho's avatar
Clement Ho committed
299 300
        expect(page).to have_selector(container)
        expect(page).to have_selector("#{container} .wiki .task-list .task-list-item .task-list-item-checkbox")
Filipa Lacerda's avatar
Filipa Lacerda committed
301
        expect(page).to have_selector("#{container} .js-task-list-field")
Clement Ho's avatar
Clement Ho committed
302 303 304
        expect(page).to have_selector('form.js-issuable-update')
        expect(page).to have_selector('a.btn-close')
      end
305

Clement Ho's avatar
Clement Ho committed
306 307 308
      it 'is only editable by author' do
        visit_merge_request(project, merge)
        expect(page).to have_selector('.js-task-list-container')
309

Clement Ho's avatar
Clement Ho committed
310
        logout(:user)
311

Clement Ho's avatar
Clement Ho committed
312 313 314 315 316 317
        login_as(user2)
        visit current_path
        expect(page).not_to have_selector('.js-task-list-container')
      end

      it 'provides a summary on MergeRequests#index' do
318
        visit project_merge_requests_path(project)
Clement Ho's avatar
Clement Ho committed
319 320 321
        expect(page).to have_content("2 of 6 tasks completed")
      end
    end
322

Clement Ho's avatar
Clement Ho committed
323 324 325 326 327 328 329 330 331 332 333 334
    describe 'single incomplete task' do
      let!(:merge) { create(:merge_request, :simple, description: singleIncompleteMarkdown, author: user, source_project: project) }

      it 'renders for description' do
        visit_merge_request(project, merge)

        expect(page).to have_selector('ul.task-list',      count: 1)
        expect(page).to have_selector('li.task-list-item', count: 1)
        expect(page).to have_selector('ul input[checked]', count: 0)
      end

      it 'provides a summary on MergeRequests#index' do
335
        visit project_merge_requests_path(project)
Clement Ho's avatar
Clement Ho committed
336 337
        expect(page).to have_content("0 of 1 task completed")
      end
338 339
    end

Clement Ho's avatar
Clement Ho committed
340 341 342 343 344 345 346 347 348 349 350 351
    describe 'single complete task' do
      let!(:merge) { create(:merge_request, :simple, description: singleCompleteMarkdown, author: user, source_project: project) }

      it 'renders for description' do
        visit_merge_request(project, merge)

        expect(page).to have_selector('ul.task-list',      count: 1)
        expect(page).to have_selector('li.task-list-item', count: 1)
        expect(page).to have_selector('ul input[checked]', count: 1)
      end

      it 'provides a summary on MergeRequests#index' do
352
        visit project_merge_requests_path(project)
Clement Ho's avatar
Clement Ho committed
353 354
        expect(page).to have_content("1 of 1 task completed")
      end
355 356 357
    end
  end
end