diff --git a/.gitignore b/.gitignore
index f9db17e..2bf95fd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -43,4 +43,3 @@ requirements.txt
requirement/ignore_requirements.txt
screenshots
screencasts
-script/todo/todo_override.json
diff --git a/conf/make.docker.Makefile b/conf/make.docker.Makefile
index cd1750f..f421029 100644
--- a/conf/make.docker.Makefile
+++ b/conf/make.docker.Makefile
@@ -53,14 +53,26 @@ docker_exec_erplibre_repo_show_status:
docker_build_odoo_16:
./script/docker/docker_build.sh --odoo_16
+.PHONY: docker_build_odoo_16_clean
+docker_build_odoo_16_clean:
+ ./script/docker/docker_build.sh --odoo_16 --no-cache
+
.PHONY: docker_build_odoo_14
docker_build_odoo_14:
./script/docker/docker_build.sh --odoo_14
+.PHONY: docker_build_odoo_14_clean
+docker_build_odoo_14_clean:
+ ./script/docker/docker_build.sh --odoo_14 --no-cache
+
.PHONY: docker_build_odoo_12
docker_build_odoo_12:
./script/docker/docker_build.sh --odoo_12
+.PHONY: docker_build_odoo_12_clean
+docker_build_odoo_12_clean:
+ ./script/docker/docker_build.sh --odoo_12 --no-cache
+
# build docker release
.PHONY: docker_build_release
docker_build_release:
diff --git a/doc/FAQ.md b/doc/FAQ.md
index 65a51f3..a950c05 100644
--- a/doc/FAQ.md
+++ b/doc/FAQ.md
@@ -221,3 +221,9 @@ cat /proc/sys/fs/inotify/max_user_watches
Tips, when doing `sudo sysctl -p --system`, validate the order of the process, another process can overwrite your new
value.
+
+## How killing all process from selenium
+
+```bash
+pkill -f "firefox.*--marionette"
+```
diff --git a/docker/docker-compose_odoo_12.0.yml b/docker/docker-compose_odoo_12.0.yml
index dcdaccb..2e58086 100644
--- a/docker/docker-compose_odoo_12.0.yml
+++ b/docker/docker-compose_odoo_12.0.yml
@@ -27,6 +27,7 @@ services:
# See the volume section at the end of the file
- erplibre_data_dir:/home/odoo/.local/share/Odoo
- ./addons/addons:/ERPLibre/addons/addons
+ - ./private:/ERPLibre/private
- erplibre_conf:/etc/odoo
restart: always
diff --git a/docker/docker-compose_odoo_14.0.yml b/docker/docker-compose_odoo_14.0.yml
index a36b178..cb67650 100644
--- a/docker/docker-compose_odoo_14.0.yml
+++ b/docker/docker-compose_odoo_14.0.yml
@@ -1,7 +1,7 @@
version: "3.3"
services:
ERPLibre:
- image: technolibre/erplibre:1.6.0_odoo_14.0_2a8af84
+ image: technolibre/erplibre:1.6.0_odoo_14.0_1890768
ports:
- 8069:8069
- 8071:8071
@@ -27,6 +27,7 @@ services:
# See the volume section at the end of the file
- erplibre_data_dir:/home/odoo/.local/share/Odoo
- ./addons/addons:/ERPLibre/addons/addons
+ - ./private:/ERPLibre/private
- erplibre_conf:/etc/odoo
restart: always
diff --git a/docker/docker-compose_odoo_16.0.yml b/docker/docker-compose_odoo_16.0.yml
index adf1c55..7ffd6be 100644
--- a/docker/docker-compose_odoo_16.0.yml
+++ b/docker/docker-compose_odoo_16.0.yml
@@ -27,6 +27,7 @@ services:
# See the volume section at the end of the file
- erplibre_data_dir:/home/odoo/.local/share/Odoo
- ./addons/addons:/ERPLibre/addons/addons
+ - ./private:/ERPLibre/private
- erplibre_conf:/etc/odoo
restart: always
diff --git a/manifest/default.dev.odoo16.0.xml b/manifest/default.dev.odoo16.0.xml
index b47ea74..615856b 100644
--- a/manifest/default.dev.odoo16.0.xml
+++ b/manifest/default.dev.odoo16.0.xml
@@ -97,7 +97,7 @@
-
+
@@ -107,20 +107,20 @@
-
+
-
+
-
+
-
-
+
+
-
+
@@ -129,7 +129,7 @@
-
+
diff --git a/private/TODO.md b/private/TODO.md
new file mode 100644
index 0000000..068db6f
--- /dev/null
+++ b/private/TODO.md
@@ -0,0 +1 @@
+Move your private file and project configuration here. The docker will share a volume with this repertory.
diff --git a/private/__init__.py b/private/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/script/selenium/selenium_lib.py b/script/selenium/selenium_lib.py
index c488f69..d802867 100644
--- a/script/selenium/selenium_lib.py
+++ b/script/selenium/selenium_lib.py
@@ -8,7 +8,13 @@ import random
import re
import sys
import time
+import json
+import tempfile
from subprocess import getoutput
+import tkinter as tk
+from tkinter import filedialog
+import getpass
+from pykeepass import PyKeePass
from randomwordfr import RandomWordFr
from selenium import webdriver
@@ -20,16 +26,24 @@ from selenium.webdriver import ActionChains
from selenium.webdriver.common.actions.wheel_input import ScrollOrigin
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
+from selenium.webdriver.firefox.options import Options
from selenium.webdriver.firefox.service import Service
from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
+# TODO maybe use TODO lib
+CONFIG_FILE = "./script/todo/todo.json"
+CONFIG_OVERRIDE_FILE = "./private/todo.json"
+LOGO_ASCII_FILE = "./script/todo/logo_ascii.txt"
+
class SeleniumLib(object):
def __init__(self, config):
self.config = config
+ self.kdbx = None
self.video_recorder = None
+ self.default_download_dir_path = tempfile.mkdtemp()
if self.config.video_suffix:
self.filename_recording = (
f"video_{self.config.video_suffix}_"
@@ -67,6 +81,9 @@ class SeleniumLib(object):
if not self.config.not_private_mode:
firefox_options.add_argument("--private")
+ if self.config.headless:
+ firefox_options.add_argument("--headless")
+
# firefox_options.set_preference("browser.link.open_newwindow", 3)
# firefox_options.set_preference("browser.link.open_newwindow.restriction", 2)
@@ -75,6 +92,18 @@ class SeleniumLib(object):
firefox_options.set_preference(
"permissions.default.desktop-notification", 1
)
+ firefox_options.set_preference("browser.download.folderList", 2)
+ firefox_options.set_preference(
+ "browser.download.manager.showWhenStarting", False
+ )
+ firefox_options.set_preference(
+ "browser.download.dir", self.default_download_dir_path
+ )
+ firefox_options.set_preference(
+ "browser.helperApps.neverAsk.saveToDisk",
+ "application/octet-stream,application/pdf,application/x-pdf",
+ )
+ firefox_options.set_preference("pdfjs.disabled", True)
firefox_services = None
if self.config.firefox_binary_path:
firefox_services = Service(
@@ -182,6 +211,53 @@ class SeleniumLib(object):
self.driver.close()
self.driver.switch_to.window(self.driver.window_handles[0])
+ def get_kdbx(self):
+ if self.kdbx:
+ return self.kdbx
+ # Open file
+ chemin_fichier_kdbx = self.get_config(["kdbx", "path"])
+ if not chemin_fichier_kdbx:
+ root = tk.Tk()
+ root.withdraw() # Hide the main window
+ chemin_fichier_kdbx = filedialog.askopenfilename(
+ title="Select a File",
+ filetypes=(("KeepassX files", "*.kdbx"),),
+ )
+ if not chemin_fichier_kdbx:
+ # _logger.error(f"KDBX is not configured, please fill {CONFIG_FILE}")
+ return
+
+ mot_de_passe_kdbx = self.get_config(["kdbx", "password"])
+ if not mot_de_passe_kdbx:
+ mot_de_passe_kdbx = getpass.getpass(
+ prompt="Entrez votre mot de passe : "
+ )
+
+ kp = PyKeePass(chemin_fichier_kdbx, password=mot_de_passe_kdbx)
+
+ if kp:
+ self.kdbx = kp
+ return kp
+
+ def get_config(self, lst_params):
+ # Open file
+ config_file = CONFIG_FILE
+ if os.path.exists(CONFIG_OVERRIDE_FILE):
+ config_file = CONFIG_OVERRIDE_FILE
+
+ with open(config_file) as cfg:
+ dct_data = json.load(cfg)
+ for param in lst_params:
+ try:
+ dct_data = dct_data[param]
+ except KeyError:
+ # _logger.error(
+ # f"KeyError on file {config_file} with keys"
+ # f" {lst_params}"
+ # )
+ return
+ return dct_data
+
@staticmethod
def get_french_word_no_space_no_accent():
word = ""
@@ -248,6 +324,12 @@ class SeleniumLib(object):
return ele
+ def get_text_from_element(
+ self, by: str = By.ID, value: str = None, timeout=5
+ ):
+ ele = self.get_element(by, value, timeout=timeout)
+ return ele.text
+
def get_all_element(self, by: str = By.ID, value: str = None, timeout=5):
wait = WebDriverWait(self.driver, timeout)
ele = wait.until(
@@ -1133,6 +1215,11 @@ def fill_parser(parser):
action="store_true",
help="Default is private mode.",
)
+ group_browser.add_argument(
+ "--headless",
+ action="store_true",
+ help="For automation without GUI.",
+ )
group_browser.add_argument(
"--no_dark_mode",
action="store_true",
diff --git a/script/todo/README.md b/script/todo/README.md
index 983796d..245167c 100644
--- a/script/todo/README.md
+++ b/script/todo/README.md
@@ -1,4 +1,4 @@
TODO is an assistant robot to use ERPLibre
Execute it with `./script/todo/todo.py` or `make todo`.
-For a new project, copy todo_example.json to todo_override.json and edit it.
+For a new project, copy todo_example.json to private/todo.json and edit it.
diff --git a/script/todo/todo.py b/script/todo/todo.py
index de1c700..b78b87a 100755
--- a/script/todo/todo.py
+++ b/script/todo/todo.py
@@ -87,7 +87,7 @@ except ModuleNotFoundError as e:
_logger = logging.getLogger(__name__)
CONFIG_FILE = "./script/todo/todo.json"
-CONFIG_OVERRIDE_FILE = "./script/todo/todo_override.json"
+CONFIG_OVERRIDE_FILE = "./private/todo.json"
LOGO_ASCII_FILE = "./script/todo/logo_ascii.txt"