adopted-ember-addons / ember-light-table

Lightweight, contextual component based table for Ember
http://adopted-ember-addons.github.io/ember-light-table/
MIT License
312 stars 131 forks source link

Unique data-test-* row attributes for ember-test-selectors #500

Open bgentry opened 7 years ago

bgentry commented 7 years ago

I'm using ember-test-selectors and really prefer to select elements in my tests using those data-test-* selectors.

I was trying to figure out how best to get that same functionality in ember-light table. I realized that the data I was already passing to my tables already had a unique ID in all cases (globally unique ID of the data model for that row). I then realized I could just create a custom row component that automatically binds to that attribute:

app/components/my-table/row.js:

import { readOnly } from "@ember/object/computed";
import Row from "ember-light-table/components/lt-row";

export default Row.extend({
  "data-test-row-id": readOnly("row.id"),
});

Then when invoking the light-table component, I can just specify that row component:

{{#t.body
    rowComponent=(component "ac-table/row")
    as |body|
  }}

I'm posting this here not because there's an issue to resolve, but because others might find it useful. Feel free to just close this, or maybe there's something that can be added to the docs to make these sorts of customizations more discoverable.

Thanks for your work on this addon :v:

BitBrit commented 5 years ago

I'm not sure I understand how to use the above information. As I understand it, a data-test-selector is for use in a test so that something can be selected in a repeatable way. As the row.id can change, a test cannot rely on it to select anything. Am I missing something here?

I think that data-test-selectors for rows and the columns would be useful. Each row could have data-test-row=<row number> and each column could have data-test-column=<column.valuePath>.

With this I could assert on a specific cell using something like:

assert.dom('[data-test-row="3"] [data-test-column="userName"]').exists();

For a static set of test data the above selector would work every time.

Please let me know if I have missed anything in the suggestion above comment that would help me do what I just described.

Techn1x commented 5 years ago

This helped me a lot, thanks. Would be great if we could somehow implement this, then specify a new default column/cell component for ELT to use (like with rowComponent, instead of having to then specify it for every column)

// components/new-base-column.js
export default Column.extend({
  "data-test-column": readOnly("column.valuePath"),
});

Then something like this

{{t.body
  columnComponent=(component "new-base-column")
  cellComponent=(component "new-base-cell")
}}

Instead of

columns: [
  { label: 'colA', type: 'new-base-column', ... },
  { label: 'colB', type: 'new-base-column', ... },
  { label: 'colC', type: 'new-base-column', ... },
  { label: 'colD', type: 'new-base-column', ... },
]
b2point0h commented 3 years ago

For some reason, this isn't working for me. I need to be able to set the UUID returned on the model row, to the ELT row for automation testing since ember generates new ones everytime.

Any help on extending the row component?

import Row from 'ember-light-table/components/lt-row';
import { readOnly } from '@ember/object/computed';

/**
 * Row component for the zt-light-table component.
 *
 * @class ZtLightTable/TableRow
 * @extends EmberLightTable.LtRow
 */
export default Row.extend({
  classNameBindings: ['active'],

  /**
   * When row has 'active' set, will bind the active class to the row.
   *
   * @property active
   * @type {Boolean}
   */
  active: readOnly('row.active'),

  'data-test-row-id': readOnly('row.id')
});
{{#light-table table
  height=height
  tableClassNames=_tableClassNames
  tableActions=tableActions
  as |t|}}
  {{#if showThead}}
    {{t.head
      iconSortable=_iconSortable
      iconAscending=_iconAscending
      iconDescending=_iconDescending
      fixed=true
    }}
  {{/if}}

  {{#t.body
    canSelect=false
    scrollTo=scrollTo
    scrollToRow=scrollToRow
    onScroll=(action (mut currentScrollOffset))
    onScrolledToBottom=(action 'onScrolledToBottom')
    onRowClick=(action 'onRowClick')
    rowComponent=(component 'zt-light-table/table-row')
    as |body|
  }}
    {{#if isLoading}}
      {{#body.loader}}
        {{is-loading}}
      {{/body.loader}}
    {{else}}
      {{#if table.isEmpty}}
        {{#body.no-data}}
          {{#if noDataComponent}}
            {{component noDataComponent}}
          {{else if noDataText}}
            <div class="text-muted text-center">{{noDataText}}</div>
          {{/if}}
        {{/body.no-data}}
      {{/if}}
    {{/if}}
  {{/t.body}}

  {{#t.foot fixed=true as |columns|}}
  {{/t.foot}}

{{/light-table}}