UNPKG

siesta-lite

Version:

Stress-free JavaScript unit testing and functional testing tool, works in NodeJS and browsers

382 lines (262 loc) 12.4 kB
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>The source code</title> <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" /> <script type="text/javascript" src="../resources/prettify/prettify.js"></script> <style type="text/css"> .highlight { display: block; background-color: #ddd; } </style> <script type="text/javascript"> function highlight() { document.getElementById(location.hash.replace(/#/, "")).className = "highlight"; } </script> </head> <body onload="prettyPrint(); highlight();"> <pre class="prettyprint lang-js">/* Siesta 5.6.1 Copyright(c) 2009-2022 Bryntum AB https://bryntum.com/contact https://bryntum.com/products/siesta/license */ Class(&#39;Ariadne.QueryFinder.Maze&#39;, { does : [ Siesta.Util.Role.CanGetType ], has : { finder : { required : true }, nodes : Joose.I.Array, segmentsIdGen : 1, encounteredMandatoryId : false }, methods : { getRoot : function () { return this.nodes[ this.nodes.length - 1 ] }, doQuery : function (query, rootNode) { var queryCache = rootNode.queryCache // TUNE // if (queryCache[ query ]) console.log(&quot;CACHE HIT!&quot;) if (queryCache[ query ]) return queryCache[ query ] // // TUNE // QUERYCOUNTER = window.QUERYCOUNTER || 0 // QUERYCOUNTER++ // console.log(&quot;QUERY from:&quot;, rootNode.index, &quot; query: &quot;, query) return queryCache[ query ] = this.finder.doQuery(query, rootNode.el) }, buildVertices : function (target, root) { // console.time(&#39;buildVertices&#39;) var nodes = this.nodes = [] var currentEl = target var prevNode var finder = this.finder var identifiers = finder.identifiers var directChildIdentifier = finder.directChildIdentifier while (currentEl) { var node = new Ariadne.QueryFinder.Node({ finder : finder, maze : this, el : currentEl, index : nodes.length }) if (prevNode) { prevNode.upNode = node node.downNode = prevNode if (directChildIdentifier) { var segment = directChildIdentifier.identify(prevNode.el, root, this) if (segment) { segment = this.normalizeIdentifierResult(segment)[ 0 ] var directChildUpEdge = new Ariadne.QueryFinder.Edge({ finder : finder, maze : this, isDirectChild : true, fromNode : prevNode, toNode : node }) prevNode.directChildUpEdge = directChildUpEdge prevNode.adoptSegment(segment) directChildUpEdge.consumeVariant([ segment ], finder.combineSegments([ segment ], true)) } } } prevNode = node nodes.push(node) // exit a bit earlier for root node - segments won&#39;t be set for it if (currentEl == root) break var segments = [] for (var j = 0; j &lt; identifiers.length; j++) { var compSegments = identifiers[ j ].identify(currentEl, root, this) if (compSegments) { segments.push.apply(segments, this.normalizeIdentifierResult(compSegments)) } } node.setSegments(segments) currentEl = finder.getParent(currentEl) } nodes[ 0 ].weightOptions = [ { weight : 0, minFromEdgesById : {} } ] nodes[ 0 ].weightOptionsByWeight[ 0 ] = nodes[ 0 ].weightOptions[ 0 ] // console.timeEnd(&#39;buildVertices&#39;) }, normalizeIdentifierResult : function (segments) { var me = this if (this.typeOf(segments) != &#39;Array&#39;) segments = [ segments ] return segments.map(function (segment) { if (me.typeOf(segment) == &#39;String&#39;) return { query : segment, weight : 1000 } else { if (!segment.hasOwnProperty(&#39;weight&#39;)) segment.weight = 1000 return segment } }) }, computePath : function (prevUpdatedNodes) { var nodes = this.nodes var root = this.getRoot() var iteration = 0 if (!prevUpdatedNodes) { prevUpdatedNodes = {} prevUpdatedNodes[ nodes[ 0 ].id ] = nodes[ 0 ] } do { iteration++ var updatedNodes = {} var somethingUpdated = false for (var id in prevUpdatedNodes) { var fromNode = prevUpdatedNodes[ id ] if (fromNode.weightOptions.length === 0) continue for (var toIndex in fromNode.edgesToByIndex) { var edge = fromNode.edgesToByIndex[ toIndex ] var toNode = edge.toNode if (edge.relax()) { updatedNodes[ toNode.id ] = toNode somethingUpdated = true } } var directChildUpEdge = fromNode.directChildUpEdge if (directChildUpEdge &amp;&amp; directChildUpEdge.relax()) { var toNode = directChildUpEdge.toNode updatedNodes[ toNode.id ] = toNode somethingUpdated = true } } prevUpdatedNodes = updatedNodes } while (somethingUpdated &amp;&amp; iteration &lt; nodes.length) }, buildEdges : function () { // console.time(&#39;buildEdges&#39;) var recognizers = this.finder.recognizers for (var j = 0; j &lt; recognizers.length; j++) { recognizers[ j ].recognize(this) } var nodes = this.nodes for (var i = 0; i &lt; nodes.length - 1; i++) { // early exit, as soon as we found identifying edge // by definition, we aren&#39;t interested in edges above it if (nodes[ i ].buildEdges3(1) === false) break nodes[ i ].buildEdges3(2) nodes[ i ].buildEdges3(3) } // console.timeEnd(&#39;buildEdges&#39;) }, expandSimplePaths : function (paths) { var nodes = this.nodes var pathsHashes = {} var pathVariants = [] for (var i = 0; i &lt; paths.length; i++) { var path = paths[ i ].split(&#39;_&#39;) var variants = [] var prevIndex for (var j = path.length - 1; j &gt; 1; j--) { var isDirectChildEdge = path[ j ][ 0 ] == &#39;+&#39; var onlyWithOwnIndex = j &lt; path.length - 1 &amp;&amp; path[ j + 1 ][ 0 ] == &#39;+&#39; var fromNode = nodes[ Number(path[ j ]) ] var edge = isDirectChildEdge ? fromNode.directChildUpEdge : fromNode.edgesToByIndex[ Number(path[ j - 1 ]) ] variants = fromNode.extendPathVariants(variants, edge.segmentVariants, onlyWithOwnIndex ? fromNode.index : null) } for (var k = 0; k &lt; variants.length; k++) { var pathVariant = variants[ k ] if (!pathsHashes[ pathVariant.hash ]) { pathVariants.push(pathVariant) pathsHashes[ pathVariant.hash ] = true } } } pathVariants.sort(function (a, b) { return a.weight - b.weight }) return pathVariants }, findAllPaths : function (options) { // console.time(&#39;computePath&#39;) this.computePath() // console.timeEnd(&#39;computePath&#39;) var me = this var root = this.getRoot() // console.time(&#39;collectAllPaths&#39;) var simplePathsCollection = root.collectFullSimplePathCollection() // console.timeEnd(&#39;collectAllPaths&#39;) // console.log(&quot;Simple paths: &quot;, simplePathsCollection) for (var i = 0; i &lt; simplePathsCollection.length; i++) { var simplePaths = simplePathsCollection[ i ].simplePaths var queryInfos = this.verifySimplePathGroup(simplePaths, options) if (queryInfos.length) { if (options &amp;&amp; options.detailed) { return queryInfos } else return queryInfos.map(function (queryInfo) { return queryInfo.query }) } } return [] }, verifySimplePathGroup : function (simplePaths, options) { var root = this.getRoot() var finder = this.finder // console.time(&#39;expandAllPaths&#39;) var pathVariants = this.expandSimplePaths(simplePaths) // console.timeEnd(&#39;expandAllPaths&#39;) // console.time(&#39;verifyAllPaths&#39;) var queryInfos = [] var targetEl = this.nodes[ 0 ].el var rootEl = root.el for (var i = 0; i &lt; pathVariants.length; i++) { var variant = pathVariants[ i ] var segments = [] for (var id in variant.segmentsById) segments.push(variant.segmentsById[ id ]) // query can potentially not be constructed because of clash between leading segments var queryInfo = finder.combineSegments(segments) if (queryInfo) { if (finder.verifyQuery(queryInfo.query, targetEl, rootEl)) { queryInfos.push(queryInfo) if (options &amp;&amp; options.singleOnly) return queryInfos } else { // console.log(&quot;WRONG QUERY: &quot; + queryInfo.query) } } } // console.timeEnd(&#39;verifyAllPaths&#39;) return queryInfos }, // DEBUG METHOD countEdges : function (log) { var counter = 0 this.nodes.forEach(function (node) { for (var index in node.edgesToByIndex) { var edge = node.edgesToByIndex[ index ] counter += edge.segmentVariants.length if (log) { edge.segmentVariants.forEach(function (variant) { console.log(&quot;Edge from: &quot; + edge.fromNode.index + &quot;[&quot; + edge.fromNode.el.tagName + &quot;] to &quot; + edge.toNode.index + &quot;[&quot; + edge.toNode.el.tagName + &quot;] query: &quot; + edge.finder.combineSegments(variant.variant).query) }) } } }) return counter } } }); </pre> </body> </html>