# Thread: Selecting grid entries with composite key

1. ## Answered: Selecting grid entries with composite key

Say I have a grid where a row is uniquely identified by a combination of two or more columns (in my case 3); a composite key.

In this scenario there are 2^3 possible combinations

 COL_A_composite_key COL_B_composite_key COL_C_composite_key some_column 1 1 1 test 1 1 0 values 1 0 1 to 0 1 1 demonstrate 1 0 0 the 0 1 0 problem 0 0 1 temp 0 0 0 blub

How do I precisely access a cell (say where COL_A = 1, COL_B = 1, COL_C =0), based on the combination of multiple values?

I could do sth. like this but I then would have to know how many rows are displayed in the the grid, which can differ in my use case from time to time.

Code:
let gridEntries = [];

for(let rowIndex = 0; rowIndex<8; rowIndex++){
for(let columnIndex = 0; columnIndex<=3; columnIndex++){
ST.grid('locator')
.rowAt(rowIndex)
.cellAt(columnIndex)
.focus()
.get('innerText')
.and(function(future) {
gridEntries[rowIndex]=[];
gridEntries[rowIndex][columnIndex] = future.data.innerText;
});
}
}

// Then check the 2D-array

2. The APIs in Sencha Test don't currently allow for filtering or locating rows by more than one property and value. Instead, you would need to use the Ext JS Store's "findBy" method, wrapped inside of an "execute" function in Sencha Test. Below is an example that shows how this can be achieved on one of the Kitchen Sink grids. In this example, a grid row is being located by two properties:

Code:
// WebDriver scenario example.
//
// Scenario URL: https://examples.sencha.com/extjs/6.7.0/examples/kitchensink/frame-index.html?classic#cell-editing

describe('Grid tests', function() {
it('should find a grid row by multiple properties', function() {
// Define the property values you want to search
var common = 'Bee Balm',

ST.grid('cell-editing')
.and(function(future) {
// Set the property names and values on the "future" object
future.data = future.data || {};
future.data.common = common;
future.data.light = light;
})
.execute(function(grid) {
// This function gets passed to the browser for execution.
// In order for it to have access to your property names and values,
// you need to add them to the "future.data" object, as above.
var me = this;

// Use the Ext JS "findBy" method of the Store to locate a record
// index by a custom function, and return the index.
return grid.getStore().findBy(function(record, id) {
return record.get('common') === me.future.data.common
&& record.get('light') === me.future.data.light;
});
})
.and(function(future) {
// "executeResult" contains the return value from the function above.
var rowIndex = future.data.executeResult;

// Now interact with the grid row, now we know the index
ST.grid('cell-editing')
.rowAt(rowIndex)
.click();
});
});
});

3. The APIs in Sencha Test don't currently allow for filtering or locating rows by more than one property and value. Instead, you would need to use the Ext JS Store's "findBy" method, wrapped inside of an "execute" function in Sencha Test. Below is an example that shows how this can be achieved on one of the Kitchen Sink grids. In this example, a grid row is being located by two properties:

Code:
// WebDriver scenario example.
//
// Scenario URL: https://examples.sencha.com/extjs/6.7.0/examples/kitchensink/frame-index.html?classic#cell-editing

describe('Grid tests', function() {
it('should find a grid row by multiple properties', function() {
// Define the property values you want to search
var common = 'Bee Balm',

ST.grid('cell-editing')
.and(function(future) {
// Set the property names and values on the "future" object
future.data = future.data || {};
future.data.common = common;
future.data.light = light;
})
.execute(function(grid) {
// This function gets passed to the browser for execution.
// In order for it to have access to your property names and values,
// you need to add them to the "future.data" object, as above.
var me = this;

// Use the Ext JS "findBy" method of the Store to locate a record
// index by a custom function, and return the index.
return grid.getStore().findBy(function(record, id) {
return record.get('common') === me.future.data.common
&& record.get('light') === me.future.data.light;
});
})
.and(function(future) {
// "executeResult" contains the return value from the function above.
var rowIndex = future.data.executeResult;

// Now interact with the grid row, now we know the index
ST.grid('cell-editing')
.rowAt(rowIndex)
.click();
});
});
});

4. Thanks,

the KitchenSink version works perfectly fine, but transferred to my site I am running into a problem.

Executing the findby-Method directly in the Browser gives me the desired rowIndex:

Code:
.getStore().findBy(function(record, id) {
return record.get('contract_id') === "FKNOP081AA"
&& record.get('Origin') === "IDJKT"
&& record.get('Destination') === "USOAK"
&& record.get('container') === "20 DV"
&& record.get('commodity_id') === "JET_SKIS";});
In my testcase I am using a slighly different locator (that works with every other regular ST-API function such as rowAt, cellWith, etc.) that goes the following:

Code:
Applying the findby()-function to this locator and running it in the browser results in an error: "....getStore is not a function...".
(In the testcase the rowIndex results in -1, indicating that no matching record was found)

This is probably because I need to access the first element in the array that is returned by the query and then perform the method, like this:

(1 is the right index, as the desired record is the second one in the grid)

Can I modify my ST-Locator using for example the down()-Method to access the right element?

Here is the DOM FWIW:

Code:
>"pltx-gridBuilder-1758"

Or can I modify the grid argument in the execute-method?

Code:
.execute(function(grid) {
// This function gets passed to the browser for execution.
// In order for it to have access to your property names and values,
// you need to add them to the "future.data" object, as above.
var me = this;

// Use the Ext JS "findBy" method of the Store to locate a record
// index by a custom function, and return the index.
return grid.getStore().findBy(function(record, id) {
return record.get('common') === me.future.data.common
&& record.get('light') === me.future.data.light;
});
})
(grid=grid[0]; does not work)..

Thanks!

5. In the example code I sent, the "grid" argument that's provided within the "execute" function is based on the previous component that was selected with "ST.grid". I'm not too sure why that would throw an error about not being able to reference the store, without seeing a running example.

In any case, you can wrap any browser code inside of an "execute" function, so you could add your full "Ext.ComponentQuery.query" logic inside of an "execute" function, and ignore the provided "grid" argument:

Code:
// Define the property values you want to search
var common = 'Bee Balm',

ST.grid('cell-editing')
.and(function(future) {
future.data = future.data || {};
future.data.common = common;
future.data.light = light;
})
.execute(function(grid) {
var me = this;

return record.get('common') === me.future.data.common
&& record.get('light') === me.future.data.light;
});
})
.and(function(future) {
// "executeResult" contains the return value from the function above.
var rowIndex = future.data.executeResult;

// Now interact with the grid row, now we know the index
ST.grid('cell-editing')
.rowAt(rowIndex)
.click();
});

6. Ah, I found the problem!

Turns out it wasn't the locators as I previously suspected.

The grid's records get fetched from a DB and as I invoke the execute function right after navigating to the grid, the findBy()-Method is probably executed before the grids records are fully 'loaded'.

Right now I just added a ST.wait(10000) statement right after opening the page that contains my grid, which in the end finds me the right record.

But this is a rather ugly solution to the problem, could you reccommend a better alternative?

Btw thank you so much for your tireless support and extremely helpful insight into these topics, really appreciate it.

7. Happy to help!

Does your grid always contain at least one record? I'm guessing it would, based on the fact you're trying to reference a specific row within the test. So you could add a "rowAt(0)" before the "execute" function, which will force the test to wait until there's at least one row in the grid:

Code:
ST.grid('cell-editing')
.and(function(future) {
future.data = future.data || {};
future.data.common = common;
future.data.light = light;
})
.rowAt(0)  // Wait until there is data in the grid
.execute(function(grid) {
...
By default, "rowAt" will wait up to the default timeout (5 seconds) for the presence of a row. If you want to wait for longer (e.g. 10 seconds), you can define a timeout:

Code:
.rowAt(0, 10000)  // Wait up to 10 seconds
If the row is found sooner than 10 seconds, it will proceed to the "execute" function. It doesn't just wait for 10 seconds.

8. Hmm yes, that would work.

Although,

Code:
.execute(function(grid) {

would now be

Code:
.execute(function(row) {

so the

Code:
grid.getStore().findBy()

-Method would not work anymore and this

Code:

is necessary.

Or is there a way to achieve the same wait condition and still use the grid.getStore().. method?

9. You can use the row's "grid()" method to return to the grid, so "execute" then has a reference to the grid, rather than the row:

Code:
ST.grid('cell-editing')
.and(function(future) {
future.data = future.data || {};
future.data.common = common;
future.data.light = light;
})
.rowAt(0)
.grid()
.execute(function(grid) {
var me = this;

return grid.getStore().findBy(function(record, id) {
return record.get('common') === me.future.data.common
&& record.get('light') === me.future.data.light;
});
})

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•