last updates

This commit is contained in:
2025-10-20 21:05:31 +02:00
parent 8d28600318
commit ac52d6eec5
6 changed files with 65 additions and 27 deletions

View File

7
app.py
View File

@@ -1,7 +1,7 @@
from flask import Flask, render_template, request, send_file, jsonify
from datetime import datetime
from scraper import get_google_first_page
import io, json, csv, yaml, os
from api import get_google_first_page
import io, json, csv, yaml, os, requests
from dotenv import load_dotenv
load_dotenv()
@@ -10,6 +10,7 @@ app = Flask(__name__)
@app.route("/", methods=["GET"])
def index():
return render_template("index.html", results=[])
@app.route("/search", methods=["POST"])
@@ -17,6 +18,7 @@ def search():
query = request.form.get("q", "").strip()
if not query:
return render_template("index.html", error="Zadejte dotaz.")
try:
results = get_google_first_page(query) # list of dicts
except Exception as e:
@@ -32,6 +34,7 @@ def search():
@app.route("/export", methods=["POST"])
def export():
data = request.get_json()
ext = data.get("format", "json")
results = data.get("results", [])

View File

@@ -11,6 +11,6 @@ services:
healthcheck:
test: ["CMD-SHELL", "python -m pytest || exit 1"]
interval: 1m
timeout: 20s
retries: 3
start_period: 20s
timeout: 10s
retries: 1
start_period: 10s

6
pytest.ini Normal file
View File

@@ -0,0 +1,6 @@
[pytest]
# Show logs during test runs (not only on failures)
log_cli = true
log_cli_level = INFO
log_format = %(asctime)s %(levelname)s %(name)s - %(message)s
log_date_format = %H:%M:%S

View File

@@ -6,25 +6,42 @@
<title>Výsledky pro "{{ query }}" - vontor.cz</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
<script>
function download(fmt) {
const payload = { format: fmt, results: JSON.parse(document.getElementById('json-data').textContent) };
function download(format) {
const resultsJsonElement = document.getElementById('json-data');
const results = JSON.parse(resultsJsonElement.textContent);
const requestPayload = { format, results };
fetch('/export', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(payload)
}).then(r => {
if (r.ok) return r.blob();
return r.json().then(j=>{throw j});
}).then(blob=>{
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'results.' + fmt;
document.body.appendChild(a);
a.click();
a.remove();
window.URL.revokeObjectURL(url);
}).catch(e=>{ alert('Export failed: ' + JSON.stringify(e));});
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(requestPayload)
})
.then(function(response) {
if (response.ok){
return response.blob();
}
//error
return response.json().then(function(errorBody) { throw errorBody; });
})
.then(function(fileBlob) {
//blob
const objectUrl = window.URL.createObjectURL(fileBlob);
const downloadLink = document.createElement('a');
downloadLink.href = objectUrl;
downloadLink.download = 'results.' + format;
document.body.appendChild(downloadLink);
downloadLink.click();
downloadLink.remove();
window.URL.revokeObjectURL(objectUrl);
})
.catch(function(error) {
alert('Export failed: ' + JSON.stringify(error));
});
}
</script>
</head>

View File

@@ -1,8 +1,9 @@
import os
import logging
import pytest
from dotenv import load_dotenv
import scraper
import api
def test_env_variables_present():
@@ -13,6 +14,10 @@ def test_env_variables_present():
key = (os.getenv("GOOGLE_DEVELOPER_KEY") or "").strip()
cx = (os.getenv("GOOGLE_CSE_ID") or "").strip()
# Log presence without exposing secrets
logging.info("GOOGLE_DEVELOPER_KEY present: %s", bool(key))
logging.info("GOOGLE_CSE_ID present: %s", bool(cx))
assert key, "GOOGLE_DEVELOPER_KEY is missing or empty"
assert cx, "GOOGLE_CSE_ID is missing or empty"
@@ -27,17 +32,24 @@ def test_integration_search_youtube(monkeypatch):
cx = (os.getenv("GOOGLE_CSE_ID") or "").strip()
if not key or not cx:
logging.warning("Skipping integration test: missing GOOGLE_DEVELOPER_KEY or GOOGLE_CSE_ID")
pytest.skip("Integration test skipped: GOOGLE_DEVELOPER_KEY/GOOGLE_CSE_ID not set")
# Speed up: don't wait during the test
monkeypatch.setattr(scraper, "RATE_SECONDS", 0)
monkeypatch.setattr(scraper, "last_api_call", 0)
monkeypatch.setattr(api, "RATE_SECONDS", 0)
monkeypatch.setattr(api, "last_api_call", 0)
results = []
try:
results = scraper.get_google_first_page("youtube")
logging.info("Calling get_google_first_page for query 'youtube'")
results = api.get_google_first_page("youtube")
logging.info("Received %d results. First title: %s", len(results), (results[0].get("title") if results else None))
except RuntimeError as e:
logging.error("API error during integration test: %s", e)
return pytest.skip(f"Integration test skipped due to API error: {e}")
assert isinstance(results, list) and len(results) > 0
assert any("youtube.com" in (item.get("link") or "") for item in results)
has_youtube = any("youtube.com" in (item.get("link") or "") for item in results)
logging.info("Contains youtube.com link: %s", has_youtube)
assert has_youtube