Coverage for tdom/scope_test.py: 100%

51 statements  

« prev     ^ index     » next       coverage.py v7.14.3, created at 2026-06-23 04:35 +0000

1"""Tests for `tdom.context` -- Provider components and `create_context`. 

2 

3Each test runs in a fresh `contextvars.Context` (via the `@isolated` 

4decorator) so `.set()` calls in one test cannot leak into another. 

5""" 

6 

7import functools 

8from contextvars import ContextVar, copy_context 

9from dataclasses import dataclass 

10from string.templatelib import Template 

11 

12from . import html 

13from .scope import Scope, ScopedTemplate 

14 

15 

16def isolated(fn): 

17 """Run the test in a fresh contextvars.Context.""" 

18 

19 @functools.wraps(fn) 

20 def wrapper(*args, **kwargs): 

21 return copy_context().run(fn, *args, **kwargs) 

22 

23 return wrapper 

24 

25 

26theme: ContextVar[str] = ContextVar("theme", default="auto") 

27 

28 

29@isolated 

30def test_scope_activate(): 

31 scope = Scope(theme, "dark") 

32 assert theme.get() == "auto" 

33 with scope.activate(): 

34 assert theme.get() == "dark" 

35 

36 

37@isolated 

38def test_scoped_template_from_component_is_activated(): 

39 def SubComponent() -> Template: 

40 return t'<h1 data-sub-theme="{theme.get()}">test</h1>' 

41 

42 def Component() -> ScopedTemplate: 

43 return ScopedTemplate( 

44 Scope(theme, "dank"), 

45 t'<div data-theme="{theme.get()}"><{SubComponent} /></div>', 

46 ) 

47 

48 result = html(t"<{Component} />") 

49 assert 'data-theme="auto"' in result 

50 assert 'data-sub-theme="dank"' in result 

51 

52 

53@isolated 

54def test_provider_style_component(): 

55 def ThemeProvider(children: Template, value: str) -> ScopedTemplate: 

56 return ScopedTemplate(Scope(theme, value), children) 

57 

58 def SubComponent() -> Template: 

59 return t'<h1 data-sub-theme="{theme.get()}">test</h1>' 

60 

61 def Component() -> Template: 

62 return t''' 

63 <div data-theme="{theme.get()}"> 

64 <{ThemeProvider} value="musty"> 

65 <{SubComponent} /> 

66 </{ThemeProvider}> 

67 </div> 

68 ''' 

69 

70 result = html(t"<{Component} />") 

71 assert 'data-theme="auto"' in result 

72 assert 'data-sub-theme="musty"' in result 

73 

74 

75@isolated 

76def test_scoped_template_from_factory_component_is_activated(): 

77 @dataclass 

78 class SubComponent: 

79 def __call__(self) -> Template: 

80 return t'<h1 data-sub-theme="{theme.get()}">test</h1>' 

81 

82 @dataclass 

83 class Component: 

84 def __call__(self) -> ScopedTemplate: 

85 return ScopedTemplate( 

86 Scope(theme, "stuffy"), 

87 t'<div data-theme="{theme.get()}"><{SubComponent} /></div>', 

88 ) 

89 

90 result = html(t"<{Component} />") 

91 assert 'data-theme="auto"' in result 

92 assert 'data-sub-theme="stuffy"' in result