Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions extensions/MozChangeField/Extension.pm
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use Bugzilla::Constants;
use Bugzilla::Logging;

use Bugzilla::Extension::MozChangeField::Pre::CanConfirm;
use Bugzilla::Extension::MozChangeField::Pre::CheckinNeededTB;
use Bugzilla::Extension::MozChangeField::Pre::CommentClosedBugs;
use Bugzilla::Extension::MozChangeField::Pre::CustomField;
use Bugzilla::Extension::MozChangeField::Pre::Graveyard;
Expand All @@ -25,6 +26,7 @@ use Bugzilla::Extension::MozChangeField::Pre::TypePriSevEditbugs;

my @pre_instances = (
Bugzilla::Extension::MozChangeField::Pre::CanConfirm->new,
Bugzilla::Extension::MozChangeField::Pre::CheckinNeededTB->new,
Bugzilla::Extension::MozChangeField::Pre::CommentClosedBugs->new,
Bugzilla::Extension::MozChangeField::Pre::CustomField->new,
Bugzilla::Extension::MozChangeField::Pre::Graveyard->new,
Expand All @@ -50,6 +52,15 @@ my @post_instances = (

our $VERSION = '0.1';

sub bug_start_of_set_all {
my ($self, $args) = @_;

foreach my $instance (@pre_instances) {
next if !$instance->can('evaluate_set_all');
$instance->evaluate_set_all($args);
}
}

sub bug_check_can_change_field {
my ($self, $args) = @_;

Expand Down
65 changes: 65 additions & 0 deletions extensions/MozChangeField/lib/Pre/CheckinNeededTB.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.

package Bugzilla::Extension::MozChangeField::Pre::CheckinNeededTB;

use 5.10.1;

use Moo;

use Bugzilla::Error;

use constant CHECKIN_KEYWORD => 'checkin-needed-tb';
use constant PRODUCTS => ('Calendar', 'MailNews Core', 'Thunderbird');

sub evaluate_set_all {
my ($self, $args) = @_;

my $bug = $args->{bug};
my $params = $args->{params};

my $product
= exists $params->{product} ? $params->{product} : $bug->product_obj->name;
return unless grep { $_ eq $product } PRODUCTS;

my $keyword_params = $params->{keywords};
return unless $keyword_params;

# This rule only applies when checkin-needed-tb is newly added.
return if $bug->has_keyword(CHECKIN_KEYWORD);

my $keyword_added;
if (exists $keyword_params->{set}) {
$keyword_added = _contains_checkin_keyword($keyword_params->{set});
}
else {
$keyword_added
= _contains_checkin_keyword($keyword_params->{add})
&& !_contains_checkin_keyword($keyword_params->{remove});
}
return unless $keyword_added;

my $milestone = exists $params->{target_milestone}
? $params->{target_milestone}
: $bug->target_milestone;

if (!defined $milestone || $milestone eq '' || $milestone eq '---') {
ThrowUserError('mozchangefield_checkin_needed_tb_requires_milestone');
}
}

sub _contains_checkin_keyword {
my ($keywords) = @_;
return 0 unless defined $keywords;

my @keywords
= ref $keywords eq 'ARRAY' ? @$keywords : split(/[\s,]+/, $keywords);

return scalar grep { lc($_) eq CHECKIN_KEYWORD } @keywords;
}

1;
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,9 @@
[% title = "Invalid Change" %]
You need "editbugs" permissions to alter the '[% field FILTER html %]' field.

[% ELSIF error == "mozchangefield_checkin_needed_tb_requires_milestone" %]
[% title = "Target Milestone Required" %]
A target milestone must be selected when adding the
<b>checkin-needed-tb</b> keyword.

[% END %]
144 changes: 144 additions & 0 deletions t/bmo/checkin-needed-tb-milestone.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
#!/usr/bin/env perl

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.

use 5.10.1;

use strict;
use warnings;

use lib qw(. lib local/lib/perl5);

use Test::More;

require './extensions/MozChangeField/lib/Pre/CheckinNeededTB.pm';

{
package Local::Product;

sub new {
my ($class, $name) = @_;
return bless {name => $name}, $class;
}

sub name {
return $_[0]->{name};
}
}

{
package Local::Bug;

sub new {
my ($class, %args) = @_;
return bless \%args, $class;
}

sub product_obj {
return Local::Product->new($_[0]->{product});
}

sub has_keyword {
return $_[0]->{has_keyword};
}

sub target_milestone {
return $_[0]->{milestone};
}
}

package main;

my $rule
= Bugzilla::Extension::MozChangeField::Pre::CheckinNeededTB->new;

sub evaluate_rule {
my (%args) = @_;

my $bug = Local::Bug->new(
product => $args{product} || 'Thunderbird',
has_keyword => $args{has_keyword} || 0,
milestone => exists $args{milestone} ? $args{milestone} : '---',
);

eval {
$rule->evaluate_set_all({
bug => $bug,
params => $args{params},
});
};

return $@;
}

{
no warnings qw(once redefine);

local
*Bugzilla::Extension::MozChangeField::Pre::CheckinNeededTB::ThrowUserError
= sub { die "$_[0]\n"; };

foreach my $product ('Calendar', 'MailNews Core', 'Thunderbird') {
like(
evaluate_rule(
product => $product,
params => {keywords => {add => ['checkin-needed-tb']}},
),
qr/mozchangefield_checkin_needed_tb_requires_milestone/,
"Adding checkin-needed-tb without a milestone is rejected for $product"
);
}

is(
evaluate_rule(
milestone => 'Thunderbird 153',
params => {keywords => {add => ['checkin-needed-tb']}},
),
'',
'An existing target milestone allows the keyword'
);

is(
evaluate_rule(
params => {
keywords => {add => ['checkin-needed-tb']},
target_milestone => 'Thunderbird 153',
},
),
'',
'The keyword and target milestone can be set together'
);

is(
evaluate_rule(
product => 'Firefox',
params => {keywords => {add => ['checkin-needed-tb']}},
),
'',
'Other products are unaffected'
);

is(
evaluate_rule(
has_keyword => 1,
params => {keywords => {add => ['another-keyword']}},
),
'',
'A bug that already has checkin-needed-tb is unaffected'
);

like(
evaluate_rule(
params => {keywords => {set => ['checkin-needed-tb']}},
),
qr/mozchangefield_checkin_needed_tb_requires_milestone/,
'Setting the complete keyword list is also validated'
);
}

done_testing();