using Esprima.Ast; using Jint.Runtime.Debugger; namespace Jint.Tests.Runtime.Debugger { public class StepFlowTests { private List CollectStepNodes(string script) { var engine = new Engine(options => options .DebugMode() .InitialStepMode(StepMode.Into)); var nodes = new List(); engine.DebugHandler.Step += (sender, info) => { nodes.Add(info.CurrentNode); return StepMode.Into; }; engine.Execute(script); return nodes; } [Fact] public void StepsThroughWhileLoop() { string script = @" let x = 0; while (x < 2) { x++; } "; var nodes = CollectStepNodes(script); Assert.Collection(nodes, node => Assert.IsType(node), // let x = 0; node => Assert.IsType(node), // while ... node => Assert.IsType(node), // x < 2 node => Assert.IsType(node), // x++; node => Assert.IsType(node), // x < 2 node => Assert.IsType(node), // x++; node => Assert.IsType(node) // x < 2 (false) ); } [Fact] public void StepsThroughDoWhileLoop() { string script = @" let x = 0; do { x++; } while (x < 2) "; var nodes = CollectStepNodes(script); Assert.Collection(nodes, node => Assert.IsType(node), // let x = 0; node => Assert.IsType(node), // do ... node => Assert.IsType(node), // x++; node => Assert.IsType(node), // x < 2 node => Assert.IsType(node), // x++; node => Assert.IsType(node) // x < 2 (false) ); } [Fact] public void StepsThroughForLoop() { string script = @" for (let x = 0; x < 2; x++) { 'dummy'; } "; var nodes = CollectStepNodes(script); Assert.Collection(nodes, node => Assert.IsType(node), // for ... node => Assert.IsType(node), // let x = 0 node => Assert.IsType(node), // x < 2 node => Assert.IsType(node), // 'dummy'; node => Assert.IsType(node), // x++; node => Assert.IsType(node), // x < 2 node => Assert.IsType(node), // 'dummy'; node => Assert.IsType(node), // x++; node => Assert.IsType(node) // x < 2 (false) ); } [Fact] public void StepsThroughForOfLoop() { string script = @" const arr = [1, 2]; for (const item of arr) { 'dummy'; } "; var nodes = CollectStepNodes(script); Assert.Collection(nodes, node => Assert.IsType(node), // let arr = [1, 2]; node => Assert.IsType(node), // for ... node => Assert.IsType(node), // item node => Assert.IsType(node), // 'dummy'; node => Assert.IsType(node), // item node => Assert.IsType(node) // 'dummy'; ); } [Fact] public void StepsThroughForInLoop() { string script = @" const obj = { x: 1, y: 2 }; for (const key in obj) { 'dummy'; } "; var nodes = CollectStepNodes(script); Assert.Collection(nodes, node => Assert.IsType(node), // let obj = { x: 1, y: 2 }; node => Assert.IsType(node), // for ... node => Assert.IsType(node), // key node => Assert.IsType(node), // 'dummy'; node => Assert.IsType(node), // key node => Assert.IsType(node) // 'dummy'; ); } [Fact] public void SkipsFunctionBody() { string script = @" function test() { 'dummy'; } test(); "; var nodes = CollectStepNodes(script); Assert.Collection(nodes, node => Assert.IsType(node), // function(test) ...; node => Assert.IsType(node), // test(); node => Assert.IsType(node), // 'dummy'; node => Assert.Null(node) // return point ); } } }