diff --git a/app/jobs/hearings/download_transcription_file_job.rb b/app/jobs/hearings/download_transcription_file_job.rb index 55449d634f8..8a64c6b144f 100644 --- a/app/jobs/hearings/download_transcription_file_job.rb +++ b/app/jobs/hearings/download_transcription_file_job.rb @@ -109,7 +109,7 @@ def hearing def parse_hearing identifiers = file_name.split(".").first hearing_id = identifiers.split("_")[1] - hearing_type = identifiers.split("_")[2] + hearing_type = identifiers.split("_").last.split("-").first hearing_type.constantize.find(hearing_id) rescue StandardError => error raise FileNameError, "Encountered error #{error} when attempting to parse hearing from file name '#{file_name}'" @@ -130,7 +130,7 @@ def docket_number # # Returns: TranscriptionFile object def find_or_create_transcription_file(file_name_arg = file_name) - Hearings::TranscriptionFile.find_or_create_by( + TranscriptionFile.find_or_create_by( file_name: file_name_arg, hearing_id: hearing.id, hearing_type: hearing.class.name, diff --git a/app/jobs/hearings/get_webex_recordings_details_job.rb b/app/jobs/hearings/get_webex_recordings_details_job.rb new file mode 100644 index 00000000000..d25b00d9707 --- /dev/null +++ b/app/jobs/hearings/get_webex_recordings_details_job.rb @@ -0,0 +1,68 @@ +# frozen_string_literal: true + +# This job will retrieve a list of webex hearing recording detail links +# and download the information from the links + +class Hearings::GetWebexRecordingsDetailsJob < CaseflowJob + include Hearings::EnsureCurrentUserIsSet + + queue_with_priority :low_priority + application_attr :hearing_schedule + attr_reader :id + + retry_on(Caseflow::Error::WebexApiError, wait: :exponentially_longer) do |job, exception| + # TO IMPLEMENT: SEND EMAIL TO VA OPS TEAM + job.log_error(exception) + end + + def perform(id:) + ensure_current_user_is_set + data = get_recording_details(id) + topic = data.topic + + mp4_link = data.mp4_link + send_file(topic, "mp4", mp4_link) + + vtt_link = data.vtt_link + send_file(topic, "vtt", vtt_link) + + mp3_link = data.mp3_link + send_file(topic, "mp3", mp3_link) + end + + def log_error(error) + Rails.logger.error("Retrying #{self.class.name} because failed with error: #{error}") + extra = { + application: self.class.name, + job_id: job_id + } + Raven.capture_exception(error, extra: extra) + end + + private + + def get_recording_details(id) + query = { "id": id } + + WebexService.new( + host: ENV["WEBEX_HOST_MAIN"], + port: ENV["WEBEX_PORT"], + aud: ENV["WEBEX_ORGANIZATION"], + apikey: ENV["WEBEX_BOTTOKEN"], + domain: ENV["WEBEX_DOMAIN_MAIN"], + api_endpoint: ENV["WEBEX_API_MAIN"], + query: query + ).get_recording_details + end + + def create_file_name(topic, extension) + subject = topic.split("-").second.lstrip + counter = topic.split("-").last + "#{subject}-#{counter}.#{extension}" + end + + def send_file(topic, extension, link) + file_name = create_file_name(topic, extension) + Hearings::DownloadTranscriptionFileJob.perform_later(download_link: link, file_name: file_name) + end +end diff --git a/app/jobs/hearings/get_webex_recordings_list_job.rb b/app/jobs/hearings/get_webex_recordings_list_job.rb index d10ac4a99a8..a13687be142 100644 --- a/app/jobs/hearings/get_webex_recordings_list_job.rb +++ b/app/jobs/hearings/get_webex_recordings_list_job.rb @@ -17,7 +17,7 @@ class Hearings::GetWebexRecordingsListJob < CaseflowJob def perform ensure_current_user_is_set get_recordings_list.ids.each do |n| - get_recording_details(n) + Hearings::GetWebexRecordingsDetailsJob.perform_later(id: n) end end @@ -47,8 +47,4 @@ def get_recordings_list query: query ).get_recordings_list end - - def get_recording_details(id) - nil - end end diff --git a/app/models/hearings/transcription_file.rb b/app/models/hearings/transcription_file.rb index 04381be2bac..989c3ebc297 100644 --- a/app/models/hearings/transcription_file.rb +++ b/app/models/hearings/transcription_file.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -class Hearings::TranscriptionFile < CaseflowRecord +class TranscriptionFile < CaseflowRecord include BelongsToPolymorphicHearingConcern belongs_to_polymorphic_hearing :hearing @@ -25,7 +25,7 @@ def convert_to_rtf! hearing_info = { judge: hearing.judge&.full_name, appeal_id: hearing.appeal&.veteran_file_number, - date: hearing.scheduled_time + date: hearing.scheduled_for } file_paths = TranscriptionTransformer.new(tmp_location, hearing_info).call update_status!(process: :conversion, status: :success) diff --git a/app/services/external_api/webex_service.rb b/app/services/external_api/webex_service.rb index 3b0e8aa01c6..7fe6406c860 100644 --- a/app/services/external_api/webex_service.rb +++ b/app/services/external_api/webex_service.rb @@ -64,6 +64,15 @@ def get_recordings_list ExternalApi::WebexService::RecordingsListResponse.new(resp) end + def get_recording_details + body = nil + method = "GET" + resp = send_webex_request(body, method) + return if resp.nil? + + ExternalApi::WebexService::RecordingDetailsResponse.new(resp) + end + private # :nocov: diff --git a/app/services/external_api/webex_service/recording_details_response.rb b/app/services/external_api/webex_service/recording_details_response.rb new file mode 100644 index 00000000000..08e8ef18e82 --- /dev/null +++ b/app/services/external_api/webex_service/recording_details_response.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +class ExternalApi::WebexService::RecordingDetailsResponse < ExternalApi::WebexService::Response + def data + JSON.parse(resp.raw_body) + end + + def mp4_link + data["temporaryDirectDownloadLinks"]["recordingDownloadLink"] + end + + def vtt_link + data["temporaryDirectDownloadLinks"]["transcriptionDownloadLink"] + end + + def mp3_link + data["temporaryDirectDownloadLinks"]["audioDownloadLink"] + end + + def topic + data["topic"] + end +end diff --git a/lib/fakes/webex_service.rb b/lib/fakes/webex_service.rb index 45c738da4cd..ea939122dd6 100644 --- a/lib/fakes/webex_service.rb +++ b/lib/fakes/webex_service.rb @@ -69,6 +69,22 @@ def get_recordings_list ) end + def get_recording_details + if error? + return ExternalApi::WebexService::RecordingDetailsResponse.new( + HTTPI::Response.new(@status_code, {}, error_response) + ) + end + + ExternalApi::WebexService::RecordingDetailsResponse.new( + HTTPI::Response.new( + 200, + {}, + fake_recording_details_data.to_json + ) + ) + end + # rubocop:disable Metrics/MethodLength def fake_recordings_list_data { @@ -78,7 +94,7 @@ def fake_recordings_list_data "meetingId": "f91b6edce9864428af084977b7c68291_I_166641849979635652", "scheduledMeetingId": "f91b6edce9864428af084977b7c68291_20200713T121500Z", "meetingSeriesId": "f91b6edce9864428af084977b7c68291", - "topic": "200103-61110_2000061110_Appeal", + "topic": "200103-61110_2000061110_Hearing", "createTime": "2020-07-13T17:11:35Z", "timeRecorded": "2020-07-13T17:05:35Z", "siteUrl": "site4-example.webex.com", @@ -90,10 +106,10 @@ def fake_recordings_list_data "durationSeconds": 18_416, "sizeBytes": 168_103, "shareToMe": false, - "integrationTags": [ - "dbaeceebea5c4a63ac9d5ef1edfe36b9", - "85e1d6319aa94c0583a6891280e3437d", - "27226d1311b947f3a68d6bdf8e4e19a1" + "integrationTags": %w[ + dbaeceebea5c4a63ac9d5ef1edfe36b9 + 85e1d6319aa94c0583a6891280e3437d + 27226d1311b947f3a68d6bdf8e4e19a1 ], "status": "available" }, @@ -102,7 +118,7 @@ def fake_recordings_list_data "meetingId": "f91b6edce9864428af084977b7c68291_I_166641849979635652", "scheduledMeetingId": "f91b6edce9864428af084977b7c68291_20200713T121500Z", "meetingSeriesId": "f91b6edce9864428af084977b7c68291", - "topic": "150000248290335_343_LegacyAppeal", + "topic": "150000248290336_302_LegacyHearing", "createTime": "2020-07-13T17:11:34Z", "timeRecorded": "2020-07-13T17:05:35Z", "siteUrl": "site4-example.webex.com", @@ -114,10 +130,10 @@ def fake_recordings_list_data "durationSeconds": 181_562, "sizeBytes": 199_134, "shareToMe": false, - "integrationTags": [ - "dbaeceebea5c4a63ac9d5ef1edfe36b9", - "85e1d6319aa94c0583a6891280e3437d", - "27226d1311b947f3a68d6bdf8e4e19a1" + "integrationTags": %w[ + dbaeceebea5c4a63ac9d5ef1edfe36b9 + 85e1d6319aa94c0583a6891280e3437d + 27226d1311b947f3a68d6bdf8e4e19a1 ], "status": "available" }, @@ -126,7 +142,7 @@ def fake_recordings_list_data "meetingId": "f91b6edce9864428af084977b7c68291_I_166641849979635652", "scheduledMeetingId": "f91b6edce9864428af084977b7c68291_20200713T121500Z", "meetingSeriesId": "f91b6edce9864428af084977b7c68291", - "topic": "231207-1177_1177_Appeal", + "topic": "231207-1177_1177_Hearing", "createTime": "2020-07-13T17:11:33Z", "timeRecorded": "2020-07-13T17:05:35Z", "siteUrl": "site4-example.webex.com", @@ -138,16 +154,49 @@ def fake_recordings_list_data "durationSeconds": 181_562, "sizeBytes": 199_134, "shareToMe": true, - "integrationTags": [ - "dbaeceebea5c4a63ac9d5ef1edfe36b9", - "85e1d6319aa94c0583a6891280e3437d", - "27226d1311b947f3a68d6bdf8e4e19a1" + "integrationTags": %w[ + dbaeceebea5c4a63ac9d5ef1edfe36b9 + 85e1d6319aa94c0583a6891280e3437d + 27226d1311b947f3a68d6bdf8e4e19a1 ], "status": "available" } ] } end + + def fake_recording_details_data + { + "id": "4f914b1dfe3c4d11a61730f18c0f5387", + "meetingId": "f91b6edce9864428af084977b7c68291_I_166641849979635652", + "scheduledMeetingId": "f91b6edce9864428af084977b7c68291_20200713T121500Z", + "meetingSeriesId": "f91b6edce9864428af084977b7c68291", + "topic": "Virtual Visit - 180000304_1_LegacyHearing-20240213 1712-1", + "createTime": "2020-07-13T17:11:35Z", + "timeRecorded": "2020-07-13T17:05:35Z", + "siteUrl": "site4-example.webex.com", + "downloadUrl": "https://site4-example.webex.com/site4/lsr.php?RCID=b91990e37417bda24986e46cf43345ab", + "playbackUrl": "https://site4-example.webex.com/site4/ldr.php?RCID=69201a61d1d94a84aca18817261d1a73", + "password": "BgJep@43", + "temporaryDirectDownloadLinks": { + "recordingDownloadLink": "https://www.learningcontainer.com/mp4-sample-video-files-download/#", + "audioDownloadLink": "https://freetestdata.com/audio-files/mp3/", + "transcriptionDownloadLink": "https://www.capsubservices.com/assets/downloads/web/WebVTT.vtt", + "expiration": "2022-05-01T10:30:25Z" + }, + "format": "ARF", + "serviceType": "MeetingCenter", + "durationSeconds": 18_416, + "sizeBytes": 168_103, + "shareToMe": false, + "integrationTags": %w[ + dbaeceebea5c4a63ac9d5ef1edfe36b9 + 85e1d6319aa94c0583a6891280e3437d + 27226d1311b947f3a68d6bdf8e4e19a1 + ], + "status": "available" + } + end # rubocop:enable Metrics/MethodLength private diff --git a/spec/jobs/hearings/download_transcription_file_job_spec.rb b/spec/jobs/hearings/download_transcription_file_job_spec.rb index e55fe41161e..51f3f8d2349 100644 --- a/spec/jobs/hearings/download_transcription_file_job_spec.rb +++ b/spec/jobs/hearings/download_transcription_file_job_spec.rb @@ -9,7 +9,7 @@ let(:docket_number) { hearing.docket_number } let(:file_name) { "#{docket_number}_#{hearing.id}_#{hearing.class}.#{file_type}" } let(:tmp_location) { File.join(Rails.root, "tmp", "transcription_files", file_type, file_name) } - let(:transcription_file) { Hearings::TranscriptionFile.find_by(file_name: file_name) } + let(:transcription_file) { TranscriptionFile.find_by(file_name: file_name) } let(:s3_sub_bucket) { "vaec-appeals-caseflow" } let(:folder_name) { (Rails.deploy_env == :prod) ? s3_sub_bucket : "#{s3_sub_bucket}-#{Rails.deploy_env}" } let(:s3_sub_folders) do @@ -30,7 +30,7 @@ shared_examples "all file types" do it "saves downloaded file to correct tmp sub-directory" do - allow_any_instance_of(Hearings::TranscriptionFile).to receive(:clean_up_tmp_location).and_return(nil) + allow_any_instance_of(TranscriptionFile).to receive(:clean_up_tmp_location).and_return(nil) subject expect(File.exist?(tmp_location)).to be true end @@ -54,7 +54,7 @@ shared_examples "failed download from Webex" do it "raises error and creates TranscriptionFileRecord" do expect { subject }.to raise_error(Hearings::DownloadTranscriptionFileJob::FileDownloadError) - .and change(Hearings::TranscriptionFile, :count).by(1) + .and change(TranscriptionFile, :count).by(1) end it "updates file_status of TranscriptionFile record, leaves date_receipt_webex nil" do @@ -77,7 +77,7 @@ context "successful download from Webex and upload to S3" do it "creates new TranscriptionFile record" do - expect { subject }.to change(Hearings::TranscriptionFile, :count).by(1) + expect { subject }.to change(TranscriptionFile, :count).by(1) expect(transcription_file.file_type).to eq(file_type) end @@ -100,7 +100,7 @@ shared_context "convertible file" do let(:converted_file_name) { file_name.gsub(file_type, conversion_type) } let(:converted_tmp_location) { tmp_location.gsub(file_type, conversion_type) } - let(:converted_transcription_file) { Hearings::TranscriptionFile.find_by(file_name: converted_file_name) } + let(:converted_transcription_file) { TranscriptionFile.find_by(file_name: converted_file_name) } let(:converted_s3_location) { "#{folder_name}/#{s3_sub_folders[conversion_type.to_sym]}/#{converted_file_name}" } it "updates date_receipt_webex of TranscriptionFile record" do @@ -133,7 +133,7 @@ after { File.delete(converted_tmp_location) if File.exist?(converted_tmp_location) } it "creates two new TranscriptionFile records" do - expect { subject }.to change(Hearings::TranscriptionFile, :count).by(2) + expect { subject }.to change(TranscriptionFile, :count).by(2) expect(transcription_file.file_type).to eq(file_type) expect(converted_transcription_file.file_type).to eq(conversion_type) end @@ -171,7 +171,7 @@ include_context "convertible file" it "creates three new TranscriptionFile records" do - expect { subject }.to change(Hearings::TranscriptionFile, :count).by(3) + expect { subject }.to change(TranscriptionFile, :count).by(3) expect(transcription_file.file_type).to eq(file_type) expect(converted_transcription_file.file_type).to eq(conversion_type) end @@ -197,12 +197,12 @@ it "raises error and creates TranscriptionFileRecord" do expect { subject }.to raise_error(TranscriptionTransformer::FileConversionError) - .and change(Hearings::TranscriptionFile, :count).by(1) + .and change(TranscriptionFile, :count).by(1) expect(transcription_file.file_type).to eq(file_type) end it "saves downloaded file to correct tmp sub-directory" do - allow_any_instance_of(Hearings::TranscriptionFile).to receive(:clean_up_tmp_location).and_return(nil) + allow_any_instance_of(TranscriptionFile).to receive(:clean_up_tmp_location).and_return(nil) expect { subject }.to raise_error(TranscriptionTransformer::FileConversionError) expect(File.exist?(tmp_location)).to be true end diff --git a/spec/jobs/hearings/get_webex_recordings_details_job_spec.rb b/spec/jobs/hearings/get_webex_recordings_details_job_spec.rb new file mode 100644 index 00000000000..9f4cfe50fd4 --- /dev/null +++ b/spec/jobs/hearings/get_webex_recordings_details_job_spec.rb @@ -0,0 +1,63 @@ +# frozen_string_literal: true + +describe Hearings::GetWebexRecordingsDetailsJob, type: :job do + include ActiveJob::TestHelper + let(:id) { "4f914b1dfe3c4d11a61730f18c0f5387" } + let(:mp4_link) { "https://www.learningcontainer.com/mp4-sample-video-files-download/#" } + let(:mp3_link) { "https://freetestdata.com/audio-files/mp3/" } + let(:vtt_link) { "https://www.capsubservices.com/assets/downloads/web/WebVTT.vtt" } + let(:topic) { "Virtual Visit - 180000304_1_LegacyHearing-20240213 1712-1" } + let(:mp4_file_name) { "180000304_1_LegacyHearing-1.mp4" } + let(:vtt_file_name) { "180000304_1_LegacyHearing-1.vtt" } + let(:mp3_file_name) { "180000304_1_LegacyHearing-1.mp3" } + + subject { described_class.perform_now(id: id) } + + context "method testing" do + before do + allow_any_instance_of(Hearings::DownloadTranscriptionFileJob) + .to receive(:perform) + .and_return(nil) + end + + it "hits the webex API and returns recording details" do + get_details = Hearings::GetWebexRecordingsDetailsJob.new + run = get_details.send(:get_recording_details, id) + + expect(run.mp4_link).to eq(mp4_link) + expect(run.mp3_link).to eq(mp3_link) + expect(run.vtt_link).to eq(vtt_link) + expect(run.topic).to eq(topic) + end + + it "names the files correctly" do + get_details = Hearings::GetWebexRecordingsDetailsJob.new + run_mp4 = get_details.send(:create_file_name, topic, "mp4") + run_vtt = get_details.send(:create_file_name, topic, "vtt") + run_mp3 = get_details.send(:create_file_name, topic, "mp3") + + expect(run_mp4).to eq(mp4_file_name) + expect(run_vtt).to eq(vtt_file_name) + expect(run_mp3).to eq(mp3_file_name) + end + end + + context "job errors" do + before do + allow_any_instance_of(WebexService) + .to receive(:get_recording_details) + .and_raise(Caseflow::Error::WebexApiError.new(code: 400, message: "Fake Error")) + end + + it "Successfully catches errors and adds to retry queue" do + subject + expect(enqueued_jobs.size).to eq(1) + end + + it "retries and logs errors" do + subject + expect(Rails.logger).to receive(:error).with(/Retrying/) + perform_enqueued_jobs { described_class.perform_later(id: id) } + end + end +end diff --git a/spec/jobs/hearings/get_webex_recordings_list_job_spec.rb b/spec/jobs/hearings/get_webex_recordings_list_job_spec.rb index 720b1662e72..59a990ac4c5 100644 --- a/spec/jobs/hearings/get_webex_recordings_list_job_spec.rb +++ b/spec/jobs/hearings/get_webex_recordings_list_job_spec.rb @@ -6,6 +6,9 @@ subject { described_class.perform_now } it "Returns the correct array of ids" do + allow_any_instance_of(Hearings::DownloadTranscriptionFileJob) + .to receive(:perform) + .and_return(nil) expect(subject).to eq(%w[4f914b1dfe3c4d11a61730f18c0f5387 3324fb76946249cfa07fc30b3ccbf580 42b80117a2a74dcf9863bf06264f8075]) end diff --git a/spec/services/external_api/webex_service_spec.rb b/spec/services/external_api/webex_service_spec.rb index 5b8f7329a2a..9ff5c4c169c 100644 --- a/spec/services/external_api/webex_service_spec.rb +++ b/spec/services/external_api/webex_service_spec.rb @@ -140,58 +140,113 @@ end describe "get recordings list" do - describe "get recording request" do - let(:query) do - from = CGI.escape(2.days.ago.in_time_zone("America/New_York").end_of_day.iso8601) - to = CGI.escape(1.day.ago.in_time_zone("America/New_York").end_of_day.iso8601) - { "from": from, "to": to } - end + let(:query) do + from = CGI.escape(2.days.ago.in_time_zone("America/New_York").end_of_day.iso8601) + to = CGI.escape(1.day.ago.in_time_zone("America/New_York").end_of_day.iso8601) + { "from": from, "to": to } + end - let(:success_recordings_resp) do - HTTPI::Response.new(200, {}, {}) - end + let(:success_recordings_resp) do + HTTPI::Response.new(200, {}, {}) + end - let(:error_recordings_resp) do - HTTPI::Response.new(400, {}, {}) - end + let(:error_recordings_resp) do + HTTPI::Response.new(400, {}, {}) + end - let(:body) { nil } + let(:body) { nil } - let(:method) { "GET" } + let(:method) { "GET" } - subject { webex_service.get_recordings_list } + subject { webex_service.get_recordings_list } - it "it calls send webex request with nil body and GET method" do - expect(webex_service).to receive(:send_webex_request).with(body, method) - subject - end + it "it calls send webex request with nil body and GET method" do + expect(webex_service).to receive(:send_webex_request).with(body, method) + subject + end + + it "returns a successful instance of RecordingsListResponse class" do + allow(webex_service).to receive(:send_webex_request).with(body, method).and_return(success_create_resp) - it "returns a successful instance of RecordingsListResponse class" do - allow(webex_service).to receive(:send_webex_request).with(body, method).and_return(success_create_resp) + expect(subject).to be_instance_of(ExternalApi::WebexService::RecordingsListResponse) + expect(subject.code).to eq(200) + expect(subject.success?).to eq(true) + end - expect(subject).to be_instance_of(ExternalApi::WebexService::RecordingsListResponse) + it "returns recordings error response" do + allow(webex_service).to receive(:send_webex_request).with(body, method).and_return(error_create_resp) + + expect(subject.code).to eq(400) + expect(subject.success?).to eq(false) + expect(subject.error).to eq(Caseflow::Error::WebexBadRequestError.new(code: 400)) + end + + describe "with fakes" do + let(:webex_service) do + Fakes::WebexService.new + end + + it "gets a list of ids" do expect(subject.code).to eq(200) - expect(subject.success?).to eq(true) + expect(subject.ids).to eq(%w[4f914b1dfe3c4d11a61730f18c0f5387 3324fb76946249cfa07fc30b3ccbf580 42b80117a2a74dcf9863bf06264f8075]) + subject end + end + end - it "returns recordings error response" do - allow(webex_service).to receive(:send_webex_request).with(body, method).and_return(error_create_resp) + describe "get recording details" do + let(:query) do + id = "4f914b1dfe3c4d11a61730f18c0f5387" + { "id": id } + end - expect(subject.code).to eq(400) - expect(subject.success?).to eq(false) - expect(subject.error).to eq(Caseflow::Error::WebexBadRequestError.new(code: 400)) - end + let(:success_details_resp) do + HTTPI::Response.new(200, {}, {}) + end + + let(:error_details_resp) do + HTTPI::Response.new(400, {}, {}) + end + + let(:body) { nil } + + let(:method) { "GET" } + + subject { webex_service.get_recording_details } - describe "with fakes" do - let(:webex_service) do - Fakes::WebexService.new - end + it "it calls send webex request with nil body and GET method" do + expect(webex_service).to receive(:send_webex_request).with(body, method) + subject + end + + it "returns a successful instance of RecordingDetailsResponse class" do + allow(webex_service).to receive(:send_webex_request).with(body, method).and_return(success_create_resp) - it "gets a list of ids" do - expect(subject.code).to eq(200) - expect(subject.ids).to eq(%w[4f914b1dfe3c4d11a61730f18c0f5387 3324fb76946249cfa07fc30b3ccbf580 42b80117a2a74dcf9863bf06264f8075]) - subject - end + expect(subject).to be_instance_of(ExternalApi::WebexService::RecordingDetailsResponse) + expect(subject.code).to eq(200) + expect(subject.success?).to eq(true) + end + + it "returns recording details error response" do + allow(webex_service).to receive(:send_webex_request).with(body, method).and_return(error_create_resp) + + expect(subject.code).to eq(400) + expect(subject.success?).to eq(false) + expect(subject.error).to eq(Caseflow::Error::WebexBadRequestError.new(code: 400)) + end + + describe "with fakes" do + let(:webex_service) do + Fakes::WebexService.new + end + + it "gets a list of ids" do + expect(subject.code).to eq(200) + expect(subject.mp4_link).to eq("https://www.learningcontainer.com/mp4-sample-video-files-download/#") + expect(subject.vtt_link).to eq("https://www.capsubservices.com/assets/downloads/web/WebVTT.vtt") + expect(subject.mp3_link).to eq("https://freetestdata.com/audio-files/mp3/") + expect(subject.topic).to eq("Virtual Visit - 180000304_1_LegacyHearing-20240213 1712-1") + subject end end end