|
5 | 5 | import idom
|
6 | 6 | from idom import html
|
7 | 7 | from idom.config import IDOM_DEBUG_MODE
|
8 |
| -from idom.core.hooks import COMPONENT_DID_RENDER_EFFECT, LifeCycleHook, current_hook |
| 8 | +from idom.core.hooks import ( |
| 9 | + COMPONENT_DID_RENDER_EFFECT, |
| 10 | + LifeCycleHook, |
| 11 | + current_hook, |
| 12 | + strictly_equal, |
| 13 | +) |
9 | 14 | from idom.core.layout import Layout
|
10 | 15 | from idom.core.serve import render_json_patch
|
11 | 16 | from idom.testing import DisplayFixture, HookCatcher, assert_idom_did_log, poll
|
@@ -1272,3 +1277,102 @@ def SecondCondition():
|
1272 | 1277 | set_state.current(False)
|
1273 | 1278 | await layout.render()
|
1274 | 1279 | assert used_context_values == ["the-value-1", "the-value-2"]
|
| 1280 | + |
| 1281 | + |
| 1282 | +@pytest.mark.parametrize( |
| 1283 | + "x, y, result", |
| 1284 | + [ |
| 1285 | + ("text", "text", True), |
| 1286 | + ("text", "not-text", False), |
| 1287 | + (b"text", b"text", True), |
| 1288 | + (b"text", b"not-text", False), |
| 1289 | + (bytearray([1, 2, 3]), bytearray([1, 2, 3]), True), |
| 1290 | + (bytearray([1, 2, 3]), bytearray([1, 2, 3, 4]), False), |
| 1291 | + (1.0, 1.0, True), |
| 1292 | + (1.0, 2.0, False), |
| 1293 | + (1j, 1j, True), |
| 1294 | + (1j, 2j, False), |
| 1295 | + # ints less than 5 and greater than 256 are always identical |
| 1296 | + (-100000, -100000, True), |
| 1297 | + (100000, 100000, True), |
| 1298 | + (123, 456, False), |
| 1299 | + ], |
| 1300 | +) |
| 1301 | +def test_strictly_equal(x, y, result): |
| 1302 | + assert strictly_equal(x, y) is result |
| 1303 | + |
| 1304 | + |
| 1305 | +STRICT_EQUALITY_VALUE_CONSTRUCTORS = [ |
| 1306 | + lambda: "string-text", |
| 1307 | + lambda: b"byte-text", |
| 1308 | + lambda: bytearray([1, 2, 3]), |
| 1309 | + lambda: bytearray([1, 2, 3]), |
| 1310 | + lambda: 1.0, |
| 1311 | + lambda: 10000000, |
| 1312 | + lambda: 1j, |
| 1313 | +] |
| 1314 | + |
| 1315 | + |
| 1316 | +@pytest.mark.parametrize("get_value", STRICT_EQUALITY_VALUE_CONSTRUCTORS) |
| 1317 | +async def test_use_state_compares_with_strict_equality(get_value): |
| 1318 | + render_count = idom.Ref(0) |
| 1319 | + set_state = idom.Ref() |
| 1320 | + |
| 1321 | + @idom.component |
| 1322 | + def SomeComponent(): |
| 1323 | + _, set_state.current = idom.use_state(get_value()) |
| 1324 | + render_count.current += 1 |
| 1325 | + |
| 1326 | + async with idom.Layout(SomeComponent()) as layout: |
| 1327 | + await layout.render() |
| 1328 | + assert render_count.current == 1 |
| 1329 | + set_state.current(get_value()) |
| 1330 | + with pytest.raises(asyncio.TimeoutError): |
| 1331 | + await asyncio.wait_for(layout.render(), timeout=0.1) |
| 1332 | + |
| 1333 | + |
| 1334 | +@pytest.mark.parametrize("get_value", STRICT_EQUALITY_VALUE_CONSTRUCTORS) |
| 1335 | +async def test_use_effect_compares_with_strict_equality(get_value): |
| 1336 | + effect_count = idom.Ref(0) |
| 1337 | + value = idom.Ref("string") |
| 1338 | + hook = HookCatcher() |
| 1339 | + |
| 1340 | + @idom.component |
| 1341 | + @hook.capture |
| 1342 | + def SomeComponent(): |
| 1343 | + @idom.use_effect(dependencies=[value.current]) |
| 1344 | + def incr_effect_count(): |
| 1345 | + effect_count.current += 1 |
| 1346 | + |
| 1347 | + async with idom.Layout(SomeComponent()) as layout: |
| 1348 | + await layout.render() |
| 1349 | + assert effect_count.current == 1 |
| 1350 | + value.current = "string" # new string instance but same value |
| 1351 | + hook.latest.schedule_render() |
| 1352 | + await layout.render() |
| 1353 | + # effect does not trigger |
| 1354 | + assert effect_count.current == 1 |
| 1355 | + |
| 1356 | + |
| 1357 | +@pytest.mark.parametrize("get_value", STRICT_EQUALITY_VALUE_CONSTRUCTORS) |
| 1358 | +async def test_use_context_compares_with_strict_equality(get_value): |
| 1359 | + hook = HookCatcher() |
| 1360 | + context = idom.create_context(None) |
| 1361 | + inner_render_count = idom.Ref(0) |
| 1362 | + |
| 1363 | + @idom.component |
| 1364 | + @hook.capture |
| 1365 | + def OuterComponent(): |
| 1366 | + return context(InnerComponent(), value=get_value()) |
| 1367 | + |
| 1368 | + @idom.component |
| 1369 | + def InnerComponent(): |
| 1370 | + idom.use_context(context) |
| 1371 | + inner_render_count.current += 1 |
| 1372 | + |
| 1373 | + async with idom.Layout(OuterComponent()) as layout: |
| 1374 | + await layout.render() |
| 1375 | + assert inner_render_count.current == 1 |
| 1376 | + hook.latest.schedule_render() |
| 1377 | + await layout.render() |
| 1378 | + assert inner_render_count.current == 1 |
0 commit comments