Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redesign a selector's system #798

Closed
22 tasks done
inikulin opened this issue Sep 13, 2016 · 12 comments
Closed
22 tasks done

Redesign a selector's system #798

inikulin opened this issue Sep 13, 2016 · 12 comments
Assignees
Labels
API MODIFICATION LEVEL: breaking changes AREA: client AREA: server STATE: Auto-locked An issue has been automatically locked by the Lock bot. SYSTEM: API TYPE: enhancement The accepted proposal for future implementation.
Milestone

Comments

@inikulin
Copy link
Contributor

inikulin commented Sep 13, 2016

I've got this idea while thinking about #795 and making API examples. Currently we have selector and snapshots. Selectors are functions that allow you retrieve node state aka node snapshot. Having a node snapshot you can retrieve other snapshots in DOM hierarchy. Moreover, we are going to add find method that will allow you to retrieve descendants of the element represented by snapshot. There is a problem with this approach: we have everything messed up together. It's confusing and we don't have ability to implement some scenarios due to this approach. E.g. having a selector A how can I write selector B which will select some child of the element given by selector A? And we should be able to pass this descendant selector to action and should have all properties like regular selectors. The correct answer is that selectors should be combinable in order to reuse selectors to get nodes that are in relation with nodes, given by selector.

The proposal

  • Remove all selector methods from node snapshot: getParentNode, getChildNode,...
  • Introduce methods above to selectors itself, which will return new selector, e.g. parentNode()
  • Add method descendant and ancestor to selector
  • Add Selector.count() method, that returns number of matching elements

So, e.g. instead of:

const ul = Selector('#list');

const paragraph = Selector(() => {
    var list = getList();

    if (!list) 
      return null;

   return list.querySelector('p');
}, { dependencies: { getList: ul } };

We'll be able to write:

const ul = Selector('#list');
const paragraph = ul.descendant('p');

// Now you can filter paragraphs by text:
paragraphWithText = paragraph.with({text:'Yo'});

it's extremely useful e.g. in page models, there need to build relations without data actual retrieval.

I'm not sure, but seems like we can even get rid of dependencies with this approach.

Also, we will have consistent API: selectors are all about retrieval and can be combined in the functional programming style. Snapshots are just plain data.

\cc @DevExpress/testcafe


Update (22.09.16)

Proposed API:

  • Deprecate snapshot hierarchy selectors (e.g. getChildNode)

  • Deprecate t.select

  • Deprecate options.index

  • Deprecate options.dependencies

  • Deprecate options.text

  • Allow unawaited calls to Selector outside of test context.

  • Return null if Selector returns single node and index is more than 0.

  • .nth(idx)

  • .withText(text|re)

  • .find(cssSelector)

  • .find(filterFn)

  • .parent(idx = 0)

  • .parent(cssSelector)

  • .parent(filterFn)

  • .child(idx = 0)

  • .child(cssSelector)

  • .child(filterFn)

  • .sibling(idx = 0)

  • .sibling(cssSelector)

  • .sibling(filterFn)

  • .count

  • .exists

@AlexanderMoskovkin
Copy link
Contributor

👍 Looks good

I'm not sure, but seems like we can even get rid of dependencies with this approach.

const getElementById     = Selector(id => document.querySelector(`#${id}`));
const getStatusBtn       = Selector(() => getElementById('statusBtn'), { dependencies: { getElementById } });

As a see we can't get rid of dependencies in this case or we can?

@inikulin
Copy link
Contributor Author

@AlexanderMoskovkin It's synthetic example, you can just do:

const getStatusBtn = Selector('#statusBtn');

But it would be nice if you add more examples, to see how they will fit into new paradigm

@AlexanderMoskovkin
Copy link
Contributor

an example from our documentation:

const getGridRow  = Selector(n => document.getElementsByClassName('grid-row')[n]);
const getGridCell = Selector((m, n) => getGridRow(m).children[n], {
     dependencies: { getGridRow }
});

@helen-dikareva
Copy link
Collaborator

I like it

@kirovboris
Copy link
Collaborator

kirovboris commented Sep 13, 2016

Looks good, but in my opinion descendant and ancestor too long to type.

@helen-dikareva
Copy link
Collaborator

helen-dikareva commented Sep 13, 2016

maybe child/parent @VasilyStrelyaev

@helen-dikareva
Copy link
Collaborator

helen-dikareva commented Sep 13, 2016

child/parent looks like we'll searching for one level

@inikulin
Copy link
Contributor Author

@helen-dikareva Correct. Child/parent means single level, but we'll have them as well.

@inikulin
Copy link
Contributor Author

@kirovboris What do you think? Does fits well for you selector extensions?

@kirovboris
Copy link
Collaborator

kirovboris commented Sep 14, 2016

If we're discussing the selector extensions, not the snapshot extension, it looks useful.
I mean this change can't replace the snapshot extending for react-selectors plugin.

@inikulin
Copy link
Contributor Author

inikulin commented Sep 14, 2016

@kirovboris It applies only to selector combination. Snapshot extensions looks even more meaningful with this one.

@inikulin inikulin added TYPE: enhancement The accepted proposal for future implementation. and removed TYPE: proposal labels Sep 21, 2016
@inikulin inikulin added this to the Planned features milestone Sep 21, 2016
@inikulin inikulin changed the title Make selectors the only point for the element/element properties retrieval Redesign selector system Nov 3, 2016
@inikulin inikulin modified the milestones: Sprint #2, Planned features Nov 3, 2016
@inikulin inikulin self-assigned this Nov 3, 2016
AlexanderMoskovkin added a commit to AlexanderMoskovkin/testcafe that referenced this issue Nov 28, 2016
testcafe-build-bot added a commit to testcafe-build-bot/testcafe that referenced this issue Nov 28, 2016
testcafe-build-bot added a commit to testcafe-build-bot/testcafe that referenced this issue Nov 28, 2016
@MarinaRukavitsyna MarinaRukavitsyna changed the title Redesign selector system Redesign a selector's system Nov 29, 2016
AlexanderMoskovkin added a commit to AlexanderMoskovkin/testcafe that referenced this issue Dec 6, 2016
inikulin pushed a commit that referenced this issue Dec 6, 2016
* [docs] Redesigned selectors docs (closes #798)

* Fix broken links

* Fix typo

* Corrections

* Getting started section updated

* Some more corrections

* Review remarks

* Some fixes

* Fix numered list

* Landing page selectors article updated

* Selector.md reworked

* Linting fixed

* Corrections

* A typo fixed

* selectors.md corrections

* Remove obsolete info

* Fix a typo
@lock
Copy link

lock bot commented Mar 29, 2019

This thread has been automatically locked since it is closed and there has not been any recent activity. Please open a new issue for related bugs or feature requests. We recommend you ask TestCafe API, usage and configuration inquiries on StackOverflow.

@lock lock bot added the STATE: Auto-locked An issue has been automatically locked by the Lock bot. label Mar 29, 2019
@lock lock bot locked as resolved and limited conversation to collaborators Mar 29, 2019
kirovboris pushed a commit to kirovboris/testcafe-phoenix that referenced this issue Dec 18, 2019
* Deprecate old properties

* Add filter methods: .nth() and .withText()

* Allow unawaited Selector calls outside of test run

* .find() method implemented

* .parent() method implemented

* .child() method implemented

* .sibling() method implemented

* .count and .exists properties

* .find(): Don't apply implicit index when used as transitive selector, so it searches elements in all elements matching a parent selector.

* Refactor derivative collection filtering code

* .parent(): Filter mode

* .child() and .sibling(): Filter mode

* Fix lint errors

* Fix texts
kirovboris pushed a commit to kirovboris/testcafe-phoenix that referenced this issue Dec 18, 2019
)

* [docs] Redesigned selectors docs (closes DevExpress#798)

* Fix broken links

* Fix typo

* Corrections

* Getting started section updated

* Some more corrections

* Review remarks

* Some fixes

* Fix numered list

* Landing page selectors article updated

* Selector.md reworked

* Linting fixed

* Corrections

* A typo fixed

* selectors.md corrections

* Remove obsolete info

* Fix a typo
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
API MODIFICATION LEVEL: breaking changes AREA: client AREA: server STATE: Auto-locked An issue has been automatically locked by the Lock bot. SYSTEM: API TYPE: enhancement The accepted proposal for future implementation.
Projects
None yet
Development

No branches or pull requests

4 participants