0
\$\begingroup\$

I'm writing some function tests and wrapping a Microsoft Playwright (it's similar to Selenium for those unfamiliar) IPage with a page object containing some helper functions to simplify the test code.

The following function reads a table on the HTML page and makes the data available in a format that is easier for test assertions (where the column headers are the rows' dictionary keys). I'm wondering if there are some simpler ways to assembly this data for the desired output format. Thoughts?

public async Task<IEnumerable<IDictionary<string, string>>> GetTableData()
{
    var headerCells = (await _page.QuerySelectorAllAsync("#results th"))
        .Select(async c => await c.TextContentAsync())
        .Select((t, i) => new 
        { 
            Text = t.Result?.Trim() ?? string.Empty, 
            ColumnIndex = i 
        })
        .ToList();

    var dataRows = (await _page.QuerySelectorAllAsync("#results td"))
        .Select(async c => await c.TextContentAsync())
        .Select((t, i) => new 
        { 
            Text = t.Result?.Trim() ?? string.Empty, 
            Index = i, 
            ColumnIndex = i % headerCells.Count 
        })
        .GroupBy(o => o.Index / headerCells.Count)
        .ToList();

    var result = dataRows.Select(g => g
        .Zip(headerCells, (dr, hr) => new KeyValuePair<string, string>(hr.Text, dr.Text))
        .Where(kvp => !string.IsNullOrWhiteSpace(kvp.Key)) // <- drop columns with no headers (e.g. Edit button column)
        .ToDictionary(kvp => kvp.Key, kvp => kvp.Value))
        .ToList();

    return result;
}
```
\$\endgroup\$
2
  • 1
    \$\begingroup\$ A tip: async c => await c.TextContentAsync() is equal to c => c.TextContentAsync() but without generating yet another state machine. Or .Select.Select can be always merged into single .Select. \$\endgroup\$
    – aepot
    Commented Feb 10, 2022 at 21:55
  • 1
    \$\begingroup\$ Then look at IAsyncEnumerable usage. Then .ToArray a bit mre efficient than .ToList if you don't need add/remove the list items after creation. And finally, dictionary is overkill, too many copies of the keys. Better to use DataTable here. \$\endgroup\$
    – aepot
    Commented Feb 10, 2022 at 22:02

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.