Skip to content

Commit 39e3a7d

Browse files
committed
go to defenition feature, few ui cahnges and readme
1 parent d1f2547 commit 39e3a7d

12 files changed

Lines changed: 249 additions & 89 deletions

README.md

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,25 @@ A user-friendly desktop application to edit test cases for keyword-driven testin
88

99
## Features
1010

11-
* **Basic Spreadsheet Suite:** All the basic spreadsheet editing features you are used to.
12-
* **MultiTab Functionality:** MultiTab function to actively open and edit multiple tests.
13-
* **Custom File Explorer:** Custom built file explorer to move through project files.
14-
* **Command Manager:** Cross-file Command(functions)/Objects retrieval with dropdown in table for ease of use.
15-
* **Auto Update ID:** Auto Update ID (when inserting or removing rows).
16-
* **Smart Cell Merging:** Automatically merges the 'Description' column for test case blocks between StartScenario and EndScenario commands.
17-
* **Clean UI:** Clean and professional Dark mode UI/Light mode in the works.
18-
* **Excel File Support:** Edit standard (`.xlsx`) test case files.
11+
### Editing
12+
13+
* **Intuitive Spreadsheet Interface:** All the basic spreadsheet editing features you are used to.
14+
* **Multi-Tab Functionality:** Open and edit multiple test cases in separate tabs.
15+
* **Auto Update ID:** Automatically update test step IDs when inserting or removing rows.
16+
* **Smart Cell Merging:** Automatically merge the 'Description' column for test case blocks.
17+
18+
### Test Execution
1919

20-
## Upcoming Features
20+
* **Run Tests:** Run test cases directly from the editor.
21+
* **Configurable Run Settings:** Configure the test execution with settings like project, module, base URL, browser, and video option. │
22+
* **Live Console Output:** View the live output of the test execution in the console panel.
23+
* **HTML Log Viewer:** Automatically open and view detailed HTML log files after a test run.
2124

22-
* **Run:** Run TestCases directly from editor.
23-
* **Light Mode:** Light theme option for different preferences.
24-
* **Command Argument validation:** Syntax Highlighting on commands to indicate required arguments met.
25-
* **Navigate to Object Definition** Scenario -> Object Repo jump for quick editing of objects.
25+
### Project and File Management
26+
27+
* **Custom File Explorer:** A built-in file explorer to navigate through your project files.
28+
* **Excel File Support:** Edit standard (`.xlsx`) test case files.
29+
* **Project Structure:** Works with a predefined project structure for test suites and object repositories.
2630

2731
## Known Issues
2832

@@ -105,9 +109,8 @@ This project uses the following major libraries:
105109
* **Edit -> Generate Test Cases**
106110
> Generate steps performed and expected result based on the command, object and value.
107111

108-
* Start editing with the intuitive spreadsheet interface
109-
110-
* Use the multi-tab feature to work on multiple test files simultaneously.
112+
* **Run Icon**
113+
> Run the current module based on the preset config for run.
111114

112115
## Contributing
113116

core/file_controller.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ def new_file(self):
4040

4141
def open_file(self):
4242
ui = FileUI(main=self.main,mode="open")
43+
ui.e2e_dir_changed.connect(self.main.set_e2e_dir)
4344
if ui.exec() != QDialog.DialogCode.Accepted:
4445
return
4546

@@ -79,12 +80,12 @@ def open_file(self):
7980
tab.model2.loadData(objects_df)
8081

8182
scenario_table_view = tab.table1.table
82-
scenario_table_view.setColumnWidth(0, 50) # Type
83-
scenario_table_view.setColumnWidth(1, 130) # ID
84-
scenario_table_view.setColumnWidth(2, 50) # Skip
85-
scenario_table_view.setColumnWidth(3, 300) # Description
86-
scenario_table_view.setColumnWidth(4, 350) # Steps Performed
87-
scenario_table_view.setColumnWidth(5, 50) # Expected Results
83+
scenario_table_view.setColumnWidth(0, 40) # Type
84+
scenario_table_view.setColumnWidth(1, 121) # ID
85+
scenario_table_view.setColumnWidth(2, 30) # Skip
86+
scenario_table_view.setColumnWidth(3, 230) # Description
87+
scenario_table_view.setColumnWidth(4, 290) # Steps Performed
88+
scenario_table_view.setColumnWidth(5, 40) # Expected Results
8889
scenario_table_view.setColumnWidth(6, 250) # Command
8990
for col_index in range(7, 12):
9091
scenario_table_view.setColumnWidth(col_index, 250)
@@ -130,6 +131,7 @@ def save_file_as(self, tab):
130131
tab = self.main.get_current_tab()
131132

132133
ui = FileUI(main=self.main,mode="save")
134+
ui.e2e_dir_changed.connect(self.main.set_e2e_dir)
133135
if ui.exec() != QDialog.DialogCode.Accepted:
134136
return
135137

models/model.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ def setData(self, index, value, role=Qt.ItemDataRole.EditRole):
4646
def headerData(self, section: int, orientation: Qt.Orientation, role: int = Qt.ItemDataRole.DisplayRole) -> Any:
4747
if role == Qt.ItemDataRole.DisplayRole:
4848
if orientation == Qt.Orientation.Horizontal:
49-
return chr(65 + section) if section < 26 else f"Col{section+1}"
49+
return " "
5050
if orientation == Qt.Orientation.Vertical:
51-
return str(section + 1)
51+
return ""
5252
return None
5353

5454
def flags(self, index):

test_editor-sample-workspace.png

-113 KB
Loading

ui/delegates.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,12 @@ def paint(self, painter, option, index):
207207
option = QStyleOptionViewItem(option)
208208
is_special_row = False
209209

210+
# Make selected text bold
211+
if option.state & QStyle.StateFlag.State_Selected:
212+
font = option.font
213+
font.setBold(True)
214+
option.font = font
215+
210216
if isinstance(model, TestScenarioModel):
211217
if (current_row == 0 or
212218
current_row == 1 or

ui/file_ui.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66
QPushButton, QListWidgetItem, QFileDialog, QMessageBox,
77
QSplitter, QWidget
88
)
9-
from PyQt6.QtCore import Qt, QSettings
9+
from PyQt6.QtCore import Qt, QSettings, pyqtSignal
1010

1111
class FileUI(QDialog):
12+
e2e_dir_changed = pyqtSignal(str)
1213
def __init__(self,main = None, mode="open"):
1314
super().__init__(main)
1415
self.mode = mode
@@ -138,6 +139,7 @@ def _select_e2e_directory(self):
138139
self._save_last_directory()
139140
self._populate_projects()
140141
self._load_last_project()
142+
self.e2e_dir_changed.emit(self.e2e_dir)
141143
else:
142144
QMessageBox.warning(self, "Invalid Directory",
143145
"Selected directory should be the E2E application root with 'data/' subdirectory")

ui/menu.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -159,12 +159,12 @@ def apply_fixed_widths(self) -> None:
159159
if isinstance(tab, TabWidget) and tab.inner_tabs.currentIndex() == 0:
160160
scenario_table_view = tab.table1.table
161161

162-
scenario_table_view.setColumnWidth(0, 50) # Type
163-
scenario_table_view.setColumnWidth(1, 130) # ID
164-
scenario_table_view.setColumnWidth(2, 50) # Skip
165-
scenario_table_view.setColumnWidth(3, 300) # Description
166-
scenario_table_view.setColumnWidth(4, 350) # Steps Performed
167-
scenario_table_view.setColumnWidth(5, 50) # Expected Results
162+
scenario_table_view.setColumnWidth(0, 40) # Type
163+
scenario_table_view.setColumnWidth(1, 121) # ID
164+
scenario_table_view.setColumnWidth(2, 30) # Skip
165+
scenario_table_view.setColumnWidth(3, 230) # Description
166+
scenario_table_view.setColumnWidth(4, 290) # Steps Performed
167+
scenario_table_view.setColumnWidth(5, 40) # Expected Results
168168
scenario_table_view.setColumnWidth(6, 250) # Command
169169
for col_index in range(7, 12):
170170
scenario_table_view.setColumnWidth(col_index, 250)
@@ -179,9 +179,9 @@ def apply_fixed_widths(self) -> None:
179179

180180
def create_corner_run_toolbar(self):
181181
toolbar_widget = QWidget()
182-
toolbar_widget.setObjectName
182+
toolbar_widget.setObjectName("RunToolbar")
183183
toolbar_layout = QHBoxLayout(toolbar_widget)
184-
toolbar_layout.setContentsMargins(5, 5, 5, 0)
184+
toolbar_layout.setContentsMargins(5, 5, 5, 5)
185185
toolbar_layout.setSpacing(5)
186186

187187
self.run_button = QPushButton("▶")
@@ -200,7 +200,7 @@ def create_corner_run_toolbar(self):
200200
toolbar_layout.addWidget(self.stop_button)
201201

202202
self.config_button = QPushButton("⚙")
203-
self.config_button.setToolTip("Run Configuration")
203+
self.config_button.setToolTip("Run Configuration (Ctrl+Alt+R)")
204204
self.config_button.clicked.connect(self.show_run_config)
205205
self.config_button.setFlat(True)
206206
self.config_button.setObjectName("ConfigButton")

ui/output_dock.py

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,9 @@ def __init__(self, parent=None):
1616

1717
title_bar = QWidget()
1818
title_bar_layout = QHBoxLayout(title_bar)
19-
title_bar_layout.setContentsMargins(5, 5, 5, 0)
19+
title_bar_layout.setContentsMargins(0, 5, 0, 0)
2020
title_bar_layout.setSpacing(5)
2121

22-
title_bar_layout.addStretch()
23-
2422
self.is_maximized = False
2523
self.restore_height = 0
2624

@@ -30,46 +28,67 @@ def __init__(self, parent=None):
3028
open_log_icon = style.standardIcon(QStyle.StandardPixmap.SP_DialogOpenButton)
3129
self.maximize_icon = style.standardIcon(QStyle.StandardPixmap.SP_TitleBarMaxButton)
3230
self.restore_icon = style.standardIcon(QStyle.StandardPixmap.SP_TitleBarNormalButton)
31+
self.minimize_icon = style.standardIcon(QStyle.StandardPixmap.SP_TitleBarMinButton)
3332

3433
self.back_button = QPushButton("◀")
3534
self.forward_button = QPushButton("▶")
3635
self.refresh_button = QPushButton("⟳")
3736
self.maximize_button = QPushButton(icon=self.maximize_icon)
3837
self.open_log_button = QPushButton(icon=open_log_icon)
38+
self.minimize_button = QPushButton(icon=self.minimize_icon)
3939

4040
self.back_button.setObjectName("DockTitleBarButton")
4141
self.forward_button.setObjectName("DockTitleBarButton")
4242
self.refresh_button.setObjectName("DockTitleBarButton")
4343
self.maximize_button.setObjectName("DockTitleBarButton")
4444
self.open_log_button.setObjectName("DockTitleBarButton")
45+
self.minimize_button.setObjectName("DockTitleBarButton")
4546

4647
self.back_button.hide()
4748
self.forward_button.hide()
4849
self.refresh_button.hide()
4950

50-
title_bar_layout.addWidget(self.back_button)
51-
title_bar_layout.addWidget(self.forward_button)
52-
title_bar_layout.addWidget(self.refresh_button)
53-
title_bar_layout.addWidget(self.open_log_button)
54-
title_bar_layout.addWidget(self.maximize_button)
51+
nav_container = QWidget()
52+
nav_container.setObjectName("DockButtonContainerL")
53+
nav_layout = QHBoxLayout(nav_container)
54+
nav_layout.setContentsMargins(4, 4, 4, 4)
55+
nav_layout.setSpacing(2)
56+
nav_layout.addWidget(self.back_button)
57+
nav_layout.addWidget(self.forward_button)
58+
nav_layout.addWidget(self.refresh_button)
59+
60+
action_container = QWidget()
61+
action_container.setObjectName("DockButtonContainerR")
62+
action_layout = QHBoxLayout(action_container)
63+
action_layout.setContentsMargins(4, 4, 4, 4)
64+
action_layout.setSpacing(2)
65+
action_layout.addWidget(self.open_log_button)
66+
action_layout.addWidget(self.minimize_button)
67+
action_layout.addWidget(self.maximize_button)
68+
69+
title_bar_layout.addWidget(nav_container)
70+
title_bar_layout.addStretch()
71+
title_bar_layout.addWidget(action_container)
5572

5673
self.back_button.setFlat(True)
5774
self.forward_button.setFlat(True)
5875
self.refresh_button.setFlat(True)
5976
self.open_log_button.setFlat(True)
6077
self.maximize_button.setFlat(True)
78+
self.minimize_button.setFlat(True)
6179

62-
self.back_button.setToolTip("Go Back (Alt+Left)")
63-
self.forward_button.setToolTip("Go Forward (Alt+Right)")
80+
self.back_button.setToolTip("Back (Alt+Left)")
81+
self.forward_button.setToolTip("Forward (Alt+Right)")
6482
self.refresh_button.setToolTip("Refresh (F5)")
6583
self.open_log_button.setToolTip("Open Log File")
66-
self.maximize_button.setToolTip("Maximize/Restore Dock (Ctrl+M)")
84+
self.maximize_button.setToolTip("Maximize (Ctrl+M)")
85+
self.minimize_button.setToolTip("Minimize (Ctrl+`)")
6786

6887
self.setTitleBarWidget(title_bar)
88+
self.minimize_button.clicked.connect(self.hide)
6989
self.maximize_button.clicked.connect(self.toggle_maximize)
7090
self.refresh_button.clicked.connect(self.refresh_current_view)
7191

72-
7392
container = QWidget()
7493
layout = QVBoxLayout(container)
7594
layout.setContentsMargins(0, 0, 0, 0)
@@ -190,6 +209,10 @@ def get_scroll_and_refresh(scroll_y):
190209
if not url:
191210
return
192211

212+
if not (url.lower().endswith(".html") or url.lower().endswith(".htm")):
213+
current_widget.reload()
214+
return
215+
193216
try:
194217
with open(url, 'r', encoding='utf-8') as f:
195218
new_html = f.read()

ui/styles.py

Lines changed: 55 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -161,11 +161,22 @@ def get_stylesheet(theme) -> str:
161161
}}
162162
163163
/* Toolbar Run Control Buttons - Icon Colors Only */
164-
QPushButton#RunButton {{
164+
/* Container for dock button groups */
165+
QWidget#RunToolbar {{
166+
background-color: transparent;
167+
border-top: none;
168+
border-right: 2px solid {theme.BG};
165169
border-left: 2px solid {theme.BG};
166-
border-top: 2px solid {theme.BG};
167170
border-bottom: 1px solid {theme.BORDER};
168-
border-right: 1px solid {theme.BORDER};
171+
border-top-left-radius: 0px;
172+
border-bottom-left-radius: 6px;
173+
border-top-right-radius: 0px;
174+
border-bottom-right-radius: 6px;
175+
padding: 0px;
176+
}}
177+
178+
QPushButton#RunButton {{
179+
border: none;
169180
background-color: transparent;
170181
padding: 2px;
171182
border-radius: 6px;
@@ -197,10 +208,7 @@ def get_stylesheet(theme) -> str:
197208
}}
198209
199210
QPushButton#StopButton {{
200-
border-left: 2px solid {theme.BG};
201-
border-top: 2px solid {theme.BG};
202-
border-bottom: 1px solid {theme.BORDER};
203-
border-right: 1px solid {theme.BORDER};
211+
border: none;
204212
background-color: transparent;
205213
padding: 2px;
206214
border-radius: 6px;
@@ -232,10 +240,7 @@ def get_stylesheet(theme) -> str:
232240
}}
233241
234242
QPushButton#ConfigButton {{
235-
border-left: 2px solid {theme.BG};
236-
border-top: 2px solid {theme.BG};
237-
border-bottom: 1px solid {theme.BORDER};
238-
border-right: 1px solid {theme.BORDER};
243+
border: none;
239244
background-color: transparent;
240245
padding: 2px;
241246
border-radius: 6px;
@@ -272,16 +277,25 @@ def get_stylesheet(theme) -> str:
272277
border: none;
273278
padding: 2px 4px;
274279
background-color: transparent;
280+
border-radius: 6px;
275281
min-width: 15px;
276282
min-height: 15px;
277283
}}
278284
279285
QPushButton#StatusBarButton:hover {{
280286
background-color: {theme.BG_LIGHT};
287+
border-left: 1px solid {theme.BORDER};
288+
border-top: 1px solid {theme.BORDER};
289+
border-bottom: 1px solid {theme.BG};
290+
border-right: 1px solid {theme.BG};
281291
}}
282292
283293
QPushButton#StatusBarButton:pressed {{
284294
background-color: {theme.BG};
295+
border-left: 2px solid {theme.BG};
296+
border-top: 2px solid {theme.BG};
297+
border-bottom: 1px solid {theme.BORDER};
298+
border-right: 1px solid {theme.BORDER};
285299
}}
286300
287301
QStatusBar::item {{
@@ -485,14 +499,40 @@ def get_stylesheet(theme) -> str:
485499
background-color: transparent;
486500
}}
487501
488-
489-
490-
/* Output toolbar buttons (specific to output dock) */
491-
QPushButton#DockTitleBarButton {{
502+
/* Container for dock button groups */
503+
QWidget#DockButtonContainerR {{
504+
background-color: transparent;
505+
border: 2px solid {theme.BG};
506+
border-top: 2px solid {theme.BG};
507+
border-right: none;
492508
border-left: 2px solid {theme.BG};
509+
border-bottom: 1px solid {theme.BORDER};
510+
border-top-left-radius: 6px;
511+
border-bottom-left-radius: 6px;
512+
border-top-right-radius: 0px;
513+
border-bottom-right-radius: 0px;
514+
padding: 0px;
515+
}}
516+
517+
/* Container for dock button groups */
518+
QWidget#DockButtonContainerL {{
519+
background-color: transparent;
520+
border: none;
521+
border: 2px solid {theme.BG};
493522
border-top: 2px solid {theme.BG};
494523
border-bottom: 1px solid {theme.BORDER};
524+
border-left: none;
495525
border-right: 1px solid {theme.BORDER};
526+
border-top-left-radius: 0px;
527+
border-bottom-left-radius: 0px;
528+
border-top-right-radius: 6px;
529+
border-bottom-right-radius: 6px;
530+
padding: 0px;
531+
}}
532+
533+
/* Output toolbar buttons (specific to output dock) */
534+
QPushButton#DockTitleBarButton {{
535+
border: none;
496536
background-color: transparent;
497537
padding: 2px;
498538
border-radius: 6px;

0 commit comments

Comments
 (0)