Repository: abak-press/apress-selenium_products
Pull request #68: feat(selenium): add kirby import yml spec from the blizko
Author: login: Fort-Nox
Created: 2025-04-25T07:11:23Z | Merged: 2025-04-28T09:17:49Z

- Поправил падающие/скипнутые тесты по странице импорта yml, после редизайна страницы и перенес их в гем из проекта Blizko.
- https://jira.railsc.ru/browse/AT-639


Diff:
diff --git a/lib/apress/selenium_products/spec/company_site/kirby/import/import_yml_policy_spec.rb b/lib/apress/selenium_products/spec/company_site/kirby/import/import_yml_policy_spec.rb
new file mode 100644
index 0000000..5159cb1
--- /dev/null
+++ b/lib/apress/selenium_products/spec/company_site/kirby/import/import_yml_policy_spec.rb
@@ -0,0 +1,435 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Кирби: политики доступа страницы импорта YML', feature: 'Кирби: политики доступа страницы импорта YML' do
+  before(:all) do
+    @import_yml_page = CompanySite::ImportYMLPage.new
+    @upload_tab      = CompanySite::ImportYMLPage::UploadTab.new
+    @settings_tab    = CompanySite::ImportYMLPage::SettingsTab.new
+  end
+
+  shared_examples 'общие элементы страницы' do
+    it 'присутствует title в формате "Загрузка товаров из YML/YRL - %название компании% - %основной регион%"' do
+      expect(@import_yml_page.has_expected_title?).to be true
+    end
+
+    it 'присутствует заголовок страницы "Загрузить товары в формате Яндекс.Маркет (YML/YRL)"' do
+      expect(@import_yml_page.header).to eq 'Загрузить товары в формате Яндекс.Маркет (YML/YRL)'
+    end
+
+    it 'присутствуют вкладки "Загрузить товары" и "Расширенные настройки"' do
+      expect(@import_yml_page.upload_tab?).to be true
+      expect(@import_yml_page.settings_tab?).to be true
+    end
+  end
+
+  shared_examples 'все элементы страницы для роли с повышенными правами' do |role|
+    context 'когда на вкладке "Загрузить товары"' do
+      before(:all) { @import_yml_page.upload_tab }
+
+      it('присутствует текстовая зона') { expect(@upload_tab.text_zone?).to be true }
+
+      it 'присутствует активный блок "Формат" со значениями YML, YRL и EDIFACT' do
+        expect(@upload_tab.source_type_label?).to be true
+        expect(@upload_tab.source_type_options).to eq %w[YML YRL EDIFACT]
+      end
+
+      it('доступен режим "Товаров нет"') { expect(@upload_tab.moving_no?).to be true }
+
+      context 'когда выбран режим "Товары есть"' do
+        before(:all) { @upload_tab.moving_yes }
+
+        it('доступен режим "Оставить опубликованными"') { expect(@upload_tab.moving_keep?(2)).to be true }
+        it('доступен режим "Удалить"') { expect(@upload_tab.moving_delete?(2)).to be true }
+        it('доступен режим "Перенести в архив"') { expect(@upload_tab.moving_archive?(2)).to be true }
+
+        it('присутствует кнопка "Загрузить"') { expect(@upload_tab.upload_price?).to be true }
+      end
+
+      # TODO: Раскипать после того, как обновят образ ножа для ПЦ,
+      # тест пропускается так как файла по пути /test_files/pulscen пока нет.
+      xcontext 'когда источник - Файл' do
+        before(:all) do
+          @upload_tab.switch_to_source_file
+          @upload_tab.upload_yml(YAML_FILE_PATH)
+          @import_yml_page.settings_tab
+          @settings_tab.save_settings
+          @import_yml_page.upload_tab
+        end
+
+        it('присутствует поле с названием выбранного файла') { expect(@upload_tab.source_file?).to be true }
+        it('присутствует псевдо-ссылка выбора файла') { expect(@upload_tab.file_upload_element.exists?).to be true }
+        it('присутствует ссылка на скачивание прайса') { expect(@upload_tab.download_last_price?).to be true }
+      end
+
+      context 'когда источник - Ссылка' do
+        before(:all) { @upload_tab.switch_to_source_url }
+
+        it('присутствует поле ввода источника прайса') { expect(@upload_tab.source_url?).to be true }
+      end
+    end
+
+    context 'когда на вкладке "Расширенные настройки"' do
+      before(:all) { @import_yml_page.settings_tab }
+
+      it('присутствует заголовок "Выборочное обновление полей"') { expect(@settings_tab.selected_fields?).to be true }
+
+      it 'присутствует заголовок "Выборочное обновление товаров"' do
+        expect(@settings_tab.selected_products?).to be true
+      end
+      it('присутствует заголовок "Отчет"') { expect(@settings_tab.notification_label?).to be true }
+
+      it('присутствует заголовок "Загрузка характеристик для фильтров по товарам на вашем сайте"') do
+        expect(@settings_tab.company_traits_label?).to be true
+      end
+
+      it 'присутствует активный чекбокс "Загружать характеристики"' do
+        expect(@settings_tab.company_traits).to eq 'Загружать характеристики'
+        expect(@settings_tab.company_traits_element.checkbox_element.enabled?).to be true
+      end
+
+      it 'все чекбоксы выбора статусов обновляемых товаров активные' do
+        expect(@settings_tab.update_archived).to eq 'Обновлять товары в статусе «Архивный»'
+        expect(@settings_tab.update_archived_element.checkbox_element.enabled?).to be true
+        expect(@settings_tab.update_unpublished).to eq 'Обновлять товары в статусе «Опубликованный на сайте»'
+        expect(@settings_tab.update_unpublished_element.checkbox_element.enabled?).to be true
+      end
+
+      it 'все чекбоксы в блоке "Выборочное обновление полей" активные' do
+        CompanySite::ImportYMLPage::SettingsTab::TAGS.each do |field|
+          expect(@settings_tab.send("#{field}_element").enabled?).to be true
+        end
+      end
+
+      it 'все чекбоксы в блоке "Настройка названия товара" активные' do
+        CompanySite::ImportYMLPage::SettingsTab::NAME_TAGS.each do |field|
+          expect(@settings_tab.send("tag_#{field}_element").enabled?).to be true
+        end
+      end
+
+      it 'чекбокс "Получать отчёт о загрузке товаров и услуг" в блоке "Отчет" активный' do
+        expect(@settings_tab.notification).to eq 'Получать отчёт о загрузке товаров и услуг'
+        expect(@settings_tab.notification_element.checkbox_element.enabled?).to be true
+      end
+
+      context 'когда источник - Ссылка' do
+        before(:all) do
+          @import_yml_page.upload_tab
+          @upload_tab.switch_to_source_url
+          @import_yml_page.settings_tab
+        end
+
+        it 'отобразится активный чекбокс "Включить автоматическое обновление" в блоке "Автообновление"' do
+          expect(@settings_tab.autoupdate_label).to eq 'Автообновление'
+          expect(@settings_tab.autoupdate_element.checkbox_element.enabled?).to be true
+        end
+
+        context 'когда отмечен чекбокс "Включить автоматическое обновление"' do
+          before(:all) { @settings_tab.autoupdate_element.checkbox_element.check }
+
+          it 'отобразится блок с полями "Интервал обновления" и "Точное время обновления (MSK)"' do
+            expect(@settings_tab.autoupdate_period_label?).to be true
+            expect(@settings_tab.autoupdate_period?).to be true
+            expect(@settings_tab.autoupdate_start_date_label?).to be true
+            expect(@settings_tab.autoupdate_start_date).to be_truthy
+          end
+        end
+      end
+    end
+  end
+
+  shared_context 'роль с повышенными правами' do |role, name|
+    context "когда роль - #{name}" do
+      before(:all) do
+        log_in_as(role)
+        navigate_to(@import_yml_page.page_url_value, subdomain: CONFIG['kirby']['import']['paid_company']['subdomain'])
+      end
+      after(:all) { log_out }
+
+      include_examples 'общие элементы страницы'
+      include_examples 'все элементы страницы для роли с повышенными правами', role
+    end
+  end
+
+  context 'когда роль - Владелец' do
+    before(:all) { log_in_as(:user) }
+    after(:all) { log_out }
+
+    context 'когда своя компания с бесплатным пакетом' do
+      before(:all) do
+        navigate_to(@import_yml_page.page_url_value,
+                    subdomain: CONFIG['kirby']['import']['unpaid_company']['subdomain'])
+      end
+
+      include_examples 'общие элементы страницы'
+
+      context 'когда на вкладке "Загрузка товаров"' do
+        before(:all) { @import_yml_page.upload_tab }
+
+        it('присутствует текстовая зона') { expect(@upload_tab.text_zone?).to be true }
+        it 'присутствует активный блок "Формат" со значениями YML, YRL и EDIFACT' do
+          expect(@upload_tab.source_type_label?).to be true
+          expect(@upload_tab.source_type_options).to eq %w[YML YRL EDIFACT]
+        end
+
+        it('доступен режим "Товаров нет"') { expect(@upload_tab.moving_no?).to be true }
+
+        context 'когда выбран режим "Товары есть"' do
+          before(:all) { @upload_tab.moving_yes }
+
+          it('доступен режим "Оставить опубликованными"') { expect(@upload_tab.moving_keep?(2)).to be true }
+          it('доступен режим "Удалить"') { expect(@upload_tab.moving_delete?(2)).to be true }
+          it('не доступен режим "Перенести в архив"') { expect(@upload_tab.moving_archive_not_exists?(2)).to be true }
+          it 'присутствует НЕактивный блок "Сайт магазина"' do
+            expect(@upload_tab.store_url_label?).to be true
+            expect(@upload_tab.store_url_element.disabled?).to be true
+          end
+
+          it 'отсутствуют кнопки "Сохранить" и "Загрузить группы"' do
+            expect(@upload_tab.upload_groups_not_exists?).to be true
+            expect(@upload_tab.save_not_exists?).to be true
+          end
+
+          it('присутствует кнопка "Загрузить"') { expect(@upload_tab.upload_price?).to be true }
+        end
+
+        # TODO: Аналогично, раскипать после того, как обновят образ ножа для ПЦ
+        xcontext 'когда источник - Файл' do
+          before(:all) do
+            @upload_tab.switch_to_source_file
+            @upload_tab.upload_yml(YAML_FILE_PATH)
+            @import_yml_page.settings_tab
+            @settings_tab.save_settings
+            @import_yml_page.upload_tab
+          end
+
+          it('присутствует поле с названием выбранного файла') { expect(@upload_tab.source_file?).to be true }
+          it('присутствует псевдо-ссылка выбора файла') { expect(@upload_tab.file_upload_element.exists?).to be true }
+          it('присутствует ссылка на скачивание прайса') { expect(@upload_tab.download_last_price?).to be true }
+        end
+
+        context 'когда источник - Ссылка' do
+          before(:all) { @upload_tab.switch_to_source_url }
+
+          it('присутствует поле ввода источника прайса') { expect(@upload_tab.source_url?).to be true }
+        end
+      end
+
+      context 'когда на вкладке "Расширенные настройки"' do
+        before(:all) { @import_yml_page.settings_tab }
+
+        it('присутствует заголовок "Выборочное обновление полей"') { expect(@settings_tab.selected_fields?).to be true }
+
+        it 'присутствует заголовок "Выборочное обновление товаров"' do
+          expect(@settings_tab.selected_products?).to be true
+        end
+
+        it('присутствует заголовок "Отчет"') { expect(@settings_tab.notification_label?).to be true }
+
+        it('присутствует заголовок "Загрузка характеристик для фильтров по товарам на вашем сайте"') do
+          expect(@settings_tab.company_traits_label?).to be true
+        end
+
+        it 'присутствует активный чекбокс "Загружать характеристики"' do
+          expect(@settings_tab.company_traits).to eq 'Загружать характеристики'
+          expect(@settings_tab.company_traits_element.checkbox_element.enabled?).to be true
+        end
+
+        it 'все чекбоксы выбора статусов обновляемых товаров активные' do
+          expect(@settings_tab.update_archived).to eq 'Обновлять товары в статусе «Архивный»'
+          expect(@settings_tab.update_archived_element.checkbox_element.enabled?).to be true
+          expect(@settings_tab.update_unpublished).to eq 'Обновлять товары в статусе «Опубликованный на сайте»'
+          expect(@settings_tab.update_unpublished_element.checkbox_element.enabled?).to be true
+        end
+
+        context 'когда источник - Ссылка' do
+          before do
+            @import_yml_page.upload_tab
+            @upload_tab.switch_to_source_url
+            @import_yml_page.settings_tab
+          end
+
+          it 'не отобразится блок "Автообновление"' do
+            expect(@settings_tab.autoupdate_label_not_exists?).to be true
+            expect(@settings_tab.autoupdate_not_exists?).to be true
+          end
+        end
+
+        it 'все чекбоксы в блоке "Выборочное обновление полей" НЕактивные' do
+          CompanySite::ImportYMLPage::SettingsTab::TAGS.each do |field|
+            expect(@settings_tab.send("#{field}_element").disabled?).to be true
+          end
+        end
+
+        it 'все чекбоксы в блоке "Настройка названия товара" НЕактивные' do
+          CompanySite::ImportYMLPage::SettingsTab::NAME_TAGS.each do |field|
+            expect(@settings_tab.send("tag_#{field}_element").disabled?).to be true
+          end
+        end
+
+        it 'чекбокс "Получать отчёт о загрузке товаров и услуг" в блоке "Отчет" НЕактивный' do
+          expect(@settings_tab.notification).to eq 'Получать отчёт о загрузке товаров и услуг'
+          expect(@settings_tab.notification_element.checkbox_element.disabled?).to be true
+        end
+      end
+    end
+
+    context 'когда своя компания с платным пакетом' do
+      before(:all) do
+        navigate_to(@import_yml_page.page_url_value, subdomain: CONFIG['kirby']['import']['paid_company']['subdomain'])
+      end
+
+      include_examples 'общие элементы страницы'
+
+      context 'когда на вкладке "Загрузить товары"' do
+        before(:all) { @import_yml_page.upload_tab }
+
+        it('присутствует текстовая зона') { expect(@upload_tab.text_zone?).to be true }
+        it 'присутствует активный блок "Формат" со значениями YML, YRL и EDIFACT' do
+          expect(@upload_tab.source_type_label?).to be true
+          expect(@upload_tab.source_type_options).to eq %w[YML YRL EDIFACT]
+        end
+
+        it('доступен режим "Товаров нет"') { expect(@upload_tab.moving_no?).to be true }
+
+        context 'когда выбран режим "Товары есть"' do
+          before(:all) { @upload_tab.moving_yes }
+
+          it('доступен режим "Оставить опубликованными"') { expect(@upload_tab.moving_keep?(2)).to be true }
+          it('доступен режим "Удалить"') { expect(@upload_tab.moving_delete?(2)).to be true }
+          it('не доступен режим "Перенести в архив"') { expect(@upload_tab.moving_archive_not_exists?(2)).to be true }
+          it 'присутствует активный блок "Сайт магазина"' do
+            expect(@upload_tab.store_url_label?).to be true
+            expect(@upload_tab.store_url_element.enabled?).to be true
+          end
+
+          it('присутствует кнопка "Загрузить"') { expect(@upload_tab.upload_price?).to be true }
+        end
+
+        # TODO: Аналогично, раскипать после того, как обновят образ ножа для ПЦ
+        xcontext 'когда источник - Файл' do
+          before(:all) do
+            @upload_tab.switch_to_source_file
+            @upload_tab.upload_yml(YAML_FILE_PATH)
+            @import_yml_page.settings_tab
+            @settings_tab.save_settings
+            @import_yml_page.upload_tab
+          end
+
+          it('присутствует поле с названием выбранного файла') { expect(@upload_tab.source_file?).to be true }
+          it('присутствует псевдо-ссылка выбора файла') { expect(@upload_tab.file_upload_element.exists?).to be true }
+          it('присутствует ссылка на скачивание прайса') { expect(@upload_tab.download_last_price?).to be true }
+        end
+
+        context 'когда источник - Ссылка' do
+          before(:all) { @upload_tab.switch_to_source_url }
+
+          it('присутствует поле ввода источника прайса') { expect(@upload_tab.source_url?).to be true }
+        end
+      end
+
+      context 'когда на вкладке "Расширенные настройки"' do
+        before(:all) { @import_yml_page.settings_tab }
+
+        it('присутствует заголовок "Выборочное обновление полей"') { expect(@settings_tab.selected_fields?).to be true }
+
+        it 'присутствует заголовок "Выборочное обновление товаров"' do
+          expect(@settings_tab.selected_products?).to be true
+        end
+        it('присутствует заголовок "Отчет"') { expect(@settings_tab.notification_label?).to be true }
+
+        it('присутствует заголовок "Загрузка характеристик для фильтров по товарам на вашем сайте"') do
+          expect(@settings_tab.company_traits_label?).to be true
+        end
+
+        it 'присутствует активный чекбокс "Загружать характеристики"' do
+          expect(@settings_tab.company_traits).to eq 'Загружать характеристики'
+          expect(@settings_tab.company_traits_element.checkbox_element.enabled?).to be true
+        end
+
+        it 'все чекбоксы выбора статусов обновляемых товаров активные' do
+          expect(@settings_tab.update_archived).to eq 'Обновлять товары в статусе «Архивный»'
+          expect(@settings_tab.update_archived_element.checkbox_element.enabled?).to be true
+          expect(@settings_tab.update_unpublished).to eq 'Обновлять товары в статусе «Опубликованный на сайте»'
+          expect(@settings_tab.update_unpublished_element.checkbox_element.enabled?).to be true
+        end
+
+        context 'когда источник - Ссылка' do
+          before do
+            @import_yml_page.upload_tab
+            @upload_tab.switch_to_source_url
+            @import_yml_page.settings_tab
+          end
+
+          it 'не отобразится блок "Автообновление"' do
+            expect(@settings_tab.autoupdate_label_not_exists?).to be true
+            expect(@settings_tab.autoupdate_not_exists?).to be true
+          end
+        end
+
+        it 'все чекбоксы в блоке "Выборочное обновление полей" активные' do
+          CompanySite::ImportYMLPage::SettingsTab::TAGS.each do |field|
+            expect(@settings_tab.send("#{field}_element").enabled?).to be true
+          end
+        end
+
+        it 'все чекбоксы в блоке "Настройка названия товара" активные' do
+          CompanySite::ImportYMLPage::SettingsTab::NAME_TAGS.each do |field|
+            expect(@settings_tab.send("tag_#{field}_element").enabled?).to be true
+          end
+        end
+
+        it 'чекбокс "Получать отчёт о загрузке товаров и услуг" в блоке "Отчет" активный' do
+          expect(@settings_tab.notification).to eq 'Получать отчёт о загрузке товаров и услуг'
+          expect(@settings_tab.notification_element.checkbox_element.enabled?).to be true
+        end
+      end
+    end
+  end
+  
+  # TODO: Раскипать после обновления дампа на ПЦ.
+  xcontext 'когда авторизованный пользователь' do
+    before do
+      log_in_as(:empty_user)
+      navigate_to(@import_yml_page.page_url_value, subdomain: CONFIG['kirby']['import']['paid_company']['subdomain'])
+    end
+    after { log_out }
+
+    it('нет доступа к просмотру и редактированию - 403 код') do
+      expect(error_403?).to be true
+      expect(@import_yml_page.text).to include 'У Вас недостаточно прав для просмотра данной страницы.'
+    end
+  end
+
+  # TODO: Аналогично, раскипать после обновления дампа на ПЦ.
+  xcontext 'когда неавторизованный пользователь' do
+    before do
+      navigate_to(@import_yml_page.page_url_value, subdomain: CONFIG['kirby']['import']['paid_company']['subdomain'])
+    end
+
+    it('произойдет редирект на страницу авторизации') { expect(Page.current_url).to include '/users/session/new' }
+  end
+
+  include_context 'роль с повышенными правами', :admin, 'Супер-юзер'
+  include_context 'роль с повышенными правами', :editor, 'Редактор СК'
+  include_context 'роль с повышенными правами', :franchise_ru, 'Франшиза (регион компании)'
+
+  context 'когда роль - Франшиза (из другого региона)' do
+    before(:all) do
+      log_in_as(:franchise_kz)
+      navigate_to(@import_yml_page.page_url_value, subdomain: CONFIG['kirby']['import']['paid_company']['subdomain'])
+    end
+    after(:all) { log_out }
+
+    context 'когда на вкладке "Загрузить товары"' do
+      before(:all) { @import_yml_page.upload_tab }
+
+      it 'не отобразятся кнопки сохранения и загрузки' do
+        expect(@upload_tab.save_not_exists?).to be true
+        expect(@upload_tab.upload_price_not_exists?).to be true
+        expect(@upload_tab.upload_groups_not_exists?).to be true
+      end
+    end
+  end
+end
diff --git a/lib/apress/selenium_products/version.rb b/lib/apress/selenium_products/version.rb
index 57dab3b..52048b1 100644
--- a/lib/apress/selenium_products/version.rb
+++ b/lib/apress/selenium_products/version.rb
@@ -2,6 +2,6 @@
 
 module Apress
   module SeleniumProducts
-    VERSION = '1.0.4'
+    VERSION = '1.1.0'
   end
 end
diff --git a/lib/pages/company_site/import_yml_page.rb b/lib/pages/company_site/import_yml_page.rb
new file mode 100644
index 0000000..92b8c7e
--- /dev/null
+++ b/lib/pages/company_site/import_yml_page.rb
@@ -0,0 +1,103 @@
+# frozen_string_literal: true
+
+module CompanySite
+  class ImportYMLPage < Page
+    page_url '/admin/import_yml/edit'
+    expected_title %r{Загрузка товаров из YML/YRL - .+-.+}
+
+    h1(:header, css: '.company-admin-page-header h1')
+    link(:upload_tab, css: 'a[href="#upload"]')
+    link(:settings_tab, css: 'a[href="#settings"]')
+    link(:warnings_tab, css: 'a[href="#errors"]')
+
+    class UploadTab < ImportYMLPage
+      MOVING = %i[none keep delete archive].freeze
+
+      div(:text_zone, css: '.yml-import-textzone')
+      label(:source_label, css: '.yml-import-label-required')
+
+      # Элементы источника - Ссылка
+      link(:switch_to_source_url, css: 'a[href="#switcher-tabs-1"]')
+      text_field(:source_url, css: '.js-url-field')
+      div(:source_url_validation_message, css: '#switcher-tabs-1 .js-validation-message')
+
+      # Элементы источника - Файл
+      link(:switch_to_source_file, css: 'a[href="#switcher-tabs-2"]')
+      text_field(:source_file, css: '.yml-file-name')
+      span(:file_upload, xpath: '//*[@type="file"]')
+      link(:download_last_price, css: '.custom-yml-link')
+
+      # Тип источника (формат)
+      div(:source_type_label, xpath: '//label[contains(text(), "Формат:")]')
+      select_list(:source_type, css: '#online_store_source_type')
+      link(:warnings_link, css: '.js-open-errors-tab')
+
+      # Сайт магазина
+      label(:store_url_label, xpath: '//label[contains(text(), "Сайт магазина:")]')
+      text_field(:store_url, css: '#online_store_store_url')
+
+      # Тип магазина
+      label(:store_type_label, xpath: '//label[contains(text(), "Тип магазина:")]')
+      select_list(:store_type, css: '#online_store_store_type')
+
+      # Выбор режима загрузки
+      div(:care_about_products, css: '.form-item-input-box .notice')
+      link(:moving_no, css: 'a[href="#switcher-tabs-3"]')
+      link(:moving_yes, css: 'a[href="#switcher-tabs-4"]')
+
+      MOVING.each do |type|
+        select("moving_#{type}", xpath: "//select[@id='moving']//option[@value='#{type}']")
+      end
+
+      # Блок кнопок (Сохранение, загрузка прайса и товаров)
+      button(:save, css: '.js-yml-import-button.js-yml-save')
+      button(:upload_price, css: '.js-yml-import-button.js-yml-upload')
+      button(:upload_groups, css: '.js-yml-import-button.js-yml-groups-upload')
+
+      def upload_yml(file_path)
+        upload_file(file_upload_element, file_path)
+      end
+    end
+
+    class SettingsTab < ImportYMLPage
+      TAGS      = %w[name image_urls announce description price wholesale_price exists product_group].freeze
+      NAME_TAGS = %w[name typePrefix vendor model].freeze
+
+      label(:selected_fields, xpath: '//label[text()="Выборочное обновление полей"]')
+      label(:selected_products, xpath: '//label[text()="Выборочное обновление товаров"]')
+
+      div(:update_archived, xpath: '//div[child::*[@id="online_store_update_archived"]]')
+      div(:update_unpublished, xpath: '//div[child::*[@id="online_store_update_unpublished"]]')
+
+      # Автообновление
+      label(:autoupdate_label, xpath: '//label[text()="Автообновление"]')
+      div(:autoupdate, xpath: '//div[child::*[@id="online_store_updating_settings_attributes_enabled"]]')
+      label(:autoupdate_period_label, xpath: '//label[text()="Интервал обновления"]')
+      text_field(:autoupdate_period, css: '#online_store_updating_settings_attributes_period')
+      label(:autoupdate_start_date_label, xpath: '//label[text()="Точное время обновления (MSK)"]')
+      text_field(:autoupdate_start_date, css: '#online_store_updating_settings_attributes_start_date')
+
+      # Отчет
+      label(:notification_label, xpath: '//label[text()="Отчет"]')
+      div(:notification, xpath: '//div[child::*[@id="online_store_send_notifications"]]')
+
+      # Пользовательские характеристики
+      label(:company_traits_label,
+            xpath: '//label[contains(text(), "Загрузка характеристик") and contains(@class, "tab-title")]')
+      div(:company_traits, xpath: '//div[child::*[@id="online_store_update_company_traits"]]')
+      label(:name_tags, xpath: '//label[text()="Настройка названия товара"]')
+      button(:save, css: '.yml-import-button.js-yml-save')
+      button(:save_settings, xpath: '//div[contains(@class, "js-yml-settings-buttons")]//input[@value="Сохранить"]')
+      
+      # Теги для обновления
+      TAGS.each do |field|
+        checkbox(field, css: "#online_store_selected_fields_#{field}")
+      end
+
+      # Теги, попадающие в название
+      NAME_TAGS.each do |field|
+        checkbox("tag_#{field}", css: "#online_store_product_name_tags_#{field}")
+      end
+    end
+  end
+end


Reviews:
user: login: apress-hound
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-25T07:11:41Z
user: login: Fort-Nox
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-25T07:29:21Z
user: login: Fort-Nox
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-25T07:32:23Z
user: login: KirillGaliulin
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-25T07:45:43Z
user: login: KirillGaliulin
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-25T07:48:49Z
user: login: KirillGaliulin
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-25T07:52:16Z
user: login: KirillGaliulin
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-25T07:54:58Z
user: login: apress-hound
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-25T07:58:44Z
user: login: Fort-Nox
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-25T08:57:02Z
user: login: Fort-Nox
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-25T09:00:17Z
user: login: Fort-Nox
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-25T09:00:42Z
user: login: apress-hound
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-25T09:18:21Z
user: login: KirillGaliulin
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-25T09:20:12Z
user: login: Fort-Nox
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-25T09:21:46Z
user: login: Fort-Nox
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-25T09:24:13Z
user: login: SeniorTe
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-28T04:59:39Z

Review comments:
diff_hunk: @@ -0,0 +1,104 @@
+# frozen_string_literal: true
+
+module CompanySite
+  class ImportYMLPage < Page
+    page_url '/admin/import_yml/edit'
+    expected_title %r{Загрузка товаров из YML\/YRL - .+-.+}
+
+    h1(:header, css: '.company-admin-page-header h1')
+    link(:upload_tab, css: 'a[href="#upload"]')
+    link(:settings_tab, css: 'a[href="#settings"]')
+    link(:warnings_tab, css: 'a[href="#errors"]')
+
+    class UploadTab < ImportYMLPage
+      MOVING = %i[none keep delete archive].freeze
+
+      div(:text_zone, css: '.yml-import-textzone')
+      label(:source_label, css: '.yml-import-label-required')
+
+      # Элементы источника - Ссылка
+      link(:switch_to_source_url, css: 'a[href="#switcher-tabs-1"]')
+      text_field(:source_url, css: '.js-url-field')
+      div(:source_url_validation_message, css: '#switcher-tabs-1 .js-validation-message')
+
+      # Элементы источника - Файл
+      link(:switch_to_source_file, css: 'a[href="#switcher-tabs-2"]')
+      text_field(:source_file, css: '.yml-file-name')
+      span(:file_upload, xpath: '//*[@type="file"]')
+      link(:download_last_price, css: '.custom-yml-link')
+
+      # Тип источника (формат)
+      div(:source_type_label, xpath: '//label[contains(text(), "Формат:")]')
+      select_list(:source_type, css: '#online_store_source_type')
+      link(:warnings_link, css: '.js-open-errors-tab')
+
+      # Сайт магазина
+      label(:store_url_label, xpath: '//label[contains(text(), "Сайт магазина:")]')
+      text_field(:store_url, css: '#online_store_store_url')
+
+      # Тип магазина
+      label(:store_type_label, xpath: '//label[contains(text(), "Тип магазина:")]')
+      select_list(:store_type, css: '#online_store_store_type')
+
+      # Выбор режима загрузки
+      div(:care_about_products, css: '.form-item-input-box .notice')
+      link(:moving_no, css: 'a[href="#switcher-tabs-3"]')
+      link(:moving_yes, css: 'a[href="#switcher-tabs-4"]')
+
+      MOVING.each do |type|
+        select("moving_#{type}", xpath: "//select[@id='moving']//option[@value='#{type}']")
+      end
+
+      # Блок кнопок (Сохранение, загрузка прайса и товаров)
+      button(:save, css: '.js-yml-import-button.js-yml-save')
+      button(:upload_price, css: '.js-yml-import-button.js-yml-upload')
+      button(:upload_groups, css: '.js-yml-import-button.js-yml-groups-upload')
+
+      def upload_yml(file_path)
+        upload_file(file_upload_element, file_path)
+      end
+    end
+
+    class SettingsTab < ImportYMLPage
+      TAGS      = %w[name image_urls announce description price wholesale_price exists product_group].freeze
+      NAME_TAGS = %w[name typePrefix vendor model].freeze
+
+      label(:selected_fields, xpath: '//label[text()="Выборочное обновление полей"]')
+      label(:selected_products, xpath: '//label[text()="Выборочное обновление товаров"]')
+
+      div(:update_archived, xpath: '//div[child::*[@id="online_store_update_archived"]]')
+      div(:update_unpublished, xpath: '//div[child::*[@id="online_store_update_unpublished"]]')
+
+      # Автообновление
+      label(:autoupdate_label, xpath: '//label[text()="Автообновление"]')
+      div(:autoupdate, xpath: '//div[child::*[@id="online_store_updating_settings_attributes_enabled"]]')
+      label(:autoupdate_period_label, xpath: '//label[text()="Интервал обновления"]')
+      text_field(:autoupdate_period, css: '#online_store_updating_settings_attributes_period')
+      label(:autoupdate_start_date_label, xpath: '//label[text()="Точное время обновления (MSK)"]')
+      text_field(:autoupdate_start_date, css: '#online_store_updating_settings_attributes_start_date')
+
+      # Отчет
+      label(:notification_label, xpath: '//label[text()="Отчет"]')
+      div(:notification, xpath: '//div[child::*[@id="online_store_send_notifications"]]')
+
+      # Пользовательские характеристики
+      label(:company_traits_label,
+            xpath: '//label[text()="Загрузка характеристик для фильтров по товарам на вашем сайте"]')
+      div(:company_traits, xpath: '//div[child::*[@id="online_store_update_company_traits"]]')
+
+      label(:name_tags, xpath: '//label[text()="Настройка названия товара"]')
+      button(:save, css: '.yml-import-button.js-yml-save')
+      button(:save_settings, xpath: '//div[contains(@class, "js-yml-settings-buttons")]//input[@value="Сохранить"]')
+      
path: lib/pages/company_site/import_yml_page.rb
user: login: apress-hound
body: [Correctable] Layout/TrailingWhitespace: Trailing whitespace detected.
created_at: 2025-04-25T07:11:41Z
author_association: NONE
diff_hunk: @@ -0,0 +1,104 @@
+# frozen_string_literal: true
+
+module CompanySite
+  class ImportYMLPage < Page
+    page_url '/admin/import_yml/edit'
+    expected_title %r{Загрузка товаров из YML\/YRL - .+-.+}
path: lib/pages/company_site/import_yml_page.rb
user: login: apress-hound
body: [Correctable] Style/RedundantRegexpEscape: Redundant escape inside regexp literal
created_at: 2025-04-25T07:11:41Z
author_association: NONE
diff_hunk: @@ -0,0 +1,104 @@
+# frozen_string_literal: true
+
+module CompanySite
+  class ImportYMLPage < Page
+    page_url '/admin/import_yml/edit'
+    expected_title %r{Загрузка товаров из YML\/YRL - .+-.+}
+
+    h1(:header, css: '.company-admin-page-header h1')
+    link(:upload_tab, css: 'a[href="#upload"]')
+    link(:settings_tab, css: 'a[href="#settings"]')
+    link(:warnings_tab, css: 'a[href="#errors"]')
+
+    class UploadTab < ImportYMLPage
+      MOVING = %i[none keep delete archive].freeze
+
+      div(:text_zone, css: '.yml-import-textzone')
+      label(:source_label, css: '.yml-import-label-required')
+
+      # Элементы источника - Ссылка
+      link(:switch_to_source_url, css: 'a[href="#switcher-tabs-1"]')
+      text_field(:source_url, css: '.js-url-field')
+      div(:source_url_validation_message, css: '#switcher-tabs-1 .js-validation-message')
+
+      # Элементы источника - Файл
+      link(:switch_to_source_file, css: 'a[href="#switcher-tabs-2"]')
+      text_field(:source_file, css: '.yml-file-name')
+      span(:file_upload, xpath: '//*[@type="file"]')
+      link(:download_last_price, css: '.custom-yml-link')
+
+      # Тип источника (формат)
+      div(:source_type_label, xpath: '//label[contains(text(), "Формат:")]')
+      select_list(:source_type, css: '#online_store_source_type')
+      link(:warnings_link, css: '.js-open-errors-tab')
+
+      # Сайт магазина
+      label(:store_url_label, xpath: '//label[contains(text(), "Сайт магазина:")]')
+      text_field(:store_url, css: '#online_store_store_url')
+
+      # Тип магазина
+      label(:store_type_label, xpath: '//label[contains(text(), "Тип магазина:")]')
+      select_list(:store_type, css: '#online_store_store_type')
+
+      # Выбор режима загрузки
+      div(:care_about_products, css: '.form-item-input-box .notice')
+      link(:moving_no, css: 'a[href="#switcher-tabs-3"]')
+      link(:moving_yes, css: 'a[href="#switcher-tabs-4"]')
+
+      MOVING.each do |type|
+        select("moving_#{type}", xpath: "//select[@id='moving']//option[@value='#{type}']")
+      end
+
+      # Блок кнопок (Сохранение, загрузка прайса и товаров)
+      button(:save, css: '.js-yml-import-button.js-yml-save')
+      button(:upload_price, css: '.js-yml-import-button.js-yml-upload')
+      button(:upload_groups, css: '.js-yml-import-button.js-yml-groups-upload')
+
+      def upload_yml(file_path)
+        upload_file(file_upload_element, file_path)
+      end
+    end
+
+    class SettingsTab < ImportYMLPage
+      TAGS      = %w[name image_urls announce description price wholesale_price exists product_group].freeze
+      NAME_TAGS = %w[name typePrefix vendor model].freeze
+
+      label(:selected_fields, xpath: '//label[text()="Выборочное обновление полей"]')
+      label(:selected_products, xpath: '//label[text()="Выборочное обновление товаров"]')
+
+      div(:update_archived, xpath: '//div[child::*[@id="online_store_update_archived"]]')
+      div(:update_unpublished, xpath: '//div[child::*[@id="online_store_update_unpublished"]]')
+
+      # Автообновление
+      label(:autoupdate_label, xpath: '//label[text()="Автообновление"]')
+      div(:autoupdate, xpath: '//div[child::*[@id="online_store_updating_settings_attributes_enabled"]]')
+      label(:autoupdate_period_label, xpath: '//label[text()="Интервал обновления"]')
+      text_field(:autoupdate_period, css: '#online_store_updating_settings_attributes_period')
+      label(:autoupdate_start_date_label, xpath: '//label[text()="Точное время обновления (MSK)"]')
+      text_field(:autoupdate_start_date, css: '#online_store_updating_settings_attributes_start_date')
+
+      # Отчет
+      label(:notification_label, xpath: '//label[text()="Отчет"]')
+      div(:notification, xpath: '//div[child::*[@id="online_store_send_notifications"]]')
+
+      # Пользовательские характеристики
+      label(:company_traits_label,
+            xpath: '//label[text()="Загрузка характеристик для фильтров по товарам на вашем сайте"]')
+      div(:company_traits, xpath: '//div[child::*[@id="online_store_update_company_traits"]]')
+
+      label(:name_tags, xpath: '//label[text()="Настройка названия товара"]')
+      button(:save, css: '.yml-import-button.js-yml-save')
+      button(:save_settings, xpath: '//div[contains(@class, "js-yml-settings-buttons")]//input[@value="Сохранить"]')
+      
path: lib/pages/company_site/import_yml_page.rb
user: login: Fort-Nox
body: Поправил.
created_at: 2025-04-25T07:29:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,104 @@
+# frozen_string_literal: true
+
+module CompanySite
+  class ImportYMLPage < Page
+    page_url '/admin/import_yml/edit'
+    expected_title %r{Загрузка товаров из YML\/YRL - .+-.+}
path: lib/pages/company_site/import_yml_page.rb
user: login: Fort-Nox
body: Изначально так было в [проекте](https://github.com/abak-press/blizko/blob/020156d665c721395a19176853aacf17089c33d0/selenium/lib/pages/company_site_pages/kirby/import_yml_page.rb#L3), но решил поправить, думаю что это избыточно.
created_at: 2025-04-25T07:32:23Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,429 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Кирби: политики доступа страницы импорта YML', feature: 'Кирби: политики доступа страницы импорта YML' do
+  before(:all) do
+    @import_yml_page = CompanySite::ImportYMLPage.new
+    @upload_tab      = CompanySite::ImportYMLPage::UploadTab.new
+    @settings_tab    = CompanySite::ImportYMLPage::SettingsTab.new
+  end
+
+  shared_examples 'общие элементы страницы' do
+    it 'присутствует title в формате "Загрузка товаров из YML/YRL - %название компании% - %основной регион%"' do
+      expect(@import_yml_page.has_expected_title?).to be true
+    end
+
+    it 'присутствует заголовок страницы "Загрузить товары в формате Яндекс.Маркет (YML/YRL)"' do
+      expect(@import_yml_page.header).to eq 'Загрузить товары в формате Яндекс.Маркет (YML/YRL)'
+    end
+
+    it 'присутствуют вкладки "Загрузить товары" и "Расширенные настройки"' do
+      expect(@import_yml_page.upload_tab?).to be true
+      expect(@import_yml_page.settings_tab?).to be true
+    end
+  end
+
+  shared_examples 'все элементы страницы для роли с повышенными правами' do |role|
+    context 'когда на вкладке "Загрузить товары"' do
+      before(:all) { @import_yml_page.upload_tab }
+
+      it('присутствует текстовая зона') { expect(@upload_tab.text_zone?).to be true }
+
+      it 'присутствует активный блок "Формат" со значениями YML, YRL и EDIFACT' do
+        expect(@upload_tab.source_type_label?).to be true
+        expect(@upload_tab.source_type_options).to eq %w[YML YRL EDIFACT]
+      end
+
+      it('доступен режим "Товаров нет"') { expect(@upload_tab.moving_no?).to be true }
+
+      context 'когда выбран режим "Товары есть"' do
+        before(:all) { @upload_tab.moving_yes }
+
+        it('доступен режим "Оставить опубликованными"') { expect(@upload_tab.moving_keep?(2)).to be true }
+        it('доступен режим "Удалить"') { expect(@upload_tab.moving_delete?(2)).to be true }
+        it('доступен режим "Перенести в архив"') { expect(@upload_tab.moving_archive?(2)).to be true }
+
+        it('присутствует кнопка "Загрузить"') { expect(@upload_tab.upload_price?).to be true }
+      end
+
+      xcontext 'когда источник - Файл' do
path: lib/apress/selenium_products/spec/company_site/kirby/import/import_yml_policy_spec.rb
user: login: KirillGaliulin
body: Лучше комментарием добавить прям в коде почему скипается и когда расскипать кратенько
А то так и останется надолгое время заскипаным) 

Аналогично для других пропущенных тестов
created_at: 2025-04-25T07:45:43Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,103 @@
+# frozen_string_literal: true
+
+module CompanySite
+  class ImportYMLPage < Page
+    page_url '/admin/import_yml/edit'
+    expected_title %r{Загрузка товаров из YML/YRL - .+-.+}
+
+    h1(:header, css: '.company-admin-page-header h1')
+    link(:upload_tab, css: 'a[href="#upload"]')
+    link(:settings_tab, css: 'a[href="#settings"]')
+    link(:warnings_tab, css: 'a[href="#errors"]')
+
+    class UploadTab < ImportYMLPage
+      MOVING = %i[none keep delete archive].freeze
+
+      div(:text_zone, css: '.yml-import-textzone')
+      label(:source_label, css: '.yml-import-label-required')
+
+      # Элементы источника - Ссылка
+      link(:switch_to_source_url, css: 'a[href="#switcher-tabs-1"]')
+      text_field(:source_url, css: '.js-url-field')
+      div(:source_url_validation_message, css: '#switcher-tabs-1 .js-validation-message')
+
+      # Элементы источника - Файл
+      link(:switch_to_source_file, css: 'a[href="#switcher-tabs-2"]')
+      text_field(:source_file, css: '.yml-file-name')
+      span(:file_upload, xpath: '//*[@type="file"]')
+      link(:download_last_price, css: '.custom-yml-link')
+
+      # Тип источника (формат)
+      div(:source_type_label, xpath: '//label[contains(text(), "Формат:")]')
+      select_list(:source_type, css: '#online_store_source_type')
+      link(:warnings_link, css: '.js-open-errors-tab')
+
+      # Сайт магазина
+      label(:store_url_label, xpath: '//label[contains(text(), "Сайт магазина:")]')
+      text_field(:store_url, css: '#online_store_store_url')
+
+      # Тип магазина
+      label(:store_type_label, xpath: '//label[contains(text(), "Тип магазина:")]')
+      select_list(:store_type, css: '#online_store_store_type')
+
+      # Выбор режима загрузки
+      div(:care_about_products, css: '.form-item-input-box .notice')
+      link(:moving_no, css: 'a[href="#switcher-tabs-3"]')
+      link(:moving_yes, css: 'a[href="#switcher-tabs-4"]')
+
+      MOVING.each do |type|
+        select("moving_#{type}", xpath: "//select[@id='moving']//option[@value='#{type}']")
+      end
+
+      # Блок кнопок (Сохранение, загрузка прайса и товаров)
+      button(:save, css: '.js-yml-import-button.js-yml-save')
+      button(:upload_price, css: '.js-yml-import-button.js-yml-upload')
+      button(:upload_groups, css: '.js-yml-import-button.js-yml-groups-upload')
+
+      def upload_yml(file_path)
+        upload_file(file_upload_element, file_path)
+      end
+    end
+
+    class SettingsTab < ImportYMLPage
+      TAGS      = %w[name image_urls announce description price wholesale_price exists product_group].freeze
+      NAME_TAGS = %w[name typePrefix vendor model].freeze
+
+      label(:selected_fields, xpath: '//label[text()="Выборочное обновление полей"]')
+      label(:selected_products, xpath: '//label[text()="Выборочное обновление товаров"]')
+
+      div(:update_archived, xpath: '//div[child::*[@id="online_store_update_archived"]]')
+      div(:update_unpublished, xpath: '//div[child::*[@id="online_store_update_unpublished"]]')
+
+      # Автообновление
+      label(:autoupdate_label, xpath: '//label[text()="Автообновление"]')
+      div(:autoupdate, xpath: '//div[child::*[@id="online_store_updating_settings_attributes_enabled"]]')
+      label(:autoupdate_period_label, xpath: '//label[text()="Интервал обновления"]')
+      text_field(:autoupdate_period, css: '#online_store_updating_settings_attributes_period')
+      label(:autoupdate_start_date_label, xpath: '//label[text()="Точное время обновления (MSK)"]')
+      text_field(:autoupdate_start_date, css: '#online_store_updating_settings_attributes_start_date')
+
+      # Отчет
+      label(:notification_label, xpath: '//label[text()="Отчет"]')
+      div(:notification, xpath: '//div[child::*[@id="online_store_send_notifications"]]')
+
+      # Пользовательские характеристики
+      label(:company_traits_label,
+            xpath: '//label[text()="Загрузка характеристик для фильтров по товарам на вашем сайте"]')
path: lib/pages/company_site/import_yml_page.rb
user: login: KirillGaliulin
body: Опасно делать локатор по такому длинному тексту, т.к. может измениться потом разработчиками какая-то небольшая часть из этого текста, и весь локатор будет неактуальным
Есть ли возможность иначе локатор определить? Если нет, то лучше через `contains` с важными словами, которые точно не поменяются
created_at: 2025-04-25T07:48:49Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,104 @@
+# frozen_string_literal: true
+
+module CompanySite
+  class ImportYMLPage < Page
+    page_url '/admin/import_yml/edit'
+    expected_title %r{Загрузка товаров из YML\/YRL - .+-.+}
+
+    h1(:header, css: '.company-admin-page-header h1')
+    link(:upload_tab, css: 'a[href="#upload"]')
+    link(:settings_tab, css: 'a[href="#settings"]')
+    link(:warnings_tab, css: 'a[href="#errors"]')
+
+    class UploadTab < ImportYMLPage
+      MOVING = %i[none keep delete archive].freeze
+
+      div(:text_zone, css: '.yml-import-textzone')
+      label(:source_label, css: '.yml-import-label-required')
+
+      # Элементы источника - Ссылка
+      link(:switch_to_source_url, css: 'a[href="#switcher-tabs-1"]')
+      text_field(:source_url, css: '.js-url-field')
+      div(:source_url_validation_message, css: '#switcher-tabs-1 .js-validation-message')
+
+      # Элементы источника - Файл
+      link(:switch_to_source_file, css: 'a[href="#switcher-tabs-2"]')
+      text_field(:source_file, css: '.yml-file-name')
+      span(:file_upload, xpath: '//*[@type="file"]')
+      link(:download_last_price, css: '.custom-yml-link')
+
+      # Тип источника (формат)
+      div(:source_type_label, xpath: '//label[contains(text(), "Формат:")]')
+      select_list(:source_type, css: '#online_store_source_type')
+      link(:warnings_link, css: '.js-open-errors-tab')
+
+      # Сайт магазина
+      label(:store_url_label, xpath: '//label[contains(text(), "Сайт магазина:")]')
+      text_field(:store_url, css: '#online_store_store_url')
+
+      # Тип магазина
+      label(:store_type_label, xpath: '//label[contains(text(), "Тип магазина:")]')
+      select_list(:store_type, css: '#online_store_store_type')
+
+      # Выбор режима загрузки
+      div(:care_about_products, css: '.form-item-input-box .notice')
+      link(:moving_no, css: 'a[href="#switcher-tabs-3"]')
+      link(:moving_yes, css: 'a[href="#switcher-tabs-4"]')
+
+      MOVING.each do |type|
+        select("moving_#{type}", xpath: "//select[@id='moving']//option[@value='#{type}']")
+      end
+
+      # Блок кнопок (Сохранение, загрузка прайса и товаров)
+      button(:save, css: '.js-yml-import-button.js-yml-save')
+      button(:upload_price, css: '.js-yml-import-button.js-yml-upload')
+      button(:upload_groups, css: '.js-yml-import-button.js-yml-groups-upload')
+
+      def upload_yml(file_path)
+        upload_file(file_upload_element, file_path)
+      end
+    end
+
+    class SettingsTab < ImportYMLPage
+      TAGS      = %w[name image_urls announce description price wholesale_price exists product_group].freeze
+      NAME_TAGS = %w[name typePrefix vendor model].freeze
+
+      label(:selected_fields, xpath: '//label[text()="Выборочное обновление полей"]')
+      label(:selected_products, xpath: '//label[text()="Выборочное обновление товаров"]')
+
+      div(:update_archived, xpath: '//div[child::*[@id="online_store_update_archived"]]')
+      div(:update_unpublished, xpath: '//div[child::*[@id="online_store_update_unpublished"]]')
+
+      # Автообновление
+      label(:autoupdate_label, xpath: '//label[text()="Автообновление"]')
+      div(:autoupdate, xpath: '//div[child::*[@id="online_store_updating_settings_attributes_enabled"]]')
+      label(:autoupdate_period_label, xpath: '//label[text()="Интервал обновления"]')
+      text_field(:autoupdate_period, css: '#online_store_updating_settings_attributes_period')
+      label(:autoupdate_start_date_label, xpath: '//label[text()="Точное время обновления (MSK)"]')
+      text_field(:autoupdate_start_date, css: '#online_store_updating_settings_attributes_start_date')
+
+      # Отчет
+      label(:notification_label, xpath: '//label[text()="Отчет"]')
+      div(:notification, xpath: '//div[child::*[@id="online_store_send_notifications"]]')
+
+      # Пользовательские характеристики
+      label(:company_traits_label,
+            xpath: '//label[text()="Загрузка характеристик для фильтров по товарам на вашем сайте"]')
+      div(:company_traits, xpath: '//div[child::*[@id="online_store_update_company_traits"]]')
+
+      label(:name_tags, xpath: '//label[text()="Настройка названия товара"]')
+      button(:save, css: '.yml-import-button.js-yml-save')
+      button(:save_settings, xpath: '//div[contains(@class, "js-yml-settings-buttons")]//input[@value="Сохранить"]')
+      
path: lib/pages/company_site/import_yml_page.rb
user: login: KirillGaliulin
body: Эти комментарии можно позакрывать, т.к. очень некритичные замечания и ты их поправил. Но решай сам)
created_at: 2025-04-25T07:52:16Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,104 @@
+# frozen_string_literal: true
+
+module CompanySite
+  class ImportYMLPage < Page
+    page_url '/admin/import_yml/edit'
+    expected_title %r{Загрузка товаров из YML\/YRL - .+-.+}
path: lib/pages/company_site/import_yml_page.rb
user: login: KirillGaliulin
body: Сомнительно, но окЭй))
Нетипичное определение переменной
created_at: 2025-04-25T07:54:58Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,434 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Кирби: политики доступа страницы импорта YML', feature: 'Кирби: политики доступа страницы импорта YML' do
+  before(:all) do
+    @import_yml_page = CompanySite::ImportYMLPage.new
+    @upload_tab      = CompanySite::ImportYMLPage::UploadTab.new
+    @settings_tab    = CompanySite::ImportYMLPage::SettingsTab.new
+  end
+
+  shared_examples 'общие элементы страницы' do
+    it 'присутствует title в формате "Загрузка товаров из YML/YRL - %название компании% - %основной регион%"' do
+      expect(@import_yml_page.has_expected_title?).to be true
+    end
+
+    it 'присутствует заголовок страницы "Загрузить товары в формате Яндекс.Маркет (YML/YRL)"' do
+      expect(@import_yml_page.header).to eq 'Загрузить товары в формате Яндекс.Маркет (YML/YRL)'
+    end
+
+    it 'присутствуют вкладки "Загрузить товары" и "Расширенные настройки"' do
+      expect(@import_yml_page.upload_tab?).to be true
+      expect(@import_yml_page.settings_tab?).to be true
+    end
+  end
+
+  shared_examples 'все элементы страницы для роли с повышенными правами' do |role|
+    context 'когда на вкладке "Загрузить товары"' do
+      before(:all) { @import_yml_page.upload_tab }
+
+      it('присутствует текстовая зона') { expect(@upload_tab.text_zone?).to be true }
+
+      it 'присутствует активный блок "Формат" со значениями YML, YRL и EDIFACT' do
+        expect(@upload_tab.source_type_label?).to be true
+        expect(@upload_tab.source_type_options).to eq %w[YML YRL EDIFACT]
+      end
+
+      it('доступен режим "Товаров нет"') { expect(@upload_tab.moving_no?).to be true }
+
+      context 'когда выбран режим "Товары есть"' do
+        before(:all) { @upload_tab.moving_yes }
+
+        it('доступен режим "Оставить опубликованными"') { expect(@upload_tab.moving_keep?(2)).to be true }
+        it('доступен режим "Удалить"') { expect(@upload_tab.moving_delete?(2)).to be true }
+        it('доступен режим "Перенести в архив"') { expect(@upload_tab.moving_archive?(2)).to be true }
+
+        it('присутствует кнопка "Загрузить"') { expect(@upload_tab.upload_price?).to be true }
+      end
+
+      #TODO: Раскипать после того, как обновят образ ножа для ПЦ, тест пропускается так как файла по пути /test_files/pulscen пока нет.
+      xcontext 'когда источник - Файл' do
+        before(:all) do
+          @upload_tab.switch_to_source_file
+          @upload_tab.upload_yml(YAML_FILE_PATH)
+          @import_yml_page.settings_tab
+          @settings_tab.save_settings
+          @import_yml_page.upload_tab
+        end
+
+        it('присутствует поле с названием выбранного файла') { expect(@upload_tab.source_file?).to be true }
+        it('присутствует псевдо-ссылка выбора файла') { expect(@upload_tab.file_upload_element.exists?).to be true }
+        it('присутствует ссылка на скачивание прайса') { expect(@upload_tab.download_last_price?).to be true }
+      end
+
+      context 'когда источник - Ссылка' do
+        before(:all) { @upload_tab.switch_to_source_url }
+
+        it('присутствует поле ввода источника прайса') { expect(@upload_tab.source_url?).to be true }
+      end
+    end
+
+    context 'когда на вкладке "Расширенные настройки"' do
+      before(:all) { @import_yml_page.settings_tab }
+
+      it('присутствует заголовок "Выборочное обновление полей"') { expect(@settings_tab.selected_fields?).to be true }
+
+      it 'присутствует заголовок "Выборочное обновление товаров"' do
+        expect(@settings_tab.selected_products?).to be true
+      end
+      it('присутствует заголовок "Отчет"') { expect(@settings_tab.notification_label?).to be true }
+
+      it('присутствует заголовок "Загрузка характеристик для фильтров по товарам на вашем сайте"') do
+        expect(@settings_tab.company_traits_label?).to be true
+      end
+
+      it 'присутствует активный чекбокс "Загружать характеристики"' do
+        expect(@settings_tab.company_traits).to eq 'Загружать характеристики'
+        expect(@settings_tab.company_traits_element.checkbox_element.enabled?).to be true
+      end
+
+      it 'все чекбоксы выбора статусов обновляемых товаров активные' do
+        expect(@settings_tab.update_archived).to eq 'Обновлять товары в статусе «Архивный»'
+        expect(@settings_tab.update_archived_element.checkbox_element.enabled?).to be true
+        expect(@settings_tab.update_unpublished).to eq 'Обновлять товары в статусе «Опубликованный на сайте»'
+        expect(@settings_tab.update_unpublished_element.checkbox_element.enabled?).to be true
+      end
+
+      it 'все чекбоксы в блоке "Выборочное обновление полей" активные' do
+        CompanySite::ImportYMLPage::SettingsTab::TAGS.each do |field|
+          expect(@settings_tab.send("#{field}_element").enabled?).to be true
+        end
+      end
+
+      it 'все чекбоксы в блоке "Настройка названия товара" активные' do
+        CompanySite::ImportYMLPage::SettingsTab::NAME_TAGS.each do |field|
+          expect(@settings_tab.send("tag_#{field}_element").enabled?).to be true
+        end
+      end
+
+      it 'чекбокс "Получать отчёт о загрузке товаров и услуг" в блоке "Отчет" активный' do
+        expect(@settings_tab.notification).to eq 'Получать отчёт о загрузке товаров и услуг'
+        expect(@settings_tab.notification_element.checkbox_element.enabled?).to be true
+      end
+
+      context 'когда источник - Ссылка' do
+        before(:all) do
+          @import_yml_page.upload_tab
+          @upload_tab.switch_to_source_url
+          @import_yml_page.settings_tab
+        end
+
+        it 'отобразится активный чекбокс "Включить автоматическое обновление" в блоке "Автообновление"' do
+          expect(@settings_tab.autoupdate_label).to eq 'Автообновление'
+          expect(@settings_tab.autoupdate_element.checkbox_element.enabled?).to be true
+        end
+
+        context 'когда отмечен чекбокс "Включить автоматическое обновление"' do
+          before(:all) { @settings_tab.autoupdate_element.checkbox_element.check }
+
+          it 'отобразится блок с полями "Интервал обновления" и "Точное время обновления (MSK)"' do
+            expect(@settings_tab.autoupdate_period_label?).to be true
+            expect(@settings_tab.autoupdate_period?).to be true
+            expect(@settings_tab.autoupdate_start_date_label?).to be true
+            expect(@settings_tab.autoupdate_start_date).to be_truthy
+          end
+        end
+      end
+    end
+  end
+
+  shared_context 'роль с повышенными правами' do |role, name|
+    context "когда роль - #{name}" do
+      before(:all) do
+        log_in_as(role)
+        navigate_to(@import_yml_page.page_url_value, subdomain: CONFIG['kirby']['import']['paid_company']['subdomain'])
+      end
+      after(:all) { log_out }
+
+      include_examples 'общие элементы страницы'
+      include_examples 'все элементы страницы для роли с повышенными правами', role
+    end
+  end
+
+  context 'когда роль - Владелец' do
+    before(:all) { log_in_as(:user) }
+    after(:all) { log_out }
+
+    context 'когда своя компания с бесплатным пакетом' do
+      before(:all) do
+        navigate_to(@import_yml_page.page_url_value,
+                    subdomain: CONFIG['kirby']['import']['unpaid_company']['subdomain'])
+      end
+
+      include_examples 'общие элементы страницы'
+
+      context 'когда на вкладке "Загрузка товаров"' do
+        before(:all) { @import_yml_page.upload_tab }
+
+        it('присутствует текстовая зона') { expect(@upload_tab.text_zone?).to be true }
+        it 'присутствует активный блок "Формат" со значениями YML, YRL и EDIFACT' do
+          expect(@upload_tab.source_type_label?).to be true
+          expect(@upload_tab.source_type_options).to eq %w[YML YRL EDIFACT]
+        end
+
+        it('доступен режим "Товаров нет"') { expect(@upload_tab.moving_no?).to be true }
+
+        context 'когда выбран режим "Товары есть"' do
+          before(:all) { @upload_tab.moving_yes }
+
+          it('доступен режим "Оставить опубликованными"') { expect(@upload_tab.moving_keep?(2)).to be true }
+          it('доступен режим "Удалить"') { expect(@upload_tab.moving_delete?(2)).to be true }
+          it('не доступен режим "Перенести в архив"') { expect(@upload_tab.moving_archive_not_exists?(2)).to be true }
+          it 'присутствует НЕактивный блок "Сайт магазина"' do
+            expect(@upload_tab.store_url_label?).to be true
+            expect(@upload_tab.store_url_element.disabled?).to be true
+          end
+
+          it 'отсутствуют кнопки "Сохранить" и "Загрузить группы"' do
+            expect(@upload_tab.upload_groups_not_exists?).to be true
+            expect(@upload_tab.save_not_exists?).to be true
+          end
+
+          it('присутствует кнопка "Загрузить"') { expect(@upload_tab.upload_price?).to be true }
+        end
+
+        #TODO: Аналогично, раскипать после того, как обновят образ ножа для ПЦ
+        xcontext 'когда источник - Файл' do
+          before(:all) do
+            @upload_tab.switch_to_source_file
+            @upload_tab.upload_yml(YAML_FILE_PATH)
+            @import_yml_page.settings_tab
+            @settings_tab.save_settings
+            @import_yml_page.upload_tab
+          end
+
+          it('присутствует поле с названием выбранного файла') { expect(@upload_tab.source_file?).to be true }
+          it('присутствует псевдо-ссылка выбора файла') { expect(@upload_tab.file_upload_element.exists?).to be true }
+          it('присутствует ссылка на скачивание прайса') { expect(@upload_tab.download_last_price?).to be true }
+        end
+
+        context 'когда источник - Ссылка' do
+          before(:all) { @upload_tab.switch_to_source_url }
+
+          it('присутствует поле ввода источника прайса') { expect(@upload_tab.source_url?).to be true }
+        end
+      end
+
+      context 'когда на вкладке "Расширенные настройки"' do
+        before(:all) { @import_yml_page.settings_tab }
+
+        it('присутствует заголовок "Выборочное обновление полей"') { expect(@settings_tab.selected_fields?).to be true }
+
+        it 'присутствует заголовок "Выборочное обновление товаров"' do
+          expect(@settings_tab.selected_products?).to be true
+        end
+
+        it('присутствует заголовок "Отчет"') { expect(@settings_tab.notification_label?).to be true }
+
+        it('присутствует заголовок "Загрузка характеристик для фильтров по товарам на вашем сайте"') do
+          expect(@settings_tab.company_traits_label?).to be true
+        end
+
+        it 'присутствует активный чекбокс "Загружать характеристики"' do
+          expect(@settings_tab.company_traits).to eq 'Загружать характеристики'
+          expect(@settings_tab.company_traits_element.checkbox_element.enabled?).to be true
+        end
+
+        it 'все чекбоксы выбора статусов обновляемых товаров активные' do
+          expect(@settings_tab.update_archived).to eq 'Обновлять товары в статусе «Архивный»'
+          expect(@settings_tab.update_archived_element.checkbox_element.enabled?).to be true
+          expect(@settings_tab.update_unpublished).to eq 'Обновлять товары в статусе «Опубликованный на сайте»'
+          expect(@settings_tab.update_unpublished_element.checkbox_element.enabled?).to be true
+        end
+
+        context 'когда источник - Ссылка' do
+          before do
+            @import_yml_page.upload_tab
+            @upload_tab.switch_to_source_url
+            @import_yml_page.settings_tab
+          end
+
+          it 'не отобразится блок "Автообновление"' do
+            expect(@settings_tab.autoupdate_label_not_exists?).to be true
+            expect(@settings_tab.autoupdate_not_exists?).to be true
+          end
+        end
+
+        it 'все чекбоксы в блоке "Выборочное обновление полей" НЕактивные' do
+          CompanySite::ImportYMLPage::SettingsTab::TAGS.each do |field|
+            expect(@settings_tab.send("#{field}_element").disabled?).to be true
+          end
+        end
+
+        it 'все чекбоксы в блоке "Настройка названия товара" НЕактивные' do
+          CompanySite::ImportYMLPage::SettingsTab::NAME_TAGS.each do |field|
+            expect(@settings_tab.send("tag_#{field}_element").disabled?).to be true
+          end
+        end
+
+        it 'чекбокс "Получать отчёт о загрузке товаров и услуг" в блоке "Отчет" НЕактивный' do
+          expect(@settings_tab.notification).to eq 'Получать отчёт о загрузке товаров и услуг'
+          expect(@settings_tab.notification_element.checkbox_element.disabled?).to be true
+        end
+      end
+    end
+
+    context 'когда своя компания с платным пакетом' do
+      before(:all) do
+        navigate_to(@import_yml_page.page_url_value, subdomain: CONFIG['kirby']['import']['paid_company']['subdomain'])
+      end
+
+      include_examples 'общие элементы страницы'
+
+      context 'когда на вкладке "Загрузить товары"' do
+        before(:all) { @import_yml_page.upload_tab }
+
+        it('присутствует текстовая зона') { expect(@upload_tab.text_zone?).to be true }
+        it 'присутствует активный блок "Формат" со значениями YML, YRL и EDIFACT' do
+          expect(@upload_tab.source_type_label?).to be true
+          expect(@upload_tab.source_type_options).to eq %w[YML YRL EDIFACT]
+        end
+
+        it('доступен режим "Товаров нет"') { expect(@upload_tab.moving_no?).to be true }
+
+        context 'когда выбран режим "Товары есть"' do
+          before(:all) { @upload_tab.moving_yes }
+
+          it('доступен режим "Оставить опубликованными"') { expect(@upload_tab.moving_keep?(2)).to be true }
+          it('доступен режим "Удалить"') { expect(@upload_tab.moving_delete?(2)).to be true }
+          it('не доступен режим "Перенести в архив"') { expect(@upload_tab.moving_archive_not_exists?(2)).to be true }
+          it 'присутствует активный блок "Сайт магазина"' do
+            expect(@upload_tab.store_url_label?).to be true
+            expect(@upload_tab.store_url_element.enabled?).to be true
+          end
+
+          it('присутствует кнопка "Загрузить"') { expect(@upload_tab.upload_price?).to be true }
+        end
+
+        #TODO: Аналогично, раскипать после того, как обновят образ ножа для ПЦ
+        xcontext 'когда источник - Файл' do
+          before(:all) do
+            @upload_tab.switch_to_source_file
+            @upload_tab.upload_yml(YAML_FILE_PATH)
+            @import_yml_page.settings_tab
+            @settings_tab.save_settings
+            @import_yml_page.upload_tab
+          end
+
+          it('присутствует поле с названием выбранного файла') { expect(@upload_tab.source_file?).to be true }
+          it('присутствует псевдо-ссылка выбора файла') { expect(@upload_tab.file_upload_element.exists?).to be true }
+          it('присутствует ссылка на скачивание прайса') { expect(@upload_tab.download_last_price?).to be true }
+        end
+
+        context 'когда источник - Ссылка' do
+          before(:all) { @upload_tab.switch_to_source_url }
+
+          it('присутствует поле ввода источника прайса') { expect(@upload_tab.source_url?).to be true }
+        end
+      end
+
+      context 'когда на вкладке "Расширенные настройки"' do
+        before(:all) { @import_yml_page.settings_tab }
+
+        it('присутствует заголовок "Выборочное обновление полей"') { expect(@settings_tab.selected_fields?).to be true }
+
+        it 'присутствует заголовок "Выборочное обновление товаров"' do
+          expect(@settings_tab.selected_products?).to be true
+        end
+        it('присутствует заголовок "Отчет"') { expect(@settings_tab.notification_label?).to be true }
+
+        it('присутствует заголовок "Загрузка характеристик для фильтров по товарам на вашем сайте"') do
+          expect(@settings_tab.company_traits_label?).to be true
+        end
+
+        it 'присутствует активный чекбокс "Загружать характеристики"' do
+          expect(@settings_tab.company_traits).to eq 'Загружать характеристики'
+          expect(@settings_tab.company_traits_element.checkbox_element.enabled?).to be true
+        end
+
+        it 'все чекбоксы выбора статусов обновляемых товаров активные' do
+          expect(@settings_tab.update_archived).to eq 'Обновлять товары в статусе «Архивный»'
+          expect(@settings_tab.update_archived_element.checkbox_element.enabled?).to be true
+          expect(@settings_tab.update_unpublished).to eq 'Обновлять товары в статусе «Опубликованный на сайте»'
+          expect(@settings_tab.update_unpublished_element.checkbox_element.enabled?).to be true
+        end
+
+        context 'когда источник - Ссылка' do
+          before do
+            @import_yml_page.upload_tab
+            @upload_tab.switch_to_source_url
+            @import_yml_page.settings_tab
+          end
+
+          it 'не отобразится блок "Автообновление"' do
+            expect(@settings_tab.autoupdate_label_not_exists?).to be true
+            expect(@settings_tab.autoupdate_not_exists?).to be true
+          end
+        end
+
+        it 'все чекбоксы в блоке "Выборочное обновление полей" активные' do
+          CompanySite::ImportYMLPage::SettingsTab::TAGS.each do |field|
+            expect(@settings_tab.send("#{field}_element").enabled?).to be true
+          end
+        end
+
+        it 'все чекбоксы в блоке "Настройка названия товара" активные' do
+          CompanySite::ImportYMLPage::SettingsTab::NAME_TAGS.each do |field|
+            expect(@settings_tab.send("tag_#{field}_element").enabled?).to be true
+          end
+        end
+
+        it 'чекбокс "Получать отчёт о загрузке товаров и услуг" в блоке "Отчет" активный' do
+          expect(@settings_tab.notification).to eq 'Получать отчёт о загрузке товаров и услуг'
+          expect(@settings_tab.notification_element.checkbox_element.enabled?).to be true
+        end
+      end
+    end
+  end
+  
+  #TODO: Раскипать после обновления дампа на ПЦ.
+  xcontext 'когда авторизованный пользователь' do
+    before do
+      log_in_as(:empty_user)
+      navigate_to(@import_yml_page.page_url_value, subdomain: CONFIG['kirby']['import']['paid_company']['subdomain'])
+    end
+    after { log_out }
+
+    it('нет доступа к просмотру и редактированию - 403 код') do
+      expect(error_403?).to be true
+      expect(@import_yml_page.text).to include 'У Вас недостаточно прав для просмотра данной страницы.'
+    end
+  end
+
+  #TODO: Аналогично, раскипать после обновления дампа на ПЦ.
path: lib/apress/selenium_products/spec/company_site/kirby/import/import_yml_policy_spec.rb
user: login: apress-hound
body: [Correctable] Layout/LeadingCommentSpace: Missing space after #.
created_at: 2025-04-25T07:58:44Z
author_association: NONE
diff_hunk: @@ -0,0 +1,434 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Кирби: политики доступа страницы импорта YML', feature: 'Кирби: политики доступа страницы импорта YML' do
+  before(:all) do
+    @import_yml_page = CompanySite::ImportYMLPage.new
+    @upload_tab      = CompanySite::ImportYMLPage::UploadTab.new
+    @settings_tab    = CompanySite::ImportYMLPage::SettingsTab.new
+  end
+
+  shared_examples 'общие элементы страницы' do
+    it 'присутствует title в формате "Загрузка товаров из YML/YRL - %название компании% - %основной регион%"' do
+      expect(@import_yml_page.has_expected_title?).to be true
+    end
+
+    it 'присутствует заголовок страницы "Загрузить товары в формате Яндекс.Маркет (YML/YRL)"' do
+      expect(@import_yml_page.header).to eq 'Загрузить товары в формате Яндекс.Маркет (YML/YRL)'
+    end
+
+    it 'присутствуют вкладки "Загрузить товары" и "Расширенные настройки"' do
+      expect(@import_yml_page.upload_tab?).to be true
+      expect(@import_yml_page.settings_tab?).to be true
+    end
+  end
+
+  shared_examples 'все элементы страницы для роли с повышенными правами' do |role|
+    context 'когда на вкладке "Загрузить товары"' do
+      before(:all) { @import_yml_page.upload_tab }
+
+      it('присутствует текстовая зона') { expect(@upload_tab.text_zone?).to be true }
+
+      it 'присутствует активный блок "Формат" со значениями YML, YRL и EDIFACT' do
+        expect(@upload_tab.source_type_label?).to be true
+        expect(@upload_tab.source_type_options).to eq %w[YML YRL EDIFACT]
+      end
+
+      it('доступен режим "Товаров нет"') { expect(@upload_tab.moving_no?).to be true }
+
+      context 'когда выбран режим "Товары есть"' do
+        before(:all) { @upload_tab.moving_yes }
+
+        it('доступен режим "Оставить опубликованными"') { expect(@upload_tab.moving_keep?(2)).to be true }
+        it('доступен режим "Удалить"') { expect(@upload_tab.moving_delete?(2)).to be true }
+        it('доступен режим "Перенести в архив"') { expect(@upload_tab.moving_archive?(2)).to be true }
+
+        it('присутствует кнопка "Загрузить"') { expect(@upload_tab.upload_price?).to be true }
+      end
+
+      #TODO: Раскипать после того, как обновят образ ножа для ПЦ, тест пропускается так как файла по пути /test_files/pulscen пока нет.
+      xcontext 'когда источник - Файл' do
+        before(:all) do
+          @upload_tab.switch_to_source_file
+          @upload_tab.upload_yml(YAML_FILE_PATH)
+          @import_yml_page.settings_tab
+          @settings_tab.save_settings
+          @import_yml_page.upload_tab
+        end
+
+        it('присутствует поле с названием выбранного файла') { expect(@upload_tab.source_file?).to be true }
+        it('присутствует псевдо-ссылка выбора файла') { expect(@upload_tab.file_upload_element.exists?).to be true }
+        it('присутствует ссылка на скачивание прайса') { expect(@upload_tab.download_last_price?).to be true }
+      end
+
+      context 'когда источник - Ссылка' do
+        before(:all) { @upload_tab.switch_to_source_url }
+
+        it('присутствует поле ввода источника прайса') { expect(@upload_tab.source_url?).to be true }
+      end
+    end
+
+    context 'когда на вкладке "Расширенные настройки"' do
+      before(:all) { @import_yml_page.settings_tab }
+
+      it('присутствует заголовок "Выборочное обновление полей"') { expect(@settings_tab.selected_fields?).to be true }
+
+      it 'присутствует заголовок "Выборочное обновление товаров"' do
+        expect(@settings_tab.selected_products?).to be true
+      end
+      it('присутствует заголовок "Отчет"') { expect(@settings_tab.notification_label?).to be true }
+
+      it('присутствует заголовок "Загрузка характеристик для фильтров по товарам на вашем сайте"') do
+        expect(@settings_tab.company_traits_label?).to be true
+      end
+
+      it 'присутствует активный чекбокс "Загружать характеристики"' do
+        expect(@settings_tab.company_traits).to eq 'Загружать характеристики'
+        expect(@settings_tab.company_traits_element.checkbox_element.enabled?).to be true
+      end
+
+      it 'все чекбоксы выбора статусов обновляемых товаров активные' do
+        expect(@settings_tab.update_archived).to eq 'Обновлять товары в статусе «Архивный»'
+        expect(@settings_tab.update_archived_element.checkbox_element.enabled?).to be true
+        expect(@settings_tab.update_unpublished).to eq 'Обновлять товары в статусе «Опубликованный на сайте»'
+        expect(@settings_tab.update_unpublished_element.checkbox_element.enabled?).to be true
+      end
+
+      it 'все чекбоксы в блоке "Выборочное обновление полей" активные' do
+        CompanySite::ImportYMLPage::SettingsTab::TAGS.each do |field|
+          expect(@settings_tab.send("#{field}_element").enabled?).to be true
+        end
+      end
+
+      it 'все чекбоксы в блоке "Настройка названия товара" активные' do
+        CompanySite::ImportYMLPage::SettingsTab::NAME_TAGS.each do |field|
+          expect(@settings_tab.send("tag_#{field}_element").enabled?).to be true
+        end
+      end
+
+      it 'чекбокс "Получать отчёт о загрузке товаров и услуг" в блоке "Отчет" активный' do
+        expect(@settings_tab.notification).to eq 'Получать отчёт о загрузке товаров и услуг'
+        expect(@settings_tab.notification_element.checkbox_element.enabled?).to be true
+      end
+
+      context 'когда источник - Ссылка' do
+        before(:all) do
+          @import_yml_page.upload_tab
+          @upload_tab.switch_to_source_url
+          @import_yml_page.settings_tab
+        end
+
+        it 'отобразится активный чекбокс "Включить автоматическое обновление" в блоке "Автообновление"' do
+          expect(@settings_tab.autoupdate_label).to eq 'Автообновление'
+          expect(@settings_tab.autoupdate_element.checkbox_element.enabled?).to be true
+        end
+
+        context 'когда отмечен чекбокс "Включить автоматическое обновление"' do
+          before(:all) { @settings_tab.autoupdate_element.checkbox_element.check }
+
+          it 'отобразится блок с полями "Интервал обновления" и "Точное время обновления (MSK)"' do
+            expect(@settings_tab.autoupdate_period_label?).to be true
+            expect(@settings_tab.autoupdate_period?).to be true
+            expect(@settings_tab.autoupdate_start_date_label?).to be true
+            expect(@settings_tab.autoupdate_start_date).to be_truthy
+          end
+        end
+      end
+    end
+  end
+
+  shared_context 'роль с повышенными правами' do |role, name|
+    context "когда роль - #{name}" do
+      before(:all) do
+        log_in_as(role)
+        navigate_to(@import_yml_page.page_url_value, subdomain: CONFIG['kirby']['import']['paid_company']['subdomain'])
+      end
+      after(:all) { log_out }
+
+      include_examples 'общие элементы страницы'
+      include_examples 'все элементы страницы для роли с повышенными правами', role
+    end
+  end
+
+  context 'когда роль - Владелец' do
+    before(:all) { log_in_as(:user) }
+    after(:all) { log_out }
+
+    context 'когда своя компания с бесплатным пакетом' do
+      before(:all) do
+        navigate_to(@import_yml_page.page_url_value,
+                    subdomain: CONFIG['kirby']['import']['unpaid_company']['subdomain'])
+      end
+
+      include_examples 'общие элементы страницы'
+
+      context 'когда на вкладке "Загрузка товаров"' do
+        before(:all) { @import_yml_page.upload_tab }
+
+        it('присутствует текстовая зона') { expect(@upload_tab.text_zone?).to be true }
+        it 'присутствует активный блок "Формат" со значениями YML, YRL и EDIFACT' do
+          expect(@upload_tab.source_type_label?).to be true
+          expect(@upload_tab.source_type_options).to eq %w[YML YRL EDIFACT]
+        end
+
+        it('доступен режим "Товаров нет"') { expect(@upload_tab.moving_no?).to be true }
+
+        context 'когда выбран режим "Товары есть"' do
+          before(:all) { @upload_tab.moving_yes }
+
+          it('доступен режим "Оставить опубликованными"') { expect(@upload_tab.moving_keep?(2)).to be true }
+          it('доступен режим "Удалить"') { expect(@upload_tab.moving_delete?(2)).to be true }
+          it('не доступен режим "Перенести в архив"') { expect(@upload_tab.moving_archive_not_exists?(2)).to be true }
+          it 'присутствует НЕактивный блок "Сайт магазина"' do
+            expect(@upload_tab.store_url_label?).to be true
+            expect(@upload_tab.store_url_element.disabled?).to be true
+          end
+
+          it 'отсутствуют кнопки "Сохранить" и "Загрузить группы"' do
+            expect(@upload_tab.upload_groups_not_exists?).to be true
+            expect(@upload_tab.save_not_exists?).to be true
+          end
+
+          it('присутствует кнопка "Загрузить"') { expect(@upload_tab.upload_price?).to be true }
+        end
+
+        #TODO: Аналогично, раскипать после того, как обновят образ ножа для ПЦ
+        xcontext 'когда источник - Файл' do
+          before(:all) do
+            @upload_tab.switch_to_source_file
+            @upload_tab.upload_yml(YAML_FILE_PATH)
+            @import_yml_page.settings_tab
+            @settings_tab.save_settings
+            @import_yml_page.upload_tab
+          end
+
+          it('присутствует поле с названием выбранного файла') { expect(@upload_tab.source_file?).to be true }
+          it('присутствует псевдо-ссылка выбора файла') { expect(@upload_tab.file_upload_element.exists?).to be true }
+          it('присутствует ссылка на скачивание прайса') { expect(@upload_tab.download_last_price?).to be true }
+        end
+
+        context 'когда источник - Ссылка' do
+          before(:all) { @upload_tab.switch_to_source_url }
+
+          it('присутствует поле ввода источника прайса') { expect(@upload_tab.source_url?).to be true }
+        end
+      end
+
+      context 'когда на вкладке "Расширенные настройки"' do
+        before(:all) { @import_yml_page.settings_tab }
+
+        it('присутствует заголовок "Выборочное обновление полей"') { expect(@settings_tab.selected_fields?).to be true }
+
+        it 'присутствует заголовок "Выборочное обновление товаров"' do
+          expect(@settings_tab.selected_products?).to be true
+        end
+
+        it('присутствует заголовок "Отчет"') { expect(@settings_tab.notification_label?).to be true }
+
+        it('присутствует заголовок "Загрузка характеристик для фильтров по товарам на вашем сайте"') do
+          expect(@settings_tab.company_traits_label?).to be true
+        end
+
+        it 'присутствует активный чекбокс "Загружать характеристики"' do
+          expect(@settings_tab.company_traits).to eq 'Загружать характеристики'
+          expect(@settings_tab.company_traits_element.checkbox_element.enabled?).to be true
+        end
+
+        it 'все чекбоксы выбора статусов обновляемых товаров активные' do
+          expect(@settings_tab.update_archived).to eq 'Обновлять товары в статусе «Архивный»'
+          expect(@settings_tab.update_archived_element.checkbox_element.enabled?).to be true
+          expect(@settings_tab.update_unpublished).to eq 'Обновлять товары в статусе «Опубликованный на сайте»'
+          expect(@settings_tab.update_unpublished_element.checkbox_element.enabled?).to be true
+        end
+
+        context 'когда источник - Ссылка' do
+          before do
+            @import_yml_page.upload_tab
+            @upload_tab.switch_to_source_url
+            @import_yml_page.settings_tab
+          end
+
+          it 'не отобразится блок "Автообновление"' do
+            expect(@settings_tab.autoupdate_label_not_exists?).to be true
+            expect(@settings_tab.autoupdate_not_exists?).to be true
+          end
+        end
+
+        it 'все чекбоксы в блоке "Выборочное обновление полей" НЕактивные' do
+          CompanySite::ImportYMLPage::SettingsTab::TAGS.each do |field|
+            expect(@settings_tab.send("#{field}_element").disabled?).to be true
+          end
+        end
+
+        it 'все чекбоксы в блоке "Настройка названия товара" НЕактивные' do
+          CompanySite::ImportYMLPage::SettingsTab::NAME_TAGS.each do |field|
+            expect(@settings_tab.send("tag_#{field}_element").disabled?).to be true
+          end
+        end
+
+        it 'чекбокс "Получать отчёт о загрузке товаров и услуг" в блоке "Отчет" НЕактивный' do
+          expect(@settings_tab.notification).to eq 'Получать отчёт о загрузке товаров и услуг'
+          expect(@settings_tab.notification_element.checkbox_element.disabled?).to be true
+        end
+      end
+    end
+
+    context 'когда своя компания с платным пакетом' do
+      before(:all) do
+        navigate_to(@import_yml_page.page_url_value, subdomain: CONFIG['kirby']['import']['paid_company']['subdomain'])
+      end
+
+      include_examples 'общие элементы страницы'
+
+      context 'когда на вкладке "Загрузить товары"' do
+        before(:all) { @import_yml_page.upload_tab }
+
+        it('присутствует текстовая зона') { expect(@upload_tab.text_zone?).to be true }
+        it 'присутствует активный блок "Формат" со значениями YML, YRL и EDIFACT' do
+          expect(@upload_tab.source_type_label?).to be true
+          expect(@upload_tab.source_type_options).to eq %w[YML YRL EDIFACT]
+        end
+
+        it('доступен режим "Товаров нет"') { expect(@upload_tab.moving_no?).to be true }
+
+        context 'когда выбран режим "Товары есть"' do
+          before(:all) { @upload_tab.moving_yes }
+
+          it('доступен режим "Оставить опубликованными"') { expect(@upload_tab.moving_keep?(2)).to be true }
+          it('доступен режим "Удалить"') { expect(@upload_tab.moving_delete?(2)).to be true }
+          it('не доступен режим "Перенести в архив"') { expect(@upload_tab.moving_archive_not_exists?(2)).to be true }
+          it 'присутствует активный блок "Сайт магазина"' do
+            expect(@upload_tab.store_url_label?).to be true
+            expect(@upload_tab.store_url_element.enabled?).to be true
+          end
+
+          it('присутствует кнопка "Загрузить"') { expect(@upload_tab.upload_price?).to be true }
+        end
+
+        #TODO: Аналогично, раскипать после того, как обновят образ ножа для ПЦ
+        xcontext 'когда источник - Файл' do
+          before(:all) do
+            @upload_tab.switch_to_source_file
+            @upload_tab.upload_yml(YAML_FILE_PATH)
+            @import_yml_page.settings_tab
+            @settings_tab.save_settings
+            @import_yml_page.upload_tab
+          end
+
+          it('присутствует поле с названием выбранного файла') { expect(@upload_tab.source_file?).to be true }
+          it('присутствует псевдо-ссылка выбора файла') { expect(@upload_tab.file_upload_element.exists?).to be true }
+          it('присутствует ссылка на скачивание прайса') { expect(@upload_tab.download_last_price?).to be true }
+        end
+
+        context 'когда источник - Ссылка' do
+          before(:all) { @upload_tab.switch_to_source_url }
+
+          it('присутствует поле ввода источника прайса') { expect(@upload_tab.source_url?).to be true }
+        end
+      end
+
+      context 'когда на вкладке "Расширенные настройки"' do
+        before(:all) { @import_yml_page.settings_tab }
+
+        it('присутствует заголовок "Выборочное обновление полей"') { expect(@settings_tab.selected_fields?).to be true }
+
+        it 'присутствует заголовок "Выборочное обновление товаров"' do
+          expect(@settings_tab.selected_products?).to be true
+        end
+        it('присутствует заголовок "Отчет"') { expect(@settings_tab.notification_label?).to be true }
+
+        it('присутствует заголовок "Загрузка характеристик для фильтров по товарам на вашем сайте"') do
+          expect(@settings_tab.company_traits_label?).to be true
+        end
+
+        it 'присутствует активный чекбокс "Загружать характеристики"' do
+          expect(@settings_tab.company_traits).to eq 'Загружать характеристики'
+          expect(@settings_tab.company_traits_element.checkbox_element.enabled?).to be true
+        end
+
+        it 'все чекбоксы выбора статусов обновляемых товаров активные' do
+          expect(@settings_tab.update_archived).to eq 'Обновлять товары в статусе «Архивный»'
+          expect(@settings_tab.update_archived_element.checkbox_element.enabled?).to be true
+          expect(@settings_tab.update_unpublished).to eq 'Обновлять товары в статусе «Опубликованный на сайте»'
+          expect(@settings_tab.update_unpublished_element.checkbox_element.enabled?).to be true
+        end
+
+        context 'когда источник - Ссылка' do
+          before do
+            @import_yml_page.upload_tab
+            @upload_tab.switch_to_source_url
+            @import_yml_page.settings_tab
+          end
+
+          it 'не отобразится блок "Автообновление"' do
+            expect(@settings_tab.autoupdate_label_not_exists?).to be true
+            expect(@settings_tab.autoupdate_not_exists?).to be true
+          end
+        end
+
+        it 'все чекбоксы в блоке "Выборочное обновление полей" активные' do
+          CompanySite::ImportYMLPage::SettingsTab::TAGS.each do |field|
+            expect(@settings_tab.send("#{field}_element").enabled?).to be true
+          end
+        end
+
+        it 'все чекбоксы в блоке "Настройка названия товара" активные' do
+          CompanySite::ImportYMLPage::SettingsTab::NAME_TAGS.each do |field|
+            expect(@settings_tab.send("tag_#{field}_element").enabled?).to be true
+          end
+        end
+
+        it 'чекбокс "Получать отчёт о загрузке товаров и услуг" в блоке "Отчет" активный' do
+          expect(@settings_tab.notification).to eq 'Получать отчёт о загрузке товаров и услуг'
+          expect(@settings_tab.notification_element.checkbox_element.enabled?).to be true
+        end
+      end
+    end
+  end
+  
+  #TODO: Раскипать после обновления дампа на ПЦ.
path: lib/apress/selenium_products/spec/company_site/kirby/import/import_yml_policy_spec.rb
user: login: apress-hound
body: [Correctable] Layout/LeadingCommentSpace: Missing space after #.
created_at: 2025-04-25T07:58:44Z
author_association: NONE
diff_hunk: @@ -0,0 +1,434 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Кирби: политики доступа страницы импорта YML', feature: 'Кирби: политики доступа страницы импорта YML' do
+  before(:all) do
+    @import_yml_page = CompanySite::ImportYMLPage.new
+    @upload_tab      = CompanySite::ImportYMLPage::UploadTab.new
+    @settings_tab    = CompanySite::ImportYMLPage::SettingsTab.new
+  end
+
+  shared_examples 'общие элементы страницы' do
+    it 'присутствует title в формате "Загрузка товаров из YML/YRL - %название компании% - %основной регион%"' do
+      expect(@import_yml_page.has_expected_title?).to be true
+    end
+
+    it 'присутствует заголовок страницы "Загрузить товары в формате Яндекс.Маркет (YML/YRL)"' do
+      expect(@import_yml_page.header).to eq 'Загрузить товары в формате Яндекс.Маркет (YML/YRL)'
+    end
+
+    it 'присутствуют вкладки "Загрузить товары" и "Расширенные настройки"' do
+      expect(@import_yml_page.upload_tab?).to be true
+      expect(@import_yml_page.settings_tab?).to be true
+    end
+  end
+
+  shared_examples 'все элементы страницы для роли с повышенными правами' do |role|
+    context 'когда на вкладке "Загрузить товары"' do
+      before(:all) { @import_yml_page.upload_tab }
+
+      it('присутствует текстовая зона') { expect(@upload_tab.text_zone?).to be true }
+
+      it 'присутствует активный блок "Формат" со значениями YML, YRL и EDIFACT' do
+        expect(@upload_tab.source_type_label?).to be true
+        expect(@upload_tab.source_type_options).to eq %w[YML YRL EDIFACT]
+      end
+
+      it('доступен режим "Товаров нет"') { expect(@upload_tab.moving_no?).to be true }
+
+      context 'когда выбран режим "Товары есть"' do
+        before(:all) { @upload_tab.moving_yes }
+
+        it('доступен режим "Оставить опубликованными"') { expect(@upload_tab.moving_keep?(2)).to be true }
+        it('доступен режим "Удалить"') { expect(@upload_tab.moving_delete?(2)).to be true }
+        it('доступен режим "Перенести в архив"') { expect(@upload_tab.moving_archive?(2)).to be true }
+
+        it('присутствует кнопка "Загрузить"') { expect(@upload_tab.upload_price?).to be true }
+      end
+
+      #TODO: Раскипать после того, как обновят образ ножа для ПЦ, тест пропускается так как файла по пути /test_files/pulscen пока нет.
+      xcontext 'когда источник - Файл' do
+        before(:all) do
+          @upload_tab.switch_to_source_file
+          @upload_tab.upload_yml(YAML_FILE_PATH)
+          @import_yml_page.settings_tab
+          @settings_tab.save_settings
+          @import_yml_page.upload_tab
+        end
+
+        it('присутствует поле с названием выбранного файла') { expect(@upload_tab.source_file?).to be true }
+        it('присутствует псевдо-ссылка выбора файла') { expect(@upload_tab.file_upload_element.exists?).to be true }
+        it('присутствует ссылка на скачивание прайса') { expect(@upload_tab.download_last_price?).to be true }
+      end
+
+      context 'когда источник - Ссылка' do
+        before(:all) { @upload_tab.switch_to_source_url }
+
+        it('присутствует поле ввода источника прайса') { expect(@upload_tab.source_url?).to be true }
+      end
+    end
+
+    context 'когда на вкладке "Расширенные настройки"' do
+      before(:all) { @import_yml_page.settings_tab }
+
+      it('присутствует заголовок "Выборочное обновление полей"') { expect(@settings_tab.selected_fields?).to be true }
+
+      it 'присутствует заголовок "Выборочное обновление товаров"' do
+        expect(@settings_tab.selected_products?).to be true
+      end
+      it('присутствует заголовок "Отчет"') { expect(@settings_tab.notification_label?).to be true }
+
+      it('присутствует заголовок "Загрузка характеристик для фильтров по товарам на вашем сайте"') do
+        expect(@settings_tab.company_traits_label?).to be true
+      end
+
+      it 'присутствует активный чекбокс "Загружать характеристики"' do
+        expect(@settings_tab.company_traits).to eq 'Загружать характеристики'
+        expect(@settings_tab.company_traits_element.checkbox_element.enabled?).to be true
+      end
+
+      it 'все чекбоксы выбора статусов обновляемых товаров активные' do
+        expect(@settings_tab.update_archived).to eq 'Обновлять товары в статусе «Архивный»'
+        expect(@settings_tab.update_archived_element.checkbox_element.enabled?).to be true
+        expect(@settings_tab.update_unpublished).to eq 'Обновлять товары в статусе «Опубликованный на сайте»'
+        expect(@settings_tab.update_unpublished_element.checkbox_element.enabled?).to be true
+      end
+
+      it 'все чекбоксы в блоке "Выборочное обновление полей" активные' do
+        CompanySite::ImportYMLPage::SettingsTab::TAGS.each do |field|
+          expect(@settings_tab.send("#{field}_element").enabled?).to be true
+        end
+      end
+
+      it 'все чекбоксы в блоке "Настройка названия товара" активные' do
+        CompanySite::ImportYMLPage::SettingsTab::NAME_TAGS.each do |field|
+          expect(@settings_tab.send("tag_#{field}_element").enabled?).to be true
+        end
+      end
+
+      it 'чекбокс "Получать отчёт о загрузке товаров и услуг" в блоке "Отчет" активный' do
+        expect(@settings_tab.notification).to eq 'Получать отчёт о загрузке товаров и услуг'
+        expect(@settings_tab.notification_element.checkbox_element.enabled?).to be true
+      end
+
+      context 'когда источник - Ссылка' do
+        before(:all) do
+          @import_yml_page.upload_tab
+          @upload_tab.switch_to_source_url
+          @import_yml_page.settings_tab
+        end
+
+        it 'отобразится активный чекбокс "Включить автоматическое обновление" в блоке "Автообновление"' do
+          expect(@settings_tab.autoupdate_label).to eq 'Автообновление'
+          expect(@settings_tab.autoupdate_element.checkbox_element.enabled?).to be true
+        end
+
+        context 'когда отмечен чекбокс "Включить автоматическое обновление"' do
+          before(:all) { @settings_tab.autoupdate_element.checkbox_element.check }
+
+          it 'отобразится блок с полями "Интервал обновления" и "Точное время обновления (MSK)"' do
+            expect(@settings_tab.autoupdate_period_label?).to be true
+            expect(@settings_tab.autoupdate_period?).to be true
+            expect(@settings_tab.autoupdate_start_date_label?).to be true
+            expect(@settings_tab.autoupdate_start_date).to be_truthy
+          end
+        end
+      end
+    end
+  end
+
+  shared_context 'роль с повышенными правами' do |role, name|
+    context "когда роль - #{name}" do
+      before(:all) do
+        log_in_as(role)
+        navigate_to(@import_yml_page.page_url_value, subdomain: CONFIG['kirby']['import']['paid_company']['subdomain'])
+      end
+      after(:all) { log_out }
+
+      include_examples 'общие элементы страницы'
+      include_examples 'все элементы страницы для роли с повышенными правами', role
+    end
+  end
+
+  context 'когда роль - Владелец' do
+    before(:all) { log_in_as(:user) }
+    after(:all) { log_out }
+
+    context 'когда своя компания с бесплатным пакетом' do
+      before(:all) do
+        navigate_to(@import_yml_page.page_url_value,
+                    subdomain: CONFIG['kirby']['import']['unpaid_company']['subdomain'])
+      end
+
+      include_examples 'общие элементы страницы'
+
+      context 'когда на вкладке "Загрузка товаров"' do
+        before(:all) { @import_yml_page.upload_tab }
+
+        it('присутствует текстовая зона') { expect(@upload_tab.text_zone?).to be true }
+        it 'присутствует активный блок "Формат" со значениями YML, YRL и EDIFACT' do
+          expect(@upload_tab.source_type_label?).to be true
+          expect(@upload_tab.source_type_options).to eq %w[YML YRL EDIFACT]
+        end
+
+        it('доступен режим "Товаров нет"') { expect(@upload_tab.moving_no?).to be true }
+
+        context 'когда выбран режим "Товары есть"' do
+          before(:all) { @upload_tab.moving_yes }
+
+          it('доступен режим "Оставить опубликованными"') { expect(@upload_tab.moving_keep?(2)).to be true }
+          it('доступен режим "Удалить"') { expect(@upload_tab.moving_delete?(2)).to be true }
+          it('не доступен режим "Перенести в архив"') { expect(@upload_tab.moving_archive_not_exists?(2)).to be true }
+          it 'присутствует НЕактивный блок "Сайт магазина"' do
+            expect(@upload_tab.store_url_label?).to be true
+            expect(@upload_tab.store_url_element.disabled?).to be true
+          end
+
+          it 'отсутствуют кнопки "Сохранить" и "Загрузить группы"' do
+            expect(@upload_tab.upload_groups_not_exists?).to be true
+            expect(@upload_tab.save_not_exists?).to be true
+          end
+
+          it('присутствует кнопка "Загрузить"') { expect(@upload_tab.upload_price?).to be true }
+        end
+
+        #TODO: Аналогично, раскипать после того, как обновят образ ножа для ПЦ
+        xcontext 'когда источник - Файл' do
+          before(:all) do
+            @upload_tab.switch_to_source_file
+            @upload_tab.upload_yml(YAML_FILE_PATH)
+            @import_yml_page.settings_tab
+            @settings_tab.save_settings
+            @import_yml_page.upload_tab
+          end
+
+          it('присутствует поле с названием выбранного файла') { expect(@upload_tab.source_file?).to be true }
+          it('присутствует псевдо-ссылка выбора файла') { expect(@upload_tab.file_upload_element.exists?).to be true }
+          it('присутствует ссылка на скачивание прайса') { expect(@upload_tab.download_last_price?).to be true }
+        end
+
+        context 'когда источник - Ссылка' do
+          before(:all) { @upload_tab.switch_to_source_url }
+
+          it('присутствует поле ввода источника прайса') { expect(@upload_tab.source_url?).to be true }
+        end
+      end
+
+      context 'когда на вкладке "Расширенные настройки"' do
+        before(:all) { @import_yml_page.settings_tab }
+
+        it('присутствует заголовок "Выборочное обновление полей"') { expect(@settings_tab.selected_fields?).to be true }
+
+        it 'присутствует заголовок "Выборочное обновление товаров"' do
+          expect(@settings_tab.selected_products?).to be true
+        end
+
+        it('присутствует заголовок "Отчет"') { expect(@settings_tab.notification_label?).to be true }
+
+        it('присутствует заголовок "Загрузка характеристик для фильтров по товарам на вашем сайте"') do
+          expect(@settings_tab.company_traits_label?).to be true
+        end
+
+        it 'присутствует активный чекбокс "Загружать характеристики"' do
+          expect(@settings_tab.company_traits).to eq 'Загружать характеристики'
+          expect(@settings_tab.company_traits_element.checkbox_element.enabled?).to be true
+        end
+
+        it 'все чекбоксы выбора статусов обновляемых товаров активные' do
+          expect(@settings_tab.update_archived).to eq 'Обновлять товары в статусе «Архивный»'
+          expect(@settings_tab.update_archived_element.checkbox_element.enabled?).to be true
+          expect(@settings_tab.update_unpublished).to eq 'Обновлять товары в статусе «Опубликованный на сайте»'
+          expect(@settings_tab.update_unpublished_element.checkbox_element.enabled?).to be true
+        end
+
+        context 'когда источник - Ссылка' do
+          before do
+            @import_yml_page.upload_tab
+            @upload_tab.switch_to_source_url
+            @import_yml_page.settings_tab
+          end
+
+          it 'не отобразится блок "Автообновление"' do
+            expect(@settings_tab.autoupdate_label_not_exists?).to be true
+            expect(@settings_tab.autoupdate_not_exists?).to be true
+          end
+        end
+
+        it 'все чекбоксы в блоке "Выборочное обновление полей" НЕактивные' do
+          CompanySite::ImportYMLPage::SettingsTab::TAGS.each do |field|
+            expect(@settings_tab.send("#{field}_element").disabled?).to be true
+          end
+        end
+
+        it 'все чекбоксы в блоке "Настройка названия товара" НЕактивные' do
+          CompanySite::ImportYMLPage::SettingsTab::NAME_TAGS.each do |field|
+            expect(@settings_tab.send("tag_#{field}_element").disabled?).to be true
+          end
+        end
+
+        it 'чекбокс "Получать отчёт о загрузке товаров и услуг" в блоке "Отчет" НЕактивный' do
+          expect(@settings_tab.notification).to eq 'Получать отчёт о загрузке товаров и услуг'
+          expect(@settings_tab.notification_element.checkbox_element.disabled?).to be true
+        end
+      end
+    end
+
+    context 'когда своя компания с платным пакетом' do
+      before(:all) do
+        navigate_to(@import_yml_page.page_url_value, subdomain: CONFIG['kirby']['import']['paid_company']['subdomain'])
+      end
+
+      include_examples 'общие элементы страницы'
+
+      context 'когда на вкладке "Загрузить товары"' do
+        before(:all) { @import_yml_page.upload_tab }
+
+        it('присутствует текстовая зона') { expect(@upload_tab.text_zone?).to be true }
+        it 'присутствует активный блок "Формат" со значениями YML, YRL и EDIFACT' do
+          expect(@upload_tab.source_type_label?).to be true
+          expect(@upload_tab.source_type_options).to eq %w[YML YRL EDIFACT]
+        end
+
+        it('доступен режим "Товаров нет"') { expect(@upload_tab.moving_no?).to be true }
+
+        context 'когда выбран режим "Товары есть"' do
+          before(:all) { @upload_tab.moving_yes }
+
+          it('доступен режим "Оставить опубликованными"') { expect(@upload_tab.moving_keep?(2)).to be true }
+          it('доступен режим "Удалить"') { expect(@upload_tab.moving_delete?(2)).to be true }
+          it('не доступен режим "Перенести в архив"') { expect(@upload_tab.moving_archive_not_exists?(2)).to be true }
+          it 'присутствует активный блок "Сайт магазина"' do
+            expect(@upload_tab.store_url_label?).to be true
+            expect(@upload_tab.store_url_element.enabled?).to be true
+          end
+
+          it('присутствует кнопка "Загрузить"') { expect(@upload_tab.upload_price?).to be true }
+        end
+
+        #TODO: Аналогично, раскипать после того, как обновят образ ножа для ПЦ
+        xcontext 'когда источник - Файл' do
+          before(:all) do
+            @upload_tab.switch_to_source_file
+            @upload_tab.upload_yml(YAML_FILE_PATH)
+            @import_yml_page.settings_tab
+            @settings_tab.save_settings
+            @import_yml_page.upload_tab
+          end
+
+          it('присутствует поле с названием выбранного файла') { expect(@upload_tab.source_file?).to be true }
+          it('присутствует псевдо-ссылка выбора файла') { expect(@upload_tab.file_upload_element.exists?).to be true }
+          it('присутствует ссылка на скачивание прайса') { expect(@upload_tab.download_last_price?).to be true }
+        end
+
+        context 'когда источник - Ссылка' do
+          before(:all) { @upload_tab.switch_to_source_url }
+
+          it('присутствует поле ввода источника прайса') { expect(@upload_tab.source_url?).to be true }
+        end
+      end
+
+      context 'когда на вкладке "Расширенные настройки"' do
+        before(:all) { @import_yml_page.settings_tab }
+
+        it('присутствует заголовок "Выборочное обновление полей"') { expect(@settings_tab.selected_fields?).to be true }
+
+        it 'присутствует заголовок "Выборочное обновление товаров"' do
+          expect(@settings_tab.selected_products?).to be true
+        end
+        it('присутствует заголовок "Отчет"') { expect(@settings_tab.notification_label?).to be true }
+
+        it('присутствует заголовок "Загрузка характеристик для фильтров по товарам на вашем сайте"') do
+          expect(@settings_tab.company_traits_label?).to be true
+        end
+
+        it 'присутствует активный чекбокс "Загружать характеристики"' do
+          expect(@settings_tab.company_traits).to eq 'Загружать характеристики'
+          expect(@settings_tab.company_traits_element.checkbox_element.enabled?).to be true
+        end
+
+        it 'все чекбоксы выбора статусов обновляемых товаров активные' do
+          expect(@settings_tab.update_archived).to eq 'Обновлять товары в статусе «Архивный»'
+          expect(@settings_tab.update_archived_element.checkbox_element.enabled?).to be true
+          expect(@settings_tab.update_unpublished).to eq 'Обновлять товары в статусе «Опубликованный на сайте»'
+          expect(@settings_tab.update_unpublished_element.checkbox_element.enabled?).to be true
+        end
+
+        context 'когда источник - Ссылка' do
+          before do
+            @import_yml_page.upload_tab
+            @upload_tab.switch_to_source_url
+            @import_yml_page.settings_tab
+          end
+
+          it 'не отобразится блок "Автообновление"' do
+            expect(@settings_tab.autoupdate_label_not_exists?).to be true
+            expect(@settings_tab.autoupdate_not_exists?).to be true
+          end
+        end
+
+        it 'все чекбоксы в блоке "Выборочное обновление полей" активные' do
+          CompanySite::ImportYMLPage::SettingsTab::TAGS.each do |field|
+            expect(@settings_tab.send("#{field}_element").enabled?).to be true
+          end
+        end
+
+        it 'все чекбоксы в блоке "Настройка названия товара" активные' do
+          CompanySite::ImportYMLPage::SettingsTab::NAME_TAGS.each do |field|
+            expect(@settings_tab.send("tag_#{field}_element").enabled?).to be true
+          end
+        end
+
+        it 'чекбокс "Получать отчёт о загрузке товаров и услуг" в блоке "Отчет" активный' do
+          expect(@settings_tab.notification).to eq 'Получать отчёт о загрузке товаров и услуг'
+          expect(@settings_tab.notification_element.checkbox_element.enabled?).to be true
+        end
+      end
+    end
+  end
+  
path: lib/apress/selenium_products/spec/company_site/kirby/import/import_yml_policy_spec.rb
user: login: apress-hound
body: [Correctable] Layout/TrailingWhitespace: Trailing whitespace detected.
created_at: 2025-04-25T07:58:44Z
author_association: NONE
diff_hunk: @@ -0,0 +1,434 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Кирби: политики доступа страницы импорта YML', feature: 'Кирби: политики доступа страницы импорта YML' do
+  before(:all) do
+    @import_yml_page = CompanySite::ImportYMLPage.new
+    @upload_tab      = CompanySite::ImportYMLPage::UploadTab.new
+    @settings_tab    = CompanySite::ImportYMLPage::SettingsTab.new
+  end
+
+  shared_examples 'общие элементы страницы' do
+    it 'присутствует title в формате "Загрузка товаров из YML/YRL - %название компании% - %основной регион%"' do
+      expect(@import_yml_page.has_expected_title?).to be true
+    end
+
+    it 'присутствует заголовок страницы "Загрузить товары в формате Яндекс.Маркет (YML/YRL)"' do
+      expect(@import_yml_page.header).to eq 'Загрузить товары в формате Яндекс.Маркет (YML/YRL)'
+    end
+
+    it 'присутствуют вкладки "Загрузить товары" и "Расширенные настройки"' do
+      expect(@import_yml_page.upload_tab?).to be true
+      expect(@import_yml_page.settings_tab?).to be true
+    end
+  end
+
+  shared_examples 'все элементы страницы для роли с повышенными правами' do |role|
+    context 'когда на вкладке "Загрузить товары"' do
+      before(:all) { @import_yml_page.upload_tab }
+
+      it('присутствует текстовая зона') { expect(@upload_tab.text_zone?).to be true }
+
+      it 'присутствует активный блок "Формат" со значениями YML, YRL и EDIFACT' do
+        expect(@upload_tab.source_type_label?).to be true
+        expect(@upload_tab.source_type_options).to eq %w[YML YRL EDIFACT]
+      end
+
+      it('доступен режим "Товаров нет"') { expect(@upload_tab.moving_no?).to be true }
+
+      context 'когда выбран режим "Товары есть"' do
+        before(:all) { @upload_tab.moving_yes }
+
+        it('доступен режим "Оставить опубликованными"') { expect(@upload_tab.moving_keep?(2)).to be true }
+        it('доступен режим "Удалить"') { expect(@upload_tab.moving_delete?(2)).to be true }
+        it('доступен режим "Перенести в архив"') { expect(@upload_tab.moving_archive?(2)).to be true }
+
+        it('присутствует кнопка "Загрузить"') { expect(@upload_tab.upload_price?).to be true }
+      end
+
+      #TODO: Раскипать после того, как обновят образ ножа для ПЦ, тест пропускается так как файла по пути /test_files/pulscen пока нет.
+      xcontext 'когда источник - Файл' do
+        before(:all) do
+          @upload_tab.switch_to_source_file
+          @upload_tab.upload_yml(YAML_FILE_PATH)
+          @import_yml_page.settings_tab
+          @settings_tab.save_settings
+          @import_yml_page.upload_tab
+        end
+
+        it('присутствует поле с названием выбранного файла') { expect(@upload_tab.source_file?).to be true }
+        it('присутствует псевдо-ссылка выбора файла') { expect(@upload_tab.file_upload_element.exists?).to be true }
+        it('присутствует ссылка на скачивание прайса') { expect(@upload_tab.download_last_price?).to be true }
+      end
+
+      context 'когда источник - Ссылка' do
+        before(:all) { @upload_tab.switch_to_source_url }
+
+        it('присутствует поле ввода источника прайса') { expect(@upload_tab.source_url?).to be true }
+      end
+    end
+
+    context 'когда на вкладке "Расширенные настройки"' do
+      before(:all) { @import_yml_page.settings_tab }
+
+      it('присутствует заголовок "Выборочное обновление полей"') { expect(@settings_tab.selected_fields?).to be true }
+
+      it 'присутствует заголовок "Выборочное обновление товаров"' do
+        expect(@settings_tab.selected_products?).to be true
+      end
+      it('присутствует заголовок "Отчет"') { expect(@settings_tab.notification_label?).to be true }
+
+      it('присутствует заголовок "Загрузка характеристик для фильтров по товарам на вашем сайте"') do
+        expect(@settings_tab.company_traits_label?).to be true
+      end
+
+      it 'присутствует активный чекбокс "Загружать характеристики"' do
+        expect(@settings_tab.company_traits).to eq 'Загружать характеристики'
+        expect(@settings_tab.company_traits_element.checkbox_element.enabled?).to be true
+      end
+
+      it 'все чекбоксы выбора статусов обновляемых товаров активные' do
+        expect(@settings_tab.update_archived).to eq 'Обновлять товары в статусе «Архивный»'
+        expect(@settings_tab.update_archived_element.checkbox_element.enabled?).to be true
+        expect(@settings_tab.update_unpublished).to eq 'Обновлять товары в статусе «Опубликованный на сайте»'
+        expect(@settings_tab.update_unpublished_element.checkbox_element.enabled?).to be true
+      end
+
+      it 'все чекбоксы в блоке "Выборочное обновление полей" активные' do
+        CompanySite::ImportYMLPage::SettingsTab::TAGS.each do |field|
+          expect(@settings_tab.send("#{field}_element").enabled?).to be true
+        end
+      end
+
+      it 'все чекбоксы в блоке "Настройка названия товара" активные' do
+        CompanySite::ImportYMLPage::SettingsTab::NAME_TAGS.each do |field|
+          expect(@settings_tab.send("tag_#{field}_element").enabled?).to be true
+        end
+      end
+
+      it 'чекбокс "Получать отчёт о загрузке товаров и услуг" в блоке "Отчет" активный' do
+        expect(@settings_tab.notification).to eq 'Получать отчёт о загрузке товаров и услуг'
+        expect(@settings_tab.notification_element.checkbox_element.enabled?).to be true
+      end
+
+      context 'когда источник - Ссылка' do
+        before(:all) do
+          @import_yml_page.upload_tab
+          @upload_tab.switch_to_source_url
+          @import_yml_page.settings_tab
+        end
+
+        it 'отобразится активный чекбокс "Включить автоматическое обновление" в блоке "Автообновление"' do
+          expect(@settings_tab.autoupdate_label).to eq 'Автообновление'
+          expect(@settings_tab.autoupdate_element.checkbox_element.enabled?).to be true
+        end
+
+        context 'когда отмечен чекбокс "Включить автоматическое обновление"' do
+          before(:all) { @settings_tab.autoupdate_element.checkbox_element.check }
+
+          it 'отобразится блок с полями "Интервал обновления" и "Точное время обновления (MSK)"' do
+            expect(@settings_tab.autoupdate_period_label?).to be true
+            expect(@settings_tab.autoupdate_period?).to be true
+            expect(@settings_tab.autoupdate_start_date_label?).to be true
+            expect(@settings_tab.autoupdate_start_date).to be_truthy
+          end
+        end
+      end
+    end
+  end
+
+  shared_context 'роль с повышенными правами' do |role, name|
+    context "когда роль - #{name}" do
+      before(:all) do
+        log_in_as(role)
+        navigate_to(@import_yml_page.page_url_value, subdomain: CONFIG['kirby']['import']['paid_company']['subdomain'])
+      end
+      after(:all) { log_out }
+
+      include_examples 'общие элементы страницы'
+      include_examples 'все элементы страницы для роли с повышенными правами', role
+    end
+  end
+
+  context 'когда роль - Владелец' do
+    before(:all) { log_in_as(:user) }
+    after(:all) { log_out }
+
+    context 'когда своя компания с бесплатным пакетом' do
+      before(:all) do
+        navigate_to(@import_yml_page.page_url_value,
+                    subdomain: CONFIG['kirby']['import']['unpaid_company']['subdomain'])
+      end
+
+      include_examples 'общие элементы страницы'
+
+      context 'когда на вкладке "Загрузка товаров"' do
+        before(:all) { @import_yml_page.upload_tab }
+
+        it('присутствует текстовая зона') { expect(@upload_tab.text_zone?).to be true }
+        it 'присутствует активный блок "Формат" со значениями YML, YRL и EDIFACT' do
+          expect(@upload_tab.source_type_label?).to be true
+          expect(@upload_tab.source_type_options).to eq %w[YML YRL EDIFACT]
+        end
+
+        it('доступен режим "Товаров нет"') { expect(@upload_tab.moving_no?).to be true }
+
+        context 'когда выбран режим "Товары есть"' do
+          before(:all) { @upload_tab.moving_yes }
+
+          it('доступен режим "Оставить опубликованными"') { expect(@upload_tab.moving_keep?(2)).to be true }
+          it('доступен режим "Удалить"') { expect(@upload_tab.moving_delete?(2)).to be true }
+          it('не доступен режим "Перенести в архив"') { expect(@upload_tab.moving_archive_not_exists?(2)).to be true }
+          it 'присутствует НЕактивный блок "Сайт магазина"' do
+            expect(@upload_tab.store_url_label?).to be true
+            expect(@upload_tab.store_url_element.disabled?).to be true
+          end
+
+          it 'отсутствуют кнопки "Сохранить" и "Загрузить группы"' do
+            expect(@upload_tab.upload_groups_not_exists?).to be true
+            expect(@upload_tab.save_not_exists?).to be true
+          end
+
+          it('присутствует кнопка "Загрузить"') { expect(@upload_tab.upload_price?).to be true }
+        end
+
+        #TODO: Аналогично, раскипать после того, как обновят образ ножа для ПЦ
+        xcontext 'когда источник - Файл' do
+          before(:all) do
+            @upload_tab.switch_to_source_file
+            @upload_tab.upload_yml(YAML_FILE_PATH)
+            @import_yml_page.settings_tab
+            @settings_tab.save_settings
+            @import_yml_page.upload_tab
+          end
+
+          it('присутствует поле с названием выбранного файла') { expect(@upload_tab.source_file?).to be true }
+          it('присутствует псевдо-ссылка выбора файла') { expect(@upload_tab.file_upload_element.exists?).to be true }
+          it('присутствует ссылка на скачивание прайса') { expect(@upload_tab.download_last_price?).to be true }
+        end
+
+        context 'когда источник - Ссылка' do
+          before(:all) { @upload_tab.switch_to_source_url }
+
+          it('присутствует поле ввода источника прайса') { expect(@upload_tab.source_url?).to be true }
+        end
+      end
+
+      context 'когда на вкладке "Расширенные настройки"' do
+        before(:all) { @import_yml_page.settings_tab }
+
+        it('присутствует заголовок "Выборочное обновление полей"') { expect(@settings_tab.selected_fields?).to be true }
+
+        it 'присутствует заголовок "Выборочное обновление товаров"' do
+          expect(@settings_tab.selected_products?).to be true
+        end
+
+        it('присутствует заголовок "Отчет"') { expect(@settings_tab.notification_label?).to be true }
+
+        it('присутствует заголовок "Загрузка характеристик для фильтров по товарам на вашем сайте"') do
+          expect(@settings_tab.company_traits_label?).to be true
+        end
+
+        it 'присутствует активный чекбокс "Загружать характеристики"' do
+          expect(@settings_tab.company_traits).to eq 'Загружать характеристики'
+          expect(@settings_tab.company_traits_element.checkbox_element.enabled?).to be true
+        end
+
+        it 'все чекбоксы выбора статусов обновляемых товаров активные' do
+          expect(@settings_tab.update_archived).to eq 'Обновлять товары в статусе «Архивный»'
+          expect(@settings_tab.update_archived_element.checkbox_element.enabled?).to be true
+          expect(@settings_tab.update_unpublished).to eq 'Обновлять товары в статусе «Опубликованный на сайте»'
+          expect(@settings_tab.update_unpublished_element.checkbox_element.enabled?).to be true
+        end
+
+        context 'когда источник - Ссылка' do
+          before do
+            @import_yml_page.upload_tab
+            @upload_tab.switch_to_source_url
+            @import_yml_page.settings_tab
+          end
+
+          it 'не отобразится блок "Автообновление"' do
+            expect(@settings_tab.autoupdate_label_not_exists?).to be true
+            expect(@settings_tab.autoupdate_not_exists?).to be true
+          end
+        end
+
+        it 'все чекбоксы в блоке "Выборочное обновление полей" НЕактивные' do
+          CompanySite::ImportYMLPage::SettingsTab::TAGS.each do |field|
+            expect(@settings_tab.send("#{field}_element").disabled?).to be true
+          end
+        end
+
+        it 'все чекбоксы в блоке "Настройка названия товара" НЕактивные' do
+          CompanySite::ImportYMLPage::SettingsTab::NAME_TAGS.each do |field|
+            expect(@settings_tab.send("tag_#{field}_element").disabled?).to be true
+          end
+        end
+
+        it 'чекбокс "Получать отчёт о загрузке товаров и услуг" в блоке "Отчет" НЕактивный' do
+          expect(@settings_tab.notification).to eq 'Получать отчёт о загрузке товаров и услуг'
+          expect(@settings_tab.notification_element.checkbox_element.disabled?).to be true
+        end
+      end
+    end
+
+    context 'когда своя компания с платным пакетом' do
+      before(:all) do
+        navigate_to(@import_yml_page.page_url_value, subdomain: CONFIG['kirby']['import']['paid_company']['subdomain'])
+      end
+
+      include_examples 'общие элементы страницы'
+
+      context 'когда на вкладке "Загрузить товары"' do
+        before(:all) { @import_yml_page.upload_tab }
+
+        it('присутствует текстовая зона') { expect(@upload_tab.text_zone?).to be true }
+        it 'присутствует активный блок "Формат" со значениями YML, YRL и EDIFACT' do
+          expect(@upload_tab.source_type_label?).to be true
+          expect(@upload_tab.source_type_options).to eq %w[YML YRL EDIFACT]
+        end
+
+        it('доступен режим "Товаров нет"') { expect(@upload_tab.moving_no?).to be true }
+
+        context 'когда выбран режим "Товары есть"' do
+          before(:all) { @upload_tab.moving_yes }
+
+          it('доступен режим "Оставить опубликованными"') { expect(@upload_tab.moving_keep?(2)).to be true }
+          it('доступен режим "Удалить"') { expect(@upload_tab.moving_delete?(2)).to be true }
+          it('не доступен режим "Перенести в архив"') { expect(@upload_tab.moving_archive_not_exists?(2)).to be true }
+          it 'присутствует активный блок "Сайт магазина"' do
+            expect(@upload_tab.store_url_label?).to be true
+            expect(@upload_tab.store_url_element.enabled?).to be true
+          end
+
+          it('присутствует кнопка "Загрузить"') { expect(@upload_tab.upload_price?).to be true }
+        end
+
+        #TODO: Аналогично, раскипать после того, как обновят образ ножа для ПЦ
path: lib/apress/selenium_products/spec/company_site/kirby/import/import_yml_policy_spec.rb
user: login: apress-hound
body: [Correctable] Layout/LeadingCommentSpace: Missing space after #.
created_at: 2025-04-25T07:58:44Z
author_association: NONE
diff_hunk: @@ -0,0 +1,434 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Кирби: политики доступа страницы импорта YML', feature: 'Кирби: политики доступа страницы импорта YML' do
+  before(:all) do
+    @import_yml_page = CompanySite::ImportYMLPage.new
+    @upload_tab      = CompanySite::ImportYMLPage::UploadTab.new
+    @settings_tab    = CompanySite::ImportYMLPage::SettingsTab.new
+  end
+
+  shared_examples 'общие элементы страницы' do
+    it 'присутствует title в формате "Загрузка товаров из YML/YRL - %название компании% - %основной регион%"' do
+      expect(@import_yml_page.has_expected_title?).to be true
+    end
+
+    it 'присутствует заголовок страницы "Загрузить товары в формате Яндекс.Маркет (YML/YRL)"' do
+      expect(@import_yml_page.header).to eq 'Загрузить товары в формате Яндекс.Маркет (YML/YRL)'
+    end
+
+    it 'присутствуют вкладки "Загрузить товары" и "Расширенные настройки"' do
+      expect(@import_yml_page.upload_tab?).to be true
+      expect(@import_yml_page.settings_tab?).to be true
+    end
+  end
+
+  shared_examples 'все элементы страницы для роли с повышенными правами' do |role|
+    context 'когда на вкладке "Загрузить товары"' do
+      before(:all) { @import_yml_page.upload_tab }
+
+      it('присутствует текстовая зона') { expect(@upload_tab.text_zone?).to be true }
+
+      it 'присутствует активный блок "Формат" со значениями YML, YRL и EDIFACT' do
+        expect(@upload_tab.source_type_label?).to be true
+        expect(@upload_tab.source_type_options).to eq %w[YML YRL EDIFACT]
+      end
+
+      it('доступен режим "Товаров нет"') { expect(@upload_tab.moving_no?).to be true }
+
+      context 'когда выбран режим "Товары есть"' do
+        before(:all) { @upload_tab.moving_yes }
+
+        it('доступен режим "Оставить опубликованными"') { expect(@upload_tab.moving_keep?(2)).to be true }
+        it('доступен режим "Удалить"') { expect(@upload_tab.moving_delete?(2)).to be true }
+        it('доступен режим "Перенести в архив"') { expect(@upload_tab.moving_archive?(2)).to be true }
+
+        it('присутствует кнопка "Загрузить"') { expect(@upload_tab.upload_price?).to be true }
+      end
+
+      #TODO: Раскипать после того, как обновят образ ножа для ПЦ, тест пропускается так как файла по пути /test_files/pulscen пока нет.
+      xcontext 'когда источник - Файл' do
+        before(:all) do
+          @upload_tab.switch_to_source_file
+          @upload_tab.upload_yml(YAML_FILE_PATH)
+          @import_yml_page.settings_tab
+          @settings_tab.save_settings
+          @import_yml_page.upload_tab
+        end
+
+        it('присутствует поле с названием выбранного файла') { expect(@upload_tab.source_file?).to be true }
+        it('присутствует псевдо-ссылка выбора файла') { expect(@upload_tab.file_upload_element.exists?).to be true }
+        it('присутствует ссылка на скачивание прайса') { expect(@upload_tab.download_last_price?).to be true }
+      end
+
+      context 'когда источник - Ссылка' do
+        before(:all) { @upload_tab.switch_to_source_url }
+
+        it('присутствует поле ввода источника прайса') { expect(@upload_tab.source_url?).to be true }
+      end
+    end
+
+    context 'когда на вкладке "Расширенные настройки"' do
+      before(:all) { @import_yml_page.settings_tab }
+
+      it('присутствует заголовок "Выборочное обновление полей"') { expect(@settings_tab.selected_fields?).to be true }
+
+      it 'присутствует заголовок "Выборочное обновление товаров"' do
+        expect(@settings_tab.selected_products?).to be true
+      end
+      it('присутствует заголовок "Отчет"') { expect(@settings_tab.notification_label?).to be true }
+
+      it('присутствует заголовок "Загрузка характеристик для фильтров по товарам на вашем сайте"') do
+        expect(@settings_tab.company_traits_label?).to be true
+      end
+
+      it 'присутствует активный чекбокс "Загружать характеристики"' do
+        expect(@settings_tab.company_traits).to eq 'Загружать характеристики'
+        expect(@settings_tab.company_traits_element.checkbox_element.enabled?).to be true
+      end
+
+      it 'все чекбоксы выбора статусов обновляемых товаров активные' do
+        expect(@settings_tab.update_archived).to eq 'Обновлять товары в статусе «Архивный»'
+        expect(@settings_tab.update_archived_element.checkbox_element.enabled?).to be true
+        expect(@settings_tab.update_unpublished).to eq 'Обновлять товары в статусе «Опубликованный на сайте»'
+        expect(@settings_tab.update_unpublished_element.checkbox_element.enabled?).to be true
+      end
+
+      it 'все чекбоксы в блоке "Выборочное обновление полей" активные' do
+        CompanySite::ImportYMLPage::SettingsTab::TAGS.each do |field|
+          expect(@settings_tab.send("#{field}_element").enabled?).to be true
+        end
+      end
+
+      it 'все чекбоксы в блоке "Настройка названия товара" активные' do
+        CompanySite::ImportYMLPage::SettingsTab::NAME_TAGS.each do |field|
+          expect(@settings_tab.send("tag_#{field}_element").enabled?).to be true
+        end
+      end
+
+      it 'чекбокс "Получать отчёт о загрузке товаров и услуг" в блоке "Отчет" активный' do
+        expect(@settings_tab.notification).to eq 'Получать отчёт о загрузке товаров и услуг'
+        expect(@settings_tab.notification_element.checkbox_element.enabled?).to be true
+      end
+
+      context 'когда источник - Ссылка' do
+        before(:all) do
+          @import_yml_page.upload_tab
+          @upload_tab.switch_to_source_url
+          @import_yml_page.settings_tab
+        end
+
+        it 'отобразится активный чекбокс "Включить автоматическое обновление" в блоке "Автообновление"' do
+          expect(@settings_tab.autoupdate_label).to eq 'Автообновление'
+          expect(@settings_tab.autoupdate_element.checkbox_element.enabled?).to be true
+        end
+
+        context 'когда отмечен чекбокс "Включить автоматическое обновление"' do
+          before(:all) { @settings_tab.autoupdate_element.checkbox_element.check }
+
+          it 'отобразится блок с полями "Интервал обновления" и "Точное время обновления (MSK)"' do
+            expect(@settings_tab.autoupdate_period_label?).to be true
+            expect(@settings_tab.autoupdate_period?).to be true
+            expect(@settings_tab.autoupdate_start_date_label?).to be true
+            expect(@settings_tab.autoupdate_start_date).to be_truthy
+          end
+        end
+      end
+    end
+  end
+
+  shared_context 'роль с повышенными правами' do |role, name|
+    context "когда роль - #{name}" do
+      before(:all) do
+        log_in_as(role)
+        navigate_to(@import_yml_page.page_url_value, subdomain: CONFIG['kirby']['import']['paid_company']['subdomain'])
+      end
+      after(:all) { log_out }
+
+      include_examples 'общие элементы страницы'
+      include_examples 'все элементы страницы для роли с повышенными правами', role
+    end
+  end
+
+  context 'когда роль - Владелец' do
+    before(:all) { log_in_as(:user) }
+    after(:all) { log_out }
+
+    context 'когда своя компания с бесплатным пакетом' do
+      before(:all) do
+        navigate_to(@import_yml_page.page_url_value,
+                    subdomain: CONFIG['kirby']['import']['unpaid_company']['subdomain'])
+      end
+
+      include_examples 'общие элементы страницы'
+
+      context 'когда на вкладке "Загрузка товаров"' do
+        before(:all) { @import_yml_page.upload_tab }
+
+        it('присутствует текстовая зона') { expect(@upload_tab.text_zone?).to be true }
+        it 'присутствует активный блок "Формат" со значениями YML, YRL и EDIFACT' do
+          expect(@upload_tab.source_type_label?).to be true
+          expect(@upload_tab.source_type_options).to eq %w[YML YRL EDIFACT]
+        end
+
+        it('доступен режим "Товаров нет"') { expect(@upload_tab.moving_no?).to be true }
+
+        context 'когда выбран режим "Товары есть"' do
+          before(:all) { @upload_tab.moving_yes }
+
+          it('доступен режим "Оставить опубликованными"') { expect(@upload_tab.moving_keep?(2)).to be true }
+          it('доступен режим "Удалить"') { expect(@upload_tab.moving_delete?(2)).to be true }
+          it('не доступен режим "Перенести в архив"') { expect(@upload_tab.moving_archive_not_exists?(2)).to be true }
+          it 'присутствует НЕактивный блок "Сайт магазина"' do
+            expect(@upload_tab.store_url_label?).to be true
+            expect(@upload_tab.store_url_element.disabled?).to be true
+          end
+
+          it 'отсутствуют кнопки "Сохранить" и "Загрузить группы"' do
+            expect(@upload_tab.upload_groups_not_exists?).to be true
+            expect(@upload_tab.save_not_exists?).to be true
+          end
+
+          it('присутствует кнопка "Загрузить"') { expect(@upload_tab.upload_price?).to be true }
+        end
+
+        #TODO: Аналогично, раскипать после того, как обновят образ ножа для ПЦ
path: lib/apress/selenium_products/spec/company_site/kirby/import/import_yml_policy_spec.rb
user: login: apress-hound
body: [Correctable] Layout/LeadingCommentSpace: Missing space after #.
created_at: 2025-04-25T07:58:44Z
author_association: NONE
diff_hunk: @@ -0,0 +1,434 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Кирби: политики доступа страницы импорта YML', feature: 'Кирби: политики доступа страницы импорта YML' do
+  before(:all) do
+    @import_yml_page = CompanySite::ImportYMLPage.new
+    @upload_tab      = CompanySite::ImportYMLPage::UploadTab.new
+    @settings_tab    = CompanySite::ImportYMLPage::SettingsTab.new
+  end
+
+  shared_examples 'общие элементы страницы' do
+    it 'присутствует title в формате "Загрузка товаров из YML/YRL - %название компании% - %основной регион%"' do
+      expect(@import_yml_page.has_expected_title?).to be true
+    end
+
+    it 'присутствует заголовок страницы "Загрузить товары в формате Яндекс.Маркет (YML/YRL)"' do
+      expect(@import_yml_page.header).to eq 'Загрузить товары в формате Яндекс.Маркет (YML/YRL)'
+    end
+
+    it 'присутствуют вкладки "Загрузить товары" и "Расширенные настройки"' do
+      expect(@import_yml_page.upload_tab?).to be true
+      expect(@import_yml_page.settings_tab?).to be true
+    end
+  end
+
+  shared_examples 'все элементы страницы для роли с повышенными правами' do |role|
+    context 'когда на вкладке "Загрузить товары"' do
+      before(:all) { @import_yml_page.upload_tab }
+
+      it('присутствует текстовая зона') { expect(@upload_tab.text_zone?).to be true }
+
+      it 'присутствует активный блок "Формат" со значениями YML, YRL и EDIFACT' do
+        expect(@upload_tab.source_type_label?).to be true
+        expect(@upload_tab.source_type_options).to eq %w[YML YRL EDIFACT]
+      end
+
+      it('доступен режим "Товаров нет"') { expect(@upload_tab.moving_no?).to be true }
+
+      context 'когда выбран режим "Товары есть"' do
+        before(:all) { @upload_tab.moving_yes }
+
+        it('доступен режим "Оставить опубликованными"') { expect(@upload_tab.moving_keep?(2)).to be true }
+        it('доступен режим "Удалить"') { expect(@upload_tab.moving_delete?(2)).to be true }
+        it('доступен режим "Перенести в архив"') { expect(@upload_tab.moving_archive?(2)).to be true }
+
+        it('присутствует кнопка "Загрузить"') { expect(@upload_tab.upload_price?).to be true }
+      end
+
+      #TODO: Раскипать после того, как обновят образ ножа для ПЦ, тест пропускается так как файла по пути /test_files/pulscen пока нет.
path: lib/apress/selenium_products/spec/company_site/kirby/import/import_yml_policy_spec.rb
user: login: apress-hound
body: [Correctable] Layout/LeadingCommentSpace: Missing space after #.<br>Layout/LineLength: Line is too long. [135/120]
created_at: 2025-04-25T07:58:44Z
author_association: NONE
diff_hunk: @@ -0,0 +1,434 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Кирби: политики доступа страницы импорта YML', feature: 'Кирби: политики доступа страницы импорта YML' do
+  before(:all) do
+    @import_yml_page = CompanySite::ImportYMLPage.new
+    @upload_tab      = CompanySite::ImportYMLPage::UploadTab.new
+    @settings_tab    = CompanySite::ImportYMLPage::SettingsTab.new
+  end
+
+  shared_examples 'общие элементы страницы' do
+    it 'присутствует title в формате "Загрузка товаров из YML/YRL - %название компании% - %основной регион%"' do
+      expect(@import_yml_page.has_expected_title?).to be true
+    end
+
+    it 'присутствует заголовок страницы "Загрузить товары в формате Яндекс.Маркет (YML/YRL)"' do
+      expect(@import_yml_page.header).to eq 'Загрузить товары в формате Яндекс.Маркет (YML/YRL)'
+    end
+
+    it 'присутствуют вкладки "Загрузить товары" и "Расширенные настройки"' do
+      expect(@import_yml_page.upload_tab?).to be true
+      expect(@import_yml_page.settings_tab?).to be true
+    end
+  end
+
+  shared_examples 'все элементы страницы для роли с повышенными правами' do |role|
+    context 'когда на вкладке "Загрузить товары"' do
+      before(:all) { @import_yml_page.upload_tab }
+
+      it('присутствует текстовая зона') { expect(@upload_tab.text_zone?).to be true }
+
+      it 'присутствует активный блок "Формат" со значениями YML, YRL и EDIFACT' do
+        expect(@upload_tab.source_type_label?).to be true
+        expect(@upload_tab.source_type_options).to eq %w[YML YRL EDIFACT]
+      end
+
+      it('доступен режим "Товаров нет"') { expect(@upload_tab.moving_no?).to be true }
+
+      context 'когда выбран режим "Товары есть"' do
+        before(:all) { @upload_tab.moving_yes }
+
+        it('доступен режим "Оставить опубликованными"') { expect(@upload_tab.moving_keep?(2)).to be true }
+        it('доступен режим "Удалить"') { expect(@upload_tab.moving_delete?(2)).to be true }
+        it('доступен режим "Перенести в архив"') { expect(@upload_tab.moving_archive?(2)).to be true }
+
+        it('присутствует кнопка "Загрузить"') { expect(@upload_tab.upload_price?).to be true }
+      end
+
+      #TODO: Раскипать после того, как обновят образ ножа для ПЦ, тест пропускается так как файла по пути /test_files/pulscen пока нет.
+      xcontext 'когда источник - Файл' do
+        before(:all) do
+          @upload_tab.switch_to_source_file
+          @upload_tab.upload_yml(YAML_FILE_PATH)
path: lib/apress/selenium_products/spec/company_site/kirby/import/import_yml_policy_spec.rb
user: login: KirillGaliulin
body: Название константы YAML_FILE_PATH остается таким для обоих проектов по итогу?)
created_at: 2025-04-25T08:01:11Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,429 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Кирби: политики доступа страницы импорта YML', feature: 'Кирби: политики доступа страницы импорта YML' do
+  before(:all) do
+    @import_yml_page = CompanySite::ImportYMLPage.new
+    @upload_tab      = CompanySite::ImportYMLPage::UploadTab.new
+    @settings_tab    = CompanySite::ImportYMLPage::SettingsTab.new
+  end
+
+  shared_examples 'общие элементы страницы' do
+    it 'присутствует title в формате "Загрузка товаров из YML/YRL - %название компании% - %основной регион%"' do
+      expect(@import_yml_page.has_expected_title?).to be true
+    end
+
+    it 'присутствует заголовок страницы "Загрузить товары в формате Яндекс.Маркет (YML/YRL)"' do
+      expect(@import_yml_page.header).to eq 'Загрузить товары в формате Яндекс.Маркет (YML/YRL)'
+    end
+
+    it 'присутствуют вкладки "Загрузить товары" и "Расширенные настройки"' do
+      expect(@import_yml_page.upload_tab?).to be true
+      expect(@import_yml_page.settings_tab?).to be true
+    end
+  end
+
+  shared_examples 'все элементы страницы для роли с повышенными правами' do |role|
+    context 'когда на вкладке "Загрузить товары"' do
+      before(:all) { @import_yml_page.upload_tab }
+
+      it('присутствует текстовая зона') { expect(@upload_tab.text_zone?).to be true }
+
+      it 'присутствует активный блок "Формат" со значениями YML, YRL и EDIFACT' do
+        expect(@upload_tab.source_type_label?).to be true
+        expect(@upload_tab.source_type_options).to eq %w[YML YRL EDIFACT]
+      end
+
+      it('доступен режим "Товаров нет"') { expect(@upload_tab.moving_no?).to be true }
+
+      context 'когда выбран режим "Товары есть"' do
+        before(:all) { @upload_tab.moving_yes }
+
+        it('доступен режим "Оставить опубликованными"') { expect(@upload_tab.moving_keep?(2)).to be true }
+        it('доступен режим "Удалить"') { expect(@upload_tab.moving_delete?(2)).to be true }
+        it('доступен режим "Перенести в архив"') { expect(@upload_tab.moving_archive?(2)).to be true }
+
+        it('присутствует кнопка "Загрузить"') { expect(@upload_tab.upload_price?).to be true }
+      end
+
+      xcontext 'когда источник - Файл' do
path: lib/apress/selenium_products/spec/company_site/kirby/import/import_yml_policy_spec.rb
user: login: Fort-Nox
body: Добавил.
created_at: 2025-04-25T08:57:01Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,103 @@
+# frozen_string_literal: true
+
+module CompanySite
+  class ImportYMLPage < Page
+    page_url '/admin/import_yml/edit'
+    expected_title %r{Загрузка товаров из YML/YRL - .+-.+}
+
+    h1(:header, css: '.company-admin-page-header h1')
+    link(:upload_tab, css: 'a[href="#upload"]')
+    link(:settings_tab, css: 'a[href="#settings"]')
+    link(:warnings_tab, css: 'a[href="#errors"]')
+
+    class UploadTab < ImportYMLPage
+      MOVING = %i[none keep delete archive].freeze
+
+      div(:text_zone, css: '.yml-import-textzone')
+      label(:source_label, css: '.yml-import-label-required')
+
+      # Элементы источника - Ссылка
+      link(:switch_to_source_url, css: 'a[href="#switcher-tabs-1"]')
+      text_field(:source_url, css: '.js-url-field')
+      div(:source_url_validation_message, css: '#switcher-tabs-1 .js-validation-message')
+
+      # Элементы источника - Файл
+      link(:switch_to_source_file, css: 'a[href="#switcher-tabs-2"]')
+      text_field(:source_file, css: '.yml-file-name')
+      span(:file_upload, xpath: '//*[@type="file"]')
+      link(:download_last_price, css: '.custom-yml-link')
+
+      # Тип источника (формат)
+      div(:source_type_label, xpath: '//label[contains(text(), "Формат:")]')
+      select_list(:source_type, css: '#online_store_source_type')
+      link(:warnings_link, css: '.js-open-errors-tab')
+
+      # Сайт магазина
+      label(:store_url_label, xpath: '//label[contains(text(), "Сайт магазина:")]')
+      text_field(:store_url, css: '#online_store_store_url')
+
+      # Тип магазина
+      label(:store_type_label, xpath: '//label[contains(text(), "Тип магазина:")]')
+      select_list(:store_type, css: '#online_store_store_type')
+
+      # Выбор режима загрузки
+      div(:care_about_products, css: '.form-item-input-box .notice')
+      link(:moving_no, css: 'a[href="#switcher-tabs-3"]')
+      link(:moving_yes, css: 'a[href="#switcher-tabs-4"]')
+
+      MOVING.each do |type|
+        select("moving_#{type}", xpath: "//select[@id='moving']//option[@value='#{type}']")
+      end
+
+      # Блок кнопок (Сохранение, загрузка прайса и товаров)
+      button(:save, css: '.js-yml-import-button.js-yml-save')
+      button(:upload_price, css: '.js-yml-import-button.js-yml-upload')
+      button(:upload_groups, css: '.js-yml-import-button.js-yml-groups-upload')
+
+      def upload_yml(file_path)
+        upload_file(file_upload_element, file_path)
+      end
+    end
+
+    class SettingsTab < ImportYMLPage
+      TAGS      = %w[name image_urls announce description price wholesale_price exists product_group].freeze
+      NAME_TAGS = %w[name typePrefix vendor model].freeze
+
+      label(:selected_fields, xpath: '//label[text()="Выборочное обновление полей"]')
+      label(:selected_products, xpath: '//label[text()="Выборочное обновление товаров"]')
+
+      div(:update_archived, xpath: '//div[child::*[@id="online_store_update_archived"]]')
+      div(:update_unpublished, xpath: '//div[child::*[@id="online_store_update_unpublished"]]')
+
+      # Автообновление
+      label(:autoupdate_label, xpath: '//label[text()="Автообновление"]')
+      div(:autoupdate, xpath: '//div[child::*[@id="online_store_updating_settings_attributes_enabled"]]')
+      label(:autoupdate_period_label, xpath: '//label[text()="Интервал обновления"]')
+      text_field(:autoupdate_period, css: '#online_store_updating_settings_attributes_period')
+      label(:autoupdate_start_date_label, xpath: '//label[text()="Точное время обновления (MSK)"]')
+      text_field(:autoupdate_start_date, css: '#online_store_updating_settings_attributes_start_date')
+
+      # Отчет
+      label(:notification_label, xpath: '//label[text()="Отчет"]')
+      div(:notification, xpath: '//div[child::*[@id="online_store_send_notifications"]]')
+
+      # Пользовательские характеристики
+      label(:company_traits_label,
+            xpath: '//label[text()="Загрузка характеристик для фильтров по товарам на вашем сайте"]')
path: lib/pages/company_site/import_yml_page.rb
user: login: Fort-Nox
body: Урезал текст заголовка до "Загрузка характеристик", его думаю точно не поменяют, и явно указал на класс, в котором есть этот заголовок.
created_at: 2025-04-25T09:00:17Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,434 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Кирби: политики доступа страницы импорта YML', feature: 'Кирби: политики доступа страницы импорта YML' do
+  before(:all) do
+    @import_yml_page = CompanySite::ImportYMLPage.new
+    @upload_tab      = CompanySite::ImportYMLPage::UploadTab.new
+    @settings_tab    = CompanySite::ImportYMLPage::SettingsTab.new
+  end
+
+  shared_examples 'общие элементы страницы' do
+    it 'присутствует title в формате "Загрузка товаров из YML/YRL - %название компании% - %основной регион%"' do
+      expect(@import_yml_page.has_expected_title?).to be true
+    end
+
+    it 'присутствует заголовок страницы "Загрузить товары в формате Яндекс.Маркет (YML/YRL)"' do
+      expect(@import_yml_page.header).to eq 'Загрузить товары в формате Яндекс.Маркет (YML/YRL)'
+    end
+
+    it 'присутствуют вкладки "Загрузить товары" и "Расширенные настройки"' do
+      expect(@import_yml_page.upload_tab?).to be true
+      expect(@import_yml_page.settings_tab?).to be true
+    end
+  end
+
+  shared_examples 'все элементы страницы для роли с повышенными правами' do |role|
+    context 'когда на вкладке "Загрузить товары"' do
+      before(:all) { @import_yml_page.upload_tab }
+
+      it('присутствует текстовая зона') { expect(@upload_tab.text_zone?).to be true }
+
+      it 'присутствует активный блок "Формат" со значениями YML, YRL и EDIFACT' do
+        expect(@upload_tab.source_type_label?).to be true
+        expect(@upload_tab.source_type_options).to eq %w[YML YRL EDIFACT]
+      end
+
+      it('доступен режим "Товаров нет"') { expect(@upload_tab.moving_no?).to be true }
+
+      context 'когда выбран режим "Товары есть"' do
+        before(:all) { @upload_tab.moving_yes }
+
+        it('доступен режим "Оставить опубликованными"') { expect(@upload_tab.moving_keep?(2)).to be true }
+        it('доступен режим "Удалить"') { expect(@upload_tab.moving_delete?(2)).to be true }
+        it('доступен режим "Перенести в архив"') { expect(@upload_tab.moving_archive?(2)).to be true }
+
+        it('присутствует кнопка "Загрузить"') { expect(@upload_tab.upload_price?).to be true }
+      end
+
+      #TODO: Раскипать после того, как обновят образ ножа для ПЦ, тест пропускается так как файла по пути /test_files/pulscen пока нет.
+      xcontext 'когда источник - Файл' do
+        before(:all) do
+          @upload_tab.switch_to_source_file
+          @upload_tab.upload_yml(YAML_FILE_PATH)
+          @import_yml_page.settings_tab
+          @settings_tab.save_settings
+          @import_yml_page.upload_tab
+        end
+
+        it('присутствует поле с названием выбранного файла') { expect(@upload_tab.source_file?).to be true }
+        it('присутствует псевдо-ссылка выбора файла') { expect(@upload_tab.file_upload_element.exists?).to be true }
+        it('присутствует ссылка на скачивание прайса') { expect(@upload_tab.download_last_price?).to be true }
+      end
+
+      context 'когда источник - Ссылка' do
+        before(:all) { @upload_tab.switch_to_source_url }
+
+        it('присутствует поле ввода источника прайса') { expect(@upload_tab.source_url?).to be true }
+      end
+    end
+
+    context 'когда на вкладке "Расширенные настройки"' do
+      before(:all) { @import_yml_page.settings_tab }
+
+      it('присутствует заголовок "Выборочное обновление полей"') { expect(@settings_tab.selected_fields?).to be true }
+
+      it 'присутствует заголовок "Выборочное обновление товаров"' do
+        expect(@settings_tab.selected_products?).to be true
+      end
+      it('присутствует заголовок "Отчет"') { expect(@settings_tab.notification_label?).to be true }
+
+      it('присутствует заголовок "Загрузка характеристик для фильтров по товарам на вашем сайте"') do
+        expect(@settings_tab.company_traits_label?).to be true
+      end
+
+      it 'присутствует активный чекбокс "Загружать характеристики"' do
+        expect(@settings_tab.company_traits).to eq 'Загружать характеристики'
+        expect(@settings_tab.company_traits_element.checkbox_element.enabled?).to be true
+      end
+
+      it 'все чекбоксы выбора статусов обновляемых товаров активные' do
+        expect(@settings_tab.update_archived).to eq 'Обновлять товары в статусе «Архивный»'
+        expect(@settings_tab.update_archived_element.checkbox_element.enabled?).to be true
+        expect(@settings_tab.update_unpublished).to eq 'Обновлять товары в статусе «Опубликованный на сайте»'
+        expect(@settings_tab.update_unpublished_element.checkbox_element.enabled?).to be true
+      end
+
+      it 'все чекбоксы в блоке "Выборочное обновление полей" активные' do
+        CompanySite::ImportYMLPage::SettingsTab::TAGS.each do |field|
+          expect(@settings_tab.send("#{field}_element").enabled?).to be true
+        end
+      end
+
+      it 'все чекбоксы в блоке "Настройка названия товара" активные' do
+        CompanySite::ImportYMLPage::SettingsTab::NAME_TAGS.each do |field|
+          expect(@settings_tab.send("tag_#{field}_element").enabled?).to be true
+        end
+      end
+
+      it 'чекбокс "Получать отчёт о загрузке товаров и услуг" в блоке "Отчет" активный' do
+        expect(@settings_tab.notification).to eq 'Получать отчёт о загрузке товаров и услуг'
+        expect(@settings_tab.notification_element.checkbox_element.enabled?).to be true
+      end
+
+      context 'когда источник - Ссылка' do
+        before(:all) do
+          @import_yml_page.upload_tab
+          @upload_tab.switch_to_source_url
+          @import_yml_page.settings_tab
+        end
+
+        it 'отобразится активный чекбокс "Включить автоматическое обновление" в блоке "Автообновление"' do
+          expect(@settings_tab.autoupdate_label).to eq 'Автообновление'
+          expect(@settings_tab.autoupdate_element.checkbox_element.enabled?).to be true
+        end
+
+        context 'когда отмечен чекбокс "Включить автоматическое обновление"' do
+          before(:all) { @settings_tab.autoupdate_element.checkbox_element.check }
+
+          it 'отобразится блок с полями "Интервал обновления" и "Точное время обновления (MSK)"' do
+            expect(@settings_tab.autoupdate_period_label?).to be true
+            expect(@settings_tab.autoupdate_period?).to be true
+            expect(@settings_tab.autoupdate_start_date_label?).to be true
+            expect(@settings_tab.autoupdate_start_date).to be_truthy
+          end
+        end
+      end
+    end
+  end
+
+  shared_context 'роль с повышенными правами' do |role, name|
+    context "когда роль - #{name}" do
+      before(:all) do
+        log_in_as(role)
+        navigate_to(@import_yml_page.page_url_value, subdomain: CONFIG['kirby']['import']['paid_company']['subdomain'])
+      end
+      after(:all) { log_out }
+
+      include_examples 'общие элементы страницы'
+      include_examples 'все элементы страницы для роли с повышенными правами', role
+    end
+  end
+
+  context 'когда роль - Владелец' do
+    before(:all) { log_in_as(:user) }
+    after(:all) { log_out }
+
+    context 'когда своя компания с бесплатным пакетом' do
+      before(:all) do
+        navigate_to(@import_yml_page.page_url_value,
+                    subdomain: CONFIG['kirby']['import']['unpaid_company']['subdomain'])
+      end
+
+      include_examples 'общие элементы страницы'
+
+      context 'когда на вкладке "Загрузка товаров"' do
+        before(:all) { @import_yml_page.upload_tab }
+
+        it('присутствует текстовая зона') { expect(@upload_tab.text_zone?).to be true }
+        it 'присутствует активный блок "Формат" со значениями YML, YRL и EDIFACT' do
+          expect(@upload_tab.source_type_label?).to be true
+          expect(@upload_tab.source_type_options).to eq %w[YML YRL EDIFACT]
+        end
+
+        it('доступен режим "Товаров нет"') { expect(@upload_tab.moving_no?).to be true }
+
+        context 'когда выбран режим "Товары есть"' do
+          before(:all) { @upload_tab.moving_yes }
+
+          it('доступен режим "Оставить опубликованными"') { expect(@upload_tab.moving_keep?(2)).to be true }
+          it('доступен режим "Удалить"') { expect(@upload_tab.moving_delete?(2)).to be true }
+          it('не доступен режим "Перенести в архив"') { expect(@upload_tab.moving_archive_not_exists?(2)).to be true }
+          it 'присутствует НЕактивный блок "Сайт магазина"' do
+            expect(@upload_tab.store_url_label?).to be true
+            expect(@upload_tab.store_url_element.disabled?).to be true
+          end
+
+          it 'отсутствуют кнопки "Сохранить" и "Загрузить группы"' do
+            expect(@upload_tab.upload_groups_not_exists?).to be true
+            expect(@upload_tab.save_not_exists?).to be true
+          end
+
+          it('присутствует кнопка "Загрузить"') { expect(@upload_tab.upload_price?).to be true }
+        end
+
+        #TODO: Аналогично, раскипать после того, как обновят образ ножа для ПЦ
+        xcontext 'когда источник - Файл' do
+          before(:all) do
+            @upload_tab.switch_to_source_file
+            @upload_tab.upload_yml(YAML_FILE_PATH)
+            @import_yml_page.settings_tab
+            @settings_tab.save_settings
+            @import_yml_page.upload_tab
+          end
+
+          it('присутствует поле с названием выбранного файла') { expect(@upload_tab.source_file?).to be true }
+          it('присутствует псевдо-ссылка выбора файла') { expect(@upload_tab.file_upload_element.exists?).to be true }
+          it('присутствует ссылка на скачивание прайса') { expect(@upload_tab.download_last_price?).to be true }
+        end
+
+        context 'когда источник - Ссылка' do
+          before(:all) { @upload_tab.switch_to_source_url }
+
+          it('присутствует поле ввода источника прайса') { expect(@upload_tab.source_url?).to be true }
+        end
+      end
+
+      context 'когда на вкладке "Расширенные настройки"' do
+        before(:all) { @import_yml_page.settings_tab }
+
+        it('присутствует заголовок "Выборочное обновление полей"') { expect(@settings_tab.selected_fields?).to be true }
+
+        it 'присутствует заголовок "Выборочное обновление товаров"' do
+          expect(@settings_tab.selected_products?).to be true
+        end
+
+        it('присутствует заголовок "Отчет"') { expect(@settings_tab.notification_label?).to be true }
+
+        it('присутствует заголовок "Загрузка характеристик для фильтров по товарам на вашем сайте"') do
+          expect(@settings_tab.company_traits_label?).to be true
+        end
+
+        it 'присутствует активный чекбокс "Загружать характеристики"' do
+          expect(@settings_tab.company_traits).to eq 'Загружать характеристики'
+          expect(@settings_tab.company_traits_element.checkbox_element.enabled?).to be true
+        end
+
+        it 'все чекбоксы выбора статусов обновляемых товаров активные' do
+          expect(@settings_tab.update_archived).to eq 'Обновлять товары в статусе «Архивный»'
+          expect(@settings_tab.update_archived_element.checkbox_element.enabled?).to be true
+          expect(@settings_tab.update_unpublished).to eq 'Обновлять товары в статусе «Опубликованный на сайте»'
+          expect(@settings_tab.update_unpublished_element.checkbox_element.enabled?).to be true
+        end
+
+        context 'когда источник - Ссылка' do
+          before do
+            @import_yml_page.upload_tab
+            @upload_tab.switch_to_source_url
+            @import_yml_page.settings_tab
+          end
+
+          it 'не отобразится блок "Автообновление"' do
+            expect(@settings_tab.autoupdate_label_not_exists?).to be true
+            expect(@settings_tab.autoupdate_not_exists?).to be true
+          end
+        end
+
+        it 'все чекбоксы в блоке "Выборочное обновление полей" НЕактивные' do
+          CompanySite::ImportYMLPage::SettingsTab::TAGS.each do |field|
+            expect(@settings_tab.send("#{field}_element").disabled?).to be true
+          end
+        end
+
+        it 'все чекбоксы в блоке "Настройка названия товара" НЕактивные' do
+          CompanySite::ImportYMLPage::SettingsTab::NAME_TAGS.each do |field|
+            expect(@settings_tab.send("tag_#{field}_element").disabled?).to be true
+          end
+        end
+
+        it 'чекбокс "Получать отчёт о загрузке товаров и услуг" в блоке "Отчет" НЕактивный' do
+          expect(@settings_tab.notification).to eq 'Получать отчёт о загрузке товаров и услуг'
+          expect(@settings_tab.notification_element.checkbox_element.disabled?).to be true
+        end
+      end
+    end
+
+    context 'когда своя компания с платным пакетом' do
+      before(:all) do
+        navigate_to(@import_yml_page.page_url_value, subdomain: CONFIG['kirby']['import']['paid_company']['subdomain'])
+      end
+
+      include_examples 'общие элементы страницы'
+
+      context 'когда на вкладке "Загрузить товары"' do
+        before(:all) { @import_yml_page.upload_tab }
+
+        it('присутствует текстовая зона') { expect(@upload_tab.text_zone?).to be true }
+        it 'присутствует активный блок "Формат" со значениями YML, YRL и EDIFACT' do
+          expect(@upload_tab.source_type_label?).to be true
+          expect(@upload_tab.source_type_options).to eq %w[YML YRL EDIFACT]
+        end
+
+        it('доступен режим "Товаров нет"') { expect(@upload_tab.moving_no?).to be true }
+
+        context 'когда выбран режим "Товары есть"' do
+          before(:all) { @upload_tab.moving_yes }
+
+          it('доступен режим "Оставить опубликованными"') { expect(@upload_tab.moving_keep?(2)).to be true }
+          it('доступен режим "Удалить"') { expect(@upload_tab.moving_delete?(2)).to be true }
+          it('не доступен режим "Перенести в архив"') { expect(@upload_tab.moving_archive_not_exists?(2)).to be true }
+          it 'присутствует активный блок "Сайт магазина"' do
+            expect(@upload_tab.store_url_label?).to be true
+            expect(@upload_tab.store_url_element.enabled?).to be true
+          end
+
+          it('присутствует кнопка "Загрузить"') { expect(@upload_tab.upload_price?).to be true }
+        end
+
+        #TODO: Аналогично, раскипать после того, как обновят образ ножа для ПЦ
+        xcontext 'когда источник - Файл' do
+          before(:all) do
+            @upload_tab.switch_to_source_file
+            @upload_tab.upload_yml(YAML_FILE_PATH)
+            @import_yml_page.settings_tab
+            @settings_tab.save_settings
+            @import_yml_page.upload_tab
+          end
+
+          it('присутствует поле с названием выбранного файла') { expect(@upload_tab.source_file?).to be true }
+          it('присутствует псевдо-ссылка выбора файла') { expect(@upload_tab.file_upload_element.exists?).to be true }
+          it('присутствует ссылка на скачивание прайса') { expect(@upload_tab.download_last_price?).to be true }
+        end
+
+        context 'когда источник - Ссылка' do
+          before(:all) { @upload_tab.switch_to_source_url }
+
+          it('присутствует поле ввода источника прайса') { expect(@upload_tab.source_url?).to be true }
+        end
+      end
+
+      context 'когда на вкладке "Расширенные настройки"' do
+        before(:all) { @import_yml_page.settings_tab }
+
+        it('присутствует заголовок "Выборочное обновление полей"') { expect(@settings_tab.selected_fields?).to be true }
+
+        it 'присутствует заголовок "Выборочное обновление товаров"' do
+          expect(@settings_tab.selected_products?).to be true
+        end
+        it('присутствует заголовок "Отчет"') { expect(@settings_tab.notification_label?).to be true }
+
+        it('присутствует заголовок "Загрузка характеристик для фильтров по товарам на вашем сайте"') do
+          expect(@settings_tab.company_traits_label?).to be true
+        end
+
+        it 'присутствует активный чекбокс "Загружать характеристики"' do
+          expect(@settings_tab.company_traits).to eq 'Загружать характеристики'
+          expect(@settings_tab.company_traits_element.checkbox_element.enabled?).to be true
+        end
+
+        it 'все чекбоксы выбора статусов обновляемых товаров активные' do
+          expect(@settings_tab.update_archived).to eq 'Обновлять товары в статусе «Архивный»'
+          expect(@settings_tab.update_archived_element.checkbox_element.enabled?).to be true
+          expect(@settings_tab.update_unpublished).to eq 'Обновлять товары в статусе «Опубликованный на сайте»'
+          expect(@settings_tab.update_unpublished_element.checkbox_element.enabled?).to be true
+        end
+
+        context 'когда источник - Ссылка' do
+          before do
+            @import_yml_page.upload_tab
+            @upload_tab.switch_to_source_url
+            @import_yml_page.settings_tab
+          end
+
+          it 'не отобразится блок "Автообновление"' do
+            expect(@settings_tab.autoupdate_label_not_exists?).to be true
+            expect(@settings_tab.autoupdate_not_exists?).to be true
+          end
+        end
+
+        it 'все чекбоксы в блоке "Выборочное обновление полей" активные' do
+          CompanySite::ImportYMLPage::SettingsTab::TAGS.each do |field|
+            expect(@settings_tab.send("#{field}_element").enabled?).to be true
+          end
+        end
+
+        it 'все чекбоксы в блоке "Настройка названия товара" активные' do
+          CompanySite::ImportYMLPage::SettingsTab::NAME_TAGS.each do |field|
+            expect(@settings_tab.send("tag_#{field}_element").enabled?).to be true
+          end
+        end
+
+        it 'чекбокс "Получать отчёт о загрузке товаров и услуг" в блоке "Отчет" активный' do
+          expect(@settings_tab.notification).to eq 'Получать отчёт о загрузке товаров и услуг'
+          expect(@settings_tab.notification_element.checkbox_element.enabled?).to be true
+        end
+      end
+    end
+  end
+  
+  #TODO: Раскипать после обновления дампа на ПЦ.
+  xcontext 'когда авторизованный пользователь' do
+    before do
+      log_in_as(:empty_user)
+      navigate_to(@import_yml_page.page_url_value, subdomain: CONFIG['kirby']['import']['paid_company']['subdomain'])
+    end
+    after { log_out }
+
+    it('нет доступа к просмотру и редактированию - 403 код') do
+      expect(error_403?).to be true
+      expect(@import_yml_page.text).to include 'У Вас недостаточно прав для просмотра данной страницы.'
+    end
+  end
+
+  #TODO: Аналогично, раскипать после обновления дампа на ПЦ.
path: lib/apress/selenium_products/spec/company_site/kirby/import/import_yml_policy_spec.rb
user: login: Fort-Nox
body: Добавил пробел.
created_at: 2025-04-25T09:00:42Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,435 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Кирби: политики доступа страницы импорта YML', feature: 'Кирби: политики доступа страницы импорта YML' do
+  before(:all) do
+    @import_yml_page = CompanySite::ImportYMLPage.new
+    @upload_tab      = CompanySite::ImportYMLPage::UploadTab.new
+    @settings_tab    = CompanySite::ImportYMLPage::SettingsTab.new
+  end
+
+  shared_examples 'общие элементы страницы' do
+    it 'присутствует title в формате "Загрузка товаров из YML/YRL - %название компании% - %основной регион%"' do
+      expect(@import_yml_page.has_expected_title?).to be true
+    end
+
+    it 'присутствует заголовок страницы "Загрузить товары в формате Яндекс.Маркет (YML/YRL)"' do
+      expect(@import_yml_page.header).to eq 'Загрузить товары в формате Яндекс.Маркет (YML/YRL)'
+    end
+
+    it 'присутствуют вкладки "Загрузить товары" и "Расширенные настройки"' do
+      expect(@import_yml_page.upload_tab?).to be true
+      expect(@import_yml_page.settings_tab?).to be true
+    end
+  end
+
+  shared_examples 'все элементы страницы для роли с повышенными правами' do |role|
+    context 'когда на вкладке "Загрузить товары"' do
+      before(:all) { @import_yml_page.upload_tab }
+
+      it('присутствует текстовая зона') { expect(@upload_tab.text_zone?).to be true }
+
+      it 'присутствует активный блок "Формат" со значениями YML, YRL и EDIFACT' do
+        expect(@upload_tab.source_type_label?).to be true
+        expect(@upload_tab.source_type_options).to eq %w[YML YRL EDIFACT]
+      end
+
+      it('доступен режим "Товаров нет"') { expect(@upload_tab.moving_no?).to be true }
+
+      context 'когда выбран режим "Товары есть"' do
+        before(:all) { @upload_tab.moving_yes }
+
+        it('доступен режим "Оставить опубликованными"') { expect(@upload_tab.moving_keep?(2)).to be true }
+        it('доступен режим "Удалить"') { expect(@upload_tab.moving_delete?(2)).to be true }
+        it('доступен режим "Перенести в архив"') { expect(@upload_tab.moving_archive?(2)).to be true }
+
+        it('присутствует кнопка "Загрузить"') { expect(@upload_tab.upload_price?).to be true }
+      end
+
+      # TODO: Раскипать после того, как обновят образ ножа для ПЦ, 
path: lib/apress/selenium_products/spec/company_site/kirby/import/import_yml_policy_spec.rb
user: login: apress-hound
body: [Correctable] Layout/TrailingWhitespace: Trailing whitespace detected.
created_at: 2025-04-25T09:18:21Z
author_association: NONE
diff_hunk: @@ -0,0 +1,434 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Кирби: политики доступа страницы импорта YML', feature: 'Кирби: политики доступа страницы импорта YML' do
+  before(:all) do
+    @import_yml_page = CompanySite::ImportYMLPage.new
+    @upload_tab      = CompanySite::ImportYMLPage::UploadTab.new
+    @settings_tab    = CompanySite::ImportYMLPage::SettingsTab.new
+  end
+
+  shared_examples 'общие элементы страницы' do
+    it 'присутствует title в формате "Загрузка товаров из YML/YRL - %название компании% - %основной регион%"' do
+      expect(@import_yml_page.has_expected_title?).to be true
+    end
+
+    it 'присутствует заголовок страницы "Загрузить товары в формате Яндекс.Маркет (YML/YRL)"' do
+      expect(@import_yml_page.header).to eq 'Загрузить товары в формате Яндекс.Маркет (YML/YRL)'
+    end
+
+    it 'присутствуют вкладки "Загрузить товары" и "Расширенные настройки"' do
+      expect(@import_yml_page.upload_tab?).to be true
+      expect(@import_yml_page.settings_tab?).to be true
+    end
+  end
+
+  shared_examples 'все элементы страницы для роли с повышенными правами' do |role|
+    context 'когда на вкладке "Загрузить товары"' do
+      before(:all) { @import_yml_page.upload_tab }
+
+      it('присутствует текстовая зона') { expect(@upload_tab.text_zone?).to be true }
+
+      it 'присутствует активный блок "Формат" со значениями YML, YRL и EDIFACT' do
+        expect(@upload_tab.source_type_label?).to be true
+        expect(@upload_tab.source_type_options).to eq %w[YML YRL EDIFACT]
+      end
+
+      it('доступен режим "Товаров нет"') { expect(@upload_tab.moving_no?).to be true }
+
+      context 'когда выбран режим "Товары есть"' do
+        before(:all) { @upload_tab.moving_yes }
+
+        it('доступен режим "Оставить опубликованными"') { expect(@upload_tab.moving_keep?(2)).to be true }
+        it('доступен режим "Удалить"') { expect(@upload_tab.moving_delete?(2)).to be true }
+        it('доступен режим "Перенести в архив"') { expect(@upload_tab.moving_archive?(2)).to be true }
+
+        it('присутствует кнопка "Загрузить"') { expect(@upload_tab.upload_price?).to be true }
+      end
+
+      #TODO: Раскипать после того, как обновят образ ножа для ПЦ, тест пропускается так как файла по пути /test_files/pulscen пока нет.
+      xcontext 'когда источник - Файл' do
+        before(:all) do
+          @upload_tab.switch_to_source_file
+          @upload_tab.upload_yml(YAML_FILE_PATH)
path: lib/apress/selenium_products/spec/company_site/kirby/import/import_yml_policy_spec.rb
user: login: Fort-Nox
body: Думаю да, пусть будет единообразие)
created_at: 2025-04-25T09:21:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,435 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Кирби: политики доступа страницы импорта YML', feature: 'Кирби: политики доступа страницы импорта YML' do
+  before(:all) do
+    @import_yml_page = CompanySite::ImportYMLPage.new
+    @upload_tab      = CompanySite::ImportYMLPage::UploadTab.new
+    @settings_tab    = CompanySite::ImportYMLPage::SettingsTab.new
+  end
+
+  shared_examples 'общие элементы страницы' do
+    it 'присутствует title в формате "Загрузка товаров из YML/YRL - %название компании% - %основной регион%"' do
+      expect(@import_yml_page.has_expected_title?).to be true
+    end
+
+    it 'присутствует заголовок страницы "Загрузить товары в формате Яндекс.Маркет (YML/YRL)"' do
+      expect(@import_yml_page.header).to eq 'Загрузить товары в формате Яндекс.Маркет (YML/YRL)'
+    end
+
+    it 'присутствуют вкладки "Загрузить товары" и "Расширенные настройки"' do
+      expect(@import_yml_page.upload_tab?).to be true
+      expect(@import_yml_page.settings_tab?).to be true
+    end
+  end
+
+  shared_examples 'все элементы страницы для роли с повышенными правами' do |role|
+    context 'когда на вкладке "Загрузить товары"' do
+      before(:all) { @import_yml_page.upload_tab }
+
+      it('присутствует текстовая зона') { expect(@upload_tab.text_zone?).to be true }
+
+      it 'присутствует активный блок "Формат" со значениями YML, YRL и EDIFACT' do
+        expect(@upload_tab.source_type_label?).to be true
+        expect(@upload_tab.source_type_options).to eq %w[YML YRL EDIFACT]
+      end
+
+      it('доступен режим "Товаров нет"') { expect(@upload_tab.moving_no?).to be true }
+
+      context 'когда выбран режим "Товары есть"' do
+        before(:all) { @upload_tab.moving_yes }
+
+        it('доступен режим "Оставить опубликованными"') { expect(@upload_tab.moving_keep?(2)).to be true }
+        it('доступен режим "Удалить"') { expect(@upload_tab.moving_delete?(2)).to be true }
+        it('доступен режим "Перенести в архив"') { expect(@upload_tab.moving_archive?(2)).to be true }
+
+        it('присутствует кнопка "Загрузить"') { expect(@upload_tab.upload_price?).to be true }
+      end
+
+      # TODO: Раскипать после того, как обновят образ ножа для ПЦ, 
path: lib/apress/selenium_products/spec/company_site/kirby/import/import_yml_policy_spec.rb
user: login: Fort-Nox
body: Перенос не понравился, поправил)
created_at: 2025-04-25T09:24:13Z
author_association: CONTRIBUTOR

PR comments:
user: login: KirillGaliulin
created_at: 2025-04-25T08:02:05Z
body: По остальному гуд, красавчик ;)
author_association: CONTRIBUTOR
user: login: Fort-Nox
created_at: 2025-04-25T09:03:09Z
body: @KirillGaliulin up :)
author_association: CONTRIBUTOR
user: login: Fort-Nox
created_at: 2025-04-28T05:49:44Z
body: @DenisDenis9331 / @ovsyanik-ka прошу смержить :)
author_association: CONTRIBUTOR