Beispiel #1
0
    def test_log_page_POST_request_return_filtered_logs(self):
        service1 = ServiceFactory(repo_name='service_1')
        service2 = ServiceFactory(repo_name='service_2')
        service3 = ServiceFactory(repo_name='service_3')
        log1 = LogFactory(service=service1)
        log2 = LogFactory(service=service2)
        log3 = LogFactory(service=service3, status=False)

        post_request = RequestFactory().post('/request', {
            'services': 0,
            'status': 0
        })
        view = setup_view(LogView(), post_request)
        response = view.post(view.request)
        self.assertContains(response, 'No Results')

        post_request = RequestFactory().post('/request', {
            'services': service1.pk,
            'status': 1
        })
        view = setup_view(LogView(), post_request)
        response = view.post(view.request)
        self.assertContains(response, log1.service)
        self.assertNotContains(response, log3.service)

        post_request = RequestFactory().post('/request', {
            'services': service3.pk,
            'status': 0
        })
        view = setup_view(LogView(), post_request)
        response = view.post(view.request)

        self.assertContains(response, log3.service)
        self.assertNotContains(response, log1.service)
        self.assertNotContains(response, log2.service)
    def test_service_dashboard_view_display_services(self):
        service1 = ServiceFactory()
        service2 = ServiceFactory()

        view = setup_view(DashboardView(), self.get_request)
        response = view.get(view.request)

        self.assertContains(response, service1.repo_name)
        self.assertContains(response, service2.repo_name)
    def test_service_dashboard_view_set_services_in_appropriate_order(self):
        service1 = ServiceFactory()
        service2 = ServiceFactory(status=False)
        service3 = ServiceFactory()

        log1 = LogFactory(service=service1)
        log2 = LogFactory(service=service2)
        log3 = LogFactory(service=service3)

        view = setup_view(DashboardView(), self.get_request)
        response = view.get(view.request)
        object_list = list(response.context_data['object_list'])

        self.assertListEqual(object_list, [service2, service3, service1])
Beispiel #4
0
    def setUp(self):
        self.service = ServiceFactory()

        log = LogFactory(service=self.service)
        payload = json.loads(log.payload)
        self.data = commits_parser(payload['commits'],
                                   self.service.repo_source)
    def test_service_dashboard_view_POST_request_return_filtered_services(
            self):
        service1 = ServiceFactory(repo_name='repo_name1')
        service2 = ServiceFactory(repo_name='repo_name2')

        post_request = RequestFactory().post('/request',
                                             {'services': service1.pk})
        view = setup_view(DashboardView(), post_request)
        response = view.post(view.request)
        self.assertContains(response, service1.repo_name)
        self.assertNotContains(response, service2.repo_name)

        post_request = RequestFactory().post('/request',
                                             {'services': service2.pk})
        view = setup_view(DashboardView(), post_request)
        response = view.post(view.request)
        self.assertContains(response, service2.repo_name)
        self.assertNotContains(response, service1.repo_name)
    def setUp(self):

        self.client = Client()
        self.payload = LoadPayload()
        self.service_bb = ServiceFactory()
        self.service_gh = ServiceFactory(repo_source='gh')

        self.service_ftp_bb = ServiceFactory(
            ftp_host=settings.FTP_TEST_SETTINGS['host'],
            ftp_username=settings.FTP_TEST_SETTINGS['username'],
            ftp_password=settings.FTP_TEST_SETTINGS['password'],
            ftp_path=settings.FTP_TEST_SETTINGS['path']
        )
        self.service_ftp_gh = ServiceFactory(
            ftp_host=settings.FTP_TEST_SETTINGS['host'],
            ftp_username=settings.FTP_TEST_SETTINGS['username'],
            ftp_password=settings.FTP_TEST_SETTINGS['password'],
            ftp_path=settings.FTP_TEST_SETTINGS['path'],
            repo_source='gh'
        )
Beispiel #7
0
    def setUp(self):
        notification = NotificationFactory(
            success=
            '[email protected],[email protected],[email protected]',
            fail='[email protected],[email protected]',
            deploy_user=[])

        self.service = ServiceFactory(notification=notification)
        self.log = LogFactory(service=self.service)

        request_factory = RequestFactory()
        request = request_factory.get('/example')
        self.host = absolute_url(request).build()
 def setUp(self):
     self.service = ServiceFactory()
     self.get_request = RequestFactory().get('/request')
 def setUp(self):
     self.service_bb = ServiceFactory()
     self.service_gh = ServiceFactory(repo_source='gh')
     self.get_request = RequestFactory().get('/request')
     self.post_request = RequestFactory().post('/request',
                                               {'payload': True})
 def setUp(self):
     self.service = ServiceFactory()
     service = Service.objects.filter(pk=self.service.pk).values()
     self.get_request = RequestFactory().get('/request')
     self.post_request = RequestFactory().post('/request', service[0])
    def test_can_see_service_dashboard_page_and_manage_services(self):

        self.user_authenticate()

        # User go to services page by click left menu 'Services' link

        page = self.browser.find_element_by_id('page')
        page.find_element_by_link_text("Services").click()
        self.wait_for_load()
        page_header = self.browser.find_element_by_class_name('page-header').text

        # He can see Services Dashboard title
        self.assertIn('Services Dashboard', page_header)

        # He is welcome with message and see big 'Add Service' button
        page = self.browser.find_element_by_id('page')
        page.find_element_by_class_name('well')
        add_service_btn = self.browser.find_element_by_class_name('btn-success')
        self.assertIn('Add Service', add_service_btn.text)

        # He click Add service button and go do service form page
        add_service_btn.click()
        self.wait_for_load()
        self.assertIn('Service Add', self.browser.find_element_by_class_name('page-header').text)

        page = self.browser.find_element_by_id('page')
        page.find_element_by_id('service-form')

        # Saveing checking is omit intentionaly because of cost of validation process
        # Service is add programmatically without check process

        service1 = ServiceFactory(repo_hook=False, status=False)
        service2 = ServiceFactory(repo_hook=False, status=False)
        service3 = ServiceFactory(repo_hook=False, status=False)

        self.browser.get(self.live_server_url + reverse('ftpdeploy_dashboard'))
        self.wait_for_load()

        # After he added 3 services, he can see all of them on the list
        service_list = self.browser.find_element_by_id('service-list')
        self.assertIn(service1.repo_name, service_list.text)
        self.assertIn(service2.repo_name, service_list.text)
        self.assertIn(service3.repo_name, service_list.text)

        # He use filter and confirm filter works as expected

        form = self.browser.find_element_by_id('service-filter')
        options = form.find_elements_by_tag_name('option')

        for option in options:
            if option.text == service1.repo_name:
                option.click()

        time.sleep(0.1)
        table_rows = self.browser.find_elements_by_xpath("//tbody[@id='service-list']/tr")
        self.assertEqual(len(table_rows), 1)

        table = self.browser.find_element_by_id('service-list')
        self.assertIn(service1.repo_name, table.text)
        self.assertNotIn(service2.repo_name, table.text)
        self.assertNotIn(service3.repo_name, table.text)

        for option in options:
            if option.text == service2.repo_name:
                option.click()

        time.sleep(0.1)
        table_rows = self.browser.find_elements_by_xpath("//tbody[@id='service-list']/tr")
        self.assertEqual(len(table_rows), 1)

        table = self.browser.find_element_by_id('service-list')
        self.assertIn(service2.repo_name, table.text)
        self.assertNotIn(service1.repo_name, table.text)
        self.assertNotIn(service3.repo_name, table.text)

        # He noticed he can add new service by the 'Add Service' if service already exist as well
        # He click it and see add service form again.

        page = self.browser.find_element_by_id('page')
        page.find_element_by_link_text('Add Service').click()
        self.wait_for_load()

        page = self.browser.find_element_by_id('page')
        page.find_element_by_id('service-form')
        self.browser.get(self.live_server_url + reverse('ftpdeploy_dashboard'))
        self.wait_for_load()

        # He click 'Edit' link next to the service and go to edit form. He noticed thah form is prepopulated by saved values

        first_service = self.browser.find_element_by_xpath("//tbody[@id='service-list']/tr[1]")
        first_service.find_element_by_link_text('Edit').click()
        self.wait_for_load()

        form = self.browser.find_element_by_id('service-form')
        repo_name = self.browser.find_element_by_id('id_repo_name')
        secret_key = self.browser.find_element_by_id('id_secret_key')

        self.assertIn(service1.repo_name, repo_name.get_attribute('value'))
        self.assertIn(service1.secret_key, secret_key.get_attribute('value'))

        # He notice there is 'Manage' link on page header. He click it and go to Manage Page

        page_header = self.browser.find_element_by_class_name('page-header')
        page_header.find_element_by_link_text('Manage').click()
        self.wait_for_load()

        page_header = self.browser.find_element_by_class_name('page-header')
        self.assertIn('%s Manage' % service1.repo_name, page_header.text)

        self.browser.get(self.live_server_url + reverse('ftpdeploy_dashboard'))
        self.wait_for_load()

        # He click 'Manage' link next to the service and go to manage page

        first_service = self.browser.find_element_by_xpath("//tbody[@id='service-list']/tr[1]")
        first_service.find_element_by_link_text('Manage').click()
        self.wait_for_load()

        # He can see 'Repo_name Manage' header
        page_header = self.browser.find_element_by_class_name('page-header')
        self.assertIn('%s Manage' % service1.repo_name, page_header.text)

        # He notice service status fail because of invalid hook, and see 'Add hook' link

        page = self.browser.find_element_by_id('page')
        self.assertIn('Add hook', page.text)

        # Add hook link test is omit because of time consuming by request
        # check flag is change programmatically

        service = Service.objects.get(pk=service1.pk)
        service.repo_hook = True
        service.save()

        self.browser.get(self.live_server_url + reverse('ftpdeploy_service_manage', args=(service.pk,)))
        self.wait_for_load()

        # After he click 'Add hook' he noticed that link disappear
        page = self.browser.find_element_by_id('page')
        self.assertNotIn('Add hook', page.text)

        # After few commits he can see Recent deploys table with latests deploys
        log1 = LogFactory(service=service1)
        log2 = LogFactory(service=service1)
        log3 = LogFactory(service=service1, status=False)
        log4 = LogFactory(service=service1, status=False)

        self.browser.get(self.live_server_url + reverse('ftpdeploy_service_manage', args=(service.pk,)))
        self.wait_for_load()

        # He notice two of deploys fails, and is able to see Fail Deploys table along with 'Restore Deploys' button.
        fail_deploys = self.browser.find_element_by_id('fail-deploys')
        fail_deploys.find_element_by_link_text('Restore Deploys')
        restore_list_rows = self.browser.find_elements_by_xpath("//tbody[@id='restore-list']/tr")
        self.assertEqual(len(restore_list_rows), 2)

        # He decided to skip first of failed deploys, and click 'Skip' button,
        # and then skip entry is not in 'Fail Deploys' table any more

        first_fail_deploy_row = self.browser.find_element_by_xpath("//tbody[@id='restore-list']/tr[1]")
        first_fail_deploy_row.find_element_by_link_text('Skip').click()
        first_fail_deploy_row.find_element_by_link_text('Confirm').click()

        self.browser.get(self.live_server_url + reverse('ftpdeploy_service_manage', args=(service.pk,)))
        self.wait_for_load()

        restore_list_rows = self.browser.find_elements_by_xpath("//tbody[@id='restore-list']/tr")
        self.assertEqual(len(restore_list_rows), 1)

        # He cilck 'Restore Deploys' and see popup with 'Restore Tree' title

        fail_deploys = self.browser.find_element_by_id('fail-deploys')
        fail_deploys.find_element_by_link_text('Restore Deploys').click()

        self.wait.until(lambda browser: browser.find_element_by_id('restore-modal'))

        time.sleep(1)
        restore_modal = self.browser.find_element_by_id('restore-modal')
        modal_title = restore_modal.find_element_by_class_name('modal-title')
        self.assertIn('Restore Tree', restore_modal.text)

        # He is able to see 'New', 'Modified' and 'Removed' files in restore information
        # along with commits informations
        self.assertIn('New', restore_modal.text)
        self.assertIn('Modified', restore_modal.text)
        self.assertIn('Removed', restore_modal.text)
        self.assertIn('commit 1', restore_modal.text)
        self.assertIn('commit 2', restore_modal.text)

        # He click close button and close modal window
        restore_modal.find_element_by_xpath("//button[@data-dismiss='modal']").click()
        time.sleep(1)
        body = self.browser.find_element_by_tag_name('body')
        self.assertNotIn('Restore Tree', body.text)

        # He decided change notifications for service so he click 'Notification' link
        notification = NotificationFactory(name='Default')

        self.browser.find_element_by_id('notification').click()
        self.wait.until(lambda browser: browser.find_element_by_id('notification-modal'))
        time.sleep(1)
        restore_modal = self.browser.find_element_by_id('notification-modal')
        modal_title = restore_modal.find_element_by_class_name('modal-title')
        self.assertIn('Notification', restore_modal.text)

        # In the popup he select 'Default' notification and click save
        form = self.browser.find_element_by_id('notification-form')
        options = form.find_elements_by_tag_name('option')

        for option in options:
            if option.text == notification.name:
                option.click()

        time.sleep(1)
        form.find_element_by_xpath("//button[@type='submit']").click()
        self.wait_for_load()
        # He see save notification success message
        self.browser.find_element_by_class_name('alert-success')

        # He see notification name in Statistics section
        page = self.browser.find_element_by_id('page')
        self.assertIn('Notifications: Default', page.text)

        # He noticed status icon is actually a link to refresh service status
        self.browser.find_element_by_xpath("//a[@id='service-manage-status']")

        # He click 'Edit' link and see service edit form
        page_header = self.browser.find_element_by_class_name('page-header')
        page_header.find_element_by_link_text('Edit').click()
        self.wait_for_load()

        form = self.browser.find_element_by_id('service-form')
        repo_name = self.browser.find_element_by_id('id_repo_name')
        secret_key = self.browser.find_element_by_id('id_secret_key')

        self.assertIn(service1.repo_name, repo_name.get_attribute('value'))
        self.assertIn(service1.secret_key, secret_key.get_attribute('value'))

        # He decide to delete service and click 'Delete' link, and then confirm delete
        page_header = self.browser.find_element_by_class_name('page-header')
        page_header.find_element_by_class_name('dropdown-toggle').click()
        page_header.find_element_by_link_text('Delete').click()
        page_header.find_element_by_xpath("//button[@type='submit']").click()
        self.wait_for_load()
        self.browser.find_element_by_class_name('alert-success')

        # He is redirect to service dashboard
        # see success message and doesn't see removed service on the list any more
        self.browser.find_element_by_class_name('alert-success')

        service_list = self.browser.find_element_by_id('service-list')
        self.assertNotIn(service1.repo_name, service_list.text)
        self.assertIn(service2.repo_name, service_list.text)
        self.assertIn(service3.repo_name, service_list.text)
 def setUp(self):
     self.client = Client()
     self.payload = LoadPayload()
     self.service_bb = ServiceFactory()
     self.service_gh = ServiceFactory(repo_source='gh')
Beispiel #13
0
 def setUp(self):
     self.service_bb = ServiceFactory()
     self.service_gh = ServiceFactory(repo_source='gh')
Beispiel #14
0
class UtilsRepoAPI(TestCase):
    def setUp(self):
        self.service_bb = ServiceFactory()
        self.service_gh = ServiceFactory(repo_source='gh')

    @patch('ftp_deploy.utils.repo.curl_connection')
    def test_repo_init_bb_perform_curl_initialization(self,
                                                      mock_curl_connection):
        api = repository_api(self.service_bb.repo_source)
        mock_curl_connection.assert_called_once_with(
            BITBUCKET_SETTINGS['username'], BITBUCKET_SETTINGS['password'])
        mock_curl_connection.assert_has_calls(call().authenticate())

    @patch('ftp_deploy.utils.repo.curl_connection')
    def test_repo_init_gh_perform_curl_initialization(self,
                                                      mock_curl_connection):
        api = repository_api(self.service_gh.repo_source)
        mock_curl_connection.assert_called_once_with(
            GITHUB_SETTINGS['username'], GITHUB_SETTINGS['password'])
        mock_curl_connection.assert_has_calls(call().authenticate())

    @patch('ftp_deploy.utils.repo.curl_connection')
    def test_repo_repositories_bb_use_proper_url(self, mock_curl_connection):
        api = repository_api(self.service_bb.repo_source)
        api.curl = MagicMock(name="mock_curl")
        api.repositories()
        api.curl.assert_has_calls(
            [call.perform('https://bitbucket.org/api/1.0/user/repositories')])

    @patch('ftp_deploy.utils.repo.curl_connection')
    def test_repo_repositories_gh_use_proper_url(self, mock_curl_connection):
        api = repository_api(self.service_gh.repo_source)
        api.curl = MagicMock(name="mock_curl")
        api.repositories()
        api.curl.assert_has_calls(
            [call.perform('https://api.github.com/user/repos')])

    @patch('ftp_deploy.utils.repo.absolute_url')
    @patch('ftp_deploy.utils.repo.curl_connection')
    def test_repo_add_hook_bb_use_proper_url(self, mock_curl_connection,
                                             mock_absolute_url):
        absolute_url = MagicMock(name='absolute_url')
        absolute_url.build = MagicMock(return_value='build')
        mock_absolute_url.return_value = absolute_url
        api = repository_api(self.service_bb.repo_source)
        api.curl = MagicMock(name="mock_curl")
        api.add_hook(self.service_bb,
                     MagicMock(name='request', return_value='request'))

        calls = [
            call.perform_post(
                'https://api.bitbucket.org/1.0/repositories/%s/%s/services/' %
                (BITBUCKET_SETTINGS['username'],
                 self.service_bb.repo_slug_name),
                'type=POST&URL=build/ftpdeploy/deploy/%s' %
                (self.service_bb.secret_key))
        ]
        api.curl.assert_has_calls(calls)

    @patch('ftp_deploy.utils.repo.absolute_url')
    @patch('ftp_deploy.utils.repo.curl_connection')
    def test_repo_add_hook_gh_use_proper_url(self, mock_curl_connection,
                                             mock_absolute_url):
        absolute_url = MagicMock(name='absolute_url')
        absolute_url.build = MagicMock(return_value='build')
        mock_absolute_url.return_value = absolute_url
        api = repository_api(self.service_gh.repo_source)
        api.curl = MagicMock(name="mock_curl")
        api.add_hook(self.service_gh,
                     MagicMock(name='request', return_value='request'))

        json_call = json.loads(api.curl.mock_calls[0][1][1])
        url_call = api.curl.mock_calls[0][1][0]

        self.assertEqual(
            url_call, 'https://api.github.com/repos/%s/%s/hooks' %
            (GITHUB_SETTINGS['username'], self.service_gh.repo_slug_name))

        self.assertEqual(json_call['name'], 'web')
        self.assertEqual(json_call['active'], True)
        self.assertEqual(json_call['config']['url'],
                         'build%s' % self.service_gh.hook_url())
        self.assertEqual(json_call['config']['content_type'], 'json')
Beispiel #15
0
class ServiceTest(TestCase):
    def setUp(self):
        self.service = ServiceFactory()

    def test_service_deploy_method(self):
        """service deploy method return number of related logs"""
        self.assertEqual(self.service.deploys(), 0)
        log = LogFactory(service=self.service)

        self.assertEqual(self.service.deploys(), 1)

        log.status = False
        log.save()

        self.assertEqual(self.service.deploys(), 0)

    def test_service_fail_deploys_method(self):
        """"service fail_deploy method return number of related logs with status False"""
        log = LogFactory(service=self.service)
        self.assertEqual(self.service.fail_deploys(), 0)
        log.status = False
        log.save()

        self.assertEqual(self.service.fail_deploys(), 1)

    def test_service_skipped_deploys_method(self):
        """service skipped_deploys method return number of relatet logs with skiped status True """
        log = LogFactory(service=self.service)

        self.assertEqual(self.service.skipped_deploys(), 0)

        log.status = False
        log.skip = True
        log.save()

        self.assertEqual(self.service.skipped_deploys(), 1)

    def test_service_latest_log_date_method(self):
        """service latest_log_date method return latest related log create date"""
        log1 = LogFactory(service=self.service)
        log2 = LogFactory(service=self.service)
        self.assertEqual(self.service.latest_log_date(),
                         self.service.log_set.latest('created').created)

    def test_service_latest_log_user_method(self):
        """service latest_log_user method return latest related log user"""
        log1 = LogFactory(service=self.service)
        log2 = LogFactory(service=self.service)
        self.assertEqual(self.service.latest_log_user(),
                         self.service.log_set.latest('created').user)

    def test_service_hook_url_method(self):
        """service hook_url method return hook url for appropriate repository"""
        self.assertEqual(
            self.service.hook_url(),
            reverse('ftpdeploy_deploy',
                    kwargs={'secret_key': self.service.secret_key}))

    def test_service_get_logs_tree_method(self):
        """service get_logs_tree method return logs in proper order and omit skipped"""
        log1 = LogFactory(service=self.service)
        log2 = LogFactory(service=self.service, status=False, skip=True)
        log3 = LogFactory(service=self.service)
        log4 = LogFactory(service=self.service, status=False)
        log5 = LogFactory(service=self.service)
        log6 = LogFactory(service=self.service, status=False, skip=True)
        log7 = LogFactory(service=self.service)

        self.assertListEqual(list(self.service.get_logs_tree()),
                             [log3, log4, log5, log7])

    @patch('ftp_deploy.models.service.service_check')
    def test_service_check_method(self, mock_service_check):
        """service check method perform check, set repo_hook and status_message"""
        mock_service_check().check_all = MagicMock(
            'check_all',
            return_value=([True, True, True], ['message1', 'message2']))
        self.service.validate()

        mock_service_check().check_all.assert_called_once_with()
        self.assertEqual(self.service.status_message, 'message1<br>message2')
        self.assertFalse(self.service.repo_hook)

        mock_service_check().check_all = MagicMock(
            'check_all', return_value=([False, False, False], []))
        self.service.validate()
        self.assertEqual(self.service.status_message, '')
        self.assertTrue(self.service.repo_hook)

    def test_service_lock_method(self):
        task = TaskFactory(service=self.service)
        self.assertFalse(self.service.lock())
        task1 = TaskFactory(service=self.service, active=True)
        self.assertTrue(self.service.lock())

    def test_service_has_queue_method(self):
        task = TaskFactory(service=self.service)
        self.assertTrue(self.service.has_queue())
 def setUp(self):
     self.client = Client()
     self.service = ServiceFactory()
Beispiel #17
0
 def setUp(self):
     self.service = ServiceFactory()
    def test_can_see_and_use_log_page(self):
        self.user_authenticate()

        # User go to log page by click Log link on top menu
        nav = self.browser.find_element_by_xpath("//div[@role='navigation']")
        nav.find_element_by_link_text("Log").click()
        self.wait_for_load()

        # He noticed Log Dashboard header
        # along with empty log table
        page_header = self.browser.find_element_by_class_name('page-header').text
        self.assertIn('Log', page_header)
        table_first_row = self.browser.find_element_by_xpath("//table/tbody/tr[1]")
        self.assertIn('No Results', table_first_row.text)

        # He create 2 services and perform one deploy each.
        service1 = ServiceFactory()
        service2 = ServiceFactory()
        Log1 = LogFactory(service=service1)
        Log2 = LogFactory(service=service1, status=False)
        Log3 = LogFactory(service=service2)

        self.browser.get(self.live_server_url + reverse('ftpdeploy_log'))
        self.wait_for_load()

        # He noticed there are log entries in table
        # In addition he notices one deploy fail
        table_rows = self.browser.find_elements_by_xpath("//table/tbody/tr")
        self.assertEqual(len(table_rows), 3)

        # He test log filter
        # he tick fail status and see only one row in table

        form = self.browser.find_element_by_id('log-filter')
        form.find_element_by_id('status').click()
        time.sleep(0.1)

        table_rows = self.browser.find_elements_by_xpath("//table/tbody/tr")
        self.assertEqual(len(table_rows), 1)

        table_first_row = self.browser.find_element_by_xpath("//table/tbody/tr[1]")
        self.assertIn(Log2.service.repo_name, table_first_row.text)

        # after he untick fail only checkbox and is able to see all 3 rows again

        form.find_element_by_id('status').click()
        time.sleep(0.1)
        table_rows = self.browser.find_elements_by_xpath("//table/tbody/tr")
        self.assertEqual(len(table_rows), 3)

        # next he select log with first service1 assign to it,
        # and see two rows in table with appropriate service repo name

        form.find_element_by_tag_name('select')
        options = form.find_elements_by_tag_name('option')

        for option in options:
            if option.text == Log1.service.repo_name:
                option.click()

        time.sleep(0.1)
        table_rows = self.browser.find_elements_by_xpath("//table/tbody/tr")
        self.assertEqual(len(table_rows), 2)

        table = self.browser.find_element_by_tag_name('table')
        self.assertIn(Log1.service.repo_name, table.text)

        # afterwords he select log with service2 assign to it
        # and see only one row in table with appropriate service repo name

        form.find_element_by_tag_name('select')
        options = form.find_elements_by_tag_name('option')

        for option in options:
            if option.text == Log3.service.repo_name:
                option.click()

        time.sleep(0.1)
        table_rows = self.browser.find_elements_by_xpath("//table/tbody/tr")
        self.assertEqual(len(table_rows), 1)

        table = self.browser.find_element_by_tag_name('table')
        self.assertIn(Log3.service.repo_name, table.text)