require "rails_helper" feature "User performs video analysis" do let(:current_user) { create(:user, :admin) } # Only admin users can see the VideoAnalysis button now let(:project) { create(:project, account: current_user.primary_account) } let(:video) { create(:video, :with_graphics_only_edl_file, project: project, analysis_status: :pending) } let(:edl_event) do BrayniacAI::EdlParseResult.new({ "channel" => "V", "start_time" => 0, "timecode_in" => "01:00:00:00", "timecode_out" => "01:00:02:00", "duration" => "00:00:02", "source_file_name" => "source_file_name", "clip_name" => "clip_name", "description" => "description", "matches" => [], }) end before :each do VideoAnalysis.use_overlay_video = false allow(BrayniacAI::EdlParse).to receive(:create).and_return( BrayniacAI::EdlParse.new({ results: [edl_event], edl_timecode_start: "00:00:10:00" }) ) end scenario "does not see Back to Projects" do sign_in current_user visit video_video_analyses_path(video) expect(page).not_to have_content("Back to Project") end scenario "sees video name with project name" do sign_in current_user visit video_video_analyses_path(video) expect(page).to have_content("#{video.name} (#{project.name})") end scenario "sees EDLs dropdown's downlod options" do sign_in current_user visit video_video_analyses_path(video) expect(page).to have_css("a.dropdown-item", text: "Download EDL") expect(page).to have_css("a.dropdown-item", text: "Download Graphics Only EDL") expect(page).to have_css("a.dropdown-item", text: "Download Audio Only EDL") end scenario "sees download report button" do sign_in current_user visit video_video_analyses_path(video) click_on "Reports" expect(page).to have_link("Production Elements Log") expect(page).to have_link("GFX Cue List") expect(page).to have_link("Music Cue Sheet", href: video_audio_reports_path(video, { format: "xlsx", type: "discovery" })) expect(page).to have_link("BiG Music Cue Sheet", href: video_audio_reports_path(video, { format: "xlsx", type: "big" })) expect(page).to have_link("Issues and Concerns Report") end scenario "adding a bookmark", js: true do sign_in current_user visit video_video_analyses_path(video) create_bookmark(video, notes: "Test notes") expect(page).to have_bookmark(notes: "Test notes") end scenario "searching for releases", js: true do robert, chris = [ create(:appearance_release, project: project, person_first_name: "Robert", person_last_name: "Downey Jr."), create(:appearance_release, project: project, person_first_name: "Chris", person_last_name: "Evans") ] cheers, cipriani = [ create(:location_release_with_photo, project: project, name: "Cheers"), create(:location_release_with_photo, project: project, name: "Cipriani") ] mac, pc = [ create(:material_release, name: "Apple MacBook Air", project: project), create(:material_release, name: "Microsoft Surface Pro", project: project) ] acquired_media = create(:acquired_media_release, project: project) acquired_file_info_1, acquired_file_info_2 = [ create(:file_info, filename: "Still Image", releasable: acquired_media), create(:file_info, filename: "Artwork", releasable: acquired_media) ] music_release = create(:music_release, project: project) music_file_info_1, music_file_info_2 = [ create(:file_info, filename: "I'm not afraid", releasable: music_release), create(:file_info, filename: "Lose yourself", releasable: music_release) ] sign_in current_user visit video_video_analyses_path(video) within "#appearance_releases_section" do search_for(:appearance_release, text: "Robert") expect(page).to have_content("Robert") expect(page).not_to have_content("Chris") end within "#location_releases_section" do search_for(:location_release, text: "Cheers") expect(page).to have_content("Cheers") expect(page).not_to have_content("Cipriani") end within "#material_releases_section" do search_for(:material_release, text: "Apple") expect(page).to have_content("Apple") expect(page).not_to have_content("Microsoft") end within "#acquired_media_releases_section" do search_for(:acquired_media_releases, text: "till") expect(page).to have_content("Still Image") expect(page).not_to have_content("Artwork") end within "#music_releases_section" do search_for(:music_releases, text: "not") expect(page).to have_content("I'm not afraid") expect(page).not_to have_content("Lose yourself") end end scenario "viewing EDL information", js: true do video_event = BrayniacAI::EdlParseResult.new({ "channel" => "V", "start_time" => 0, "timecode_in" => "01:00:00:00", "timecode_out" => "01:00:02:00", "duration" => "00:00:02", "source_file_name" => "source_file_name", "clip_name" => "clip_name", "description" => "description", "matches" => [], }) audio_event = BrayniacAI::EdlParseResult.new({ "channel" => "A1", "start_time" => 0, "timecode_in" => "01:00:00:00", "timecode_out" => "01:00:02:00", "duration" => "00:00:02", "source_file_name" => "source_file_name.wav", "clip_name" => "clip_name", "description" => "description", "matches" => [], }) allow(BrayniacAI::EdlParse).to receive(:create).and_return( BrayniacAI::EdlParse.new({ results: [video_event, audio_event], edl_timecode_start: "00:00:00:00" }) ) sign_in current_user visit video_video_analyses_path(video) click_button "EDL Info" expect(page).to have_edl_event_modal within "#edl_events" do expect(page).to have_content("V") expect(page).to have_content("01:00:00:00") expect(page).to have_content("01:00:02:00") expect(page).to have_content("00:00:02") expect(page).to have_content("source_file_name") expect(page).to have_content("clip_name") expect(page).to have_content("description") expect(page).to have_content("A1") expect(page).to have_content("source_file_name.wav") end end scenario "seeking to a particular timecode", js: true do sign_in current_user visit video_video_analyses_path(video) find("#player .container").click find("#player .container").click fill_in "seek", with: "00:00:03:00" click_button "Seek" expect(page).to have_field("seek", with: "00:00:03:00") expect(page).to have_css(".media-control-indicator", text: "00:03", visible: :all) by "putting in a bad timecode" do fill_in "seek", with: "00:00:03" click_button "Seek" expect(page).to have_field("seek", with: "") expect(page).to have_css(".media-control-indicator", text: "00:03", visible: :all) end end scenario "views EDL events", js: true do video_event = BrayniacAI::EdlParseResult.new({ "channel" => "V", "start_time" => 0, "timecode_in" => "01:00:00:00", "timecode_out" => "01:00:02:00", "duration" => "00:00:02", "source_file_name" => "source_file_name", "clip_name" => "clip_name", "description" => "description", "matches" => [], }) audio_event = BrayniacAI::EdlParseResult.new({ "channel" => "A1", "start_time" => 0, "timecode_in" => "01:00:01:00", "timecode_out" => "01:00:02:00", "duration" => "00:00:02", "source_file_name" => "source_file_name.wav", "clip_name" => "clip_name", "description" => "description", "matches" => [], }) last_audio_event = BrayniacAI::EdlParseResult.new({ "channel" => "A1", "start_time" => 0, "timecode_in" => "01:00:05:00", "timecode_out" => "01:00:07:00", "duration" => "00:00:02", "source_file_name" => "source_file_name.wav", "clip_name" => "clip_name", "description" => "description", "matches" => [], }) edl_events = [video_event] 20.times { |_| edl_events << audio_event } edl_events.append last_audio_event allow(BrayniacAI::EdlParse).to receive(:create).and_return( BrayniacAI::EdlParse.new({ results: edl_events, edl_timecode_start: "00:00:00:00" }) ) resize_window_to(1_000, 1_000) do sign_in current_user visit video_video_analyses_path(video) within "#edl_events_list" do expect(page).to have_content "Channel" expect(page).to have_content "Source" expect(page).to have_content "Clip" expect(page).to have_content "TC In" expect(page).to have_content "TC Out" expect(page).to have_content "V" expect(page).to have_content "source_file_name" expect(page).to have_content "clip_name" expect(page).to have_content "01:00:00:00" expect(page).to have_content "01:00:02:00" expect(page).to have_content "A1" expect(page).to have_content "source_file_name.wav" end by "jumping to a specific EDL event using timecode in" do expect(find("[data-timecode-in='01:00:00:00']")).not_to be_obscured fill_in "go_to", with: "01:00:05:00" click_on "Go" expect(find("[data-timecode-in='01:00:00:00']")).to be_obscured end and_by "putting in a bad timecode" do fill_in "go_to", with: "bob" click_on "Go" expect(page).to have_field("go_to", with: "") end end end context "for Video tab" do scenario "video analysis is not complete", js: true do appearance_release = create(:appearance_release, project: project) bookmark = create(:bookmark, video: video, notes: "Test notes") unreleased_appearance = create(:unreleased_appearance, video: video, notes: "Test notes") sign_in current_user visit video_video_analyses_path(video) expect(page).to have_content("Video is still being analyzed") expect(page).to have_bookmark(notes: bookmark.notes) expect(page).to have_unreleased_appearance(notes: unreleased_appearance.notes) end scenario "confirming a talent release" do talent_release = create(:talent_release, project: project) sign_in current_user visit video_video_analyses_path(video) expect(page).to have_unconfirmed_release(talent_release) confirm_release(video, talent_release) expect(page).to have_confirmed_release(talent_release) expect(page).not_to have_unconfirmed_release(talent_release) unconfirm_release(VideoReleaseConfirmation.last) expect(page).not_to have_confirmed_release(talent_release) expect(page).to have_unconfirmed_release(talent_release) end scenario "confirming an appearance release", js: true do appearance_release = create(:appearance_release, project: project) sign_in current_user visit video_video_analyses_path(video) expect(page).to have_unconfirmed_release(appearance_release) confirm_first_release_using_edl_modal(video, appearance_release) expect(page).to have_confirmed_release(appearance_release) expect(page).not_to have_unconfirmed_release(appearance_release) unconfirm_release(VideoReleaseConfirmation.last) expect(page).not_to have_confirmed_release(appearance_release) expect(page).to have_unconfirmed_release(appearance_release) end scenario "confirming a location release", js: true do location_release = create(:location_release_with_photo, project: project) sign_in current_user visit video_video_analyses_path(video) expect(page).to have_unconfirmed_release(location_release) confirm_first_release_using_edl_modal(video, location_release) expect(page).to have_confirmed_release(location_release) expect(page).not_to have_unconfirmed_release(location_release) unconfirm_release(VideoReleaseConfirmation.last) expect(page).not_to have_confirmed_release(location_release) expect(page).to have_unconfirmed_release(location_release) end scenario "confirming an acquired media release", js: true do acquired_media_release = create(:acquired_media_release_with_file_infos, project: project) acquired_media_release.file_infos.first.update(filename: "shark jumping") acquired_media_release.file_infos.second.update(filename: "pig flying") acquired_media_release.file_infos.third.update(filename: "panda sneezing") sign_in current_user visit video_video_analyses_path(video) expect(page).to have_unconfirmed_file_info_release(acquired_media_release, "shark jumping", count: 1) expect(page).to have_unconfirmed_file_info_release(acquired_media_release, "pig flying", count: 1) expect(page).to have_unconfirmed_file_info_release(acquired_media_release, "panda sneezing", count: 1) confirm_first_release_using_edl_modal(video, acquired_media_release, text: "shark jumping") expect(page).to have_confirmed_release(acquired_media_release, text: "shark jumping") expect(page).to have_unconfirmed_file_info_release(acquired_media_release, "pig flying", count: 1) expect(page).to have_unconfirmed_file_info_release(acquired_media_release, "panda sneezing", count: 1) unconfirm_release(VideoReleaseConfirmation.last) expect(page).not_to have_confirmed_release(acquired_media_release, text: "shark jumping") expect(page).to have_unconfirmed_file_info_release(acquired_media_release, "shark jumping", count: 1) expect(page).to have_unconfirmed_file_info_release(acquired_media_release, "pig flying", count: 1) expect(page).to have_unconfirmed_file_info_release(acquired_media_release, "panda sneezing", count: 1) end scenario "confirming a material release", js: true do material_release = create(:material_release, project: project) sign_in current_user visit video_video_analyses_path(video) expect(page).to have_unconfirmed_release(material_release) confirm_first_release_using_edl_modal(video, material_release) expect(page).to have_confirmed_release(material_release) expect(page).not_to have_unconfirmed_release(material_release) unconfirm_release(VideoReleaseConfirmation.last) expect(page).not_to have_confirmed_release(material_release) expect(page).to have_unconfirmed_release(material_release) end scenario "confirming an appearance release match", js: true do video.analysis_success! appearance_release = create(:appearance_release, project: project) allow(BrayniacAI::FacialRecognition).to receive(:find).and_return( BrayniacAI::FacialRecognition.new({ bucket_name: "", overlay_video_url: nil, first_appearances: [ BrayniacAI::FacialRecognitionResult.new({ "start_time": 0, "end_time": 100, "external_image_id": "appearance_release_#{appearance_release.id}", }) ], }) ) sign_in current_user visit video_video_analyses_path(video) find("#player .container").click find("#player .container").click expect(page).to have_suggested_match(appearance_release, text: "Jane Doe") within "#suggested_matches" do expect(page).not_to have_css(".fa-check-circle") end confirm_suggested_match(video, appearance_release) within "#suggested_matches" do expect(page).to have_css(".fa-check-circle") end expect(page).to have_confirmed_release(appearance_release, text: "") unconfirm_release(VideoReleaseConfirmation.last) within "#suggested_matches" do expect(page).not_to have_css(".fa-check-circle") end end scenario "confirming a talent release match", js: true do video.analysis_success! talent_release = create(:talent_release, project: project) allow(BrayniacAI::FacialRecognition).to receive(:find).and_return( BrayniacAI::FacialRecognition.new({ bucket_name: "", overlay_video_url: nil, first_appearances: [ BrayniacAI::FacialRecognitionResult.new({ "start_time": 0, "end_time": 100, "external_image_id": "talent_release_#{talent_release.id}", }) ], }) ) sign_in current_user visit video_video_analyses_path(video) find("#player .container").click find("#player .container").click expect(page).to have_suggested_match(talent_release, text: "Jane Doe") within "#suggested_matches" do expect(page).not_to have_css(".fa-check-circle") end confirm_suggested_talent_match(video, talent_release) within "#suggested_matches" do expect(page).to have_css(".fa-check-circle") end expect(page).to have_confirmed_release(talent_release, text: "") unconfirm_release(VideoReleaseConfirmation.last) within "#suggested_matches" do expect(page).not_to have_css(".fa-check-circle") end end scenario "copying data from multiple EDL events ", js: true do edl_events = [ BrayniacAI::EdlParseResult.new({ "channel" => "V", "start_time" => 0, "timecode_in" => "01:00:00:00", "timecode_out" => "01:00:02:00", "duration" => "00:00:02", "source_file_name" => "source_file_name1", "clip_name" => "clip_name", "description" => "description", "matches" => [], }), BrayniacAI::EdlParseResult.new({ "channel" => "V", "start_time" => 15, "timecode_in" => "01:00:15:00", "timecode_out" => "01:00:18:00", "duration" => "00:00:02", "source_file_name" => "source_file_name2", "clip_name" => "clip_name", "description" => "description", "matches" => [], }) ] allow(BrayniacAI::EdlParse).to receive(:create).and_return( BrayniacAI::EdlParse.new({ results: edl_events, edl_timecode_start: "00:00:00:00" }) ) release = create(:appearance_release, project: project) sign_in current_user visit video_video_analyses_path(video) new_path = polymorphic_path([:new, video, release, :video_release_confirmation]) first("form[action='#{new_path}']").click_button expect(page).to have_content "Timecode In" expect(page).to have_content "Source File Name" click_on "Show/Hide EDL Events" within "#edl_events" do expect(page).to have_content("V") expect(page).to have_content("source_file_name2") end click_on_edl_event(2) expect(page).to have_field("video_release_confirmation[timecode_in]", with: "01:00:15:00") expect(page).to have_field("video_release_confirmation[source_file_name]", with: "source_file_name2") end scenario "filters out non-video EDL events", js: true do edl_events = [ BrayniacAI::EdlParseResult.new({ "channel" => "V", "start_time" => 0, "timecode_in" => "01:00:00:00", "timecode_out" => "01:00:02:00", "duration" => "00:00:02", "source_file_name" => "source_file_name", "clip_name" => "clip_name", "description" => "description", "matches" => [], }), BrayniacAI::EdlParseResult.new({ "channel" => "A1", "start_time" => 0, "timecode_in" => "01:00:00:00", "timecode_out" => "01:00:02:00", "duration" => "00:00:02", "source_file_name" => "source_file_name.wav", "clip_name" => "clip_name", "description" => "description", "matches" => [], }), ] allow(BrayniacAI::EdlParse).to receive(:create).and_return( BrayniacAI::EdlParse.new({ results: edl_events, edl_timecode_start: "00:00:00:00" }) ) release = create(:appearance_release, project: project) sign_in current_user visit video_video_analyses_path(video) new_path = polymorphic_path([:new, video, release, :video_release_confirmation]) first("form[action='#{new_path}']").click_button expect(page).to have_content "Timecode In" expect(page).to have_content "Source File Name" click_on "Show/Hide EDL Events" within "#edl_events" do expect(page).not_to have_content("A1") expect(page).to have_content("V") expect(page).to have_content("source_file_name") end end end context "for Graphics tab" do scenario "confirming graphics element match", js: true do video.analysis_success! allow(BrayniacAI::FacialRecognition).to receive(:find).and_return( BrayniacAI::FacialRecognition.new({ bucket_name: "", overlay_video_url: nil, first_appearances: [], }) ) allow(BrayniacAI::EdlParse).to receive(:create).and_return( BrayniacAI::EdlParse.new({ results: [ BrayniacAI::EdlParseResult.new({ "channel" => "V", "start_time" => 0, "timecode_in" => "01:00:00:00", "timecode_out" => "01:00:02:00", "duration" => "00:00:02", "source_file_name" => "source_file_name", "clip_name" => "clip_name", "description" => "description", "matches" => [], }), ], edl_timecode_start: "00:00:00:00", }) ) sign_in current_user visit video_video_analyses_path(video) click_link "Graphics" expect(page).not_to have_graphics_element_match(text: "source_file_name") by "verifying a graphics element displays after video starts" do find("#player .container").click find("#player .container").click expect(page).to have_graphics_element_match(text: "source_file_name") end and_by "adding a graphics match to the report" do confirm_graphics_element_match expect(page.find("#matched_file_name").value).to eq "source_file_name" expect(page).to have_field("Source EDL", with: "Graphics") create_graphics_element(video, text: "MTV") expect(page).to have_graphics_element(text: "01:00:00:00") expect(page).to have_confirmed_graphics_match(text: "source_file_name") end and_by "verifying checkmark gets removed if graphics removed from report" do delete_graphics_element(GraphicsElement.last) expect(page).not_to have_confirmed_graphics_match(text: "source_file_name") expect(page).not_to have_graphics_element(text: "01:00:00:00") end end scenario "managing a graphics element", js: true do sign_in current_user visit video_video_analyses_path(video) click_link "Graphics" open_graphics_element_modal(video) click_on "Show/Hide EDL Events" within '#edl_events' do expect(page).to have_content "V" expect(page).to have_content "00:00:00" expect(page).to have_content "00:00:02" expect(page).to have_content "00:00:02" expect(page).to have_content "source_file_name" expect(page).to have_content "clip_name" expect(page).to have_content "description" end expect(page).to have_field("Source EDL", with: "All Tracks") expect(page).to have_field("Timecode in", with: "01:00:00:00") expect(page).to have_field("Timecode out", with: "01:00:02:00") expect(page).to have_field("Duration", with: "00:00:02") expect(page).to have_field("Source file name", with: "source_file_name") expect(page).to have_field("Clip name", with: "clip_name") expect(page).to have_field("Description", with: "description") create_graphics_element(video, text: "MTV") expect(page).to have_graphics_element(text: "01:00:00:00") open_edit_graphics_modal expect(page).to have_field("Source EDL", with: "All Tracks") edit_graphics_element(text: "Nickelodeon") expect(page).to have_graphics_element(text: "01:00:00:00") end scenario "has new layout" do sign_in current_user visit video_video_analyses_path(video) click_link "Graphics" expect(page).to have_content("EDL #") expect(page).to have_content("EDL TC") expect(page).to have_content("VID TC") expect(page).to have_content("Filename") end scenario "adding a graphics element requires text", js: true do sign_in current_user visit video_video_analyses_path(video) open_graphics_element_modal(video) create_graphics_element(video, text: "") expect(page).to have_graphics_element_modal end scenario "copying data from multiple EDL events ", js: true do edl_events = [ BrayniacAI::EdlParseResult.new({ "channel" => "V", "start_time" => 0, "timecode_in" => "01:00:00:00", "timecode_out" => "01:00:02:00", "duration" => "00:00:02", "source_file_name" => "source_file_name1", "clip_name" => "clip_name", "description" => "description", "matches" => [], }), BrayniacAI::EdlParseResult.new({ "channel" => "V", "start_time" => 15, "timecode_in" => "01:00:15:00", "timecode_out" => "01:00:18:00", "duration" => "00:00:02", "source_file_name" => "source_file_name2", "clip_name" => "clip_name", "description" => "description", "matches" => [], }) ] allow(BrayniacAI::EdlParse).to receive(:create).and_return( BrayniacAI::EdlParse.new({ results: edl_events, edl_timecode_start: "00:00:00:00" }) ) sign_in current_user visit video_video_analyses_path(video) find("#player .container").click find("#player .container").click open_graphics_element_modal(video) expect(page).to have_content "Timecode In" expect(page).to have_content "Source File Name" click_on "Show/Hide EDL Events" within "#edl_events" do expect(page).to have_content("V") expect(page).to have_content("source_file_name2") end click_on_edl_event(2) expect(page).to have_field("graphics_element[timecode_in]", with: "01:00:15:00") expect(page).to have_field("graphics_element[source_file_name]", with: "source_file_name2") end scenario "filters out non-video EDL events", js: true do edl_events = [ BrayniacAI::EdlParseResult.new({ "channel" => "V", "start_time" => 0, "timecode_in" => "01:00:00:00", "timecode_out" => "01:00:02:00", "duration" => "00:00:02", "source_file_name" => "source_file_name", "clip_name" => "clip_name", "description" => "description", "matches" => [], }), BrayniacAI::EdlParseResult.new({ "channel" => "A1", "start_time" => 0, "timecode_in" => "01:00:00:00", "timecode_out" => "01:00:02:00", "duration" => "00:00:02", "source_file_name" => "source_file_name.wav", "clip_name" => "clip_name", "description" => "description", "matches" => [], }), ] allow(BrayniacAI::EdlParse).to receive(:create).and_return( BrayniacAI::EdlParse.new({ results: edl_events, edl_timecode_start: "00:00:00:00" }) ) sign_in current_user visit video_video_analyses_path(video) open_graphics_element_modal(video) expect(page).to have_content "Timecode In" expect(page).to have_content "Source File Name" click_on "Show/Hide EDL Events" within "#edl_events" do expect(page).to have_content("V") expect(page).to have_content("source_file_name") expect(page).not_to have_content("A1") expect(page).not_to have_content("source_file_name.wav") end end end context "for Audio tab" do before :each do video.analysis_success! allow(BrayniacAI::FacialRecognition).to receive(:find).and_return( BrayniacAI::FacialRecognition.new({ bucket_name: "", overlay_video_url: nil, first_appearances: [], }) ) end scenario "confirming an acquired media match", js: true do skip "TODO: Finish implementing this functionality" video.audio_analysis_success! acquired_media_release = create(:acquired_media_release, project: project, file_infos: create_list(:file_info, 1, filename: "acquired_file_name")) allow(BrayniacAI::AudioRecognition).to receive(:find).and_return( OpenStruct.new({ results: [ OpenStruct.new( uid: acquired_media_release.file_infos.first.id, requested_filename: acquired_media_release.file_infos.first.filename, type: "acquired_media", audio_data: OpenStruct.new( filename: acquired_media_release.file_infos.first.filename, composers: [], publishers: [], catalog: "", title: "", ), edl: [ OpenStruct.new( start_time: 0, timecode_in: "01:00:00:00", ), ] ) ] }) ) allow(BrayniacAI::EdlParse).to receive(:create).and_return( BrayniacAI::EdlParse.new({ results: [ BrayniacAI::EdlParseResult.new({ "channel" => "A1", "start_time" => 0, "timecode_in" => "01:00:00:00", "timecode_out" => "01:00:02:00", "duration" => "00:00:02", "source_file_name" => acquired_media_release.file_infos.first.filename, "clip_name" => "clip_name", "description" => "description", "matches" => [], }), ], edl_timecode_start: "00:00:00:00", fps: 29.97, edl_offset_seconds: 0, }) ) sign_in current_user visit video_video_analyses_path(video) click_link "Audio" expect(page).not_to have_audio_match(text: "(A) acquired_file_name") by "verifying a music match displays after video starts" do find("#player .container").click find("#player .container").click expect(page).to have_audio_match(text: "(A) acquired_file_name") end within "#audio_matches" do expect(page).not_to have_css(".fa-check-circle") end confirm_acquired_media_match(video) sleep(1) within "#audio_matches" do expect(page).to have_css(".fa-check-circle") match_text = page.find(".fa-check-circle").find(:xpath, "../..").text expect(match_text).to include("(A) acquired_file_name") end expect(page).to have_confirmed_audio("acquired_file_name") and_by "verifying checkmark gets removed if confirmation removed from report" do unconfirm_audio(AudioConfirmation.last) expect(page).not_to have_confirmed_audio("acquired_file_name") within "#audio_matches" do expect(page).not_to have_css(".fa-check-circle") end end end scenario "confirming an original music match", js: true do video.audio_analysis_success! music_release = create(:music_release, project: project, file_infos: build_list(:file_info, 1, filename: "original_music_file_name.wav")) allow(BrayniacAI::AudioRecognition).to receive(:find).and_return( OpenStruct.new( results: [ OpenStruct.new( uid: music_release.file_infos.first.id, requested_filename: music_release.file_infos.first.filename, type: "original_music", audio_data: OpenStruct.new( filename: music_release.file_infos.first.filename, composers: [], publishers: [], catalog: "", title: "", ), edl: [ OpenStruct.new( start_time: 0, timecode_in: "01:00:00:00", ), ] ), ] ) ) allow(BrayniacAI::EdlParse).to receive(:create).and_return( BrayniacAI::EdlParse.new({ results: [ BrayniacAI::EdlParseResult.new({ "channel" => "A1", "start_time" => 0, "timecode_in" => "01:00:00:00", "timecode_out" => "01:00:02:00", "duration" => "00:00:02", "source_file_name" => music_release.file_infos.first.filename, "clip_name" => "clip_name", "description" => "description", "matches" => [], }), ], edl_timecode_start: "00:00:00:00", fps: 29.97, edl_offset_seconds: 0, }) ) sign_in current_user visit video_video_analyses_path(video) click_link "Audio" expect(page).not_to have_audio_match(text: "(O) original_music_file_name") by "verifying a music match displays after video starts" do find("#player .container").click find("#player .container").click expect(page).to have_audio_match(text: "(O) original_music_file_name") end within "#audio_matches" do expect(page).not_to have_css(".fa-check-circle") end confirm_original_music_match(video, "original_music_file_name") sleep(1) within "#audio_matches" do expect(page).to have_css(".fa-check-circle") match_text = page.find(".fa-check-circle").find(:xpath, "../..").text expect(match_text).to include("(O) original_music_file_name") end expect(page).to have_confirmed_audio("original_music_file_name") and_by "verifying checkmark gets removed if confirmation removed from report" do unconfirm_audio(AudioConfirmation.last) expect(page).not_to have_confirmed_audio("original_music_file_name.wav") within "#audio_matches" do expect(page).not_to have_css(".fa-check-circle") end end end scenario "confirming a library music match", js: true do video.audio_analysis_success! allow(BrayniacAI::AudioRecognition).to receive(:find).and_return( OpenStruct.new( results: [ OpenStruct.new( uid: "abc123", requested_filename: "library_file_name.wav", type: "library_music", audio_data: OpenStruct.new( filename: "library_file_name.wav", composers: [], publishers: [], catalog: "", title: "", ), edl: [ OpenStruct.new( start_time: 0, timecode_in: "01:00:00:00", ), ] ), ] ) ) allow(BrayniacAI::EdlParse).to receive(:create).and_return( BrayniacAI::EdlParse.new({ results: [ BrayniacAI::EdlParseResult.new({ "channel" => "A1", "start_time" => 0, "timecode_in" => "01:00:00:00", "timecode_out" => "01:00:02:00", "duration" => "00:00:02", "source_file_name" => "library_file_name.wav", "clip_name" => "clip_name", "description" => "description", "matches" => [], }), ], edl_timecode_start: "00:00:00:00", fps: 29.97, edl_offset_seconds: 0, }) ) sign_in current_user visit video_video_analyses_path(video) click_link "Audio" expect(page).not_to have_audio_match(text: "(L) library_file_name.wav") by "verifying a music match displays after video starts" do find("#player .container").click find("#player .container").click expect(page).to have_audio_match(text: "(L) library_file_name.wav") end within "#audio_matches" do expect(page).not_to have_css(".fa-check-circle") end confirm_library_music_match(video) sleep(1) within "#audio_matches" do expect(page).to have_css(".fa-check-circle") match_text = page.find(".fa-check-circle").find(:xpath, "../..").text expect(match_text).to include("(L) library_file_name.wav") end expect(page).to have_confirmed_audio("library_file_name.wav") and_by "verifying checkmark gets removed if confirmation removed from report" do unconfirm_audio(AudioConfirmation.last) expect(page).not_to have_confirmed_audio("library_file_name.wav") within "#audio_matches" do expect(page).not_to have_css(".fa-check-circle") end end end scenario "confirming a music release", js: true do music_release = create(:music_release, project: project, file_infos: [ build(:file_info, filename: "shark jumping"), build(:file_info, filename: "pig flying"), build(:file_info, filename: "panda sneezing"), ] ) allow(BrayniacAI::EdlParse).to receive(:create).and_return( BrayniacAI::EdlParse.new({ results: [ BrayniacAI::EdlParseResult.new({ "channel" => "A1", "start_time" => 0, "timecode_in" => "01:00:00:00", "timecode_out" => "01:00:02:00", "duration" => "00:00:02", "source_file_name" => "shark jumping.wav", "clip_name" => "clip_name", "description" => "description", "matches" => [], }), ], edl_timecode_start: "00:00:00:00", }) ) sign_in current_user visit video_video_analyses_path(video) click_link "Audio" find("#player .container").click find("#player .container").click expect(page).to have_unconfirmed_file_info_release(music_release, "shark jumping", count: 1) expect(page).to have_unconfirmed_file_info_release(music_release, "pig flying", count: 1) expect(page).to have_unconfirmed_file_info_release(music_release, "panda sneezing", count: 1) confirm_first_music_release_using_edl_modal(video, text: "shark jumping") expect(page).not_to have_unconfirmed_file_info_release(music_release, "shark jumping", count: 1) expect(page).to have_unconfirmed_file_info_release(music_release, "pig flying", count: 1) expect(page).to have_unconfirmed_file_info_release(music_release, "panda sneezing", count: 1) expect(page).to have_confirmed_audio("shark jumping") unconfirm_audio(AudioConfirmation.last) expect(page).not_to have_confirmed_audio("shark jumping") expect(page).to have_unconfirmed_file_info_release(music_release, "shark jumping", count: 1) expect(page).to have_unconfirmed_file_info_release(music_release, "pig flying", count: 1) expect(page).to have_unconfirmed_file_info_release(music_release, "panda sneezing", count: 1) end scenario "filters out non-audio EDL events", js: true do skip "TODO: Fix this test" edl_events = [ BrayniacAI::EdlParseResult.new({ "channel" => "V", "start_time" => 0, "timecode_in" => "01:00:00:00", "timecode_out" => "01:00:02:00", "duration" => "00:00:02", "source_file_name" => "source_file_name", "clip_name" => "clip_name", "description" => "description", "matches" => [], }), BrayniacAI::EdlParseResult.new({ "channel" => "A1", "start_time" => 0, "timecode_in" => "01:00:00:00", "timecode_out" => "01:00:02:00", "duration" => "00:00:02", "source_file_name" => "source_file_name.wav", "clip_name" => "clip_name", "description" => "description", "matches" => [], }), ] allow(BrayniacAI::EdlParse).to receive(:create).and_return( BrayniacAI::EdlParse.new({ results: edl_events, edl_timecode_start: "00:00:00:00" }) ) video = create(:video, :with_audio_only_edl_file, project: project, analysis_status: :success) sign_in current_user visit video_video_analyses_path(video) open_audio_confirmation_modal expect(page).to have_field("Origin", with: "Original Music") expect(page).to have_content "Timecode In" expect(page).to have_content "Source File Name" expect(page).to have_field("Source EDL", with: "Audio") click_on "Show/Hide EDL Events" within "#edl_events" do expect(page).not_to have_content("V") expect(page).to have_content("A1") expect(page).to have_content("source_file_name.wav") end end scenario "manually creating an audio confirmation", js: true do skip "TODO: Fix this test" sign_in current_user visit video_video_analyses_path(video) click_link "Audio" click_button "Add to Music Cue Sheet" expect(page).to have_content "Confirm Audio" within "#new_audio_confirmation_modal" do fill_in "Title", with: "Two Waves" select "Vocal", from: "Music type" select "Feature", from: "Music category" expect(page).to have_field("Source EDL", with: "All Tracks") expect(page).to have_field("Channel", with: "A1") expect(page).to have_field("Origin", with: "Library Music") expect(page).to have_field("Timecode In", with: "01:00:00:00") expect(page).to have_field("Timecode out", with: "01:00:02:00") expect(page).to have_field("Duration", with: "00:00:02") expect(page).to have_field("Source File Name", with: "source_file_name.wav") expect(page).to have_field("Clip name", with: "clip_name") expect(page).to have_field("Description", with: "description") click_on "Confirm Audio" end expect(page).to have_confirmed_audio("source_file_name.wav") end scenario "has new layout" do sign_in current_user visit video_video_analyses_path(video) click_link "Audio" expect(page).to have_content("EDL #") expect(page).to have_content("EDL TC") expect(page).to have_content("VID TC") expect(page).to have_content("Filename") end end context "for Issues and Concerns" do scenario "manages Unreleased appearances", js: true do sign_in current_user visit video_video_analyses_path(video) click_link "Issues & Concerns" by "adding an issues and concerns item" do open_unreleased_modal(video) expect(page).to have_selector("#unreleased_appearance_note_category") select_option("#unreleased_appearance_note_category","Missing talent release") expect(page).not_to have_selector("#unreleased_appearance_notes") select_option("#unreleased_appearance_note_category","Other") expect(page).to have_selector("#unreleased_appearance_notes") create_unreleased_appearance(video, notes: "Many issues present") expect(page).to have_selector("#issues_and_concerns_list", text: "Many issues present") expect(page).to have_selector("#issues_and_concerns_list", text: "Channel") expect(page).to have_selector("#issues_and_concerns_list", text: "EDL TC") expect(page).to have_selector("#issues_and_concerns_list", text: "Video TC") end and_by "editing an issues and concerns item" do edit_issues_and_concerns_item(text: "Many more issues present") expect(page).to have_selector("#issues_and_concerns_list", text: "Many more issues present") end by "adding an issues and concerns item with predefined note" do open_unreleased_modal(video) select_option("#unreleased_appearance_note_category","Missing talent release") click_button "Create Issue/Concern" expect(page).to have_selector("#issues_and_concerns_list", text: "Missing talent release") end and_by "removing an issues and concerns item" do delete_issues_and_concerns(UnreleasedAppearance.last) expect(page).not_to have_selector("#issues_and_concerns_list", text: "Missing talent release") end end scenario "copying data from multiple EDL events ", js: true do edl_events = [ BrayniacAI::EdlParseResult.new({ "channel" => "V", "start_time" => 0, "timecode_in" => "01:00:00:00", "timecode_out" => "01:00:02:00", "duration" => "00:00:02", "source_file_name" => "source_file_name1", "clip_name" => "clip_name", "description" => "description", "matches" => [], }), BrayniacAI::EdlParseResult.new({ "channel" => "V", "start_time" => 15, "timecode_in" => "01:00:15:00", "timecode_out" => "01:00:18:00", "duration" => "00:00:02", "source_file_name" => "source_file_name2", "clip_name" => "clip_name", "description" => "description", "matches" => [], }) ] allow(BrayniacAI::EdlParse).to receive(:create).and_return( BrayniacAI::EdlParse.new({ results: edl_events, edl_timecode_start: "00:00:00:00" }) ) sign_in current_user visit video_video_analyses_path(video) open_unreleased_modal(video) expect(page).to have_content "Timecode In" expect(page).to have_content "Source File Name" click_on "Show/Hide EDL Events" within "#edl_events" do expect(page).to have_content("V") expect(page).to have_content("source_file_name2") end click_on_edl_event(2) expect(page).to have_field("unreleased_appearance[timecode_in]", with: "01:00:15:00") expect(page).to have_field("unreleased_appearance[source_file_name]", with: "source_file_name2") end scenario "does not filter EDL events", js: true do edl_events = [ BrayniacAI::EdlParseResult.new({ "channel" => "V", "start_time" => 0, "timecode_in" => "01:00:00:00", "timecode_out" => "01:00:02:00", "duration" => "00:00:02", "source_file_name" => "source_file_name", "clip_name" => "clip_name", "description" => "description", "matches" => [], }), BrayniacAI::EdlParseResult.new({ "channel" => "A1", "start_time" => 0, "timecode_in" => "01:00:00:00", "timecode_out" => "01:00:02:00", "duration" => "00:00:02", "source_file_name" => "source_file_name.wav", "clip_name" => "clip_name", "description" => "description", "matches" => [], }), ] allow(BrayniacAI::EdlParse).to receive(:create).and_return( BrayniacAI::EdlParse.new({ results: edl_events, edl_timecode_start: "00:00:00:00" }) ) sign_in current_user visit video_video_analyses_path(video) open_unreleased_modal(video) expect(page).to have_content "Timecode In" expect(page).to have_content "Source File Name" click_on "Show/Hide EDL Events" within "#edl_events" do expect(page).to have_content("V") expect(page).to have_content("source_file_name") expect(page).to have_content("A1") expect(page).to have_content("source_file_name.wav") end end scenario "clicking video TC in issues & concerns tab seeks video to TC", js: true do create(:unreleased_appearance, video: video, notes: "Test issue", time_elapsed: 2) sign_in current_user visit video_video_analyses_path(video) find("#player .container").click find("#player .container").click click_link "Issues & Concerns" TC_time_selector = "[data-behavior=seekable-timecode]" expect(page).to have_content "Test issue" expect(page).to have_css(TC_time_selector, text: "00:00:02:00") find(TC_time_selector).click expect(page).to have_css(".media-control-indicator", text: "00:02", visible: :all) end end context "for Notes tab" do scenario "clicking video TC seeks video to TC", js: true do bookmark = create(:bookmark, video: video, notes: "Test notes", time_elapsed: 5) sign_in current_user visit video_video_analyses_path(video) find("#player .container").click find("#player .container").click click_link "Notes" expect(page).to have_content "Test notes" expect(page).to have_css("#bookmark_#{bookmark.id} > td:nth-child(3)", text: "00:00:05:00") find("#bookmark_#{bookmark.id} > td:nth-child(3)").click expect(page).to have_css(".media-control-indicator", text: "00:05", visible: :all) end end private def confirm_release(video, release) action = polymorphic_path([video, release, :video_release_confirmations]) form = find("form[action='#{action}']") confirm_button = "Add to Report" within form do click_button confirm_button end end def confirm_suggested_match(video, release) new_path = polymorphic_path([:new, video, release, :video_release_confirmation]) create_path = polymorphic_path([video, release, :video_release_confirmations]) first("#suggested_matches form[action='#{new_path}']").click_button expect(page).to have_content "Timecode In" within "form[action='#{create_path}']" do click_button "Confirm Release" end end def confirm_original_music_match(video, filename) open_audio_confirmation_modal create_audio_confirmation(video, filename: "original_music_file_name") end def open_audio_confirmation_modal page.execute_script <<-JS $("#audio_matches .releasable-match button")[0].click() JS expect(page).to have_content "Timecode In" end def select_option(select_id, text) page.find(select_id).find(:option, text).select_option end def create_audio_confirmation(video, filename: "source_file_name") create_path = video_video_analyses_audio_confirmations_path(video) within "form[action='#{create_path}']" do expect(page).to have_selector("#matched_file_name", text: filename) click_button "Confirm Audio" end end def confirm_library_music_match(video) create_path = video_video_analyses_audio_confirmations_path(video) page.execute_script <<-JS $("#audio_matches .releasable-match button")[0].click() JS expect(page).to have_field("Origin", with: "Library Music") expect(page).to have_content "Timecode In" within "form[action='#{create_path}']" do expect(page).to have_selector("#matched_file_name", text: "library_file_name") click_button "Confirm Audio" end end def confirm_suggested_talent_match(video, release) create_path = polymorphic_path([video, release, :video_release_confirmations]) first("#suggested_matches form[action='#{create_path}']").click_button end def unconfirm_release(confirmation) url = polymorphic_path([confirmation.video, confirmation.releasable, confirmation]) click_link "", href: url, visible: false end def unconfirm_audio(confirmation) path = audio_confirmation_path(confirmation) find("#audio_confirmations a[href='#{path}']").click end def confirm_first_release_using_edl_modal(video, release, text: "") new_path = polymorphic_path([:new, video, release, :video_release_confirmation]) create_path = polymorphic_path([video, release, :video_release_confirmations]) first("form[action='#{new_path}']", text: text).click_button expect(page).to have_content "Timecode In" within "form[action='#{create_path}']" do click_button "Confirm Release" end end def confirm_first_music_release_using_edl_modal(video, text: "") new_path = new_video_video_analyses_audio_confirmation_path(video) create_path = video_video_analyses_audio_confirmations_path(video) page.execute_script <<-JS $("[data-ujs-target=audio-confirmation-form] input[name='audio_confirmation[time_elapsed]']").attr("value", "0") JS first("#music_releases form[action='#{new_path}']", text: text).click_button expect(page).to have_field("Origin", with: "Original Music") expect(page).to have_content "Timecode In" within "form[action='#{create_path}']" do select "Vocal", from: "Music type" select "Feature", from: "Music category" fill_in "Source file name", with: text click_button "Confirm Audio" end end def click_on_edl_event(index) all("[data-behavior=fillable-fields]")[index - 1].click end def create_bookmark(video, notes:) new_path = new_video_bookmark_path(video) create_path = video_bookmarks_path(video) # Opens the new bookmark form within "form[action='#{new_path}']" do click_button end # Fills out and submits the bookmark form within "form[action='#{create_path}']" do fill_in "Notes", with: notes click_button "Create" end end def open_graphics_element_modal(video) new_path = new_video_video_analyses_graphics_element_path(video) page.execute_script("document.querySelector(\"input[name='graphics_element[time_elapsed]']\").setAttribute(\"value\", 0)") within "form[action='#{new_path}']" do click_button end end def confirm_graphics_element_match page.execute_script <<-JS $("#graphics_elements_matches .graphics-match button")[0].click() JS end def create_graphics_element(video, text:) create_path = video_video_analyses_graphics_elements_path(video) within "form[action='#{create_path}']" do select "Subtitle", from: "Graphic type" fill_in "Text", with: text click_button "Create GFX Element" end end def open_edit_graphics_modal within "#graphics_elements_list" do find(".fa-pencil").click end end def edit_graphics_element(text:) within "#edit_graphics_element_modal" do select "Logo", from: "Graphic type" fill_in "Text", with: text click_button "Update GFX Element" end end def delete_graphics_element(graphics_element) path = graphics_element_path(graphics_element) find("#graphics_elements_list a[href='#{path}']").click end def open_unreleased_modal(video) new_path = new_video_video_analyses_unreleased_appearance_path(video) within "form[action='#{new_path}']" do click_button end end def create_unreleased_appearance(video, notes:) create_path = video_video_analyses_unreleased_appearances_path(video) # Fills out and submits the unreleased appearance form within "form[action='#{create_path}']" do if notes select "Other", from: "Note" fill_in "Notes", with: notes end click_button "Create" end end def edit_issues_and_concerns_item(text:) within "#issues_and_concerns_list" do click_link "Edit" end within "#edit_unreleased_appearance_modal" do fill_in "Notes", with: text click_button "Update Issue/Concern" end end def delete_issues_and_concerns(unreleased_appearance) path = unreleased_appearance_path(unreleased_appearance) find("#issues_and_concerns_list a[href='#{path}']").click end def have_unconfirmed_file_info_release(release, text, count: 1) scope = "#" + release.class.to_s.tableize have_selector("#{scope} [data-confirmed='false'][data-hidden='false']", text: text, count: count) end def have_acquired_media_release_suggested_match(release, file_info_id, text:) have_selector("#suggested_matches [data-ujs-target=#{dom_id(release, "file_info_#{file_info_id}")}]", text: text) end def have_suggested_match(release, text:) have_selector("#suggested_matches ##{dom_id(release)}", text: text) end def have_graphics_element_match(text:) have_selector("#graphics_elements_matches", text: text) end def have_audio_match(text:) have_selector("#audio_matches", text: text) end def have_unconfirmed_release(release, count: 1) scope = "#" + release.class.to_s.tableize have_selector("#{scope} ##{dom_id(release)}[data-confirmed='false'][data-hidden='false']", count: count) end def have_confirmed_release(release, text: "00:00:00:00", scope: "#video_release_confirmations") have_selector("#{scope} [data-releasable-id='#{release.id}']", text: text) end def have_confirmed_audio(text) have_selector("#audio_confirmations", text: text) end def have_bookmark(notes:) have_selector(".standard-marker.bookmark-marker", visible: false) && have_selector(".standard-tooltip", text: notes, visible: false) end def have_graphics_element(text:) have_selector(".graphics-elements .graphics-element", text: text) end def have_confirmed_graphics_match(text:) have_selector("#graphics_elements_matches [data-confirmed='true']", text: text) end def have_graphics_element_modal have_selector("#new_graphics_element_modal") end def have_edl_event_modal have_selector("#edl_event_modal") end def have_unreleased_appearance(notes:) have_selector(".standard-marker.unreleased-appearance-marker", visible: false) && have_selector(".standard-tooltip", text: notes, visible: false) end def search_for(type, text: "") action = "video_analyses/#{type.to_s}" within "form[action*='#{action}']" do fill_in "query", with: text click_button "Search" end end def dom_id(record, prefix = nil) ActionController::Base.helpers.dom_id(record, prefix) end end