* 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>
160 lines
7.3 KiB
Python
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)
|