Как сохранить файл в Chrome с помощью Selenium

27 June 2017

В разных книгах по автоматизации тестирования дано много умных советов, как избежать загрузки файлов. Но может возникнуть множество ситуаций, когда загрузка необходима.

Например, загружаемый файл должен быть сравнен с эталоном. Или генерируется отчет, который будет использован для последующей вивисекции на предмет установления попадает ли туда нужная информация или нет.

Короче, нужно взять и загрузить. Но Хром при попытке загрузки вываливает предупреждение, работать с которым силами Селениума, увы, невозможно. А в моем случае сервер генерировал не банальные pdf или html, а целый exe (при выборе соответствующего пункта; другие варианты были менее злобными), и это приводило еще к одному предупреждению. К счастью, это все можно отключить. Но чтобы найти способ, оказалось недостаточно искать по форумам и StackOverflow, кое-что я выяснил непосредственно из исходников Хромиума (Хром, если кто не знает, это версия открытого браузера Хромиум с некоторыми вставками от Гугла; говорят, что там – анальные зонды, точно утверждать не берусь, но дома пользуюсь исключительно Хромиумом).

Итак, вот она, настоящая магия:

ChromeOptions options = new ChromeOptions();

options.addArguments("safebrowsing-disable-download-protection");

Map<String, Object> prefs = new HashMap<>();

prefs.put("safebrowsing.enabled", "true");

prefs.put("select_file_dialogs.allowed", "false");

prefs.put("download.prompt_for_download", "false");

prefs.put("download.directory_upgrade", "true");

options.setExperimentalOption("prefs", prefs);

capabilities.setCapability(ChromeOptions.CAPABILITY, options);

WebDriver driver = new ChromeDriver(capabilities);

Кое-что нужно добавить. В последних версиях Хром стал обнаруживать присутствие Селениума и зачем-то выводить гнусные сообщения о том, что он управляется извне, а также предлагать залогиниться. Мешает. Бесит. Зачем эта глупость понадобилась – не понимаю... Поэтому надо добавлять куда-то между первой и последней строкой еще три команды:

prefs.put("credentials_enable_service", Boolean.FALSE);

prefs.put("profile.password_manager_enabled", Boolean.FALSE);

options.addArguments("disable-infobars");

Тут же возникает резонный вопрос: а почему в одном случае используется "false", а в другом Boolean.FALSE? Честно отвечу, что не знаю. Вот так оно работает, а по другому – нет. У меня, по крайней мере; возможно, у кого-то сработает чуть-чуть по-другому: когда имеешь дело с Windows, возможны любые чудеса...