Merge pull request #27759 from dhruvjamwal/main
Fix #27741: Prevent camel case splitting on numbers in Property Editor.
This commit is contained in:
@@ -68,6 +68,12 @@ runs:
|
||||
testCommand: ${{ inputs.builddir }}/tests/Gui_tests_run --gtest_output=json:${{ inputs.reportdir }}gui_gtest_results.json
|
||||
testLogFile: ${{ inputs.reportdir }}gui_gtest_test_log.txt
|
||||
testName: Gui
|
||||
- name: C++ Qt tests
|
||||
id: qttests
|
||||
uses: ./.github/workflows/actions/runCPPTests/runQtTests
|
||||
with:
|
||||
builddir: ${{ inputs.builddir }}
|
||||
testLogFile: ${{ inputs.reportdir }}qt_ctest_log.txt
|
||||
- name: C++ Material tests
|
||||
id: material
|
||||
uses: ./.github/workflows/actions/runCPPTests/runSingleTest
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
# SPDX-FileNotice: Part of the FreeCAD project.
|
||||
|
||||
name: runQtTests
|
||||
description: "Run all QtTest-based C++ tests (those labelled 'Qt' in CTest), generate log and report"
|
||||
|
||||
inputs:
|
||||
builddir:
|
||||
description: "Build directory containing CTestTestfile.cmake"
|
||||
required: true
|
||||
testLogFile:
|
||||
description: "Path for the command-line output of the tests"
|
||||
required: true
|
||||
outputs:
|
||||
reportText:
|
||||
description: "Report text"
|
||||
value: ${{ steps.report.outputs.reportText }}
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Run Qt tests via CTest
|
||||
shell: bash -l {0}
|
||||
env:
|
||||
BUILD_DIR: ${{ inputs.builddir }}
|
||||
TEST_LOG_FILE: ${{ inputs.testLogFile }}
|
||||
run: |
|
||||
set -o pipefail
|
||||
ctest --test-dir "$BUILD_DIR" -L Qt --output-on-failure | tee -a "$TEST_LOG_FILE"
|
||||
- name: Parse test results
|
||||
if: always()
|
||||
id: report
|
||||
shell: bash -l {0}
|
||||
env:
|
||||
TEST_LOG_FILE: ${{ inputs.testLogFile }}
|
||||
run: |
|
||||
result=$(grep -E "(Test #|tests passed|tests failed|Total Test time)" "$TEST_LOG_FILE" || true)
|
||||
if grep -qE "[1-9][0-9]* tests failed" "$TEST_LOG_FILE"
|
||||
then
|
||||
reportText="<details><summary>:fire: QtTest C++ tests failed</summary>\n"
|
||||
else
|
||||
reportText="<details><summary>:heavy_check_mark: QtTest C++ tests succeeded</summary>\n"
|
||||
fi
|
||||
reportText+="\n"
|
||||
reportText+="Results\n"
|
||||
reportText+="\n"
|
||||
reportText+='```\n'
|
||||
reportText+="$result\n"
|
||||
reportText+='```\n'
|
||||
reportText+="</details>\n"
|
||||
reportText+="\n"
|
||||
echo "reportText<<EOD" >> $GITHUB_OUTPUT
|
||||
echo -e "$reportText" >> $GITHUB_OUTPUT
|
||||
echo "EOD" >> $GITHUB_OUTPUT
|
||||
echo -e "$reportText"
|
||||
@@ -0,0 +1,62 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
# SPDX-FileNotice: Part of the FreeCAD project.
|
||||
|
||||
name: runSingleQtTest
|
||||
description: "Run a single QtTest-based C++ test executable, generate log and report"
|
||||
|
||||
inputs:
|
||||
testCommand:
|
||||
description: "Test executable path"
|
||||
required: true
|
||||
testLogFile:
|
||||
description: "Path for the command-line output of the tests"
|
||||
required: true
|
||||
testName:
|
||||
description: "A descriptive name for the test suite"
|
||||
required: true
|
||||
outputs:
|
||||
reportText:
|
||||
description: "Report text"
|
||||
value: ${{ steps.report.outputs.reportText }}
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Run QtTest tests
|
||||
shell: bash -l {0}
|
||||
env:
|
||||
QT_QPA_PLATFORM: offscreen
|
||||
TEST_COMMAND: ${{ inputs.testCommand }}
|
||||
TEST_LOG_FILE: ${{ inputs.testLogFile }}
|
||||
run: |
|
||||
set -o pipefail
|
||||
$TEST_COMMAND | tee -a "$TEST_LOG_FILE"
|
||||
- name: Parse test results
|
||||
if: always()
|
||||
id: report
|
||||
shell: bash -l {0}
|
||||
env:
|
||||
TEST_LOG_FILE: ${{ inputs.testLogFile }}
|
||||
TEST_NAME: ${{ inputs.testName }}
|
||||
run: |
|
||||
# This bonkers sed regex is to try to find the start and end of the QtTest output block, which is not really
|
||||
# designed to be machine-readable. Why did they have to choose asterisks?!?!
|
||||
result=$(sed -n '/^\*\*\*\*\*\*\*\*\* Start/,/^\*\*\*\*\*\*\*\*\* Finished/p' "$TEST_LOG_FILE" || true)
|
||||
if grep -qE "^FAIL!" "$TEST_LOG_FILE"
|
||||
then
|
||||
reportText="<details><summary>:fire: QtTest C++ test suite '${TEST_NAME}' failed</summary>\n"
|
||||
else
|
||||
reportText="<details><summary>:heavy_check_mark: QtTest C++ test suite '${TEST_NAME}' succeeded</summary>\n"
|
||||
fi
|
||||
reportText+="\n"
|
||||
reportText+="Results\n"
|
||||
reportText+="\n"
|
||||
reportText+='```\n'
|
||||
reportText+="$result\n"
|
||||
reportText+='```\n'
|
||||
reportText+="</details>\n"
|
||||
reportText+="\n"
|
||||
echo "reportText<<EOD" >> $GITHUB_OUTPUT
|
||||
echo -e "$reportText" >> $GITHUB_OUTPUT
|
||||
echo "EOD" >> $GITHUB_OUTPUT
|
||||
echo -e "$reportText"
|
||||
@@ -574,18 +574,14 @@ void PropertyItem::setPropertyName(const QString& name, const QString& realName)
|
||||
setObjectName(propName);
|
||||
|
||||
QString display;
|
||||
bool upper = false;
|
||||
// Camel case splitting
|
||||
for (auto&& i : name) {
|
||||
if (i.isUpper() && !display.isEmpty()) {
|
||||
// if there is a sequence of capital letters do not insert spaces
|
||||
if (!upper) {
|
||||
QChar last = display.at(display.length() - 1);
|
||||
if (!last.isSpace()) {
|
||||
display += QLatin1String(" ");
|
||||
}
|
||||
QChar last = display.at(display.length() - 1);
|
||||
if (last.isLower()) {
|
||||
display += QLatin1String(" ");
|
||||
}
|
||||
}
|
||||
upper = i.isUpper();
|
||||
display += i;
|
||||
}
|
||||
|
||||
|
||||
@@ -77,6 +77,15 @@ function(setup_qt_test)
|
||||
FreeCADGui
|
||||
${QtTest_LIBRARIES}
|
||||
${${_testname}_LIBS})
|
||||
|
||||
if(NOT WIN32)
|
||||
set_target_properties(${_testname}_Tests_run PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/tests)
|
||||
endif()
|
||||
|
||||
set_tests_properties(${_testname}_Tests_run PROPERTIES
|
||||
LABELS "Qt"
|
||||
ENVIRONMENT "QT_QPA_PLATFORM=offscreen")
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
add_subdirectory(Dialogs)
|
||||
add_subdirectory(propertyeditor)
|
||||
|
||||
# Standard C++ GTest tests
|
||||
add_executable(Gui_tests_run
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
setup_qt_test(PropertyItem)
|
||||
@@ -0,0 +1,111 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
#include <QDebug>
|
||||
#include <QtTest/QTest>
|
||||
|
||||
#include <App/Application.h>
|
||||
|
||||
#include "Gui/propertyeditor/PropertyItem.h"
|
||||
#include <src/App/InitApplication.h>
|
||||
|
||||
// NOLINTBEGIN(readability-magic-numbers)
|
||||
|
||||
class MockPropertyItem final: public Gui::PropertyEditor::PropertyItem
|
||||
{
|
||||
public:
|
||||
MockPropertyItem() = default;
|
||||
|
||||
void setTestValue(const QVariant& v)
|
||||
{
|
||||
testValue = v;
|
||||
}
|
||||
QVariant lastSetValue() const
|
||||
{
|
||||
return storedSetValue;
|
||||
}
|
||||
|
||||
protected:
|
||||
QVariant value(const App::Property* /*prop*/) const override
|
||||
{
|
||||
return testValue;
|
||||
}
|
||||
void setValue(const QVariant& v) override
|
||||
{
|
||||
storedSetValue = v;
|
||||
}
|
||||
|
||||
private:
|
||||
QVariant testValue;
|
||||
QVariant storedSetValue;
|
||||
};
|
||||
|
||||
class testPropertyItem: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
testPropertyItem()
|
||||
{
|
||||
tests::initApplication();
|
||||
item.reset(new MockPropertyItem());
|
||||
}
|
||||
|
||||
private Q_SLOTS:
|
||||
|
||||
void init()
|
||||
{}
|
||||
|
||||
void cleanup()
|
||||
{}
|
||||
|
||||
void test_camelCaseSplitsTwoWords() // NOLINT
|
||||
{
|
||||
item->setPropertyName(QLatin1String("CamelCase"));
|
||||
QCOMPARE(item->propertyName(), QLatin1String("Camel Case"));
|
||||
}
|
||||
|
||||
void test_camelCaseSplitsThreeWords() // NOLINT
|
||||
{
|
||||
item->setPropertyName(QLatin1String("ThreeWordProperty"));
|
||||
QCOMPARE(item->propertyName(), QLatin1String("Three Word Property"));
|
||||
}
|
||||
|
||||
void test_digitBeforeUppercaseNotSplit() // NOLINT
|
||||
{
|
||||
item->setPropertyName(QLatin1String("View3D"));
|
||||
QCOMPARE(item->propertyName(), QLatin1String("View3D"));
|
||||
}
|
||||
|
||||
void test_camelCaseSplitButNotDigit() // NOLINT
|
||||
{
|
||||
item->setPropertyName(QLatin1String("MyView3D"));
|
||||
QCOMPARE(item->propertyName(), QLatin1String("My View3D"));
|
||||
}
|
||||
|
||||
void test_consecutiveUppercaseNotSplit() // NOLINT
|
||||
{
|
||||
item->setPropertyName(QLatin1String("MyABC"));
|
||||
QCOMPARE(item->propertyName(), QLatin1String("My ABC"));
|
||||
}
|
||||
|
||||
void test_notCleverEnoughToSplitConsecutiveCaps() // NOLINT
|
||||
{
|
||||
item->setPropertyName(QLatin1String("MyABCOfDoom"));
|
||||
QCOMPARE(item->propertyName(), QLatin1String("My ABCOf Doom"));
|
||||
}
|
||||
|
||||
void test_underscoresArentTheSameAsSpaces() // NOLINT
|
||||
{
|
||||
item->setPropertyName(QLatin1String("Box_Length"));
|
||||
QCOMPARE(item->propertyName(), QLatin1String("Box_Length"));
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<Gui::PropertyEditor::PropertyItem> item;
|
||||
};
|
||||
|
||||
// NOLINTEND(readability-magic-numbers)
|
||||
|
||||
QTEST_MAIN(testPropertyItem)
|
||||
|
||||
#include "PropertyItem.moc"
|
||||
Reference in New Issue
Block a user