UNPKG

siesta-lite

Version:

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

204 lines (136 loc) 5.92 kB
/* Siesta 5.6.1 Copyright(c) 2009-2022 Bryntum AB https://bryntum.com/contact https://bryntum.com/products/siesta/license */ Class('Ariadne.QueryFinder', { does : [ Ariadne.QueryFinder.TreeWalker ], has : { recognizers : Joose.I.Array, identifiers : Joose.I.Array, directChildIdentifier : null, // `true` to always include an #id segment of the 1st parent node with #id in the query // even if its not required // idea is that since some parent has #id, element "belongs" to that parent, and the query // will be more robust // note, that id's of the following parents won't be included enableMandatoryId : true }, methods : { initialize : function () { this.initRecognizers() this.initIdentifiers() this.recognizers.sort(function (r1, r2) { return r2.priority - r1.priority }) this.identifiers.sort(function (r1, r2) { return r2.priority - r1.priority }) }, addRecognizer : function (instance) { this.recognizers.push(instance) return instance }, addIdentifier : function (instance) { this.identifiers.push(instance) return instance }, initRecognizers : function () { }, initIdentifiers : function () { }, findQuery : function (target, root) { return this.findQueries(target, root, { singleOnly : true })[ 0 ] }, findQueries : function (target, root, options) { // TUNE // console.time('TOTAL') if (!target) throw new Error("No target") if (!root) throw new Error("No root") if (target == root) throw new Error("Can't find query - target and root are the same") if (this.contains(target, root)) throw new Error("Can't find query - root is contained within target, need to swap the arguments?") var maze = /*MAZE = */new Ariadne.QueryFinder.Maze({ finder : this }) maze.buildVertices(target, root) maze.buildEdges() var res = maze.findAllPaths(options) // TUNE // console.timeEnd('TOTAL') return res }, forAllCombinations : function (segments, func) { var combinator = new Ariadne.QueryFinder.Combinator({ elements : segments }) return combinator.forAllCombinations(func) }, bisect : function (leftIndex, rightIndex, func) { while (leftIndex <= rightIndex) { var middleIndex = Math.round((leftIndex + rightIndex) / 2) var res = func(middleIndex) if (res === false) return false if (leftIndex == rightIndex) return if (res == null) throw new Error("Unknown bisect direction") if (res < 0) rightIndex = middleIndex - 1 if (res > 0) leftIndex = middleIndex + 1 } }, combineSegments : function (segments, allowDanglingDirectChild) { var queryComponents = [] var totalWeight = 0 var ids = [] var processed = {} var hasId = false for (var i = 0; i < segments.length; i++ ) { var segment = segments[ i ] var segmentId = segment.id if (processed[ segmentId ]) continue processed[ segmentId ] = true ids.push(segmentId) var index = segment.index var queryComponent = queryComponents[ index ] if (!queryComponent) { queryComponent = queryComponents[ index ] = { segments : [], hasLeading : false, child : false } } totalWeight += segment.weight if (segment.leading) if (queryComponent.hasLeading) return null else { queryComponent.hasLeading = true queryComponent.segments.unshift(segment.query) } else queryComponent.segments.push(segment.query) if (segment.child) queryComponent.child = true if (segment.isId) hasId = true } var query = '' for (var i = queryComponents.length - 1; i >= 0; i--) { var queryComponent = queryComponents[ i ] if (queryComponent) { if (!allowDanglingDirectChild && queryComponent.child && (i == queryComponents.length - 1 || !queryComponents[ i + 1 ])) throw new Error("Invalid direct child component") var component = queryComponent.segments.join('') if (!query) query = component else query += (queryComponent.child ? ' > ' : ' ') + component } } ids.sort(function (a, b) { return a - b }) return { query : query, weight : totalWeight, hasId : hasId, hash : ids.join('') } }, doQuery : function (query, root) { throw new Error("Abstract method called: `doQuery`") }, verifyQuery : function (query, target, root) { var queryRes = this.doQuery(query, root) return queryRes.length == 1 && queryRes[ 0 ] == target } } });