@@ -1825,10 +1825,10 @@ describe("Logo safePluginExecute", () => {
18251825 logo = new Logo ( mockActivity ) ;
18261826 } ) ;
18271827
1828- test ( "calls function code with correct arguments and returns result" , ( ) => {
1829- const pluginFn = jest . fn ( ( ) => 42 ) ;
1830- const result = logo . safePluginExecute ( pluginFn , logo , 0 , 0 , null ) ;
1831- expect ( pluginFn ) . toHaveBeenCalledWith ( logo , 0 , 0 , null ) ;
1828+ afterEach ( ( ) => jest . restoreAllMocks ( ) ) ;
1829+
1830+ test ( "executes function code and returns its result" , ( ) => {
1831+ const result = logo . safePluginExecute ( ( ) => 42 , logo , 0 , 0 , null ) ;
18321832 expect ( result ) . toBe ( 42 ) ;
18331833 } ) ;
18341834
@@ -1840,7 +1840,6 @@ describe("Logo safePluginExecute", () => {
18401840 const result = logo . safePluginExecute ( crashFn , logo , 0 , 0 , null ) ;
18411841 expect ( errorSpy ) . toHaveBeenCalled ( ) ;
18421842 expect ( result ) . toBeUndefined ( ) ;
1843- errorSpy . mockRestore ( ) ;
18441843 } ) ;
18451844
18461845 test ( "returns undefined for non-string non-function code" , ( ) => {
@@ -1910,7 +1909,6 @@ describe("Logo safePluginExecute", () => {
19101909 const result = logo . safePluginExecute ( "eval('alert(1)')" , logo , 0 , 0 , null ) ;
19111910 expect ( warnSpy ) . toHaveBeenCalledWith ( expect . stringContaining ( "Blocked" ) , expect . anything ( ) ) ;
19121911 expect ( result ) . toBeUndefined ( ) ;
1913- warnSpy . mockRestore ( ) ;
19141912 } ) ;
19151913} ) ;
19161914
@@ -1931,6 +1929,8 @@ describe("Logo parseArg additional edge cases", () => {
19311929 logo . inStatusMatrix = false ;
19321930 } ) ;
19331931
1932+ afterEach ( ( ) => jest . restoreAllMocks ( ) ) ;
1933+
19341934 test ( "dectofrac with null child block shows NOINPUTERRORMSG and sets value to 0" , ( ) => {
19351935 logo . blockList = [
19361936 { name : "print" , connections : [ null , 1 ] } ,
@@ -2017,9 +2017,12 @@ describe("Logo parseArg additional edge cases", () => {
20172017 expect ( logo . returns [ 0 ] . length ) . toBe ( 0 ) ;
20182018 } ) ;
20192019
2020- test ( "unknown anyout block in evalArgDict invokes safePluginExecute" , ( ) => {
2021- logo . evalArgDict = { customplugin : jest . fn ( ) } ;
2022- logo . safePluginExecute = jest . fn ( ) ;
2020+ test ( "evalArgDict plugin result is reflected in parseArg return value" , ( ) => {
2021+ logo . evalArgDict = {
2022+ customplugin : ( l , _turtle , blk ) => {
2023+ l . blockList [ blk ] . value = 555 ;
2024+ }
2025+ } ;
20232026 logo . blockList = [
20242027 {
20252028 name : "customplugin" ,
@@ -2029,16 +2032,8 @@ describe("Logo parseArg additional edge cases", () => {
20292032 isValueBlock : ( ) => false
20302033 }
20312034 ] ;
2032- logo . parseArg ( logo , 0 , 0 , null , null ) ;
2033- expect ( logo . safePluginExecute ) . toHaveBeenCalledWith (
2034- logo . evalArgDict . customplugin ,
2035- logo ,
2036- 0 ,
2037- 0 ,
2038- null ,
2039- null ,
2040- tur
2041- ) ;
2035+ const result = logo . parseArg ( logo , 0 , 0 , null , null ) ;
2036+ expect ( result ) . toBe ( 555 ) ;
20422037 } ) ;
20432038
20442039 test ( "unknown anyout block not in evalArgDict logs console error" , ( ) => {
@@ -2055,7 +2050,6 @@ describe("Logo parseArg additional edge cases", () => {
20552050 ] ;
20562051 logo . parseArg ( logo , 0 , 0 , null , null ) ;
20572052 expect ( errorSpy ) . toHaveBeenCalled ( ) ;
2058- errorSpy . mockRestore ( ) ;
20592053 } ) ;
20602054} ) ;
20612055
@@ -2207,6 +2201,8 @@ describe("Logo doStopTurtles timer cleanup", () => {
22072201 logo . _restoreConnections = jest . fn ( ) ;
22082202 } ) ;
22092203
2204+ afterEach ( ( ) => jest . restoreAllMocks ( ) ) ;
2205+
22102206 test ( "clears delayTimeout for turtles that have a pending timer" , ( ) => {
22112207 const clearTimeoutSpy = jest . spyOn ( global , "clearTimeout" ) . mockImplementation ( ( ) => { } ) ;
22122208 tur . delayTimeout = 456 ;
@@ -2215,7 +2211,6 @@ describe("Logo doStopTurtles timer cleanup", () => {
22152211
22162212 expect ( clearTimeoutSpy ) . toHaveBeenCalledWith ( 456 ) ;
22172213 expect ( tur . delayTimeout ) . toBeNull ( ) ;
2218- clearTimeoutSpy . mockRestore ( ) ;
22192214 } ) ;
22202215
22212216 test ( "timerManager.clearAll is invoked during stop" , ( ) => {
@@ -2224,7 +2219,6 @@ describe("Logo doStopTurtles timer cleanup", () => {
22242219 logo . doStopTurtles ( ) ;
22252220
22262221 expect ( clearAllSpy ) . toHaveBeenCalled ( ) ;
2227- clearAllSpy . mockRestore ( ) ;
22282222 } ) ;
22292223
22302224 test ( "logs debug message when timerManager cancels pending timers" , ( ) => {
@@ -2234,7 +2228,6 @@ describe("Logo doStopTurtles timer cleanup", () => {
22342228 logo . doStopTurtles ( ) ;
22352229
22362230 expect ( debugSpy ) . toHaveBeenCalledWith ( expect . stringContaining ( "cancelled" ) ) ;
2237- debugSpy . mockRestore ( ) ;
22382231 } ) ;
22392232} ) ;
22402233
@@ -2265,13 +2258,16 @@ describe("Logo runLogoCommands additional coverage", () => {
22652258 } ) ;
22662259
22672260 test ( "executes each evalOnStartList plugin at run startup" , ( ) => {
2268- logo . evalOnStartList = { hook1 : jest . fn ( ) , hook2 : jest . fn ( ) } ;
2269- logo . safePluginExecute = jest . fn ( ) ;
2261+ const effects = [ ] ;
2262+ logo . evalOnStartList = {
2263+ hook1 : ( ) => effects . push ( "hook1" ) ,
2264+ hook2 : ( ) => effects . push ( "hook2" )
2265+ } ;
22702266
22712267 logo . runLogoCommands ( null , null ) ;
22722268
2273- expect ( logo . safePluginExecute ) . toHaveBeenCalledWith ( logo . evalOnStartList . hook1 , logo ) ;
2274- expect ( logo . safePluginExecute ) . toHaveBeenCalledWith ( logo . evalOnStartList . hook2 , logo ) ;
2269+ expect ( effects ) . toContain ( " hook1" ) ;
2270+ expect ( effects ) . toContain ( " hook2" ) ;
22752271 } ) ;
22762272
22772273 test ( "removes existing turtle listeners from stage before running" , ( ) => {
@@ -2332,9 +2328,9 @@ describe("Logo runFromBlockNow additional coverage", () => {
23322328 expect ( logo . stopTurtle ) . toBe ( true ) ;
23332329 } ) ;
23342330
2335- test ( "evalFlowDict plugin is called for matching flow block " , ( ) => {
2336- const pluginFn = jest . fn ( ) ;
2337- logo . evalFlowDict = { widgetblock : pluginFn } ;
2331+ test ( "evalFlowDict plugin executes when block name matches " , ( ) => {
2332+ const effects = [ ] ;
2333+ logo . evalFlowDict = { widgetblock : ( ) => effects . push ( "ran" ) } ;
23382334 logo . pluginReturnValue = null ;
23392335 logo . blockList = [
23402336 {
@@ -2348,7 +2344,7 @@ describe("Logo runFromBlockNow additional coverage", () => {
23482344
23492345 logo . runFromBlockNow ( logo , 0 , 0 , 0 , null ) ;
23502346
2351- expect ( pluginFn ) . toHaveBeenCalled ( ) ;
2347+ expect ( effects ) . toContain ( "ran" ) ;
23522348 } ) ;
23532349
23542350 test ( "arg block with null value displays 'null block value' message" , ( ) => {
@@ -2370,17 +2366,6 @@ describe("Logo runFromBlockNow additional coverage", () => {
23702366 } ) ;
23712367} ) ;
23722368
2373- // ─── processSpeak smoke test ──────────────────────────────────────────────────
2374-
2375- describe ( "Logo processSpeak" , ( ) => {
2376- test ( "does not throw for any text input" , ( ) => {
2377- const logo = new Logo ( _buildCovActivity ( ) ) ;
2378- expect ( ( ) => logo . processSpeak ( "hello world" ) ) . not . toThrow ( ) ;
2379- expect ( ( ) => logo . processSpeak ( "" ) ) . not . toThrow ( ) ;
2380- expect ( ( ) => logo . processSpeak ( null ) ) . not . toThrow ( ) ;
2381- } ) ;
2382- } ) ;
2383-
23842369// ─── constructor compatibility edge cases ─────────────────────────────────────
23852370
23862371describe ( "Logo constructor compatibility" , ( ) => {
0 commit comments