Проблемы с добавлением простого модульного теста для одностраничного отображения YouTube

Привет!

Я хочу добавить поддержку ссылок YouTube формата /shorts/.

Моя модификация класса YoutubeOnebox работает, но требуется добавить тест в youtube_onebox.rb, и мой тест не проходит.

Аналогично тесту “can parse youtube embed results”, я добавил этот код:

it "can parse youtube shorts results" do
  preview = expect(Onebox.preview('https://www.youtube.com/watch?v=wi2jAtpBl0Y').placeholder_html)
  preview.to match(/From which sound/)
  preview.to match(/hqdefault/)
end

Также я добавил это в начало файла, внутри блока before do:

stub_request(:get, "https://www.youtube.com/shorts/wi2jAtpBl0Y").to_return(status: 200, body: onebox_response("youtube-shorts"))

Я никогда раньше не занимался модульным тестированием, поэтому не до конца понимаю, как всё это работает.

Ошибка моего теста:

Failures:

  1) Onebox::Engine::YoutubeOnebox can parse youtube shorts results
     Failure/Error:
               http.request(request) do |response|

                 if cookie = response.get_fields('set-cookie')
                   # HACK: If this breaks again in the future, use HTTP::CookieJar from gem 'http-cookie'
                   # See test: it "does not send cookies to the wrong domain"
                   redir_header = { 'Cookie' => cookie.join('; ') }
                 end

                 redir_header = nil unless redir_header.is_a? Hash

     WebMock::NetConnectNotAllowedError:
       Real HTTP connections are disabled. Unregistered request: GET https://www.youtube.com/embed/wi2jAtpBl0Y with headers {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Discourse Forum Onebox v2.9.0.beta12'}

       You can stub this request with the following snippet:

       stub_request(:get, "https://www.youtube.com/embed/wi2jAtpBl0Y").
         with(
           headers: {
          'Accept'=>'*/*',
          'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
          'User-Agent'=>'Discourse Forum Onebox v2.9.0.beta12'
           }).
         to_return(status: 200, body: "", headers: {})

       registered request stubs:

       stub_request(:get, "https://www.youtube.com/shorts/wi2jAtpBl0Y")
       stub_request(:get, "https://www.youtube.com/embed/KCyIfcevExE")
       stub_request(:get, "https://www.youtube.com/playlist?list=PL5308B2E5749D1696")
       stub_request(:get, "http://www.youtube.com/user/googlechrome")
       stub_request(:get, "https://www.youtube.com/channel/UCL8ZULXASCc1I_oaOT0NaOQ")
       stub_request(:get, "https://www.youtube.com/watch?v=21Lk4YiASMo")
       stub_request(:get, "http://www.youtube.com/watch?v=21Lk4YiASMo")
       stub_request(:get, "https://www.youtube.com/embed/21Lk4YiASMo")
       stub_request(:get, "https://youtu.be/21Lk4YiASMo")
       stub_request(:get, "https://www.youtube.com/watch?feature=player_embedded&v=21Lk4YiASMo")

       ============================================================
     # ./lib/onebox/helpers.rb:83:in `block in fetch_response'
     # ./lib/onebox/helpers.rb:69:in `fetch_response'
     # ./lib/onebox/helpers.rb:28:in `fetch_html_doc'
     # ./lib/onebox/engine/youtube_onebox.rb:21:in `parse_embed_response'
     # ./lib/onebox/engine/youtube_onebox.rb:42:in `placeholder_html'
     # ./lib/onebox/preview.rb:28:in `placeholder_html'
     # ./spec/lib/onebox/engine/youtube_onebox_spec.rb:110:in `block (2 levels) in <main>'
     # ./spec/rails_helper.rb:328:in `block (2 levels) in <top (required)>'

Finished in 0.89418 seconds (files took 5.04 seconds to load)
17 examples, 1 failure

Failed examples:

rspec ./spec/lib/onebox/engine/youtube_onebox_spec.rb:109 # Onebox::Engine::YoutubeOnebox can parse youtube shorts results

Не могли бы вы подсказать, почему тест падает?

Также, что делают эти части в блоке before do?

onebox_response("youtube-embed")

Строка “youtube-embed” вроде бы нигде не используется в коде Discourse, кроме этого места. Какова её цель?

Почему там два раза встречаются ссылки с /embed/ и почему у onebox_response разные параметры?

stub_request(:get, "https://www.youtube.com/embed/21Lk4YiASMo")
.to_return(status: 200, body: onebox_response("youtube"))
stub_request(:get, "https://www.youtube.com/embed/KCyIfcevExE")
.to_return(status: 200, body: onebox_response("youtube-embed"))

Я тоже не очень в этом разбираюсь, но тебе нужно сделать так, чтобы этот заглушка возвращала ровно то же самое, что и YouTube. То есть она должна содержать некоторое подмножество того, что возвращает команда wget https://www.youtube.com/embed/wi2jAtpBl0Y. Именно это и должно быть входными данными для твоего теста.

wc wi2jAtpBl0Y 
    6   251 65245 wi2jAtpBl0Y

Это довольно большой объём текста, чтобы разобраться в нём и вставить в заглушку.

Можешь открыть черновик PR с твоими текущими изменениями? Так будет проще следить за процессом и помочь. Судя по имеющейся информации, тебе нужно создать файлы-заглушки (stub files) и заглушки, а также исходящие запросы.

Конечно, вот оно!

Я исправил это в новом PR, где указано правильное авторство с указанием вас как соавтора:

Чтобы наш набор тестов не зависел от наличия работающего интернет-соединения (и YouTube), мы заглушаем все запросы в интернет, заставляя их возвращать кэшированный ответ. Функция onebox_response обращается к файлу с именем, совпадающим с переданным параметром, из папки discourse/spec/fixtures/onebox at main · discourse/discourse · GitHub.

Я добавил новый файл .response для Shorts, чтобы у нас был хороший тест, но для этого решения этого было достаточно. Спасибо за ваш PR!

Тестирование Shorts Onebox:

https://youtube.com/shorts/VvoFuaLAslw

Видео недоступно
Загрузивший это видео не сделал его доступным в вашей стране

Помимо этого, всё должно работать :smile:

А как насчёт

?

У меня всё работает.

Вопрос на скорую руку. Вот уведомление по электронной почте, которое я получил:

Здесь URL-адрес — /embed/, а не /shorts/, но я полагаю, что это нормально?