# Authors: # Petr Vobornik # # Copyright (C) 2013 Red Hat # see file 'COPYING' for use and warranty information # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . """ Automount tests """ from ipatests.test_webui.ui_driver import UI_driver, screenshot try: from selenium.webdriver.common.keys import Keys except ImportError: pass import pytest LOC_ENTITY = 'automountlocation' MAP_ENTITY = 'automountmap' KEY_ENTITY = 'automountkey' LOC_PKEY = 'itestloc' LOC_DATA = { 'pkey': LOC_PKEY, 'add': [ ('textbox', 'cn', LOC_PKEY), ], } MAP_PKEY = 'itestmap' MAP_DATA = { 'pkey': MAP_PKEY, 'add': [ ('textbox', 'automountmapname', MAP_PKEY), ('textarea', 'description', 'map desc'), ], 'mod': [ ('textarea', 'description', 'map desc mod'), ] } KEY_PKEY = 'itestkey' KEY_DATA = { 'pkey': KEY_PKEY, 'add': [ ('textbox', 'automountkey', KEY_PKEY), ('textbox', 'automountinformation', '/itest/key'), ], 'mod': [ ('textbox', 'automountinformation', '/itest/key2'), ] } DIRECT_MAPS = [ { 'pkey': 'map1', 'add': [ ('radio', 'method', 'add'), ('textbox', 'automountmapname', 'map1'), ('textarea', 'description', 'foobar'), ], }, { 'pkey': 'map2', 'add': [ ('radio', 'method', 'add'), ('textbox', 'automountmapname', 'map2'), ('textarea', 'description', 'foobar'), ], }, { 'pkey': 'map3', 'add': [ ('radio', 'method', 'add'), ('textbox', 'automountmapname', 'map3'), ('textarea', 'description', 'foobar'), ], }, { 'pkey': 'map4', 'add': [ ('radio', 'method', 'add'), ('textbox', 'automountmapname', 'map4'), ('textarea', 'description', 'foobar'), ], }, ] INDIRECT_MAPS = [ { 'pkey': 'map1', 'add': [ ('radio', 'method', 'add'), ('textbox', 'automountmapname', 'map1'), ('textarea', 'description', 'foobar'), ], }, { 'pkey': 'map2', 'add': [ ('radio', 'method', 'add_indirect'), ('textbox', 'automountmapname', 'map2'), ('textarea', 'description', 'foobar'), ('textbox', 'key', 'mount1'), ('textbox', 'parentmap', 'map1'), ], 'mod': [ ('textarea', 'description', 'modified'), ] }, { 'pkey': 'map3', 'add': [ ('radio', 'method', 'add_indirect'), ('textbox', 'automountmapname', 'map3'), ('textarea', 'description', 'foobar'), ('textbox', 'key', 'mount2'), ('textbox', 'parentmap', 'map1'), ], }, { 'pkey': 'map4', 'add': [ ('radio', 'method', 'add_indirect'), ('textbox', 'automountmapname', 'map4'), ('textarea', 'description', 'foobar'), ('textbox', 'key', 'mount3'), ('textbox', 'parentmap', 'map1'), ], }, ] DIRECT_MAP_MOD = { 'pkey': 'map1', 'add': [ ('radio', 'method', 'add'), ('textbox', 'automountmapname', 'map1'), ('textarea', 'description', 'desc'), ], 'mod': [ ('textarea', 'description', 'modified'), ] } INDIRECT_MAP_MOD = { 'pkey': 'map1', 'add': [ ('radio', 'method', 'add_indirect'), ('textbox', 'automountmapname', 'map1'), ('textarea', 'description', 'desc'), ('textbox', 'key', 'mount1'), ], 'mod': [ ('textarea', 'description', 'modified'), ] } class Location: def __init__(self, location, ui): self.ui = ui self.location = location def __enter__(self): self.ui.add_record(LOC_ENTITY, self.location) self.ui.navigate_to_record(self.location['pkey']) return self def __exit__(self, *args): self.ui.delete(LOC_ENTITY, [self.location]) return False @pytest.mark.tier1 class TestAutomount(UI_driver): @pytest.fixture(autouse=True) def automount_setup(self, ui_driver_fsetup): self.init_app() def add_key(self, key, mount_info, **kwargs): self.add_record(MAP_ENTITY, { 'pkey': key, 'add': [ ('textbox', 'automountkey', key), ('textbox', 'automountinformation', mount_info), ], }, facet='keys', **kwargs) def _add_record_with_enter_key(self, record): self.delete_record(record['pkey']) self.assert_no_dialog() self.facet_button_click('add') self.assert_dialog('add') self.fill_fields(record['add']) dialog = self.get_dialog('add') dialog.send_keys(Keys.ENTER) self.wait_for_request() def _delete_record_with_enter_key(self, pkey): assert self.has_record(pkey) self.select_record(pkey) self.facet_button_click('remove') dialog = self.get_dialog('add') dialog.send_keys(Keys.ENTER) self.wait_for_request(n=2) self.wait() @screenshot def test_crud(self): """ Basic CRUD: automount """ self.init_app() # location self.basic_crud(LOC_ENTITY, LOC_DATA, default_facet='maps', delete=False, breadcrumb='Automount Locations' ) # map self.navigate_to_record(LOC_PKEY) self.basic_crud(MAP_ENTITY, MAP_DATA, parent_entity=LOC_ENTITY, search_facet='maps', default_facet='keys', delete=False, navigate=False, breadcrumb=LOC_PKEY, ) # key self.navigate_to_record(MAP_PKEY) self.basic_crud(KEY_ENTITY, KEY_DATA, parent_entity=MAP_ENTITY, search_facet='keys', navigate=False, breadcrumb=MAP_PKEY, ) # delete self.navigate_by_breadcrumb(LOC_PKEY) self.delete_record(MAP_PKEY) # test indirect maps direct_pkey = 'itest-direct' indirect_pkey = 'itest-indirect' self.add_record(LOC_ENTITY, { 'pkey': direct_pkey, 'add': [ ('radio', 'method', 'add'), ('textbox', 'automountmapname', direct_pkey), ('textarea', 'description', 'foobar'), ], }, facet='maps', navigate=False) self.add_record(LOC_ENTITY, { 'pkey': indirect_pkey, 'add': [ ('radio', 'method', 'add_indirect'), ('textbox', 'automountmapname', indirect_pkey), ('textarea', 'description', 'foobar'), ('textbox', 'key', 'baz'), ('textbox', 'parentmap', direct_pkey), ], }, facet='maps', navigate=False) self.assert_record(direct_pkey) self.assert_record(indirect_pkey) # delete self.delete_record(direct_pkey) self.delete_record(indirect_pkey) self.navigate_by_breadcrumb('Automount Locations') self.delete_record(LOC_PKEY) @screenshot def test_add_location_dialog(self): """ Test 'Add Automount Location' dialog behaviour """ pkeys = ['loc1', 'loc2', 'loc3', 'loc4'] locations = [{ 'pkey': pkey, 'add': [('textbox', 'cn', pkey)] } for pkey in pkeys] self.navigate_to_entity(LOC_ENTITY) # Add and add another self.add_record(LOC_ENTITY, [locations[0], locations[1]], navigate=False) self.assert_record(locations[0]['pkey']) self.assert_record(locations[1]['pkey']) # Add and edit self.add_record(LOC_ENTITY, locations[2], dialog_btn='add_and_edit', navigate=False) self.assert_facet(LOC_ENTITY, facet='maps') # Cancel dialog self.add_record(LOC_ENTITY, locations[3], dialog_btn='cancel') self.assert_record(locations[3]['pkey'], negative=True) # Add duplicated self.add_record(LOC_ENTITY, locations[0], navigate=False, negative=True, pre_delete=False) self.assert_last_error_dialog( 'automount location with name "{}" already exists' .format(locations[0]['pkey']) ) self.close_all_dialogs() # Missing field self.add_record(LOC_ENTITY, {'pkey': 'loc5', 'add': []}, navigate=False, negative=True) assert self.has_form_error('cn') self.close_all_dialogs() # Delete multiple locations self.delete_record(pkeys) @screenshot @pytest.mark.parametrize('maps', [DIRECT_MAPS, INDIRECT_MAPS]) def test_add_map_dialog(self, maps): """ Test 'Add Automount Map' dialog behaviour """ with Location(LOC_DATA, ui=self): # Add and add another self.add_record(LOC_ENTITY, [maps[0], maps[1]], facet='maps', navigate=False) self.assert_record(maps[0]['pkey']) self.assert_record(maps[1]['pkey']) # Add and edit self.add_record(LOC_ENTITY, maps[2], dialog_btn='add_and_edit', facet='maps', navigate=False) self.assert_facet(MAP_ENTITY, facet='keys') # Cancel dialog self.add_record(LOC_ENTITY, maps[3], facet='maps', dialog_btn='cancel') self.assert_record(maps[3]['pkey'], negative=True) # Delete multiple maps self.delete_record([m['pkey'] for m in maps]) @screenshot def test_add_indirect_map_with_missing_fields(self): """ Test creating automount map without mapname and mountpoint """ maps = { 'automountmapname': { 'pkey': 'map1', 'add': [ ('radio', 'method', 'add_indirect'), ('textarea', 'description', 'desc'), ('textbox', 'key', 'mount1'), ], }, 'key': { 'pkey': 'map2', 'add': [ ('radio', 'method', 'add_indirect'), ('textbox', 'automountmapname', 'map1'), ('textarea', 'description', 'desc'), ], } } with Location(LOC_DATA, ui=self): for missing_field, map_data in maps.items(): self.add_record(LOC_ENTITY, map_data, negative=True, facet='maps', navigate=False) assert self.has_form_error(missing_field) self.dialog_button_click('cancel') self.assert_record(map_data['pkey'], negative=True) @screenshot def test_add_duplicated_indirect_map(self): """ Test creating indirect automount map with duplicated field values """ original_name = 'map1' original_key = 'mount1' with Location(LOC_DATA, ui=self): self.add_record(LOC_ENTITY, { 'pkey': original_name, 'add': [ ('radio', 'method', 'add_indirect'), ('textbox', 'automountmapname', original_name), ('textarea', 'description', 'desc'), ('textbox', 'key', original_key), ], }, facet='maps', navigate=False) self.add_record(LOC_ENTITY, { 'pkey': 'map2', 'add': [ ('radio', 'method', 'add_indirect'), ('textbox', 'automountmapname', original_name), ('textarea', 'description', 'desc'), ('textbox', 'key', 'mount2'), ], }, negative=True, facet='maps', navigate=False, pre_delete=False) self.assert_last_error_dialog( 'automount map with name "{}" already exists' .format(original_name) ) self.close_all_dialogs() self.add_record(LOC_ENTITY, { 'pkey': 'map3', 'add': [ ('radio', 'method', 'add_indirect'), ('textbox', 'automountmapname', 'map3'), ('textarea', 'description', 'desc'), ('textbox', 'key', original_key), ], }, negative=True, facet='maps', navigate=False, pre_delete=False) self.assert_last_error_dialog( 'key named {} already exists'.format(original_key) ) self.close_all_dialogs() @screenshot @pytest.mark.parametrize('map_data', [DIRECT_MAP_MOD, INDIRECT_MAP_MOD]) def test_modify_map(self, map_data): """ Test automount map 'Settings' tab """ with Location(LOC_DATA, ui=self): self.add_record(LOC_ENTITY, map_data, facet='maps', navigate=False) self.navigate_to_record(map_data['pkey']) self.switch_to_facet('details') # Refresh self.fill_fields(map_data['mod'], undo=True) self.assert_facet_button_enabled('refresh') self.facet_button_click('refresh') self.wait_for_request() self.assert_facet_button_enabled('refresh') # Revert self.mod_record(MAP_ENTITY, map_data, facet_btn='revert') @screenshot def test_add_key_dialog(self): """ Test 'Add Automount Key' dialog behaviour """ pkeys = ['key1', 'key2', 'key3', 'key4'] keys = [ { 'pkey': pkey, 'add': [ ('textbox', 'automountkey', pkey), ('textbox', 'automountinformation', '/itest/%s' % pkey), ], } for pkey in pkeys ] with Location(LOC_DATA, ui=self): self.add_record(LOC_ENTITY, MAP_DATA, facet='maps', navigate=False) self.navigate_to_record(MAP_PKEY) # Add and add another self.add_record(MAP_ENTITY, [keys[0], keys[1]], facet='keys', navigate=False) self.assert_record(keys[0]['pkey']) self.assert_record(keys[1]['pkey']) # Add and edit self.add_record(MAP_ENTITY, keys[2], dialog_btn='add_and_edit', facet='keys', navigate=False) self.assert_facet(KEY_ENTITY, facet='details') # Cancel dialog self.add_record(MAP_ENTITY, keys[3], facet='keys', dialog_btn='cancel') self.assert_record(keys[3]['pkey'], negative=True) # Delete multiple keys self.delete_record(pkeys) @screenshot def test_add_key_with_missing_fields(self): """ Test creating automount key without key name and mount information """ keys = { 'automountkey': { 'pkey': 'key1', 'add': [('textbox', 'automountinformation', '/itest/key')], }, 'automountinformation': { 'pkey': 'key2', 'add': [('textbox', 'automountkey', 'key2')], }, } with Location(LOC_DATA, ui=self): self.add_record(LOC_ENTITY, MAP_DATA, facet='maps', navigate=False) self.navigate_to_record(MAP_PKEY) for missing_field, key in keys.items(): self.add_record(MAP_ENTITY, key, negative=True, facet='keys', navigate=False) assert self.has_form_error(missing_field) self.dialog_button_click('cancel') self.assert_record(key['pkey'], negative=True) @screenshot def test_add_duplicated_key(self): """ Test creating automount key with duplicated field values """ with Location(LOC_DATA, ui=self): self.add_record(LOC_ENTITY, MAP_DATA, facet='maps', navigate=False) self.navigate_to_record(MAP_PKEY) key = 'mount1' self.add_key(key, '/itest/key', navigate=False) self.add_key(key, '/itest/key2', negative=True, navigate=False, pre_delete=False) self.assert_last_error_dialog( 'key named {} already exists'.format(key) ) self.close_all_dialogs() @screenshot def test_modify_key(self): """ Test automount key 'Settings' """ with Location(LOC_DATA, ui=self): self.add_record(LOC_ENTITY, MAP_DATA, facet='maps', navigate=False) self.navigate_to_record(MAP_PKEY) self.add_record(MAP_ENTITY, KEY_DATA, facet='keys', navigate=False) self.navigate_to_record(KEY_PKEY) # Refresh self.fill_fields(KEY_DATA['mod']) self.assert_facet_button_enabled('refresh') self.facet_button_click('refresh') self.wait_for_request() self.assert_facet_button_enabled('refresh') # Revert self.mod_record(KEY_ENTITY, KEY_DATA, facet_btn='revert') @screenshot def test_confirm_dialogs_with_enter_key(self): """ Test dialogs can be closed by pressing ENTER """ # Add location self.navigate_to_entity(LOC_ENTITY, 'search') self._add_record_with_enter_key(LOC_DATA) # Add map self.navigate_to_record(LOC_PKEY) self._add_record_with_enter_key(MAP_DATA) # Add key self.navigate_to_record(MAP_PKEY) self._add_record_with_enter_key(KEY_DATA) # Delete key self._delete_record_with_enter_key(KEY_PKEY) # Delete map self.navigate_by_breadcrumb(LOC_PKEY) self._delete_record_with_enter_key(MAP_PKEY) # Delete location self.navigate_to_entity(LOC_ENTITY) self._delete_record_with_enter_key(LOC_PKEY)