33import aiounittest
44from unittest .mock import MagicMock
55
6- from botbuilder .core import TurnContext , BotState , MemoryStorage , UserState
6+ from botbuilder .core import BotState , ConversationState , MemoryStorage , Storage , StoreItem , TurnContext , UserState
77from botbuilder .core .adapters import TestAdapter
8- from botbuilder .schema import Activity
8+ from botbuilder .schema import Activity , ConversationAccount
99
1010from test_utilities import TestUtilities
1111
@@ -23,6 +23,23 @@ def key_factory(context):
2323 assert context is not None
2424 return STORAGE_KEY
2525
26+ class BotStateForTest (BotState ):
27+ def __init__ (self , storage : Storage ):
28+ super ().__init__ (storage , f"BotState:BotState" )
29+
30+ def get_storage_key (self , turn_context : TurnContext ) -> str :
31+ return f"botstate/{ turn_context .activity .channel_id } /{ turn_context .activity .conversation .id } /BotState"
32+
33+
34+ class CustomState (StoreItem ):
35+ def __init__ (self , custom_string : str = None , e_tag : str = '*' ):
36+ super ().__init__ (custom_string = custom_string , e_tag = e_tag )
37+
38+
39+ class TestPocoState :
40+ def __init__ (self , value = None ):
41+ self .value = value
42+
2643
2744class TestBotState (aiounittest .AsyncTestCase ):
2845 storage = MemoryStorage ()
@@ -334,4 +351,134 @@ async def test_LoadSaveDelete(self):
334351 obj2 = dictionary ["EmptyContext/users/empty@empty.context.org" ]
335352 self .assertEqual ("hello-2" , obj2 ["property-a" ])
336353 with self .assertRaises (KeyError ) as _ :
337- obj2 ["property-b" ]
354+ obj2 ["property-b" ]
355+
356+ async def test_state_use_bot_state_directly (self ):
357+ async def exec_test (context : TurnContext ):
358+ bot_state_manager = BotStateForTest (MemoryStorage ())
359+ test_property = bot_state_manager .create_property ("test" )
360+
361+ # read initial state object
362+ await bot_state_manager .load (context )
363+
364+ custom_state = await test_property .get (context , lambda : CustomState ())
365+
366+ # this should be a 'CustomState' as nothing is currently stored in storage
367+ assert isinstance (custom_state , CustomState )
368+
369+ # amend property and write to storage
370+ custom_state .custom_string = "test"
371+ await bot_state_manager .save_changes (context )
372+
373+ custom_state .custom_string = "asdfsadf"
374+
375+ # read into context again
376+ await bot_state_manager .load (context , True )
377+
378+ custom_state = await test_property .get (context )
379+
380+ # check object read from value has the correct value for custom_string
381+ assert custom_state .custom_string == "test"
382+
383+ adapter = TestAdapter (exec_test )
384+ await adapter .send ('start' )
385+
386+ async def test_user_state_bad_from_throws (self ):
387+ dictionary = {}
388+ user_state = UserState (MemoryStorage (dictionary ))
389+ context = TestUtilities .create_empty_context ()
390+ context .activity .from_property = None
391+ test_property = user_state .create_property ("test" )
392+ with self .assertRaises (AttributeError ):
393+ await test_property .get (context )
394+
395+ async def test_conversation_state_bad_converation_throws (self ):
396+ dictionary = {}
397+ user_state = ConversationState (MemoryStorage (dictionary ))
398+ context = TestUtilities .create_empty_context ()
399+ context .activity .conversation = None
400+ test_property = user_state .create_property ("test" )
401+ with self .assertRaises (AttributeError ):
402+ await test_property .get (context )
403+
404+ async def test_clear_and_save (self ):
405+ turn_context = TestUtilities .create_empty_context ()
406+ turn_context .activity .conversation = ConversationAccount (id = "1234" )
407+
408+ storage = MemoryStorage ({})
409+
410+ # Turn 0
411+ bot_state1 = ConversationState (storage )
412+ (await bot_state1
413+ .create_property ("test-name" )
414+ .get (turn_context , lambda : TestPocoState ())).value = "test-value"
415+ await bot_state1 .save_changes (turn_context )
416+
417+ # Turn 1
418+ bot_state2 = ConversationState (storage )
419+ value1 = (await bot_state2
420+ .create_property ("test-name" )
421+ .get (turn_context , lambda : TestPocoState (value = "default-value" ))).value
422+
423+ assert "test-value" == value1
424+
425+ # Turn 2
426+ bot_state3 = ConversationState (storage )
427+ await bot_state3 .clear_state (turn_context )
428+ await bot_state3 .save_changes (turn_context )
429+
430+ # Turn 3
431+ bot_state4 = ConversationState (storage )
432+ value2 = (await bot_state4
433+ .create_property ("test-name" )
434+ .get (turn_context , lambda : TestPocoState (value = "default-value" ))).value
435+
436+ assert "default-value" , value2
437+
438+ async def test_bot_state_delete (self ):
439+ turn_context = TestUtilities .create_empty_context ()
440+ turn_context .activity .conversation = ConversationAccount (id = "1234" )
441+
442+ storage = MemoryStorage ({})
443+
444+ # Turn 0
445+ bot_state1 = ConversationState (storage )
446+ (await bot_state1
447+ .create_property ("test-name" )
448+ .get (turn_context , lambda : TestPocoState ())).value = "test-value"
449+ await bot_state1 .save_changes (turn_context )
450+
451+ # Turn 1
452+ bot_state2 = ConversationState (storage )
453+ value1 = (await bot_state2
454+ .create_property ("test-name" )
455+ .get (turn_context , lambda : TestPocoState (value = "default-value" ))).value
456+
457+ assert "test-value" == value1
458+
459+ # Turn 2
460+ bot_state3 = ConversationState (storage )
461+ await bot_state3 .delete (turn_context )
462+
463+ # Turn 3
464+ bot_state4 = ConversationState (storage )
465+ value2 = (await bot_state4
466+ .create_property ("test-name" )
467+ .get (turn_context , lambda : TestPocoState (value = "default-value" ))).value
468+
469+ assert "default-value" == value2
470+
471+ async def test_bot_state_get (self ):
472+ turn_context = TestUtilities .create_empty_context ()
473+ turn_context .activity .conversation = ConversationAccount (id = "1234" )
474+
475+ storage = MemoryStorage ({})
476+
477+ conversation_state = ConversationState (storage )
478+ (await conversation_state
479+ .create_property ("test-name" )
480+ .get (turn_context , lambda : TestPocoState ())).value = "test-value"
481+
482+ result = conversation_state .get (turn_context )
483+
484+ assert "test-value" == result ["test-name" ].value
0 commit comments