Commit 5927399c authored by charlie ablett's avatar charlie ablett

Relate Test Reports and Requirement Issues

- Add column and foreign key
- Change column null of requirement_id so either can be used

Changelog: changed
parent 026957b9
# frozen_string_literal: true
class AddIssueIdToTestReport < ActiveRecord::Migration[6.1]
include Gitlab::Database::MigrationHelpers
def up
with_lock_retries do
add_column :requirements_management_test_reports, :issue_id, :bigint, null: true
end
end
def down
with_lock_retries do
remove_column :requirements_management_test_reports, :issue_id
end
end
end
# frozen_string_literal: true
class AddIssueIndexToTestReport < ActiveRecord::Migration[6.1]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
INDEX_NAME = 'index_test_reports_on_issue_id'
def up
add_concurrent_index :requirements_management_test_reports, :issue_id, name: INDEX_NAME
end
def down
remove_concurrent_index_by_name :requirements_management_test_reports, INDEX_NAME
end
end
# frozen_string_literal: true
class ChangeColumnNullTestReportRequirement < ActiveRecord::Migration[6.1]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
def up
with_lock_retries do
change_column_null :requirements_management_test_reports, :requirement_id, true
end
add_concurrent_foreign_key :requirements_management_test_reports, :issues, column: :issue_id
end
def down
with_lock_retries do
remove_foreign_key_if_exists(:requirements_management_test_reports, column: :issue_id)
end
with_lock_retries do
change_column_null :requirements_management_test_reports, :requirement_id, false
end
end
end
12d8de65d287cf29fa2761264c42eb42e7fe2a5b36c279e623d93897503b5313
\ No newline at end of file
fc503b8e9672eb5638d2cb3468c8df4d9c0d998332909351121ace04d3f7214a
\ No newline at end of file
cbe4cff5937f3ba39a4aeeed78dcc6dc6ece212b01b16bfcd61ccf4a20427dcc
\ No newline at end of file
...@@ -17460,10 +17460,11 @@ ALTER SEQUENCE requirements_id_seq OWNED BY requirements.id; ...@@ -17460,10 +17460,11 @@ ALTER SEQUENCE requirements_id_seq OWNED BY requirements.id;
CREATE TABLE requirements_management_test_reports ( CREATE TABLE requirements_management_test_reports (
id bigint NOT NULL, id bigint NOT NULL,
created_at timestamp with time zone NOT NULL, created_at timestamp with time zone NOT NULL,
requirement_id bigint NOT NULL, requirement_id bigint,
author_id bigint, author_id bigint,
state smallint NOT NULL, state smallint NOT NULL,
build_id bigint build_id bigint,
issue_id bigint
); );
CREATE SEQUENCE requirements_management_test_reports_id_seq CREATE SEQUENCE requirements_management_test_reports_id_seq
...@@ -24717,6 +24718,8 @@ CREATE UNIQUE INDEX index_terraform_states_on_uuid ON terraform_states USING btr ...@@ -24717,6 +24718,8 @@ CREATE UNIQUE INDEX index_terraform_states_on_uuid ON terraform_states USING btr
CREATE UNIQUE INDEX index_test_case_failures_unique_columns ON ci_test_case_failures USING btree (test_case_id, failed_at DESC, build_id); CREATE UNIQUE INDEX index_test_case_failures_unique_columns ON ci_test_case_failures USING btree (test_case_id, failed_at DESC, build_id);
CREATE INDEX index_test_reports_on_issue_id ON requirements_management_test_reports USING btree (issue_id);
CREATE INDEX index_timelogs_on_issue_id ON timelogs USING btree (issue_id); CREATE INDEX index_timelogs_on_issue_id ON timelogs USING btree (issue_id);
CREATE INDEX index_timelogs_on_merge_request_id ON timelogs USING btree (merge_request_id); CREATE INDEX index_timelogs_on_merge_request_id ON timelogs USING btree (merge_request_id);
...@@ -25760,6 +25763,9 @@ ALTER TABLE ONLY vulnerabilities ...@@ -25760,6 +25763,9 @@ ALTER TABLE ONLY vulnerabilities
ALTER TABLE ONLY bulk_import_entities ALTER TABLE ONLY bulk_import_entities
ADD CONSTRAINT fk_88c725229f FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE; ADD CONSTRAINT fk_88c725229f FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
ALTER TABLE ONLY requirements_management_test_reports
ADD CONSTRAINT fk_88f30752fc FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
ALTER TABLE ONLY issues ALTER TABLE ONLY issues
ADD CONSTRAINT fk_899c8f3231 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE; ADD CONSTRAINT fk_899c8f3231 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
...@@ -8,8 +8,10 @@ module RequirementsManagement ...@@ -8,8 +8,10 @@ module RequirementsManagement
belongs_to :requirement, inverse_of: :test_reports belongs_to :requirement, inverse_of: :test_reports
belongs_to :author, inverse_of: :test_reports, class_name: 'User' belongs_to :author, inverse_of: :test_reports, class_name: 'User'
belongs_to :build, class_name: 'Ci::Build' belongs_to :build, class_name: 'Ci::Build'
belongs_to :requirement_issue, class_name: 'Issue', foreign_key: :issue_id
validates :requirement, :state, presence: true validates :state, presence: true
validate :only_one_requirement_association
enum state: { passed: 1, failed: 2 } enum state: { passed: 1, failed: 2 }
...@@ -65,5 +67,10 @@ module RequirementsManagement ...@@ -65,5 +67,10 @@ module RequirementsManagement
end end
end end
end end
def only_one_requirement_association
errors.add(:base, 'Must be associated with either a RequirementsManagement::Requirement and an Issue of type `requirement`, but not both') unless !!requirement ^ !!requirement_issue
errors.add(:requirement_issue, 'must be an issue of type `Requirement`') if requirement_issue && !requirement_issue.requirement?
end
end end
end end
...@@ -8,14 +8,69 @@ RSpec.describe RequirementsManagement::TestReport do ...@@ -8,14 +8,69 @@ RSpec.describe RequirementsManagement::TestReport do
it { is_expected.to belong_to(:author).class_name('User') } it { is_expected.to belong_to(:author).class_name('User') }
it { is_expected.to belong_to(:requirement) } it { is_expected.to belong_to(:requirement) }
it { is_expected.to belong_to(:requirement_issue) }
it { is_expected.to belong_to(:build) } it { is_expected.to belong_to(:build) }
end end
describe 'validations' do describe 'validations' do
subject { build(:test_report) } subject { build(:test_report) }
it { is_expected.to validate_presence_of(:requirement) } let(:requirement) { build(:requirement) }
let(:requirement_issue) { build(:requirement_issue) }
let(:requirement_error) { /Must be associated with either a RequirementsManagement::Requirement and an Issue of type `requirement`, but not both/ }
it { is_expected.to validate_presence_of(:state) } it { is_expected.to validate_presence_of(:state) }
context 'requirements associations' do
subject { build(:test_report, requirement: requirement_arg, requirement_issue: requirement_issue_arg) }
context 'when both are set' do
let(:requirement_arg) { requirement }
let(:requirement_issue_arg) { requirement_issue }
specify do
expect(subject).not_to be_valid
expect(subject.errors.messages[:base]).to include(requirement_error)
end
end
context 'when neither are set' do
let(:requirement_arg) { nil }
let(:requirement_issue_arg) { nil }
specify do
expect(subject).not_to be_valid
expect(subject.errors.messages[:base]).to include(requirement_error)
end
end
context 'when only requirement is set' do
let(:requirement_arg) { requirement }
let(:requirement_issue_arg) { nil }
specify { expect(subject).to be_valid }
end
context 'when only requirement issue is set' do
let(:requirement_arg) { nil }
context 'when the requirement issue is of type requirement' do
let(:requirement_issue_arg) { requirement_issue }
specify { expect(subject).to be_valid }
end
context 'when requirement issue is non-requirement issue' do
let(:invalid_issue) { build(:issue) }
let(:requirement_issue_arg) { invalid_issue }
specify do
expect(subject).not_to be_valid
expect(subject.errors.messages[:requirement_issue]).to include(/must be an issue of type `Requirement`/)
end
end
end
end
end end
describe 'scopes' do describe 'scopes' do
......
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