forcedotcom / LightningTestingService

Apache License 2.0
122 stars 35 forks source link

Unable to get the child component reference from parent component #29

Closed paakumar closed 7 years ago

paakumar commented 7 years ago

I am trying to get the reference of a child component(dropdown) from the parent component. I have defined the aura id of the child component as I have used the same component multiple time in the parent component. Now to test the child component when I am trying to get the reference of child component in promise function using component.find function I am unable to get it as find is not defined. I tried to get the same using component,get but still could not get the reference of child component. Below is the sample example of component I am using //SampleDetails component

esalman-sfdc commented 7 years ago

My guess is that locker service is preventing access by returning SecureComponentRef instead of SecureComponent. Locker Service does that when the component being referenced is not in the same locker.

Based on the snippet looks like everything being referenced is in the same namespace, so I am guessing locker is restricting access to un-lockerized components (below api-version 40). LTS runner is lockerized (api-version 40).

Can you try changing the api versions of components under tests to 40 and try again.

By the way, just to be safe, try deploying to a different scratch org or also edit component markup as I have noticed that sometimes changing just the version doesn't immediately take effect due to some caching.

paakumar commented 7 years ago

As suggested I tried to deploy to a different scratch org and it is working. But the issue is API versions of our existing lightning components is below 40. Can you please suggest a way through which we can test the components irrespective of API versions.

esalman-sfdc commented 7 years ago

Normally you should be able to test components at different versions. LTS runner by default runs the tests with locker enabled to ensure that tests are adhering to Locker rules and don't end up being flaky long term (without locker test may be inspecting internals of a component from another namespace which may change).

As a quick workaround, you can try lowering the api version of BaseTestRunnerCmp in your repo to have your tests run without locker restrictions. Alternatively, If you want to be a bit more surgical, you could leave the runner as-is, and can add a layer of indirection via a test wrapper component which is running without locker and playing a bridge between the test and the component under test.

paakumar commented 7 years ago

As per your suggestion I tried lowering the api version of BaseTestRunnerCmp to 39, but still I am not getting the object. Also, can you please give an example how we can have layer of indirection via a test wrapper component which is running without locker and playing a bridge between the test and the component under test.

esalman-sfdc commented 7 years ago

Lowering the version of runner should do the trick (I double checked). If you are reusing an existing scratch org (where the runner is already deployed), you may need to also touch runner component's markup file (add a space) to purge the cache (as I mentioned above there seems to be a bug where cache doesn't automatically get refreshed on api-version changes).

To see if your test is inside a locker or not, try adding a breakpoint in your test (I'd add it at one of the expectations), and type window+"" in the browser console. If you get back "SecureWindow ..." (locker wrapper) your test is still in locker, if its no longer being lockerized, you'll get something like "[object Window]" (browser window object).

Lets try this out first to ensure it works for you. We can then build a wrapper/utility to selectively perform certain operations outside of locker (instead of defaulting all the tests to be unlockerized by changing runner's version).

paakumar commented 7 years ago

Component find method is still not available, below is the sample test spec. I have lowered the version of runner to 37 which is same as my existing lightning components

it("Test for processFormData", function(done) { var renderInto = document.getElementById("renderTestComponents"); $T.createComponent("c:SampleDetails", { }, renderInto) .then(function(component) { component.find('SampleInputDropdown'); //find is not defined and SampleInputDropdown is auraid of child component from example component done(); }).catch(function(e) { // end this spec as a failure done.fail(e); }); });

esalman-sfdc commented 7 years ago

Assuming you are on the pilot release, can you confirm that you did the following,

1- Lowered api version of runner component called "BaseTestRunnerCmp". 2- To avoid caching issue, either deployed to a new scratch org or touched the markup of "BaseTestRunnerCmp" to force the cache to refresh.

Doing these 2 things is guaranteed to disable Locker Service for tests (as all the tests are loaded via BaseTestRunnerCmp) and hence enable you to call find on "c:SampleDetails". I had personally confirmed this before replying last time.