whatsappicloudtweetdeckhipchattelegramhangoutsslackgmailskypefacebook-workplaceoutlookemailmicrosoft-teamsdiscordmessengercustom-servicesmacoslinuxwindowsinbox
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1052 lines
39 KiB
1052 lines
39 KiB
describe("Ext.ComponentQuery", function() { |
|
var cq, |
|
cm, |
|
EA, |
|
result, |
|
root, |
|
child1, |
|
child2, |
|
child3, |
|
child4, |
|
child5, |
|
child6, |
|
child7, |
|
child8, |
|
child9, |
|
child10, |
|
child11, |
|
child12, |
|
setup = function(o, parent) { |
|
if (o.items) { |
|
for (var i = 0; i < o.items.length; i++) { |
|
setup(o.items[i], o); |
|
} |
|
} |
|
|
|
Ext.apply(o, { |
|
getItemId: function() { |
|
return this.itemId !== undefined ? this.itemId : this.id; |
|
}, |
|
|
|
getId: function() { |
|
return this.id; |
|
}, |
|
|
|
getRefItems: function(deep) { |
|
var items = this.items || [], |
|
len = items.length, |
|
i = 0, |
|
item; |
|
|
|
if (deep) { |
|
for (; i < len; i++) { |
|
item = items[i]; |
|
if (item.getRefItems) { |
|
items = items.concat(item.getRefItems(true)); |
|
} |
|
} |
|
} |
|
|
|
return items; |
|
}, |
|
|
|
getRefOwner: function() { |
|
return this.ownerCt; |
|
}, |
|
|
|
hasCls: function(cls) { |
|
return this.cls == cls; |
|
}, |
|
|
|
isHidden: function() { |
|
return this.hidden; |
|
}, |
|
|
|
isXType: function(type) { |
|
return EA.contains(this.type.split('/'), type); |
|
}, |
|
|
|
ownerCt: parent, |
|
|
|
self: { |
|
$config: { |
|
configs: {} |
|
} |
|
} |
|
}); |
|
|
|
cm.register(o); |
|
}; |
|
|
|
function expectChildren() { |
|
var args = Array.prototype.slice.apply(arguments), |
|
result = args.shift(), |
|
len = args.length, |
|
i, expected, actual; |
|
|
|
expect(result.length).toBe(len); |
|
|
|
for (i = 0, len = args.length; i < len; i++) { |
|
expected = args[i]; |
|
actual = result[i]; |
|
|
|
expect(actual.id).toBe(expected.id); |
|
} |
|
}; |
|
|
|
beforeEach(function() { |
|
cq = Ext.ComponentQuery; |
|
cm = Ext.ComponentManager; |
|
EA = Ext.Array; |
|
|
|
root = { |
|
id: 'root', |
|
cls: 'root-cls', |
|
type: 'A', |
|
items: [child1 = { |
|
$className: 'Foo', |
|
id: 'child1', |
|
cls: 'child1-cls', |
|
type: 'B/G/Z', |
|
foo: 'bar,baz' |
|
}, child2 = { |
|
$className: 'Bar.Baz.Qux', |
|
id: 'child2', |
|
cls: 'child2-cls', |
|
type: 'B/G/Z', |
|
bar: 'foo,bar,baz' |
|
}, child3 = { |
|
$className: 'Foo', |
|
id: 'child3', |
|
cls: 'child3-cls', |
|
type: 'B/C/D', |
|
layout: 'card', |
|
items: [child4 = { |
|
id: 'child4', |
|
cls: 'child4-cls', |
|
type: 'B/C/E', |
|
layout: 'hbox', |
|
items: [child5 = { |
|
id: 'child5', |
|
cls: 'child5-cls', |
|
type: 'B/C/F', |
|
items: [child7 = { |
|
id: 'child7', |
|
cls: 'child7-cls', |
|
type: 'B/G/H' |
|
}, child8 = { |
|
id: 'child8', |
|
cls: 'child8-cls', |
|
type: 'B/G/I' |
|
}, child9 = { |
|
id: 'child9', |
|
cls: 'child9-cls', |
|
type: 'B/G/J' |
|
}] |
|
}, child6 = { |
|
id: 'child6', |
|
cls: 'child6-cls', |
|
type: 'B/G/Z', |
|
hidden: true |
|
}, child10 = { |
|
id : 'child10', |
|
cls : 'child10-cls my-foo-cls', |
|
type : 'B' |
|
}, child11 = { |
|
id : 'child.11', |
|
cls : 'child11-cls my-foo-cls-test', |
|
type : 'B' |
|
}, child12 = { |
|
id: 'child.12', |
|
itemId: 'bobby.brown.goes.down', |
|
type: 'E.2-E.4', |
|
foo: '[foo(bar)!baz#qux\\fred*]', |
|
sq: "'single' 'quotes'", |
|
dq: '"double" "quotes"' |
|
}] |
|
}] |
|
}] |
|
}; |
|
setup(root); |
|
}); |
|
|
|
afterEach(function() { |
|
cm.all = {}; |
|
}); |
|
|
|
describe("parser", function() { |
|
it("should blow up if the intra-selector comma is escaped", function() { |
|
expect(function() { |
|
cq.query('#child3\\,F', root); |
|
}).toThrow('Invalid ComponentQuery selector: ",F"'); |
|
}); |
|
|
|
it("should blow up if a selector ends with unescaped comma", function() { |
|
expect(function() { |
|
cq.query('#child3,', root); |
|
}).toThrow('Invalid ComponentQuery selector: ""'); |
|
}); |
|
|
|
it("should blow up if a selector ends with an escaped comma", function() { |
|
expect(function() { |
|
cq.query('#child3\\,', root); |
|
}).toThrow('Invalid ComponentQuery selector: ","'); |
|
}); |
|
|
|
describe("missing quotes", function() { |
|
var warning; |
|
|
|
beforeEach(function() { |
|
spyOn(Ext.log, 'warn').andCallFake(function(msg) { |
|
warning = msg; |
|
}); |
|
|
|
warning = null; |
|
}); |
|
|
|
it("should warn on missing opening double quote", function() { |
|
cq.query('[foo=bar"]'); |
|
expect(warning).toMatch(/^ComponentQuery selector.*?unescaped \("\).*?end/); |
|
}); |
|
|
|
it("should warn on missing closing double quote", function() { |
|
cq.query('[foo="bar]'); |
|
expect(warning).toMatch(/^ComponentQuery selector.*?unescaped \("\).*?beginning/); |
|
}); |
|
|
|
it("should warn on missing opening single quote", function() { |
|
cq.query("[foo=bar']"); |
|
expect(warning).toMatch(/^ComponentQuery selector.*?unescaped \('\).*end/); |
|
}); |
|
|
|
it("should warn on missing closing single quote", function() { |
|
cq.query("[foo='bar]"); |
|
expect(warning).toMatch(/^ComponentQuery selector.*?unescaped \('\).*beginning/); |
|
}); |
|
}); |
|
}); |
|
|
|
describe("Query object", function() { |
|
describe("is", function() { |
|
it("should return true if the selector is empty", function() { |
|
var q = cq.parse(''); |
|
|
|
expect(q.is(root)).toBe(true); |
|
}); |
|
}); |
|
}); |
|
|
|
describe("is", function(){ |
|
var item; |
|
beforeEach(function() { |
|
item = Ext.getCmp('root'); |
|
}); |
|
|
|
afterEach(function(){ |
|
item = null; |
|
}); |
|
|
|
it("should return true if there is no selector", function(){ |
|
expect(cq.is(root)).toBe(true); |
|
}); |
|
|
|
it("should return true if component matches the selector", function(){ |
|
expect(cq.is(root, '[type=A]')).toBe(true); |
|
}); |
|
|
|
it("should return true if component matches any selector", function(){ |
|
expect(cq.is(root, 'button, #foo, #root, [type=A]')).toBe(true); |
|
}); |
|
|
|
it("should return false if the component doesn't match the selector", function(){ |
|
expect(cq.is(root, '#foo')).toBe(false); |
|
}); |
|
|
|
it("should work with the :not pseudo", function() { |
|
var comp = new Ext.Component({ |
|
foo: 1 |
|
}); |
|
|
|
expect(comp.is('[foo]:not([bar])')).toBe(true); |
|
}); |
|
|
|
it("should be able to run on destroyed components", function(){ |
|
var comp = new Ext.Component({ |
|
foo: 1 |
|
}); |
|
|
|
comp.destroy(); |
|
expect(comp.is('[foo]:not([bar])')).toBe(true); |
|
}); |
|
|
|
describe("hierarchy selectors", function() { |
|
it("should match a direct child", function(){ |
|
expect(cq.is(child6, '#child4 > #child6')).toBe(true); |
|
}); |
|
|
|
it("should return false if it's not a direct child", function() { |
|
expect(cq.is(child6, '#child3 > #child6')).toBe(false); |
|
}); |
|
|
|
it("should match deep children", function() { |
|
expect(cq.is(child6, '#child3 #child6')).toBe(true); |
|
}); |
|
|
|
it("should match an upward selector", function() { |
|
expect(cq.is(child3, '#child6 ^ #child3')).toBe(true); |
|
}); |
|
}); |
|
}); |
|
|
|
describe("simple query by xtype", function() { |
|
it("should select all six items of type G", function() { |
|
result = cq.query('G', root); |
|
expect(result.length).toEqual(6); |
|
expect(result[2].id).toEqual(child6.id); |
|
}); |
|
|
|
it("should allow escaped dots in xtype selector", function() { |
|
result = cq.query('E\\.2-E\\.4', root); |
|
expect(result.length).toBe(1); |
|
expect(result[0].id).toBe(child12.id); |
|
}); |
|
}); |
|
|
|
describe("simple query by xtype prefixed with dot", function() { |
|
beforeEach(function() { |
|
// Silence console warnings |
|
spyOn(Ext.log, 'warn'); |
|
}); |
|
|
|
it("should select all six items of type G", function() { |
|
result = cq.query('.G', root); |
|
expect(result.length).toEqual(6); |
|
expect(result[2].id).toEqual(child6.id); |
|
}); |
|
|
|
it("should allow escaped dots in xtype selector", function() { |
|
result = cq.query('.E\\.2-E\\.4', root); |
|
expect(result.length).toBe(1); |
|
expect(result[0].id).toBe(child12.id); |
|
}); |
|
}); |
|
|
|
describe("attributes starting with $", function(){ |
|
it("should match $className variable", function(){ |
|
result = cq.query('[$className=Foo]'); |
|
expect(result.length).toBe(2); |
|
expect(result[0].id).toBe('child1'); |
|
expect(result[1].id).toBe('child3'); |
|
}); |
|
|
|
it("should allow dots in attribute values", function() { |
|
result = cq.query('[$className=Bar.Baz.Qux]', root); |
|
expectChildren(result, child2); |
|
}); |
|
}); |
|
|
|
describe("query by id", function() { |
|
it("should select the second child", function() { |
|
result = cq.query('G#child2', root); |
|
expect(result.length).toEqual(1); |
|
expect(result[0].id).toEqual(child2.id); |
|
}); |
|
|
|
it("should select the fifth child", function() { |
|
result = cq.query('#child5', root); |
|
expect(result.length).toEqual(1); |
|
expect(result[0].id).toEqual(child5.id); |
|
}); |
|
|
|
it("should allow escaped dots in query-by-id selectors", function() { |
|
result = cq.query('#child\\.11', root); |
|
expectChildren(result, child11); |
|
}); |
|
|
|
it("should allow multiple escaped commas in #itemId selectors", function() { |
|
result = cq.query('#bobby\\.brown\\.goes\\.down', root); |
|
expectChildren(result, child12); |
|
}); |
|
}); |
|
|
|
describe("query by property", function() { |
|
it("should select the second child", function() { |
|
result = cq.query('G[cls=child2-cls]', root); |
|
expect(result.length).toEqual(1); |
|
expect(result[0].id).toEqual(child2.id); |
|
}); |
|
|
|
it("should select the sixth child", function () { |
|
result = cq.query('[hidden]', root); |
|
expect(result.length).toEqual(1); |
|
expect(result[0].id).toEqual(child6.id); |
|
}); |
|
|
|
describe("property value quotes", function() { |
|
it("should allow single quoted value", function() { |
|
result = cq.query("[id='child.12']", root); |
|
expectChildren(result, child12); |
|
}); |
|
|
|
it("should allow double quoted value", function() { |
|
result = cq.query('[id="child.12"]', root); |
|
expectChildren(result, child12); |
|
}); |
|
|
|
it("should allow double quotes in single quoted value", function() { |
|
result = cq.query('[dq=\'"double" "quotes"\']', root); |
|
expectChildren(result, child12); |
|
}); |
|
|
|
it("should allow single quotes in double quoted value", function() { |
|
result = cq.query("[sq=\"'single' 'quotes'\"]", root); |
|
expectChildren(result, child12); |
|
}); |
|
}); |
|
|
|
describe("matchers", function(){ |
|
it("should select the tenth child", function () { |
|
result = cq.query('[cls~=my-foo-cls]', root); |
|
expect(result.length).toEqual(1); |
|
expect(result[0].id).toEqual(child10.id); |
|
}); |
|
|
|
it("should select items where id starts with child1", function(){ |
|
result = cq.query('[id^=child1]', root); |
|
expectChildren(result, child1, child10); |
|
}); |
|
|
|
it("should select items where cls ends with 9-cls", function(){ |
|
result = cq.query('[cls$=9-cls]', root); |
|
expect(result.length).toBe(1); |
|
expect(result[0].cls).toBe('child9-cls'); |
|
}); |
|
|
|
it("should select items with commas in properties", function() { |
|
result = cq.query('[foo=bar\\,baz]'); |
|
expect(result.length).toEqual(1); |
|
expect(result[0].id).toEqual(child1.id); |
|
}); |
|
|
|
it("should allow multiple escaped commas", function() { |
|
result = cq.query('[bar=foo\\,bar\\,baz]', root); |
|
expectChildren(result, child2); |
|
}); |
|
|
|
it("should allow escaped metacharacters", function() { |
|
result = cq.query('[foo=\\[foo\\(bar\\)\\!baz\\#qux\\\\fred\\*\\]]', root); |
|
expectChildren(result, child12); |
|
}); |
|
|
|
describe("regexen", function() { |
|
it("should match everything with an empty regex", function() { |
|
result = cq.query('[cls/=]'); |
|
expect(result.length).toBe(12); |
|
}); |
|
|
|
describe("simple regexen", function() { |
|
it("should match regexen with text as pattern", function() { |
|
result = cq.query('[cls/=my-foo]'); |
|
expectChildren(result, child10, child11); |
|
}); |
|
|
|
it("should match regexen with simple alternation", function() { |
|
result = cq.query('[cls/=child3-cls|child4-cls|child5-cls]'); |
|
expectChildren(result, child5, child4, child3); |
|
}); |
|
}); |
|
|
|
describe("complex regexen", function() { |
|
it("should match regexen with pattern quantifiers", function() { |
|
result = cq.query('[cls/="child.{2}-cls"]'); |
|
expectChildren(result, child10, child11); |
|
}); |
|
|
|
it("should match regexen with grouping and alternating", function() { |
|
result = cq.query('[cls/="child(?:7|8)-cls"]'); |
|
expectChildren(result, child7, child8); |
|
}); |
|
|
|
it("should match regexen with character classes", function() { |
|
result = cq.query('[cls/="child\\[5-7\\]-cls"]'); |
|
expectChildren(result, child7, child5, child6); |
|
}); |
|
}); |
|
}); |
|
}); |
|
}); |
|
|
|
describe("query using mode ^", function() { |
|
it("should select the fourth child", function() { |
|
result = cq.query('G[cls=child8-cls]^#child4', root); |
|
expect(result.length).toEqual(1); |
|
expect(result[0].id).toEqual(child4.id); |
|
}); |
|
}); |
|
|
|
describe("query using mode ^ and >", function() { |
|
it("should select the sixth child", function() { |
|
result = cq.query('G[cls=child8-cls]^#child4>G', root); |
|
expect(result.length).toEqual(1); |
|
expect(result[0].id).toEqual(child6.id); |
|
}); |
|
}); |
|
|
|
describe("query using multiple selectors", function() { |
|
it("should select the third and fifth child", function() { |
|
result = cq.query('#child3,F', root); |
|
expect(result.length).toEqual(2); |
|
expect(result[0].id).toEqual(child3.id); |
|
expect(result[1].id).toEqual(child5.id); |
|
}); |
|
}); |
|
|
|
describe("query using member function", function() { |
|
it("should select the sixth child that is hidden", function() { |
|
result = cq.query('{isHidden()}', root); |
|
expect(result.length).toEqual(1); |
|
expect(result[0].id).toEqual(child6.id); |
|
}); |
|
}); |
|
|
|
describe("query using pseudo-class", function() { |
|
beforeEach(function() { |
|
cq.pseudos.cardLayout = function(items) { |
|
var result = [], c, i = 0, l = items.length; |
|
for (; i < l; i++) { |
|
if ((c = items[i]).layout === 'card') { |
|
result.push(c); |
|
} |
|
} |
|
return result; |
|
}; |
|
}); |
|
|
|
it("should select the third child with layout == 'card'", function() { |
|
result = cq.query('C:cardLayout', root); |
|
delete cq.pseudos.cardLayout; |
|
expect(result.length).toEqual(1); |
|
expect(result[0].id).toEqual(child3.id); |
|
}); |
|
|
|
it("should not select the sixth child which is filtered by :not()", function(){ |
|
result = cq.query(':not([hidden])', root); |
|
var all = root.getRefItems(true), |
|
getId = function(o){ return o.id; }, |
|
allIds = EA.map(all, getId), |
|
resultIds = EA.map(result, getId), |
|
diffIds = EA.difference(allIds, resultIds); |
|
expect(result.length).toEqual(all.length - 1); |
|
expect(diffIds.length).toEqual(1); |
|
expect(diffIds[0]).toEqual(child6.id); |
|
}); |
|
|
|
it("should accept back-to-back pseudo-class selectors with cumulative results", function(){ |
|
result = cq.query(':not(G):not(F)', root); |
|
expect(result.length).toEqual(5); |
|
expect(result[0].id).toEqual(child3.id); |
|
expect(result[1].id).toEqual(child4.id); |
|
expect(result[2].id).toEqual(child10.id); |
|
expect(result[3].id).toEqual(child11.id); |
|
expect(result[4].id).toEqual(child12.id); |
|
}); |
|
|
|
it("should accept member expression selectors", function() { |
|
result = cq.query(':not({isHidden()})', root); |
|
var all = root.getRefItems(true), |
|
getId = function(o){ return o.id; }, |
|
allIds = EA.map(all, getId), |
|
resultIds = EA.map(result, getId), |
|
diffIds = EA.difference(allIds, resultIds); |
|
expect(result.length).toEqual(all.length - 1); |
|
expect(diffIds.length).toEqual(1); |
|
expect(diffIds[0]).toEqual(child6.id); |
|
}); |
|
|
|
describe("focusable", function() { |
|
// https://sencha.jira.com/browse/EXTJS-16758 |
|
it("should not blow up when card item is not a component", function() { |
|
var container = new Ext.container.Container({ |
|
renderTo: Ext.getBody(), |
|
items: [new Ext.Widget()] |
|
}); |
|
|
|
expect(function() { |
|
container.query(':focusable'); |
|
}).not.toThrow(); |
|
|
|
container.destroy(); |
|
}); |
|
}); |
|
|
|
describe("first/last", function() { |
|
var items; |
|
beforeEach(function(){ |
|
items = [ |
|
new Ext.Component({ |
|
action: 'type1', |
|
id: 'id1' |
|
}), |
|
new Ext.container.Container({ |
|
action: 'type1', |
|
id: 'id2' |
|
}), |
|
new Ext.container.Container({ |
|
action: 'type2', |
|
id: 'id3' |
|
}), |
|
new Ext.Component({ |
|
action: 'type2', |
|
id: 'id4' |
|
}), |
|
new Ext.container.Container({ |
|
action: 'type2', |
|
id: 'id5' |
|
}) |
|
]; |
|
}); |
|
|
|
afterEach(function(){ |
|
Ext.Array.forEach(items, function(item){ |
|
item.destroy(); |
|
}); |
|
items = null; |
|
}); |
|
|
|
describe("first", function(){ |
|
it("should return an empty array if no items match", function(){ |
|
var result = cq.query('button:first', items); |
|
expect(result).toEqual([]); |
|
}); |
|
|
|
it("should return the first matching component by type", function(){ |
|
var result = cq.query('container:first', items); |
|
expect(result).toEqual([items[1]]); |
|
}); |
|
|
|
it("should return the last matching component by attribute", function(){ |
|
var result = cq.query('[action=type2]:first', items); |
|
expect(result).toEqual([items[2]]); |
|
}); |
|
|
|
it("should return the first component", function(){ |
|
var result = cq.query('*:first', items); |
|
expect(result).toEqual([items[0]]); |
|
}); |
|
|
|
describe("no items/single item", function(){ |
|
it("should return an empty array if there are no items", function(){ |
|
var result = cq.query('*:first', []); |
|
expect(result).toEqual([]); |
|
}); |
|
|
|
it("should return an a single item if it matches", function(){ |
|
var c = new Ext.Component(); |
|
var result = cq.query('component:first', [c]); |
|
expect(result).toEqual([c]); |
|
c.destroy(); |
|
}); |
|
}); |
|
}); |
|
|
|
describe("last", function(){ |
|
it("should return an empty array if no items match", function(){ |
|
var result = cq.query('button:last', items); |
|
expect(result).toEqual([]); |
|
}); |
|
|
|
it("should return the last matching component by type", function(){ |
|
var result = cq.query('component:last', items); |
|
expect(result).toEqual([items[4]]); |
|
}); |
|
|
|
it("should return the first matching component by attribute", function(){ |
|
var result = cq.query('[action=type1]:last', items); |
|
expect(result).toEqual([items[1]]); |
|
}); |
|
|
|
it("should return the first component", function(){ |
|
var result = cq.query('*:last', items); |
|
expect(result).toEqual([items[4]]); |
|
}); |
|
|
|
describe("no items/single item", function(){ |
|
it("should return an empty array if there are no items", function(){ |
|
var result = cq.query('*:last', []); |
|
expect(result).toEqual([]); |
|
}); |
|
|
|
it("should return an a single item if it matches", function(){ |
|
var c = new Ext.Component(); |
|
var result = cq.query('component:last', [c]); |
|
expect(result).toEqual([c]); |
|
c.destroy(); |
|
}); |
|
}); |
|
}); |
|
}); |
|
}); |
|
|
|
describe('attribute value coercion', function() { |
|
var candidates = [{ |
|
att1: 0, |
|
att2: 0, |
|
att3: 0, |
|
att4: 0 |
|
}, { |
|
att1: null, |
|
att2: false, |
|
att3: true, |
|
att4: undefined |
|
}, { |
|
att1: 0, |
|
att2: 0, |
|
att3: 0, |
|
att4: 0 |
|
}]; |
|
|
|
if('should coerce "null" to match a null property value', function() { |
|
expect(cq.query('[att1=null]', candidates)).toBe(candidates[1]); |
|
}); |
|
|
|
if('should coerce "false" to match a Boolean property value', function() { |
|
expect(cq.query('[att2=false]', candidates)).toBe(candidates[1]); |
|
}); |
|
|
|
if('should coerce "true" to match a Boolean property value', function() { |
|
expect(cq.query('[att3=true]', candidates)).toBe(candidates[1]); |
|
}); |
|
|
|
if('should coerce "undefined" to match an undefined property value', function() { |
|
expect(cq.query('[att4=undefined]', candidates)).toBe(candidates[1]); |
|
}); |
|
}); |
|
|
|
describe('ownProperty tests', function() { |
|
var TestClass = Ext.define(null, { |
|
extend: 'Ext.Component', |
|
foo: 'bar', |
|
bletch: 0 |
|
}), |
|
candidates; |
|
|
|
// Only candidates[1] has *ownProperties* foo and bletch |
|
// And the value of bletch is zero, so by [bletch] will never match. |
|
// Test that [?bletch] tests for just *presence* of property in object. |
|
candidates = [new TestClass(), new TestClass({ |
|
foo: 'bar', |
|
bletch: 0 |
|
})]; |
|
|
|
it('should only match candidates [@foo=bar] with ownProperty "foo" equal to "bar"', function() { |
|
expect(Ext.ComponentQuery.query('[@foo=bar]', candidates).length).toBe(1); |
|
expect(Ext.ComponentQuery.query('[@foo=bar]', candidates)[0]).toBe(candidates[1]) |
|
expect(Ext.ComponentQuery.is(candidates[0], '[@foo=bar]')).toBe(false); |
|
expect(Ext.ComponentQuery.is(candidates[1], '[@foo=bar]')).toBe(true); |
|
}); |
|
|
|
it('should not match candidates [bletch] where bletch is a falsy property', function() { |
|
expect(Ext.ComponentQuery.query('[bletch]', candidates).length).toBe(0); |
|
expect(Ext.ComponentQuery.is(candidates[0], '[bletch]')).toBe(false); |
|
expect(Ext.ComponentQuery.is(candidates[1], '[bletch]')).toBe(false); |
|
}); |
|
|
|
it('should match candidates [?bletch] where bletch is a falsy property', function() { |
|
expect(Ext.ComponentQuery.query('[?bletch]', candidates).length).toBe(1); |
|
expect(Ext.ComponentQuery.query('[?bletch]', candidates)[0]).toBe(candidates[1]); |
|
expect(Ext.ComponentQuery.is(candidates[0], '[?bletch]')).toBe(false); |
|
expect(Ext.ComponentQuery.is(candidates[1], '[?bletch]')).toBe(true); |
|
}); |
|
}); |
|
|
|
describe('Querying floating descendants', function() { |
|
var c; |
|
|
|
beforeEach(function() { |
|
c = new Ext.container.Container({ |
|
items: { |
|
xtype: 'container', |
|
floating: true, |
|
id: 'floating-cq-child', |
|
items: { |
|
xtype: 'container', |
|
floating: true, |
|
id: 'floating-cq-grandchild', |
|
items: { |
|
floating: true, |
|
id: 'floating-cq-great-grandchild' |
|
} |
|
} |
|
}, |
|
renderTo: document.body |
|
}); |
|
}); |
|
afterEach(function() { |
|
c.destroy(); |
|
}); |
|
|
|
it('should find all descendants', function() { |
|
var d = c.query(); |
|
expect(d.length).toEqual(3); |
|
expect(d[0]).toBe(Ext.getCmp('floating-cq-child')); |
|
expect(d[1]).toBe(Ext.getCmp('floating-cq-grandchild')); |
|
expect(d[2]).toBe(Ext.getCmp('floating-cq-great-grandchild')); |
|
}); |
|
it('should find individual descendants', function() { |
|
var d = c.query('>*'); |
|
expect(d.length).toEqual(1); |
|
expect(d[0]).toBe(Ext.getCmp('floating-cq-child')); |
|
|
|
d = c.query('>>*'); |
|
expect(d.length).toEqual(1); |
|
expect(d[0]).toBe(Ext.getCmp('floating-cq-grandchild')); |
|
|
|
d = c.query('>>>*'); |
|
expect(d.length).toEqual(1); |
|
expect(d[0]).toBe(Ext.getCmp('floating-cq-great-grandchild')); |
|
}); |
|
}); |
|
|
|
describe('trimming spaces', function () { |
|
var c; |
|
|
|
beforeEach(function () { |
|
c = new Ext.container.Container({ |
|
items: { |
|
xtype: 'button', |
|
text: 'Test', |
|
action: 'selectVendors' |
|
}, |
|
renderTo: document.body |
|
}); |
|
}); |
|
|
|
afterEach(function () { |
|
c.destroy(); |
|
c = null; |
|
}); |
|
|
|
describe('single space', function () { |
|
describe("attribute matching expressions", function() { |
|
it('should trim leading space', function () { |
|
result = cq.query('[action =selectVendors]', c); |
|
expect(result.length).toBe(1); |
|
expect(result[0].action).toBe('selectVendors'); |
|
|
|
result = cq.query('[action ^=selectVendors]', c); |
|
expect(result.length).toBe(1); |
|
expect(result[0].action).toBe('selectVendors'); |
|
|
|
result = cq.query('[action $=selectVendors]', c); |
|
expect(result.length).toBe(1); |
|
expect(result[0].action).toBe('selectVendors'); |
|
}); |
|
|
|
it('should trim trailing space', function () { |
|
result = cq.query('[action= selectVendors]', c); |
|
expect(result.length).toBe(1); |
|
expect(result[0].action).toBe('selectVendors'); |
|
|
|
result = cq.query('[action*= selectVendors]', c); |
|
expect(result.length).toBe(1); |
|
expect(result[0].action).toBe('selectVendors'); |
|
|
|
result = cq.query('[action~= selectVendors]', c); |
|
expect(result.length).toBe(1); |
|
expect(result[0].action).toBe('selectVendors'); |
|
}); |
|
|
|
it('should trim both spaces', function () { |
|
result = cq.query('[action = selectVendors]', c); |
|
expect(result.length).toBe(1); |
|
expect(result[0].action).toBe('selectVendors'); |
|
|
|
result = cq.query('[action *= selectVendors]', c); |
|
expect(result.length).toBe(1); |
|
expect(result[0].action).toBe('selectVendors'); |
|
|
|
result = cq.query('[action ~= selectVendors]', c); |
|
expect(result.length).toBe(1); |
|
expect(result[0].action).toBe('selectVendors'); |
|
}); |
|
}); |
|
}); |
|
|
|
describe('multiple spaces', function () { |
|
describe("attribute matching expressions", function() { |
|
it('should trim multiple leading spaces', function () { |
|
result = cq.query('[action =selectVendors]', c); |
|
expect(result.length).toBe(1); |
|
expect(result[0].action).toBe('selectVendors'); |
|
|
|
result = cq.query('[action ^=selectVendors]', c); |
|
expect(result.length).toBe(1); |
|
expect(result[0].action).toBe('selectVendors'); |
|
|
|
result = cq.query('[action $=selectVendors]', c); |
|
expect(result.length).toBe(1); |
|
expect(result[0].action).toBe('selectVendors'); |
|
}); |
|
|
|
it('should trim multiple trailing spaces', function () { |
|
result = cq.query('[action= selectVendors]', c); |
|
expect(result.length).toBe(1); |
|
expect(result[0].action).toBe('selectVendors'); |
|
|
|
result = cq.query('[action*= selectVendors]', c); |
|
expect(result.length).toBe(1); |
|
expect(result[0].action).toBe('selectVendors'); |
|
|
|
result = cq.query('[action~= selectVendors]', c); |
|
expect(result.length).toBe(1); |
|
expect(result[0].action).toBe('selectVendors'); |
|
}); |
|
|
|
it('should trim multiple spaces on both sides', function () { |
|
result = cq.query('[action = selectVendors]', c); |
|
expect(result.length).toBe(1); |
|
expect(result[0].action).toBe('selectVendors'); |
|
|
|
result = cq.query('[action *= selectVendors]', c); |
|
expect(result.length).toBe(1); |
|
expect(result[0].action).toBe('selectVendors'); |
|
|
|
result = cq.query('[action ~= selectVendors]', c); |
|
expect(result.length).toBe(1); |
|
expect(result[0].action).toBe('selectVendors'); |
|
}); |
|
}); |
|
|
|
describe("id matching expressions", function() { |
|
it("should trim leading spaces", function() { |
|
result = cq.query(' #child9', root); |
|
|
|
expect(result.length).toBe(1); |
|
expect(result[0].id).toBe(child9.id); |
|
}); |
|
|
|
it("should trim trailing spaces", function() { |
|
result = cq.query('#child9 ', root); |
|
|
|
expect(result.length).toBe(1); |
|
expect(result[0].id).toBe(child9.id); |
|
}); |
|
|
|
it("should trim spaces on both sides", function() { |
|
result = cq.query(' #child9 ', root); |
|
|
|
expect(result.length).toBe(1); |
|
expect(result[0].id).toBe(child9.id); |
|
}); |
|
}); |
|
|
|
describe("descendancy expressions", function() { |
|
it("should trim leading spaces", function() { |
|
result = cq.query(' [layout=card] [type=B/G/H]', root); |
|
|
|
expect(result.length).toBe(1); |
|
expect(result[0].id).toBe(child7.id); |
|
}); |
|
|
|
it("should trim trailing spaces", function() { |
|
result = cq.query('[type=B/G/J] ^ [layout=hbox] ', root); |
|
|
|
expect(result.length).toBe(1); |
|
expect(result[0].id).toBe(child4.id); |
|
}); |
|
|
|
it("should trim spaces on both sides", function() { |
|
result = cq.query(' #child4 > [type=B/C/F] ', root); |
|
|
|
expect(result.length).toBe(1); |
|
expect(result[0].id).toBe(child5.id); |
|
}); |
|
}); |
|
}); |
|
}); |
|
|
|
describe('pre- and postOrder', function () { |
|
var foo = false; |
|
|
|
afterEach(function () { |
|
foo = false; |
|
cq.cache.clear(); |
|
}); |
|
|
|
describe('preOrder', function () { |
|
it('should call the fn regardless of whether the selector has been cached', function () { |
|
expect(cq.cache.get('')).toBeUndefined(); |
|
|
|
cq.visitPreOrder('', this, function () { |
|
foo = true; |
|
}); |
|
|
|
expect(foo).toBe(true); |
|
}); |
|
}); |
|
|
|
describe('postOrder', function () { |
|
it('should call the fn regardless of whether the selector has been cached', function () { |
|
expect(cq.cache.get('')).toBeUndefined(); |
|
|
|
cq.visitPostOrder('', this, function () { |
|
foo = true; |
|
}); |
|
|
|
expect(foo).toBe(true); |
|
}); |
|
}); |
|
}); |
|
|
|
describe("selecting by attribute", function(){ |
|
|
|
var foo, bar; |
|
beforeEach(function(){ |
|
Ext.define('spec.Foo', { |
|
extend: 'Ext.Component', |
|
config: { |
|
bar: 1 |
|
}, |
|
baz: 2 |
|
}); |
|
|
|
foo = new spec.Foo({ |
|
jaz:3 |
|
}); |
|
|
|
Ext.define('spec.Bar', { |
|
extend: 'Ext.Component', |
|
config: { |
|
bar: 4 |
|
}, |
|
baz: 5 |
|
}); |
|
|
|
bar = new spec.Bar({ |
|
jaz: 6 |
|
}); |
|
}); |
|
|
|
afterEach(function() { |
|
Ext.undefine('spec.Foo'); |
|
Ext.undefine('spec.Bar'); |
|
}); |
|
it("should match instance config", function(){ |
|
result = cq.query('[bar=1]'); |
|
expect(result.length).toBe(1); |
|
expect(result[0]).toBe(foo); |
|
}); |
|
|
|
it("should match a property on the instance", function() { |
|
result = cq.query('[baz=2]'); |
|
expect(result.length).toBe(1); |
|
expect(result[0]).toBe(foo); |
|
}); |
|
|
|
it("should match an arbitrary property on the config object", function() { |
|
result = cq.query('[jaz=3]'); |
|
expect(result.length).toBe(1); |
|
expect(result[0]).toBe(foo); |
|
}); |
|
}); |
|
}); |