Как получить доступ к API Microsoft Graph в Jenkins для тестов Robot FrameworkPython

Программы на Python
Ответить
Anonymous
 Как получить доступ к API Microsoft Graph в Jenkins для тестов Robot Framework

Сообщение Anonymous »

Я столкнулся с проблемой, из-за которой вызов API Microsoft Graph завершается сбоем при выполнении через конвейер Jenkins, где он должен был отображать содержимое определенного настраиваемого письма. Вся платформа построена на Robot Framework с использованием специальной библиотеки, написанной для обработки вызовов API Microsoft Graph. Код пользовательской библиотеки приведен ниже:

Код: Выделить всё

import os
import msal
import requests
from dotenv import load_dotenv
from bs4 import BeautifulSoup
from flask import Flask, redirect, url_for, request, session, render_template_string
import logging

load_dotenv(override=True)

app = Flask(__name__)
app.secret_key = 'replace-with-a-random-secret-key'

log_file_path = os.path.join(os.path.expanduser("~"), "flask_app.log")

logging.basicConfig(filename=log_file_path, level=logging.DEBUG,
format='%(asctime)s %(levelname)s %(message)s')

client_id = os.getenv('AZURE_CLIENT_ID')
print(client_id)
client_secret = os.getenv('AZURE_CLIENT_SECRET')
print(client_secret)
authority = os.getenv('AZURE_AUTHORITY', f"https://login.microsoftonline.com/{os.getenv('TENANT_ID')}")
print(authority)
redirect_uri = 'http://localhost:5000/getAToken'  # Change this to match your app's redirect URI
scope = ['User.Read']  # Delegated permission to read the user's profile

client = msal.ConfidentialClientApplication(
client_id,
authority=authority,
client_credential=client_secret
)

@app.route('/')
def index():
logging.info("Index route accessed")
if 'access_token' in session:
return render_template_string('''
Flask App - Home
Welcome
Access token found in session.
[url=/graphCall]Call Graph API[/url]
''')
else:
return render_template_string('''
Flask App - Login
Please [url=/login]log in[/url] to continue.
''')

@app.route('/login')
def login():
logging.info("Login route accessed")
# Redirect the user to Azure AD to log in and get an authorization code
auth_url = client.get_authorization_request_url(scopes=scope, redirect_uri=redirect_uri)
return redirect(auth_url)

@app.route('/getAToken')
def authorized():
logging.info("getAtoken route accessed")
# Exchange the authorization code for an access token
code = request.args.get('code')
if code:
token_result = client.acquire_token_by_authorization_code(code, scopes=scope, redirect_uri=redirect_uri)
if 'access_token' in token_result:
session['access_token'] = token_result['access_token']
return redirect(url_for('graph_call'))
else:
return f"Error acquiring token: {token_result.get('error_description')}"
else:
return "No authorization code found in the request."

@app.route('/graphCall')
def graph_call():
logging.info("graphCall route accessed")
access_token = session.get('access_token')

if not access_token:
logging.error("Access token is missing, redirecting to login.")
return redirect(url_for('login'))

api_url = ('https://graph.microsoft.com/v1.0/me/messages?$search="USPTO: Your authentication code"' "&$top=3")
headers = {
'Authorization': f'Bearer {access_token}'
}

try:
response = requests.get(api_url, headers=headers)
response.raise_for_status()  # Raise an HTTPError for bad responses (4xx and 5xx)

emails = response.json().get('value', [])
email_details = []

for email in emails:
subject = email.get('subject', 'No Subject')
sender = email.get('from', {}).get('emailAddress', {}).get('name', 'Unknown Sender')
body_content = email.get('body', {}).get('content', 'No Content')
email_details.append({
'subject': subject,
'sender': sender,
'body_content': body_content
})

return render_template_string('''
Flask App - Graph API
Email Details
{% for email in email_details %}
Subject:[/b] {{ email.subject }}
[b]                
Sender:[/b]  {{ email.sender }}
Email Body
{{ email.body_content|safe }}

{% endfor %}
''', email_details=email_details)

except requests.exceptions.RequestException as e:
logging.error(f"Request to Graph API failed: {str(e)}")
return f"Error: Unable to fetch emails. Details: {str(e)}"

except KeyError as e:
logging.error(f"Unexpected response format: Missing key {str(e)}")
return f"Error: Unexpected response format. Missing key: {str(e)}"

except Exception as e:
logging.error(f"An unexpected error occurred: {str(e)}")
return f"Error: An unexpected error occurred. Details: {str(e)}"

if __name__ == '__main__':
app.run(debug=True, port=5000)
Код тестового сценария Robot Framework написан ниже:

Код: Выделить всё

Login To Mail Box & Get Pair Code
Execute Javascript    window.open('${FLASK_APP_URL}', '_blank');
Switch Window   Flask App - Login
Wait Until Keyword Succeeds    60s    2s    Click Element    ${FLASK_APP_LOGIN_BTN}
Wait Until Page Contains Element    ${OUTLOOK_NEXT_BTN_&_SIGNIN_BTN}
Input Text    ${OUTLOOK_USERNAME}    ${outlook_uname}
Wait Until Keyword Succeeds    60s    2s    Click Element    ${OUTLOOK_NEXT_BTN_&_SIGNIN_BTN}
Wait Until Page Contains Element    ${OUTLOOK_NEXT_BTN_&_SIGNIN_BTN}
Input Text    ${OUTLOOK_PASSWORD}    ${outlook_pass}
Wait Until Keyword Succeeds    60s    2s    Click Element    ${OUTLOOK_NEXT_BTN_&_SIGNIN_BTN}
Wait Until Keyword Succeeds    60s    2s    Click Element
xpath=//input[@id="idSIButton9"]

Wait Until Keyword Succeeds    60s    2s    Page Should Contain Element    ${PAIR_CODE_TEXT_VAL}
${rows}    Get WebElements    ${PAIR_CODE_TEXT_VAL}
${row_count}    Get Length    ${rows}
Log    Number of rows: ${row_count}
${pair_codes}    Create List
FOR    ${row}    IN RANGE    1    ${row_count + 1}
${text}    Wait Until Keyword Succeeds    60s    2s    Get Text    xpath=(//table[@bgcolor="#ffffff"]/tbody/tr[3]/td/b)[${row}]
Append To List    ${pair_codes}    ${text}
END
Log    ${pair_codes}
Set Global Variable    ${pair_codes}
[Return]    ${pair_codes}
Выполнение происходит без каких-либо сбоев до момента, когда ${OUTLOOK_NO_BTN} и завершается сбоем на следующем шаге, где необходимо проверить доступность элемента, т. е. ${PAIR_CODE_TEXT_VAL} ( ниже для справки прикреплен скриншот)
Изображение

Я не обнаружил никаких проблем, когда выполняю тот же тестовый пример на своем локальном компьютере в безголовом режиме режим.
Изображение

Любой подскажите, в чем может быть причина и как ее решить?
Заранее спасибо за помощь

Подробнее здесь: https://stackoverflow.com/questions/792 ... work-tests
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»