Commit 80bd6f78 authored by Stan Hu's avatar Stan Hu

Merge branch '33042-persist-zoom-meetings-added-to-issues-in-the-database-2' into 'master'

Switch quick actions to use Zoom Meetings table and model

See merge request gitlab-org/gitlab!18620
parents a1eb38e3 4529c73f
...@@ -281,10 +281,7 @@ module IssuablesHelper ...@@ -281,10 +281,7 @@ module IssuablesHelper
} }
data[:hasClosingMergeRequest] = issuable.merge_requests_count(current_user) != 0 if issuable.is_a?(Issue) data[:hasClosingMergeRequest] = issuable.merge_requests_count(current_user) != 0 if issuable.is_a?(Issue)
data[:zoomMeetingUrl] = ZoomMeeting.canonical_meeting_url(issuable) if issuable.is_a?(Issue)
zoom_links = Gitlab::ZoomLinkExtractor.new(issuable.description).links
data[:zoomMeetingUrl] = zoom_links.last if zoom_links.any?
if parent.is_a?(Group) if parent.is_a?(Group)
data[:groupPath] = parent.path data[:groupPath] = parent.path
......
...@@ -40,6 +40,7 @@ class Issue < ApplicationRecord ...@@ -40,6 +40,7 @@ class Issue < ApplicationRecord
has_many :issue_assignees has_many :issue_assignees
has_many :assignees, class_name: "User", through: :issue_assignees has_many :assignees, class_name: "User", through: :issue_assignees
has_many :zoom_meetings
validates :project, presence: true validates :project, presence: true
......
...@@ -14,4 +14,13 @@ class ZoomMeeting < ApplicationRecord ...@@ -14,4 +14,13 @@ class ZoomMeeting < ApplicationRecord
scope :added_to_issue, -> { where(issue_status: :added) } scope :added_to_issue, -> { where(issue_status: :added) }
scope :removed_from_issue, -> { where(issue_status: :removed) } scope :removed_from_issue, -> { where(issue_status: :removed) }
scope :canonical, -> (issue) { where(issue: issue).added_to_issue }
def self.canonical_meeting(issue)
canonical(issue)&.take
end
def self.canonical_meeting_url(issue)
canonical_meeting(issue)&.url
end
end end
...@@ -61,8 +61,6 @@ module Issues ...@@ -61,8 +61,6 @@ module Issues
if added_mentions.present? if added_mentions.present?
notification_service.async.new_mentions_in_issue(issue, added_mentions, current_user) notification_service.async.new_mentions_in_issue(issue, added_mentions, current_user)
end end
ZoomNotesService.new(issue, project, current_user, old_description: old_associations[:description]).execute
end end
def handle_task_changes(issuable) def handle_task_changes(issuable)
......
...@@ -6,32 +6,37 @@ module Issues ...@@ -6,32 +6,37 @@ module Issues
super(issue.project, user) super(issue.project, user)
@issue = issue @issue = issue
@added_meeting = ZoomMeeting.canonical_meeting(@issue)
end end
def add_link(link) def add_link(link)
if can_add_link? && (link = parse_link(link)) if can_add_link? && (link = parse_link(link))
track_meeting_added_event begin
success(_('Zoom meeting added'), append_to_description(link)) add_zoom_meeting(link)
success(_('Zoom meeting added'))
rescue ActiveRecord::RecordNotUnique
error(_('Failed to add a Zoom meeting'))
end
else else
error(_('Failed to add a Zoom meeting')) error(_('Failed to add a Zoom meeting'))
end end
end end
def can_add_link?
can? && !link_in_issue_description?
end
def remove_link def remove_link
if can_remove_link? if can_remove_link?
track_meeting_removed_event remove_zoom_meeting
success(_('Zoom meeting removed'), remove_from_description) success(_('Zoom meeting removed'))
else else
error(_('Failed to remove a Zoom meeting')) error(_('Failed to remove a Zoom meeting'))
end end
end end
def can_add_link?
can_update_issue? && !@added_meeting
end
def can_remove_link? def can_remove_link?
can? && link_in_issue_description? can_update_issue? && !!@added_meeting
end end
def parse_link(link) def parse_link(link)
...@@ -42,10 +47,6 @@ module Issues ...@@ -42,10 +47,6 @@ module Issues
attr_reader :issue attr_reader :issue
def issue_description
issue.description || ''
end
def track_meeting_added_event def track_meeting_added_event
::Gitlab::Tracking.event('IncidentManagement::ZoomIntegration', 'add_zoom_meeting', label: 'Issue ID', value: issue.id) ::Gitlab::Tracking.event('IncidentManagement::ZoomIntegration', 'add_zoom_meeting', label: 'Issue ID', value: issue.id)
end end
...@@ -54,39 +55,33 @@ module Issues ...@@ -54,39 +55,33 @@ module Issues
::Gitlab::Tracking.event('IncidentManagement::ZoomIntegration', 'remove_zoom_meeting', label: 'Issue ID', value: issue.id) ::Gitlab::Tracking.event('IncidentManagement::ZoomIntegration', 'remove_zoom_meeting', label: 'Issue ID', value: issue.id)
end end
def success(message, description) def add_zoom_meeting(link)
ServiceResponse ZoomMeeting.create(
.success(message: message, payload: { description: description }) issue: @issue,
end project: @issue.project,
issue_status: :added,
def error(message) url: link
ServiceResponse.error(message: message) )
track_meeting_added_event
SystemNoteService.zoom_link_added(@issue, @project, current_user)
end end
def append_to_description(link) def remove_zoom_meeting
"#{issue_description}\n\n#{link}" @added_meeting.update(issue_status: :removed)
track_meeting_removed_event
SystemNoteService.zoom_link_removed(@issue, @project, current_user)
end end
def remove_from_description def success(message)
link = parse_link(issue_description) ServiceResponse.success(message: message)
return issue_description unless link
issue_description.delete_suffix(link).rstrip
end end
def link_in_issue_description? def error(message)
link = extract_link_from_issue_description ServiceResponse.error(message: message)
return unless link
Gitlab::ZoomLinkExtractor.new(link).match?
end
def extract_link_from_issue_description
issue_description[/(\S+)\z/, 1]
end end
def can? def can_update_issue?
current_user.can?(:update_issue, project) can?(current_user, :update_issue, project)
end end
end end
end end
# frozen_string_literal: true
class ZoomNotesService
def initialize(issue, project, current_user, old_description: nil)
@issue = issue
@project = project
@current_user = current_user
@old_description = old_description
end
def execute
return if @issue.description == @old_description
if zoom_link_added?
zoom_link_added_notification
elsif zoom_link_removed?
zoom_link_removed_notification
end
end
private
def zoom_link_added?
has_zoom_link?(@issue.description) && !has_zoom_link?(@old_description)
end
def zoom_link_removed?
!has_zoom_link?(@issue.description) && has_zoom_link?(@old_description)
end
def has_zoom_link?(text)
Gitlab::ZoomLinkExtractor.new(text).match?
end
def zoom_link_added_notification
SystemNoteService.zoom_link_added(@issue, @project, @current_user)
end
def zoom_link_removed_notification
SystemNoteService.zoom_link_removed(@issue, @project, @current_user)
end
end
---
title: Store Zoom URLs in a table rather than in the issue description
merge_request: 18620
author:
type: changed
...@@ -28,6 +28,7 @@ tree: ...@@ -28,6 +28,7 @@ tree:
- label: - label:
- :priorities - :priorities
- :issue_assignees - :issue_assignees
- :zoom_meetings
- snippets: - snippets:
- :award_emoji - :award_emoji
- notes: - notes:
......
...@@ -174,18 +174,14 @@ module Gitlab ...@@ -174,18 +174,14 @@ module Gitlab
params '<Zoom URL>' params '<Zoom URL>'
types Issue types Issue
condition do condition do
zoom_link_service.can_add_link? @zoom_service = zoom_link_service
@zoom_service.can_add_link?
end end
parse_params do |link| parse_params do |link|
zoom_link_service.parse_link(link) @zoom_service.parse_link(link)
end end
command :zoom do |link| command :zoom do |link|
result = zoom_link_service.add_link(link) result = @zoom_service.add_link(link)
if result.success?
@updates[:description] = result.payload[:description]
end
@execution_message[:zoom] = result.message @execution_message[:zoom] = result.message
end end
...@@ -194,15 +190,11 @@ module Gitlab ...@@ -194,15 +190,11 @@ module Gitlab
execution_message _('Zoom meeting removed') execution_message _('Zoom meeting removed')
types Issue types Issue
condition do condition do
zoom_link_service.can_remove_link? @zoom_service = zoom_link_service
@zoom_service.can_remove_link?
end end
command :remove_zoom do command :remove_zoom do
result = zoom_link_service.remove_link result = @zoom_service.remove_link
if result.success?
@updates[:description] = result.payload[:description]
end
@execution_message[:remove_zoom] = result.message @execution_message[:remove_zoom] = result.message
end end
......
...@@ -92,19 +92,6 @@ describe "User creates issue" do ...@@ -92,19 +92,6 @@ describe "User creates issue" do
.and have_content(label_titles.first) .and have_content(label_titles.first)
end end
end end
context "with Zoom link" do
it "adds Zoom button" do
issue_title = "Issue containing Zoom meeting link"
zoom_url = "https://gitlab.zoom.us/j/123456789"
fill_in("Title", with: issue_title)
fill_in("Description", with: zoom_url)
click_button("Submit issue")
expect(page).to have_link('Join Zoom meeting', href: zoom_url)
end
end
end end
context "when signed in as user with special characters in their name" do context "when signed in as user with special characters in their name" do
......
...@@ -80,6 +80,17 @@ ...@@ -80,6 +80,17 @@
"issue_id": 40 "issue_id": 40
} }
], ],
"zoom_meetings": [
{
"id": 1,
"project_id": 5,
"issue_id": 40,
"url": "https://zoom.us/j/123456789",
"issue_status": 1,
"created_at": "2016-06-14T15:02:04.418Z",
"updated_at": "2016-06-14T15:02:04.418Z"
}
],
"milestone": { "milestone": {
"id": 1, "id": 1,
"title": "test milestone", "title": "test milestone",
......
...@@ -203,42 +203,53 @@ describe IssuablesHelper do ...@@ -203,42 +203,53 @@ describe IssuablesHelper do
end end
describe '#zoomMeetingUrl in issue' do describe '#zoomMeetingUrl in issue' do
let(:issue) { create(:issue, author: user, description: description) } let(:issue) { create(:issue, author: user) }
before do before do
assign(:project, issue.project) assign(:project, issue.project)
end end
context 'no zoom links in the issue description' do shared_examples 'sets zoomMeetingUrl to nil' do
let(:description) { 'issue text' } specify do
expect(helper.issuable_initial_data(issue)[:zoomMeetingUrl])
it 'does not set zoomMeetingUrl' do .to be_nil
expect(helper.issuable_initial_data(issue))
.not_to include(:zoomMeetingUrl)
end end
end end
context 'no zoom links in the issue description if it has link but not a zoom link' do context 'with no "added" zoom mettings' do
let(:description) { 'issue text https://stackoverflow.com/questions/22' } it_behaves_like 'sets zoomMeetingUrl to nil'
context 'with multiple removed meetings' do
before do
create(:zoom_meeting, issue: issue, issue_status: :removed)
create(:zoom_meeting, issue: issue, issue_status: :removed)
end
it 'does not set zoomMeetingUrl' do it_behaves_like 'sets zoomMeetingUrl to nil'
expect(helper.issuable_initial_data(issue))
.not_to include(:zoomMeetingUrl)
end end
end end
context 'with two zoom links in description' do context 'with "added" zoom meeting' do
let(:description) do before do
<<~TEXT create(:zoom_meeting, issue: issue)
issue text and
zoom call on https://zoom.us/j/123456789 this url
and new zoom url https://zoom.us/s/lastone and some more text
TEXT
end end
it 'sets zoomMeetingUrl value to the last url' do shared_examples 'sets zoomMeetingUrl to canonical meeting url' do
expect(helper.issuable_initial_data(issue)) specify do
.to include(zoomMeetingUrl: 'https://zoom.us/s/lastone') expect(helper.issuable_initial_data(issue))
.to include(zoomMeetingUrl: 'https://zoom.us/j/123456789')
end
end
it_behaves_like 'sets zoomMeetingUrl to canonical meeting url'
context 'with muliple "removed" zoom meetings' do
before do
create(:zoom_meeting, issue: issue, issue_status: :removed)
create(:zoom_meeting, issue: issue, issue_status: :removed)
end
it_behaves_like 'sets zoomMeetingUrl to canonical meeting url'
end end
end end
end end
......
...@@ -29,6 +29,7 @@ issues: ...@@ -29,6 +29,7 @@ issues:
- prometheus_alerts - prometheus_alerts
- prometheus_alert_events - prometheus_alert_events
- self_managed_prometheus_alert_events - self_managed_prometheus_alert_events
- zoom_meetings
events: events:
- author - author
- project - project
...@@ -529,4 +530,6 @@ versions: &version ...@@ -529,4 +530,6 @@ versions: &version
- issue - issue
- designs - designs
- actions - actions
zoom_meetings:
- issue
design_versions: *version design_versions: *version
...@@ -211,6 +211,13 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do ...@@ -211,6 +211,13 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do
expect(CustomIssueTrackerService.first).not_to be_nil expect(CustomIssueTrackerService.first).not_to be_nil
end end
it 'restores zoom meetings' do
meetings = @project.issues.first.zoom_meetings
expect(meetings.count).to eq(1)
expect(meetings.first.url).to eq('https://zoom.us/j/123456789')
end
context 'Merge requests' do context 'Merge requests' do
it 'always has the new project as a target' do it 'always has the new project as a target' do
expect(MergeRequest.find_by_title('MR1').target_project).to eq(@project) expect(MergeRequest.find_by_title('MR1').target_project).to eq(@project)
......
...@@ -753,3 +753,11 @@ DesignManagement::Version: ...@@ -753,3 +753,11 @@ DesignManagement::Version:
- sha - sha
- issue_id - issue_id
- author_id - author_id
ZoomMeeting:
- id
- issue_id
- project_id
- issue_status
- url
- created_at
- updated_at
...@@ -187,7 +187,6 @@ describe Issues::UpdateService, :mailer do ...@@ -187,7 +187,6 @@ describe Issues::UpdateService, :mailer do
it 'creates system note about issue reassign' do it 'creates system note about issue reassign' do
note = find_note('assigned to') note = find_note('assigned to')
expect(note).not_to be_nil
expect(note.note).to include "assigned to #{user2.to_reference}" expect(note.note).to include "assigned to #{user2.to_reference}"
end end
...@@ -202,14 +201,12 @@ describe Issues::UpdateService, :mailer do ...@@ -202,14 +201,12 @@ describe Issues::UpdateService, :mailer do
it 'creates system note about title change' do it 'creates system note about title change' do
note = find_note('changed title') note = find_note('changed title')
expect(note).not_to be_nil
expect(note.note).to eq 'changed title from **{-Old-} title** to **{+New+} title**' expect(note.note).to eq 'changed title from **{-Old-} title** to **{+New+} title**'
end end
it 'creates system note about discussion lock' do it 'creates system note about discussion lock' do
note = find_note('locked this issue') note = find_note('locked this issue')
expect(note).not_to be_nil
expect(note.note).to eq 'locked this issue' expect(note.note).to eq 'locked this issue'
end end
end end
...@@ -221,20 +218,10 @@ describe Issues::UpdateService, :mailer do ...@@ -221,20 +218,10 @@ describe Issues::UpdateService, :mailer do
note = find_note('changed the description') note = find_note('changed the description')
expect(note).not_to be_nil
expect(note.note).to eq('changed the description') expect(note.note).to eq('changed the description')
end end
end end
it 'creates zoom_link_added system note when a zoom link is added to the description' do
update_issue(description: 'Changed description https://zoom.us/j/5873603787')
note = find_note('added a Zoom call')
expect(note).not_to be_nil
expect(note.note).to eq('added a Zoom call to this issue')
end
context 'when issue turns confidential' do context 'when issue turns confidential' do
let(:opts) do let(:opts) do
{ {
...@@ -252,7 +239,6 @@ describe Issues::UpdateService, :mailer do ...@@ -252,7 +239,6 @@ describe Issues::UpdateService, :mailer do
note = find_note('made the issue confidential') note = find_note('made the issue confidential')
expect(note).not_to be_nil
expect(note.note).to eq 'made the issue confidential' expect(note.note).to eq 'made the issue confidential'
end end
......
...@@ -14,27 +14,16 @@ describe Issues::ZoomLinkService do ...@@ -14,27 +14,16 @@ describe Issues::ZoomLinkService do
project.add_reporter(user) project.add_reporter(user)
end end
shared_context 'with Zoom link' do shared_context '"added" Zoom meeting' do
before do before do
issue.update!(description: "Description\n\n#{zoom_link}") create(:zoom_meeting, issue: issue)
end end
end end
shared_context 'with Zoom link not at the end' do shared_context '"removed" zoom meetings' do
before do before do
issue.update!(description: "Description with #{zoom_link} some where") create(:zoom_meeting, issue: issue, issue_status: :removed)
end create(:zoom_meeting, issue: issue, issue_status: :removed)
end
shared_context 'without Zoom link' do
before do
issue.update!(description: "Description\n\nhttp://example.com")
end
end
shared_context 'without issue description' do
before do
issue.update!(description: nil)
end end
end end
...@@ -45,11 +34,10 @@ describe Issues::ZoomLinkService do ...@@ -45,11 +34,10 @@ describe Issues::ZoomLinkService do
end end
describe '#add_link' do describe '#add_link' do
shared_examples 'can add link' do shared_examples 'can add meeting' do
it 'appends the link to issue description' do it 'appends the new meeting to zoom_meetings' do
expect(result).to be_success expect(result).to be_success
expect(result.payload[:description]) expect(ZoomMeeting.canonical_meeting_url(issue)).to eq(zoom_link)
.to eq("#{issue.description}\n\n#{zoom_link}")
end end
it 'tracks the add event' do it 'tracks the add event' do
...@@ -57,55 +45,63 @@ describe Issues::ZoomLinkService do ...@@ -57,55 +45,63 @@ describe Issues::ZoomLinkService do
.with('IncidentManagement::ZoomIntegration', 'add_zoom_meeting', label: 'Issue ID', value: issue.id) .with('IncidentManagement::ZoomIntegration', 'add_zoom_meeting', label: 'Issue ID', value: issue.id)
result result
end end
it 'creates a zoom_link_added notification' do
expect(SystemNoteService).to receive(:zoom_link_added).with(issue, project, user)
expect(SystemNoteService).not_to receive(:zoom_link_removed)
result
end
end end
shared_examples 'cannot add link' do shared_examples 'cannot add meeting' do
it 'cannot add the link' do it 'cannot add the meeting' do
expect(result).to be_error expect(result).to be_error
expect(result.message).to eq('Failed to add a Zoom meeting') expect(result.message).to eq('Failed to add a Zoom meeting')
end end
it 'creates no notification' do
expect(SystemNoteService).not_to receive(:zoom_link_added)
expect(SystemNoteService).not_to receive(:zoom_link_removed)
result
end
end end
subject(:result) { service.add_link(zoom_link) } subject(:result) { service.add_link(zoom_link) }
context 'without Zoom link in the issue description' do context 'without existing Zoom meeting' do
include_context 'without Zoom link' include_examples 'can add meeting'
include_examples 'can add link'
context 'with invalid Zoom link' do context 'with invalid Zoom url' do
let(:zoom_link) { 'https://not-zoom.link' } let(:zoom_link) { 'https://not-zoom.link' }
include_examples 'cannot add link' include_examples 'cannot add meeting'
end end
context 'with insufficient permissions' do context 'with insufficient permissions' do
include_context 'insufficient permissions' include_context 'insufficient permissions'
include_examples 'cannot add link' include_examples 'cannot add meeting'
end end
end end
context 'with Zoom link in the issue description' do context 'with "added" Zoom meeting' do
include_context 'with Zoom link' include_context '"added" Zoom meeting'
include_examples 'cannot add link' include_examples 'cannot add meeting'
end
context 'but not at the end' do context 'with "added" Zoom meeting and race condition' do
include_context 'with Zoom link not at the end' include_context '"added" Zoom meeting'
include_examples 'can add link' before do
allow(service).to receive(:can_add_link?).and_return(true)
end end
end
context 'without issue description' do include_examples 'cannot add meeting'
include_context 'without issue description'
include_examples 'can add link'
end end
end end
describe '#can_add_link?' do describe '#can_add_link?' do
subject { service.can_add_link? } subject { service.can_add_link? }
context 'without Zoom link in the issue description' do context 'without "added" zoom meeting' do
include_context 'without Zoom link'
it { is_expected.to eq(true) } it { is_expected.to eq(true) }
context 'with insufficient permissions' do context 'with insufficient permissions' do
...@@ -115,81 +111,93 @@ describe Issues::ZoomLinkService do ...@@ -115,81 +111,93 @@ describe Issues::ZoomLinkService do
end end
end end
context 'with Zoom link in the issue description' do context 'with Zoom meeting in the issue description' do
include_context 'with Zoom link' include_context '"added" Zoom meeting'
it { is_expected.to eq(false) } it { is_expected.to eq(false) }
end end
end end
describe '#remove_link' do describe '#remove_link' do
shared_examples 'cannot remove link' do shared_examples 'cannot remove meeting' do
it 'cannot remove the link' do it 'cannot remove the meeting' do
expect(result).to be_error expect(result).to be_error
expect(result.message).to eq('Failed to remove a Zoom meeting') expect(result.message).to eq('Failed to remove a Zoom meeting')
end end
end
subject(:result) { service.remove_link } it 'creates no notification' do
expect(SystemNoteService).not_to receive(:zoom_link_added)
expect(SystemNoteService).not_to receive(:zoom_link_removed)
result
end
end
context 'with Zoom link in the issue description' do shared_examples 'can remove meeting' do
include_context 'with Zoom link' it 'creates no notification' do
expect(SystemNoteService).not_to receive(:zoom_link_added).with(issue, project, user)
expect(SystemNoteService).to receive(:zoom_link_removed)
result
end
it 'removes the link from the issue description' do it 'can remove the meeting' do
expect(result).to be_success expect(result).to be_success
expect(result.payload[:description]) expect(ZoomMeeting.canonical_meeting_url(issue)).to eq(nil)
.to eq(issue.description.delete_suffix("\n\n#{zoom_link}"))
end end
it 'tracks the remove event' do it 'tracks the remove event' do
expect(Gitlab::Tracking).to receive(:event) expect(Gitlab::Tracking).to receive(:event)
.with('IncidentManagement::ZoomIntegration', 'remove_zoom_meeting', label: 'Issue ID', value: issue.id) .with('IncidentManagement::ZoomIntegration', 'remove_zoom_meeting', label: 'Issue ID', value: issue.id)
result result
end end
end
context 'with insufficient permissions' do subject(:result) { service.remove_link }
include_context 'insufficient permissions'
include_examples 'cannot remove link'
end
context 'but not at the end' do context 'with Zoom meeting' do
include_context 'with Zoom link not at the end' include_context '"added" Zoom meeting'
include_examples 'cannot remove link'
context 'removes the link' do
include_examples 'can remove meeting'
end end
end
context 'without Zoom link in the issue description' do context 'with insufficient permissions' do
include_context 'without Zoom link' include_context 'insufficient permissions'
include_examples 'cannot remove link' include_examples 'cannot remove meeting'
end
end end
context 'without issue description' do context 'without "added" Zoom meeting' do
include_context 'without issue description' include_context '"removed" zoom meetings'
include_examples 'cannot remove link' include_examples 'cannot remove meeting'
end end
end end
describe '#can_remove_link?' do describe '#can_remove_link?' do
subject { service.can_remove_link? } subject { service.can_remove_link? }
context 'with Zoom link in the issue description' do context 'without Zoom meeting' do
include_context 'with Zoom link' it { is_expected.to eq(false) }
end
context 'with only "removed" zoom meetings' do
include_context '"removed" zoom meetings'
it { is_expected.to eq(false) }
end
context 'with "added" Zoom meeting' do
include_context '"added" Zoom meeting'
it { is_expected.to eq(true) } it { is_expected.to eq(true) }
context 'with "removed" zoom meetings' do
include_context '"removed" zoom meetings'
it { is_expected.to eq(true) }
end
context 'with insufficient permissions' do context 'with insufficient permissions' do
include_context 'insufficient permissions' include_context 'insufficient permissions'
it { is_expected.to eq(false) } it { is_expected.to eq(false) }
end end
end end
context 'without Zoom link in the issue description' do
include_context 'without Zoom link'
it { is_expected.to eq(false) }
end
end end
describe '#parse_link' do describe '#parse_link' do
......
# frozen_string_literal: true
require 'spec_helper'
describe ZoomNotesService do
describe '#execute' do
let(:issue) { OpenStruct.new(description: description) }
let(:project) { Object.new }
let(:user) { Object.new }
let(:description) { 'an issue description' }
let(:old_description) { nil }
subject { described_class.new(issue, project, user, old_description: old_description) }
shared_examples 'no notifications' do
it "doesn't create notifications" do
expect(SystemNoteService).not_to receive(:zoom_link_added)
expect(SystemNoteService).not_to receive(:zoom_link_removed)
subject.execute
end
end
it_behaves_like 'no notifications'
context 'when the zoom link exists in both description and old_description' do
let(:description) { 'a changed issue description https://zoom.us/j/123' }
let(:old_description) { 'an issue description https://zoom.us/j/123' }
it_behaves_like 'no notifications'
end
context "when the zoom link doesn't exist in both description and old_description" do
let(:description) { 'a changed issue description' }
let(:old_description) { 'an issue description' }
it_behaves_like 'no notifications'
end
context 'when description == old_description' do
let(:old_description) { 'an issue description' }
it_behaves_like 'no notifications'
end
context 'when the description contains a zoom link and old_description is nil' do
let(:description) { 'a changed issue description https://zoom.us/j/123' }
it 'creates a zoom_link_added notification' do
expect(SystemNoteService).to receive(:zoom_link_added).with(issue, project, user)
expect(SystemNoteService).not_to receive(:zoom_link_removed)
subject.execute
end
end
context 'when the zoom link has been added to the description' do
let(:description) { 'a changed issue description https://zoom.us/j/123' }
let(:old_description) { 'an issue description' }
it 'creates a zoom_link_added notification' do
expect(SystemNoteService).to receive(:zoom_link_added).with(issue, project, user)
expect(SystemNoteService).not_to receive(:zoom_link_removed)
subject.execute
end
end
context 'when the zoom link has been removed from the description' do
let(:description) { 'a changed issue description' }
let(:old_description) { 'an issue description https://zoom.us/j/123' }
it 'creates a zoom_link_removed notification' do
expect(SystemNoteService).not_to receive(:zoom_link_added).with(issue, project, user)
expect(SystemNoteService).to receive(:zoom_link_removed)
subject.execute
end
end
end
end
...@@ -2,22 +2,19 @@ ...@@ -2,22 +2,19 @@
shared_examples 'zoom quick actions' do shared_examples 'zoom quick actions' do
let(:zoom_link) { 'https://zoom.us/j/123456789' } let(:zoom_link) { 'https://zoom.us/j/123456789' }
let(:existing_zoom_link) { 'https://zoom.us/j/123456780' }
let(:invalid_zoom_link) { 'https://invalid-zoom' } let(:invalid_zoom_link) { 'https://invalid-zoom' }
before do
issue.update!(description: description)
end
describe '/zoom' do describe '/zoom' do
shared_examples 'skip silently' do shared_examples 'skip silently' do
it 'skip addition silently' do it 'skips addition silently' do
add_note("/zoom #{zoom_link}") add_note("/zoom #{zoom_link}")
wait_for_requests wait_for_requests
expect(page).not_to have_content('Zoom meeting added') expect(page).not_to have_content('Zoom meeting added')
expect(page).not_to have_content('Failed to add a Zoom meeting') expect(page).not_to have_content('Failed to add a Zoom meeting')
expect(issue.reload.description).to eq(description) expect(ZoomMeeting.canonical_meeting_url(issue.reload)).not_to eq(zoom_link)
end end
end end
...@@ -28,13 +25,11 @@ shared_examples 'zoom quick actions' do ...@@ -28,13 +25,11 @@ shared_examples 'zoom quick actions' do
wait_for_requests wait_for_requests
expect(page).to have_content('Zoom meeting added') expect(page).to have_content('Zoom meeting added')
expect(issue.reload.description).to end_with(zoom_link) expect(ZoomMeeting.canonical_meeting_url(issue.reload)).to eq(zoom_link)
end end
end end
context 'without issue description' do context 'without zoom_meetings' do
let(:description) { nil }
include_examples 'success' include_examples 'success'
it 'cannot add invalid zoom link' do it 'cannot add invalid zoom link' do
...@@ -47,14 +42,18 @@ shared_examples 'zoom quick actions' do ...@@ -47,14 +42,18 @@ shared_examples 'zoom quick actions' do
end end
end end
context 'with Zoom link not at the end of the issue description' do context 'with "removed" zoom meeting' do
let(:description) { "A link #{zoom_link} not at the end" } before do
create(:zoom_meeting, issue_status: :removed, url: existing_zoom_link, issue: issue)
end
include_examples 'success' include_examples 'success'
end end
context 'with Zoom link at end of the issue description' do context 'with "added" zoom meeting' do
let(:description) { "Text\n#{zoom_link}" } before do
create(:zoom_meeting, issue_status: :added, url: existing_zoom_link, issue: issue)
end
include_examples 'skip silently' include_examples 'skip silently'
end end
...@@ -62,19 +61,19 @@ shared_examples 'zoom quick actions' do ...@@ -62,19 +61,19 @@ shared_examples 'zoom quick actions' do
describe '/remove_zoom' do describe '/remove_zoom' do
shared_examples 'skip silently' do shared_examples 'skip silently' do
it 'skip removal silently' do it 'skips removal silently' do
add_note('/remove_zoom') add_note('/remove_zoom')
wait_for_requests wait_for_requests
expect(page).not_to have_content('Zoom meeting removed') expect(page).not_to have_content('Zoom meeting removed')
expect(page).not_to have_content('Failed to remove a Zoom meeting') expect(page).not_to have_content('Failed to remove a Zoom meeting')
expect(issue.reload.description).to eq(description) expect(ZoomMeeting.canonical_meeting_url(issue.reload)).to be_nil
end end
end end
context 'with Zoom link in the description' do context 'with added zoom meeting' do
let(:description) { "Text with #{zoom_link}\n\n\n#{zoom_link}" } let!(:added_zoom_meeting) { create(:zoom_meeting, url: zoom_link, issue: issue, issue_status: :added) }
it 'removes last Zoom link' do it 'removes last Zoom link' do
add_note('/remove_zoom') add_note('/remove_zoom')
...@@ -82,14 +81,8 @@ shared_examples 'zoom quick actions' do ...@@ -82,14 +81,8 @@ shared_examples 'zoom quick actions' do
wait_for_requests wait_for_requests
expect(page).to have_content('Zoom meeting removed') expect(page).to have_content('Zoom meeting removed')
expect(issue.reload.description).to eq("Text with #{zoom_link}") expect(ZoomMeeting.canonical_meeting_url(issue.reload)).to be_nil
end end
end end
context 'with a Zoom link not at the end of the description' do
let(:description) { "A link #{zoom_link} not at the end" }
include_examples 'skip silently'
end
end end
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