# frozen_string_literal: true module PlatformSdk module SpecSupport RSpec.shared_examples 'OneRosterDataPipelineable' do |record_keys| let(:data) do record_keys.each_with_object({}) do |key, hash| if key == '_type' hash[:type] = record.try(key) next end hash[key.to_sym] = record.try(key) end end let(:pipeline_payload) do { "noun": "StrongMind.Platform.OneRoster.#{record.one_roster_data_type.capitalize}", "identifiers": { "sourcedId": record.roster_id }, "meta": { "version": '3', "source": 'Central OneRoster API' }, "data": one_roster_common_data.merge!(data), "envelope_version": '1.0.0', "message_timestamp": Time.current.utc.iso8601 } end let(:record) { build(described_class.to_s.underscore.to_sym) } let(:one_roster_common_data) do { "sourcedId": record.roster_id, "status": record.status, "dateLastModified": record.updated_at, "metadata": record.metadata } end let(:data_pipeline_client) { double(PlatformSdk::DataPipeline::Client) } before do allow(PlatformSdk::DataPipeline::Client).to receive(:new).and_return(data_pipeline_client) allow(data_pipeline_client).to receive(:post) Timecop.freeze(DateTime.parse('2024-06-09 04:20:00')) end after do Timecop.return end context 'create' do let(:action) { 'created' } it 'posts to the data pipeline' do record.save! expect(data_pipeline_client).to have_received(:post).with(pipeline_payload) end end context 'destroy' do let(:action) { 'destroyed' } let(:one_roster_common_data_deleted) do one_roster_common_data.merge( "status": 'tobedeleted' ) end let(:pipeline_payload_deleted) do pipeline_payload.merge("data": one_roster_common_data_deleted) end it 'posts to the data pipeline' do record.save! record.destroy expect(data_pipeline_client).to have_received(:post).with(pipeline_payload) expect(data_pipeline_client).to have_received(:post).with(pipeline_payload_deleted) end end context 'update' do let(:action) { 'modified' } before do record.save! end context 'after an update' do it 'posts a copy of our data to the data pipeline' do column = column_to_update(record) update_record(record, column) expect(data_pipeline_client).to have_received(:post).with(pipeline_payload) end end context 'after an update that does not change data' do let(:action) { 'modified' } it 'does not post to the data pipeline' do record.save! column = column_to_update(record) update_record(record, column) record.save! expect(data_pipeline_client).to have_received(:post).once.with(pipeline_payload) end end end def column_to_update(record) [:string, :integer, :boolean].each do |type| columns_to_update = record.class.columns.select { |c| c.sql_type_metadata.type == type && !c.name.match?(/_type$/) && c.name != 'id' } return columns_to_update.first.name if columns_to_update.any? end end def update_record(record, column) new_record = build(described_class.to_s.underscore.to_sym) column_value = record[column] column_class = column_value.class case column_class.to_s when 'Integer' record.update!(column => 69) when 'TrueClass', 'FalseClass' record.update!(column => !record[column]) else record.update!(column => new_record[column]) end end end end end