1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3# BitBake Toaster UI tests implementation
4#
5# Copyright (C) 2023 Savoir-faire Linux
6#
7# SPDX-License-Identifier: GPL-2.0-only
8
9
10from time import sleep
11from selenium.common.exceptions import NoSuchElementException, StaleElementReferenceException, TimeoutException
12from selenium.webdriver.common.by import By
13
14from orm.models import Build
15
16
17def wait_until_build(test_instance, state):
18    timeout = 60
19    start_time = 0
20    build_state = ''
21    while True:
22        try:
23            if start_time > timeout:
24                raise TimeoutException(
25                    f'Build did not reach {state} state within {timeout} seconds'
26                )
27            last_build_state = test_instance.driver.find_element(
28                By.XPATH,
29                '//*[@id="latest-builds"]/div[1]//div[@class="build-state"]',
30            )
31            build_state = last_build_state.get_attribute(
32                'data-build-state')
33            state_text = state.lower().split()
34            if any(x in str(build_state).lower() for x in state_text):
35                return str(build_state).lower()
36            if 'failed' in str(build_state).lower():
37                break
38        except NoSuchElementException:
39            continue
40        except TimeoutException:
41            break
42        start_time += 1
43        sleep(1) # take a breath and try again
44
45def wait_until_build_cancelled(test_instance):
46    """ Cancel build take a while sometime, the method is to wait driver action
47        until build being cancelled
48    """
49    timeout = 30
50    start_time = 0
51    build = None
52    while True:
53        try:
54            if start_time > timeout:
55                raise TimeoutException(
56                    f'Build did not reach cancelled state within {timeout} seconds'
57                )
58            last_build_state = test_instance.driver.find_element(
59                By.XPATH,
60                '//*[@id="latest-builds"]/div[1]//div[@class="build-state"]',
61            )
62            build_state = last_build_state.get_attribute(
63                'data-build-state')
64            if 'failed' in str(build_state).lower():
65                break
66            if 'cancelling' in str(build_state).lower():
67                # Change build state to cancelled
68                if not build:  # get build object only once
69                    build = Build.objects.last()
70                    build.outcome = Build.CANCELLED
71                    build.save()
72            if 'cancelled' in str(build_state).lower():
73                break
74        except NoSuchElementException:
75            continue
76        except StaleElementReferenceException:
77            continue
78        except TimeoutException:
79            break
80        start_time += 1
81        sleep(1) # take a breath and try again
82
83def get_projectId_from_url(url):
84    # url = 'http://domainename.com/toastergui/project/1656/whatever
85    # or url = 'http://domainename.com/toastergui/project/1/
86    # or url = 'http://domainename.com/toastergui/project/186
87    assert '/toastergui/project/' in url, "URL is not valid"
88    url_to_list = url.split('/toastergui/project/')
89    return  int(url_to_list[1].split('/')[0])  # project_id
90