diff --git a/app/db/db_methods.py b/app/db/db_methods.py index d80d92db..14aa3b55 100644 --- a/app/db/db_methods.py +++ b/app/db/db_methods.py @@ -1,3 +1,7 @@ +import os +import random +import string +import traceback from datetime import datetime from os.path import basename @@ -9,8 +13,9 @@ from .db_types import User, Presentation, Check, Consumers, Logs +database_name = os.getenv('DATABASE_NAME', 'pres-parser-db') client = MongoClient("mongodb://mongodb:27017") -db = client['pres-parser-db'] +db = client[database_name] fs = GridFSBucket(db) users_collection = db['users'] @@ -51,6 +56,10 @@ def validate_user(username, password_hash): return None +# def get_users(): +# for elem in files_info_collection.find(): +# print(elem) + # Returns user with given username or None def get_user(username): user = users_collection.find_one({'username': username}) @@ -230,7 +239,7 @@ def set_passbacked_flag(checks_id, flag): def get_latest_users_check(filter=None): local_filter = filter user = local_filter.get('user') - username_filter = {'username': user} if user else {} + username_filter = {'username': user} if user else {} all_users = [user['username'] for user in users_collection.find(username_filter, {'username': 1})] latest_checks = [] for user in all_users: @@ -443,3 +452,60 @@ def get_celery_task(celery_task_id): def get_celery_task_by_check(check_id): return celery_check_collection.find_one({'check_id': check_id}) + +def random_string(length=8): + letters = string.ascii_letters + string.digits + return ''.join(random.choice(letters) for _ in range(length)) + +# def fill_test_data(user_name): +# for i in range(5): +# filepath = f'document_insight_system/app/db/tests_data/test_file_{i}.docx' +# file_type = 'report' +# username = user_name +# add_file_info_and_content(username, filepath, file_type) + +def get_all_collections_name(): + collection = db.collection_names(include_system_collections=False) + lst = [] + for collect in collection: + lst.append(collect) + return lst + +def get_users_from_table(): + lst = [] + for el in users_collection.find(): + lst.append(el) + return lst + +def get_files_info_from_table(): + lst = [] + for el in files_info_collection.find(): + lst.append(el) + return lst + +def get_checks_from_table(): + lst = [] + for el in checks_collection.find(): + lst.append(el) + return lst + +def get_consumers_from_table(): + lst = [] + for el in consumers_collection.find(): + lst.append(el) + return lst + +def get_criteria_pack_from_table(): + lst = [] + for el in criteria_pack_collection.find(): + lst.append(el) + return lst + +def get_logs_from_table(): + lst = [] + for el in logs_collection.find(): + lst.append(el) + return lst + + + diff --git a/assets/scripts/check_list.js b/assets/scripts/check_list.js index 1480cabf..a07f7607 100644 --- a/assets/scripts/check_list.js +++ b/assets/scripts/check_list.js @@ -1,4 +1,4 @@ -import { debounce, isFloat, resetTable, ajaxRequest, onPopState } from "./utils" +import { debounce, isFloat, resetTable, ajaxRequest, onPopState, getLatestAjaxRequest } from "./utils" let $table; const AJAX_URL = "/check_list/data"; @@ -201,7 +201,7 @@ function buttons() { text: 'CSV', event: function () { //const queryString = window.location.search - const params = window.location.search + const params = getLatestAjaxRequest() $("[name=FetchCSV]")[0].innerHTML = " Exporting..." fetch('get_csv' + '?' + params) .then(response => response.blob()) @@ -215,7 +215,7 @@ function buttons() { buttonsObj["FetchZip"] = { text: 'Скачать архив', event: function () { - const params = window.location.search + const params = getLatestAjaxRequest() $("[name=FetchZip]")[0].innerHTML = " Архивирование..." fetch('get_zip' + '?' + params) .then(response => response.ok ? response.blob() : false) diff --git a/assets/scripts/utils.js b/assets/scripts/utils.js index 68118826..7213a3d9 100644 --- a/assets/scripts/utils.js +++ b/assets/scripts/utils.js @@ -1,62 +1,67 @@ export function debounce(func, timeout) { - return function perform(...args) { - let previousCall = this.lastCall; - let currCall = Date.now(); - this.lastCall = currCall; + return function perform(...args) { + let previousCall = this.lastCall; + let currCall = Date.now(); + this.lastCall = currCall; - if (previousCall && (currCall - previousCall <= timeout)) { - clearTimeout(this.lastCallTimer); - } + if (previousCall && (currCall - previousCall <= timeout)) { + clearTimeout(this.lastCallTimer); + } - this.lastCallTimer = setTimeout(() => func(...args), timeout); - } + this.lastCallTimer = setTimeout(() => func(...args), timeout); + } }; export function isFloat(str) { - const floatRegex = /^-?\d+(?:[.,]\d*?)?$/; - if (!floatRegex.test(str)) - return false; - - str = parseFloat(str); - if (isNaN(str)) - return false; - return true; + const floatRegex = /^-?\d+(?:[.,]\d*?)?$/; + if (!floatRegex.test(str)) + return false; + + str = parseFloat(str); + if (isNaN(str)) + return false; + return true; }; export function pushHistoryState(paramsData) { - const {limit, offset, sort, order, filter} = paramsData; + const {limit, offset, sort, order, filter} = paramsData; - // push history state - history.pushState(paramsData, "", "?" + $.param({limit, offset, filter, sort, order})) + // push history state + history.pushState(paramsData, "", "?" + $.param({limit, offset, filter, sort, order})) }; +let currentAjax = "" export function ajaxRequest(AJAX_URL, params) { - const queryString = "?" + $.param(params.data) - const url = AJAX_URL + queryString - console.log("ajax:", url); - $.get(url).then(res => params.success(res)) + const queryString = "?" + $.param(params.data) + currentAjax = queryString + const url = AJAX_URL + queryString + console.log("ajax:", url); + $.get(url).then(res => params.success(res)) - pushHistoryState(params.data) + pushHistoryState(params.data) }; +export function getLatestAjaxRequest(){ + return currentAjax +}; export function onPopState() { - location.reload() + location.reload() }; export function resetTable($table, queryParams) { - let queryString = window.location.search; - const params = Object.fromEntries(new URLSearchParams(decodeURIComponent(queryString)).entries()); - params.filter = ""; + let queryString = window.location.search; + const params = Object.fromEntries(new URLSearchParams(decodeURIComponent(queryString)).entries()); + params.filter = ""; - pushHistoryState(params); + pushHistoryState(params); - $table.bootstrapTable('refreshOptions', { - sortName: "", - sortOrder: "", - queryParams: queryParams - }); + $table.bootstrapTable('refreshOptions', { + sortName: "", + sortOrder: "", + queryParams: queryParams + }); } \ No newline at end of file diff --git a/tests/main.py b/tests/main.py index e9de1e39..46c034ed 100644 --- a/tests/main.py +++ b/tests/main.py @@ -8,6 +8,8 @@ from test_single_card_check import SingleCheckTestSelenium from test_version import VersionTestSelenium from test_file_load import FileLoadTestSelenium +from test_csv_load import CsvDownloadTestSelenium + def parse_arguments(): parser = argparse.ArgumentParser(description='Run Selenium tests with specified data') @@ -15,18 +17,22 @@ def parse_arguments(): parser.add_argument('--login', type=str, required=True, help='insert Username') parser.add_argument('--password', type=str, required=True, help='insert Password') script_dir = os.path.dirname(os.path.abspath(__file__)) - parser.add_argument('--pres', type=str, default=os.path.join(script_dir, 'tests_data/example_of_pres.pptx'), help='your path to press for testing') - parser.add_argument('--report', type=str, default=os.path.join(script_dir, 'tests_data/example_of_report.docx'), help='your path to report in .docx') - parser.add_argument('--report_doc', type=str, default=os.path.join(script_dir, 'tests_data/example_of_report.doc'), help='your path to report in .doc') - - + parser.add_argument('--pres', type=str, default=os.path.join(script_dir, 'tests_data/example_of_pres.pptx'), + help='your path to press for testing') + parser.add_argument('--report', type=str, default=os.path.join(script_dir, 'tests_data/example_of_report.docx'), + help='your path to report in .docx') + parser.add_argument('--report_doc', type=str, default=os.path.join(script_dir, 'tests_data/example_of_report.doc'), + help='your path to report in .doc') + return parser.parse_args() + def main(): args = parse_arguments() suite = unittest.TestSuite() - tests = (AuthTestSelenium, StatisticTestSelenium, FileLoadTestSelenium, SingleCheckTestSelenium, VersionTestSelenium) + tests = ( + AuthTestSelenium, StatisticTestSelenium, FileLoadTestSelenium, SingleCheckTestSelenium, VersionTestSelenium, CsvDownloadTestSelenium) param = (args.host, args.login, args.password, args.report, args.report_doc, args.pres) for test in tests: suite.addTest(BasicSeleniumTest.parametrize(test, param=param)) @@ -36,5 +42,6 @@ def main(): BasicSeleniumTest.close_driver() sys.exit(returncode) + if __name__ == '__main__': main() diff --git a/tests/requirements.txt b/tests/requirements.txt index cd2eeb88..6366b1a0 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,2 +1,3 @@ selenium==4.18.0 webdriver-manager==4.0.1 #to avoid problem with binary +pandas==2.2.2 diff --git a/tests/test_csv_load.py b/tests/test_csv_load.py new file mode 100644 index 00000000..f0b7491f --- /dev/null +++ b/tests/test_csv_load.py @@ -0,0 +1,75 @@ +import os +import time +import pandas as pd +import requests +from basic_selenium_test import BasicSeleniumTest +from selenium.webdriver.common.by import By + + +def get_downloads_path(): + if os.name == 'nt': + return os.path.join(os.environ['USERPROFILE'], 'Downloads') + else: + return os.path.join(os.environ['HOME'], 'Downloads') + +def get_latest_csv(dir): + files = [os.path.join(dir, f) for f in os.listdir(dir)] + latest_file = max(files, key=os.path.getmtime) + return latest_file + + +class CsvDownloadTestSelenium(BasicSeleniumTest): + + def test_http_connection(self): + csv_url = 'http://localhost:8080/get_csv' + + response = requests.get(csv_url) + self.assertEqual(response.status_code, 200, f"Ошибка при скачивании CSV файла. Статус: {response.status_code}") + + + def test_csv_add_download(self): + self.authorization() + URL = self.get_url('/check_list') + self.get_driver().get(URL) + self.get_driver().implicitly_wait(30) + + csv_button = self.driver.find_element(By.XPATH, '//button[text()="CSV"]') + csv_button.click() + + time.sleep(10) + + download_dir = get_downloads_path() + + csv_file = get_latest_csv(download_dir) + self.assertTrue(csv_file.endswith('.csv'), "Скачанный файл не является CSV файлом.") + + + + def test_csv_content(self): + download_dir = get_downloads_path() + csv_file = get_latest_csv(download_dir) + df = pd.read_csv(csv_file) + expected_columns =['_id', 'filename', 'criteria', 'user', 'upload-date', 'score'] + for column in expected_columns: + self.assertIn(column, df.columns, f"Столбец '{column}' не найден в файле CSV.") + + def test_csv_download_and_filter(self): + file_name_input = self.driver.find_element(By.CSS_SELECTOR, 'input.form-control.bootstrap-table-filter-control-filename.search-input') + + file_name_input.send_keys('example_of_report.docx') + file_name_sort_button = self.driver.find_element(By.XPATH, '//div[contains(@class, "th-inner") and contains(@class, "sortable") and text()="File name"]') + file_name_sort_button.click() + + time.sleep(5) + + csv_button = self.driver.find_element(By.XPATH, '//button[text()="CSV"]') + csv_button.click() + + time.sleep(10) + + download_dir = get_downloads_path() + latest_file = get_latest_csv(download_dir) + + df = pd.read_csv(latest_file) + filtered_by_name = df[df['filename'] == 'example_of_report.docx'] + self.assertTrue(len(filtered_by_name) > 0, "Нет данных, отфильтрованных по имени файла.")