Files
create/src/Mod/BIM/bimtests/TestArchSiteGui.py
Furgo b23d580941 Add BIM workbench to .pre-commit-config.yaml (#21591)
* Add BIM workbench to .pre-commit-config.yaml

* pre-commit: ignore translations

* pre-commit: add additional ignore pattern

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2025-10-13 13:07:48 +02:00

160 lines
7.3 KiB
Python

# SPDX-License-Identifier: LGPL-2.1-or-later
#
# ***************************************************************************
# * *
# * Copyright (c) 2025 Furgo *
# * *
# * This file is part of FreeCAD. *
# * *
# * FreeCAD is free software: you can redistribute it and/or modify it *
# * under the terms of the GNU Lesser General Public License as *
# * published by the Free Software Foundation, either version 2.1 of the *
# * License, or (at your option) any later version. *
# * *
# * FreeCAD is distributed in the hope that it will be useful, but *
# * WITHOUT ANY WARRANTY; without even the implied warranty of *
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
# * Lesser General Public License for more details. *
# * *
# * You should have received a copy of the GNU Lesser General Public *
# * License along with FreeCAD. If not, see *
# * <https://www.gnu.org/licenses/>. *
# * *
# ***************************************************************************
import os
import tempfile
import unittest
import FreeCAD
import Arch
from bimtests import TestArchBaseGui
class TestArchSiteGui(TestArchBaseGui.TestArchBaseGui):
def test_new_site_creation(self):
"""Test: creating a new Site adds the view properties and sets defaults."""
site = Arch.makeSite()
self.assertIsNotNone(site, "makeSite() returned None")
FreeCAD.ActiveDocument.recompute()
# Wait briefly so the document loader can attach the ViewObject and let the view provider's
# queued restore/migration callbacks (setProperties, migration, restoreConstraints) run on
# the GUI event loop before we inspect properties.
self.pump_gui_events()
# ViewObject properties should exist
vobj = site.ViewObject
props = vobj.PropertiesList
expected = [
"ShowSunPosition",
"SunDateMonth",
"SunDateDay",
"SunTimeHour",
"SolarDiagramScale",
"SolarDiagramPosition",
"ShowHourLabels",
]
for p in expected:
self.assertIn(p, props, f"Property '{p}' missing from ViewObject")
# Check defaults where applicable
if hasattr(vobj, "SunDateMonth"):
self.assertEqual(vobj.SunDateMonth, 6)
if hasattr(vobj, "SunDateDay"):
self.assertEqual(vobj.SunDateDay, 21)
if hasattr(vobj, "SunTimeHour"):
self.assertAlmostEqual(vobj.SunTimeHour, 12.0)
if hasattr(vobj, "SolarDiagramScale"):
self.assertAlmostEqual(vobj.SolarDiagramScale, 20000.0)
def test_new_site_save_and_reopen(self):
"""Test: save document and reopen; view properties must be present and constrained."""
self.printTestMessage("Save and reopen new Site...")
site = Arch.makeSite()
FreeCAD.ActiveDocument.recompute()
# Save to a temporary file
tf = tempfile.NamedTemporaryFile(delete=False, suffix=".FCStd")
tf.close()
path = tf.name
try:
FreeCAD.ActiveDocument.saveAs(path)
# Open the saved document (this returns a new Document instance)
reopened = FreeCAD.openDocument(path)
try:
# Find the Site object in the reopened document by checking proxy type
found = None
for o in reopened.Objects:
if hasattr(o, "Proxy") and getattr(o.Proxy, "Type", None) == "Site":
found = o
break
self.assertIsNotNone(found, "Site object not found after reopen")
# Ensure async GUI setup completes
self.pump_gui_events()
vobj = found.ViewObject
# 1. Verify that constraints have been reapplied by testing clamping behavior.
# Setting an out-of-bounds value should not raise an exception but
# should coerce the value to the nearest limit.
vobj.SunDateMonth = 13
self.assertEqual(
vobj.SunDateMonth, 12, "Property should be clamped to its max value"
)
vobj.SunDateMonth = 0
self.assertEqual(
vobj.SunDateMonth, 1, "Property should be clamped to its min value"
)
finally:
# Close reopened document to keep test isolation
FreeCAD.closeDocument(reopened.Name)
finally:
try:
os.unlink(path)
except Exception:
pass
def test_legacy_site_migration(self):
"""Legacy migration test (<=1.0.0 -> newer)
Verifies that loading a legacy (<=1.0.0) FreeCAD file triggers the view provider's restore
path and performs a conservative migration of legacy values.
When a Site previously saved with `SolarDiagramScale == 1.0` is loaded, the view provider's
`loads()` restore path will detect that this is a legacy value and replace it with the
modern default of 20 m radius (https://github.com/FreeCAD/FreeCAD/pull/22496). The migration
is conservative: only values less-or-equal to `1.0` (or effectively zero) are considered
legacy and will be changed.
The test waits briefly for the loader's deferred binding and normalization callbacks to run
before asserting the migrated value.
"""
self.printTestMessage("Save and reopen legacy Site...")
fixtures_dir = os.path.join(os.path.dirname(__file__), "fixtures")
fname = os.path.join(fixtures_dir, "FC_site_simple-102.FCStd")
if not os.path.exists(fname):
raise unittest.SkipTest("Legacy migration fixture not found; skipping test.")
# If fixture exists, open and validate migration
d = FreeCAD.openDocument(fname)
try:
# Wait briefly so the document loader can attach the ViewObject and let the view
# provider's queued restore/migration callbacks (setProperties, migration,
# restoreConstraints) run on the GUI event loop before we inspect properties.
self.pump_gui_events()
site = None
for o in d.Objects:
if hasattr(o, "Proxy") and getattr(o.Proxy, "Type", None) == "Site":
site = o
break
assert site is not None, "No Site found in fixture document"
vobj = site.ViewObject
# Example assertion: SolarDiagramScale should be normalized to 20000
self.assertAlmostEqual(getattr(vobj, "SolarDiagramScale", 1.0), 20000.0)
finally:
FreeCAD.closeDocument(d.Name)