Giter Site home page Giter Site logo

lightningtestingservice's Issues

chain spyOn?

When my component loads, I make multiple calls to the server. I'm not sure how to test this. The server calls are as follows:

c:pageContainer -> getOrderInvite()

getOrderInvite() then loads the component

c:shippingAddressUpdateForm -> getShippingDestinationList()

getShippingDestinationList() -> getCountryStatePicklistValues()

So three server calls are enqueued in a chain when my app loads: getOrderInvite() -> getShippingDestinationList() -> getCountryStatePicklistValues()

This is my attempt on chaining spyOn, but it doesn't appear to work.

    describe('c:pageContainer', function(){     
        it('should show the shipping address form', function(done) {
            $T.createComponent("c:pageContainer", {code: "S3UYMUTY"}, true)
            .then(function(component){ 

                var orderInvite = {
                    "Id": "a0Ff0000003FIUEEA4",
                    "Account__c": "001f000000naH9iAAE",
                    "Order_Code__c": "S3UYMUTY",
                    "Order__c": "a09f0000003Bm2jAAC",
                    "Account__r": {
                        "Order_Pickup__c": true,
                        "Id": "001f000000naH9iAAE"
                    },
                    "Order__r": {
                        "Shipping_First_Name__c": "Tyler",
                        "Shipping_Name__c": "Zikaa",
                        "Shipping_Company__c": "55 Degrees",
                        "Shipping_Country__c": "United States of America",
                        "Shipping_State__c": "Alaska",
                        "Shipping_Address__c": "1210 Church St.",
                        "Shipping_City__c": "St. Helena",
                        "Shipping_Phone__c": "7079635513",
                        "Shipping_Zip_Postal__c": "39232",
                        "Status__c": "Complete",
                        "Shipping_Sent__c": true,
                        "No_Wooden_Box__c": true,
                        "Pickup__c": false,
                        "Id": "a09f0000003Bm2jAAC"
                    }
                };

                var res = {getState : function(){return "SUCCESS";}, getReturnValue: function(){return orderInvite;}};
                spyOn($A, "enqueueAction").and.callFake(function(action1) {
                    var cb = action1.getCallback("SUCCESS")
                    cb.fn.apply(cb.s, [res]);

                    var shippingDestinationList = [
                        {
                          "disabled": false,
                          "escapeItem": false,
                          "label": "55 Degrees",
                          "selected": false,
                          "value": "a0Bf00000036M36EAE"
                        },
                        {
                          "disabled": false,
                          "escapeItem": false,
                          "label": "Pickup/Local Delivery",
                          "selected": false,
                          "value": "1"
                        },
                        {
                          "disabled": false,
                          "escapeItem": false,
                          "label": "Ship To Address Below",
                          "selected": true,
                          "value": "0"
                        }
                      ]
                    var res = {getState : function(){return "SUCCESS";}, getReturnValue: function(){return shippingDestinationList;}};
                    spyOn($A, "enqueueAction").and.callFake(function(action2) {
                        var cb = action2.getCallback("SUCCESS")
                        cb.fn.apply(cb.s, [res]);
                        
                        var countryStateListOptions = {
                            "Czech Republic": [
                              {
                                "disabled": false,
                                "escapeItem": false,
                                "label": "Outside US",
                                "selected": false,
                                "value": "Outside US"
                              }
                            ],
                            "Canada": [
                              {
                                "disabled": false,
                                "escapeItem": false,
                                "label": "Alberta",
                                "selected": false,
                                "value": "Alberta"
                              }
                            ],
                            "United States of America": [
                              {
                                "disabled": false,
                                "escapeItem": false,
                                "label": "Alabama",
                                "selected": false,
                                "value": "Alabama"
                              },
                              {
                                "disabled": false,
                                "escapeItem": false,
                                "label": "California",
                                "selected": true,
                                "value": "California"
                              },
                              {
                                "disabled": false,
                                "escapeItem": false,
                                "label": "Oregon",
                                "selected": false,
                                "value": "Oregon"
                              },
                              {
                                "disabled": false,
                                "escapeItem": false,
                                "label": "Alaska",
                                "selected": false,
                                "value": "Alaska"
                              }
                            ]
                          }
                        var res = {getState : function(){return "SUCCESS";}, getReturnValue: function(){return countryStateListOptions;}};
                        spyOn($A, "enqueueAction").and.callFake(function(action3) {
                            var cb = action3.getCallback("SUCCESS")
                            cb.fn.apply(cb.s, [res]);
                        }); 
                    }); 

                });    
                return $T.waitFor(function(){
                    return component.get("v.body").length === 1;
                })
            }).then(function() {
                expect(component.get("v.body").length).toBe(1);                
                done();
            }).catch(function(e) {
                done.fail(e);
            });              
        });
    });

All these server calls need to happen in order to load c:shippingAddressUpdateForm into the v.body of c:pageContainer, which is what I'm testing for.

I'm currently getting

Error: Error in $A.getCallback() [Cannot read property 'getState' of undefined]
so the server response.getState() isn't being set properly in my chain.

New jasmine suite not recognised

Hi there,

I'm having trouble getting a new suite to be recognised. Steps

  1. Downloaded the "Lightning Testing Service with Examples" package.
  2. Created the following javascript file

describe("Lightning Component Testing Examples", function(){
afterEach(function() {
// Each spec (test) renders its components into the same div,
// so we need to clear that div out at the end of each spec.
$T.clearRenderedTestComponents();
});

    describe('c:ContactCreatorL', function(){
    // We encourage you to have the code for c:egRenderElement side by side
    // when reading through this spec.
    it('creates a contact successfuly', function(done) {
        //instantiate the component using its name
		$T.createComponent("c:egComponentMethod", null)
        // The 'component' here is the instance of c:egRenderElement
        .then(function(component) {
            
        	var fakeResponse = {
				getState : function(){
					return "SUCCESS";
				}
			};

			//call the apexMethod function, which contains a reference to the apex controller
			spyOn($A, "enqueueAction").and.callFake(function(action) {
                var cb = action.getCallback("SUCCESS")
                cb.fn.apply(cb.s, [fakeResponse]);
            });

            expect(component.get("v.creationSucceded")).toBe(true);

            done();
        }).catch(function(e) {
            // end this spec as a failure
            done.fail(e);
        });
    });
});

});

  1. Went to the file > right click > compress > uploaded it as a static resource as application/zip
  2. Go to https://[myDomain]/c/jasmineTests.app and the test is not there.

The documentation doesn't say anything more than "uploaded the suite as a static resource", which I've done as per the above steps. The syntax appears to be correct and I'm not getting any errors or warnings.

Is there anything I need to do for this suite to be tested?

Overlapping of rendered components with the App Components

In LTS Examples, we are using the custom component "lts_jasmineRunner.cmp". In my case when we tuned as per my requirement (For Example. we tried by including the necessary scripts and jasmine libraries as in the custom component "lts_jasmineRunner" in my App) , The problem was that we are facing overlapping between the rendered component and the App Components.

We suspect that the Rendering component in the div element might causing the collision with the App components. Could you please help on getting this resolved ?

Capturing showToast events

I have some logic that display showToast event for success && failure. I'd love to catch those events and so I can validate code works correctly. Is there a way to catch system events using testing service?

Alternatively, is there a Test.isRunningTest() method equivalent from Apex in LTS so I could create a workarounds for such cases as above?

Test results in "junit" format from "sfdx force:lightning:test:run" present badly because the classname is set to an empty string

When Jenkins "Publish JUnit test result report" is setup for the output of "sfdx force:lightning:test:run" that is running LTS tests, the test results for passing tests are presented as a single line (with counts and times aggregated) instead of a line per test.

The XML output lines all have an empty string for their classname:

<testcase name="c:wizContainer : body component has been created" classname="" time="1.86"></testcase>

and the presentation code appears to group by that attribute.

This code appears to provide the values:

class LightningTestResults extends TestResults {
    constructor(testApi, tests, runResultSummaries, config) {
        super(testApi.testrunid, testApi.startTime, 'force.lightning', tests, runResultSummaries, config);
    }
    getTestContainerName() {
        return '';
    }
    getTestNamespace(test) {
        return test.NamespacePrefix;
    }
    getTestName(test) {
        return test.FullName;
    }
}

and this is the equivalent for Apex (for reference):

class ApexTestResults extends TestResults {
    constructor(testApi, tests, runResultSummaries, config) {
        super(testApi.testrunid, testApi.startTime, 'force.apex', tests, runResultSummaries, config);
    }
    getTestContainerName(test) {
        return test.ApexClass.Name;
    }
    getTestNamespace(test) {
        return test.ApexClass.NamespacePrefix;
    }
    getTestName(test) {
        return test.MethodName;
    }
}

with the XML built by:

            let classname = this.getTestContainerName(test);
            if (this.getTestNamespace(test)) {
                classname = this.getTestNamespace(test) + classname;
            }
            junit += `        <testcase name="${this.getTestName(test)}" classname="${classname}" time="${test.RunTime ? msToSeconds(test.RunTime) : 0}">\n`;

Changing LightningTestResults.getTestContainerName(test) to return the same thing as LightningTestResults.getTestName(test) would be a quick fix, but perhaps a better value could be returned.

(I realize this code isn't part of LTS but perhaps you can pass this on to the relevant team?)

Sleep utility function

It would be useful to have a sleep type function in the $T namespace. For example, I have moved some singleton functionality into a JavaScript library that my components load via ltng:require and they defer their initialisation until that script is loaded. In the case of unit tests I just want to sleep for a couple of seconds to allow the library to load and then carry out the tests.

I don't want to artificially set an attribute or the like just to be able to use waitFor, and given that my lightning component might be running at a different API version to the baseTestRunner component I can't guarantee that I can load it there and attach it to the correct Window/SecureWindow object.

I've written my own, obviously, but not the most efficient if everyone has to do that going forward :)

GAC when testing scenario 2

I am following the tutorial from the sfdx blog and am stuck on Scenario 2.

I'm having trouble completing scenario 2, Verify data binding, and I get an error that says Failed: An internal server error has occured. From modifying the code, it looks like it's breaking when trying to create the component c:componentWithDataBinding. Specifically when calling the $T.createComponent('c:componentWithDataBinding') function in the jasmine test.

I've tried creatting a new scratch org and got the same error. I've also tried to create a new component and copy&pasted the examples but can't figure out why the createComponent is not working for me.

I have an example of my code in a gh repo here. I am able to recreate the issue by:

  1. Created a DevHub org (not required) or use existing one.
  2. git clone https://github.com/joseph-ortiz/lightning-testing-service-demo
  3. cd lightning-testing-service-demo
  4. sfdx force:org:create -f config/project-scratch-def.json -a lts
  5. sfdx force:lightning:test:install -u lts
  6. sfdx force:source:push -u lts
  7. sfdx force:org:open -u lts -p /c/myTestApp.app
  8. see GAC error.

screen shot 2018-04-18 at 5 16 15 pm

https://developer.salesforce.com/blogs/2018/04/getting-started-with-the-lightning-testing-service.html

lightning:select breaks test with Error ID: 2004951991-66946

I just spent quite some time tracking down why a simple test was breaking, as the error message didn't give any indication of what the problem is.

I'm using a fresh install using the CLI install command. All the tests work apart from the data service tests which have already been reported.

How to replicate:

Add a lightning:select to the markup without a label (not a blank label, the entire label attribute missing).

Notes:

While label is a required attribute, a lightning:select renders, and does not error, when used on a component normally without the attribute.

how to tests when v.body is set

I have a function that generates a component and puts it in the body of the component.

    generateOrderForm: function(component, orderInvite) {
        $A.createComponent(
            "c:shippingAddressUpdateForm",
            {
                "aura:id": "form",
                "orderInvite": orderInvite
            },
            function(form, status, errorMessage){
                if (status === "SUCCESS") {
                    var body = component.get("v.body");
                    body.push(form);
                    component.set("v.body", body);

                    // logs true
                    console.log(component.get("v.body").length == 1);
                }
                else if (status === "ERROR") {
                        console.log("Error: " + errorMessage);
                }
            }
        );         
    }

generateOrderForm() is called on init.

My test code

    describe('c:pageContainer', function(){     
        it('determine whether to show the shipping address form or an error message based on code in url', function(done) {

            // Setup
            spyOn($A, "enqueueAction").and.callFake(function(action) {
                var cb = action.getCallback("SUCCESS")

                var orderInvite = {"Id": "a0Ff0000003FIUEEA4"};

                cb.fn.apply(cb.s, [{ getState : function(){ return "SUCCESS"; }, 
                                        getReturnValue: function(){ return orderInvite;} 
                                    }]
                            );
            }); 
                        
            $T.createComponent("c:pageContainer", {}, true)
            .then(function(component){  
                // fails
                expect(component.get("v.body").length).toBe(1);
                done();

            }).catch(function(e) {
                done.fail(e);
            });
        });

The length of v.body is returning 0. What am I doing wrong?

Cannot test clicking of elements in component

I'm trying to write a test that verifies the correct value displays after a Lightning:button is clicked. Here are the problems:

  1. There is no click() method in the aura api. So if I use component.find(), there is no way I can invoke a click action on the button to invoke the function in my controller.

  2. I also tried using vanilla js, eg document.getElementById("someId"), but because of Locker Service that returns a Proxy object and I still can't call click() on the element.

In the examples in the test suite in this project, methods from the controller are exposed in the component, which we don't wish to do. We also have a lot of picklists we would like to set without creating a bunch of aura attributes that we don't need to actually make our component work.

I tried switching to an older version of the aura API for my component and test app, but that still did not work.

Is there a work around for being able to click/interact with elements on the component/DOM?

Doc question: "test" folder behavior

Hi,

I have been looking at the documenation for the Salesforce DX project structure but I could not find anything regarding the test folder (lightning-component-tests/test/default in your repository).

I do not want to deploy my Lightning tests in production so should I use this folder in combination with the main directory like you did? I am also Java dev so this project structures means something for me but does it translate to DX?
You may want to document it if there are special rules for this folder.

Cheers,

How to mock or configure lightning:workspaceAPI in tests?

I have a Lightning Component that uses the lightning:workspaceAPI component to detect that it is (or is not) running in the console view. I'm starting to look at setting up some LTS tests and am wondering what can be done to either mock or configure so that the lightning:workspaceAPI calls work?

The methods I'm using are:

  • isConsoleNavigation
  • getEnclosingTabId
  • getFocusedTabInfo

and I want tests for both console view and non-console view.

(Nothing came back on this for this https://salesforce.stackexchange.com question).

Adding a waitForAura mechanism?

Still new to LTS, but finding $T.waitFor pretty annoying in that the condition that you want to expect on ends up in there or ends up being duplicated. Can you comment on the possibility of adding an API to the core Aura libraries of this nature (that is then exposed in LTS):

On top of this, Protractor automatically applies browser.waitForAngular() before every action to wait for all Angular $http and $timeout calls to finish. This allows developers to write the test scripts without much dread "callback hell," for the most part.

so that cleaner tests can be written?

How does SFDX get the test results?

I've written a couple of custom reporters for Salesforce/Lightning/Jasmine which I'd like to port over to LTS and integrate with SFDX. Are you able to share how the SFDX CLI gets the test results when executing "sfdx force:lightning:test:run" - e.g. is it a screen scrape or does something get inserted etc. Thanks.

prerequisites to write tests?

Writing tests for my Lightning Components has been a frustrating and difficult experience. I'm not sure what the disconnect is. I'm Platform II certified, can write apex tests no problem, have put a lightning component app that is lightning ready on the app exchange, and have coded react and angular js app that are hosted in Salesforce.

What are the perquisites to write tests?

What books of JavaScript would you recommend? Writing js for lighting componets feels very different to writing js with react/angular for me.

Accessing inherited component

I'm testing a component that manages a date input field, which extends a base input component that handles the common aspects of an input, so label, error display etc. My initial test was simply to verify that the label I'd passed the component on creation was being applied correctly.

The label is a regular HTML element, with an aura:id to make it accessible from the component, and is present in the base component.

I've followed the approach in the examples and dynamically created the date component, but when I try to verify the label, component.find() always returns null. If I move the label into the date component, the find() works correctly and retrieves the label.

Initially I thought this might be down to the locker service (although I'd expect to be able to access everything in my namespace), but having downgraded all components to API 39 I still see the same behaviour.

Is there something around the way that components are created for testing that isolates them from even the base components that they extend?

Unable to get the child component reference from parent component

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

<aura:component controller="SampleController">

	<c:SampleInputLookup aura:id="SampleInputDropdown"
		dataOptions="{!v.SampleInputSS}" 
		valueField="description" 
		labelField="description" 
		title="SampleInput Sub Segment"                         
		onchange="{!c.sampleDropdownChange}"  
		opportuityAmount="{!v.opportuitySample}"/>
	
	<c:SampleInputLookup aura:id="SampleInputDropdown1"
		dataOptions="{!v.SampleInputSS1}" 
		valueField="description" 
		labelField="description" 
		title="SampleInput Sub Segment1"                         
		onchange="{!c.sampleDropdownChange1}"  
		opportuityAmount="{!v.opportuitySample}"/>

</aura:component>

testutil component destruction issue when API versions differ

cmp.destroy() fails in the clearRenderedTestComponents function if the targeted component is outside of the locker.

The workaround is simple. Inside of testutils change

if(status === "SUCCESS"){
    cmpsToCleanup.push(component.getGlobalId());
    if (renderInto) {

to

if(status === "SUCCESS"){
    if (renderInto) {
         var renderingContainer = $A.getComponent(renderInto);
         cmpsToCleanup.push(renderingContainer.getGlobalId());

then below in the clearRenderedTestComponents

while (cmpsToCleanup.length) {
        var globalId = cmpsToCleanup.shift();
        var cmp = $A.getComponent(globalId);
        cmp.set('v.body', []);
}

There is a scenario where the component is created and fails to be set to the renderInto body that needs to be handled, but this works quick and dirty.

ERROR: Cannot read property 'endsWith' of undefined.

I am getting ERROR: Cannot read property 'endsWith' of undefined. when running sfdx force:lightning:test:run -a jasmineTests.app after upgrading to the GA release of sfdx.

Any ideas on what is going sideways?

$T namespace documentation

Is there any documentation on the functions available in the $T namespace? I can figure out what is in the examples, but curious as to whether there are any nuances (e.g. does $T.waitFor() have a configurable timeout) or additional methods that don't appear in the examples.

lightning:input.showHelpMessageIfInvalid runtime error

I don't think these is the right place to post this, but running my tests I step in this problem:

Action failed: lightning:input$controller$showHelpMessageIfInvalid [Unable to get property 'validity' of undefined or null reference]

In the test case I set an object to my component, that is binded with a list of lightning:input by value property:

<lightning:input aura:id="fields" name="name" required="true" label="Name" value="{!v.account.Name}" />

then I fire the press event on my save button that, in the end, call

let allValid = cmp.find('fields').reduce((acc, el) => {
el.showHelpMessageIfInvalid();
return acc && el.get('v.validity').valid;
}, true);

and so I get the runtime error.

support for sinon

Does jasmine in Lightning Testing Service support sinon?

It would be a nice feature to have. For example, I could mock $A.enqueueAction in order to simulate my Apex controller AuraEnabled method, without exposing the action callback as an aura:method, and test response state as SUCCESS, INCOMPLETE and ERROR.

Packaging with source:convert

When attempting to setup the project structure like the following:

force-app
├── main
│   └── default
│       ├── aura
│       │   ├── Search
│       │   │   ├── Search.cmp
│       │   │   ├── Search.cmp-meta.xml
│       │   │   ├── Search.css
│       │   │   ├── Search.scss
│       │   │   └── SearchController.js
└── test
    └── default
        ├── aura
        │   └── searchTests
        │       ├── searchTests.app
        │       ├── searchTests.app-meta.xml
        │       └── searchTests.auradoc
        └── staticresources
            ├── Search.resource
            ├── Search.resource-meta.xml
            ├── testHelpers.resource
            └── testHelpers.resource-meta.xml

Everything works great for running tests and pushing source like sfdx force:source:push

However, when I do sfdx force:source:convert, it includes the test path and all its pieces as well.

My sfdx-project.json looks like this:

{
  "packageDirectories": [
    {
      "path": "force-app",
      "default": true
    }
  ],
  "namespace": "",
  "sfdcLoginUrl": "https://login.salesforce.com",
  "sourceApiVersion": "41.0"
}

is there any way to continue including the test package for the sfdx force:source:push command but exclude it when running sfdx force:source:convert?

Question on `sfdx force:lightning:test:install -t jasmine`

I was curious if it is expected that sfdx force:lightning:test:install -t jasmine is run for each CI job? I ask this because after running sfdx force:lightning:test:install -t jasmine I then ran sfdx force:source:pull, expecting to see the Jasmine test runner component show up in my local project, so that I could check it into my project's SCM. Unfortunately that source code was not pulled.

I'm still getting used to SFDX's project structure, and from what I can tell, I cannot use my Force.com IDE plugin for Eclipse to connect to this scratch org (am I wrong there?) to pull the source.

Thanks for any insights!

-Tim

Unable to use LTS with SFDX

I'm following the instructions to connect LTS to SalesforceDX. Once I've updated the plugin to work with the beta (via sfdx plugins:install salesforcedx@pre-release) I get the following error when trying to create a scratch org:

ERROR running force:org:create: You do not have access to the [ScratchOrgInfo] object.

(I'm guessing this might be because scratch orgs get created on CS70 at present which is a Spring 17 org)

If I revert back to the latest stable plugin then I can create the scratch orgs, albeit at version 39.0, so I've been trying to get as far as I can switching between the stable and pre-release plugins.

If I try to push the source using the pre-release, I get the error "the requested resource does not exist". I can push the source using the stable version if I make a few changes to lower the API version in the Apex meta-xml and remove references to recordData. Once this is done I can execute the Tests.app, but if I switch back to the pre-release plugin to use the force:lightning:test:run, I get the following error:

ERROR running force:lightning:test:run: An error occurred when running Lightning tests. The requested resource does not exist.

Should the pre-release plugin be able to create scratch orgs at API 40.0? Feels like that might solve the problem.

Testing with namespaces and Labels

I have been running into some weird issues regarding custom labels in javascript -> https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/labels_dynamic.htm

Basically, everything seems to work fine for namespace in the regular application, but when I go to write tests, it seems there is some loading issues for the test framework. Namely, if I have a test like this:

it('should have the correct label', () => {
  const expectedLabel = $A.get('$Label.MyNamespace.MyLabel');
  expect(document.getElementsByClassName('myCssClassName')[0].textContent).to.equal(expectedLabel);
});

It works sometimes and other times it claims that expectedLabel is equal to '' (empty string)

Is there something I am missing about namespacing labels and how they are loaded?

jasmineTests.app not working

Hi,

Recently installed lightning test service and I'm getting the error attached when I attempt to run jasmine test app. I was able to run the mocha tests without any issues, so I'm not sure sure what's wrong.

screen shot 2018-08-06 at 11 24 35 am

Thanks,

API version for test components not on Winter '18

The API version of these components is not on Winter '18. With that they don't run in an org that makes use of Winter '18 components (i. e. accordion).

https://github.com/forcedotcom/LightningTestingService/tree/master/lightning-component-tests/test/default/aura

Seen because the installation of the package (via the sfdx cli) fails

1.  The API version of this bundle must be set to '41' or later to use component 'markup://lightning:accordion'
mochaTests: The API version of this bundle must be set to '41' or later to use component 'markup://lightning:accordion'

2.  The API version of this bundle must be set to '41' or later to use component 'markup://lightning:accordion'
lts_mochaRunner: The API version of this bundle must be set to '41' or later to use component 'markup://lightning:accordion'

3.  The API version of this bundle must be set to '41' or later to use component 'markup://lightning:accordion'
lts_jasmineRunner: The API version of this bundle must be set to '41' or later to use component 'markup://lightning:accordion'

4.  The API version of this bundle must be set to '41' or later to use component 'markup://lightning:accordion'
jasmineTests: The API version of this bundle must be set to '41' or later to use component 'markup://lightning:accordion'

Use full name of hierarchy for test reporting

On test reporting with mocha, the line at https://github.com/forcedotcom/LightningTestingService/blob/master/lightning-component-tests/test/default/staticresources/lts_testutil.resource#L196

indicates that we only get the immediate parent's title for the description.

Is there either way to

  1. specify the filename or
  2. specify the entire parent hierarchy for the fullname

if i have a test that looks like

describe('MyComponent', () => {
  describe('when I do X', () => {
     it('should do Y', () => {
     });
     describe('then I do A', () => {
        it('should do B', () => {
        });
     });
  });
});

I won't know what file the output is coming from when the test result full name is:

then I do A : should do B

the goal here is to set up a file for each component to test its behaviors independently of the other components rather than having one giant file (and hopefully nested behaviors for reusability of events)

Lightning Test Context

It's not clear to me if the lightning tests run in a test context like the Apex unit tests do. By this I mean are any changes made to the database from the front end are rolled back rather than committed.

I wouldn't expect to be writing tests that have these kind of side effects, but there's always the chance that code changes underneath my tests and suddenly something that was locally cached is persisted.

How to mock Server actions with spyOn for doInit()

I am trying to test a component with server actions call during doInit(). This is my spec:

describe('c:myComponent', function(){  
    it('renders stuff as expected', function(done) {
        $T.createComponent("c:myComponent", {}, document.getElementById("renderTestComponents"))
            .then(function(component) {
                // Setup
                spyOn($A, "enqueueAction").and.callFake(function(action) {
                    var cb = action.getCallback("SUCCESS")
                    cb.fn.apply(cb.s, [{ getState : function(){ return "SUCCESS"; }, 
                                            getReturnValue: function(){ return "a0DC000000vc03tMAA";} 
                                        }]
                                );
                });
            })
            // Verify
            .then(function(component) {
                expect(component.get("v.accounts").length).toBe(2);
                done();
            })
            .catch(function(e) {
                done.fail(e);
            });
    });
});

I am testing a component where doInit() uses Promises:

doInit: function(cmp, event, helper) {
   helper.callServer(cmp);
}

to call 2 helper methods which call server actions

callServer: function(cmp) {
		var action = cmp.get("c.serverAction");
action.setCallback(this, function(response) {
            cmp.set("v.accounts", response.getReturnValue());
        });
        $A.enqueueAction(action);
    }

I get obscure JS errors, so I thought maybe this is not the right way to do it. Can you provide an example on how to mock/stub initialisation?

Build error: plugin salesforcedx is not digitally signed

While building my CI with Travis I got an error while installing Salesforce DX and I just noticed that this repository is also impacted by it (build is failing at time of writing).

When running sfdx plugins:install salesforcedxthe CLI will output a blocking prompt which breaks CI:

Installing plugin salesforcedx... Checking for digital signature.
This plugin is not digitally signed and its authenticity cannot be verified. Continue installation y/n?: 

I am bit surprised that this official plugin is not signed so perhaps it's a bug in the plugin build chain.

Here is how I fixed it based on the official DX doc:

  1. Create a plugin whitelist file named unsignedPluginWhiteList.json in the config directory with the following content:
[
    "salesforcedx"
]
  1. Move the whitelist file in a specific directory before running the plugin install command:
    mv config/unsignedPluginWhiteList.json $HOME/.config/sfdx/.

I hope that it helps.

sfdx force:lightning:test:install fails with "Cannot read property 'indexOf' of undefined"

I've been seeing this error more frequently lately:

$ sfdx force:lightning:test:install -u my_org

fails with

  ▸    Cannot read property 'indexOf' of undefined

I know it is a problem with the CLI, but this was intermittent and becoming more of a burden during CI testing (it will pass 1/10 times now)

Are there any suggestions on things like waiting time, retry logic, etc. after creating a new scratch org that I can employ in order to reduce the times this install fails?

Any help is greatly appreciated

Looking for reference about $T

Team,
I looked over the sample test resources and found $T namespace. Are there any reference about the methods in this namespace like $T.fireApplicationEvent? I would like to know what and how to use those methods.

Is there any way to locate the lightning components and trigger automated actions in it ?

We are trying hard to locate and handle the lightning components such as
lightning:button menu,
lightning:button Icon,
lightning:select,
lightning:tabs ,
lightning:layouts
and trigger automated actions in it.
When we try it from the DOM it says "undefined", we suspect that due to the locker services. Is there any way to handle these components. In this sample tests also we don't find any examples for these components locator also. Could any one please guide me on this ?

saucelabs environment vars

Hi,

I am trying to connect LTS with saucelabs.com, and I has successfully connected with this command:

sfdx force:lightning:test:run -f config.json

And the following configuration in config.json

{
  "webdriverio": {
    "host": "ondemand.saucelabs.com",
    "port": "80",
    "user": "saucelabs_user",
    "key": "secretkey",
    "desiredCapabilities": {
      "browserName": "chrome",
      "chromeOption": {
        "args": [ "--no-sandbox" ]
      }
    }
  }
}

This run :)

But the question is:

Can I use two environment variables instead of push these secrets to the git repository?

This is a Best Practices and it is very interesting for continuous integration environment.

Sample:

export SAUCE_USERNAME=saucelabs_user
export SAUCE_ACCESS_KEY=secretkey
sfdx force:lightning:test:run -f config.json

Thanks.

Executing force:lightning:test:run from Docker container results in Unknown Error (13)

I'm currently getting bitbucket pipelines set up and running in a CD environment, and using LightningTestService to run lightning component tests. Bitbucket pipelines runs in a docker container.

My script fails at the following:

sfdx force:lightning:test:run -a jasmineTests.app
Waiting to resolve the Lightning Experience-enabled custom domain........
ERROR running force:lightning:test:run: An error occurred when running Lightning tests. An unknown server-side error occurred while processing the command. (UnknownError:13)

I'm using the default jasmineTests.app that comes with the "LTSExamples" package, and when I issue that same command from my local machine, it works fine.

Is it possible that since the script requires a browser to open, that this won't work from a "headless flow" or container?

Unable to handle lightning:tab components

We have referred the workaround suggested for lightning buttons and tried up with aura:method to expose the controller actions. Now we have a case where we dont have logic defined in controller actions. Necessary items where defined in the lightning:tab itself.need to switch between the tabs.
sample snippet :

<lightning:tabset>
            <lightning:tab label="label1">
             </lightning:tab>
 <lightning:tab label="label2">
             </lightning:tab>
 </lightning:tabset>

Can you please suggest some workaround to handle the lightning:tab ?

How to interact with the custom components using LTS ?

For Example I am having component c:uiInputText which has a attribute "property". My custom component extends SFDC lightning component ui:inputText and I will set the value attribute via the property attribute my custom component.

Now when I tried to set the value for the custom component, I am not able to set and also I am not seeing any error. Any idea would be great

Sample snippet:

var ruleNameCMP = component.find("ruleid");
ruleNameCMP.set("v.property","value 1"));

test an init function

it would be nice if there was an example how to test an init function on a lightning component. I didn't see any of the sample components had init being using.

Example using config file for WebDriver settings

There doesn't seem to be any way to figure out how to configure the WebDriver settings.

When I run look at the documentation for sfdx force:lightning:test:run (https://developer.salesforce.com/docs/atlas.en-us.sfdx_cli_reference.meta/sfdx_cli_reference/cli_reference_force_lightning.htm#cli_reference_test_run) - there is a --configfile option that says the following:

Path to a test configuration file to configure WebDriver and other settings. For details, see the LTS documentation.

Where is this documentation? I am attempting to run this on a CI tool (like Jenkins) for automated testing and seeing the following error message:

ERROR: not found: java.

I assume it is because I need to install a WebDriver, but there doesn't seem to be any documentation around this. Could you please point me in the right direction?

mocha hooks failures not reported

According to https://github.com/mochajs/mocha/blob/master/lib/runner.js#L42-L54 there are a few events that can happen.

Currently, the mocha suite test reporter (https://github.com/forcedotcom/LightningTestingService/blob/master/lightning-component-tests/test/default/staticresources/lts_testutil.resource#L193-L212) uses the following event:

mochaRunner.on('test end', function (test) {

unfortunately, this does not include hook failures in the report.

My proposal would be to switch out the logic to something more like:

$T._convertMochaEventToTestResult = function(test) {
  console.log(test.state, test.title, '-' + test.duration + 'ms');
  return {
    FullName: test.parent.title + ' : ' + test.title,
    Outcome: test.state,
    RunTime: test.duration,
    Message: test.err ? test.err.message : null
  };
}

$T._sfdxReportForMocha = function (mochaRunner) {
        var run_results_full = { "tests": [] };
        mochaRunner.on('fail', function(test) {
            run_results_full.tests.push($T._convertMochaEventToTestResult(test));
        }).on('pass', function(test) {
            run_results_full.tests.push($T._convertMochaEventToTestResult(test));
        }).on('pending', function(test) {
            test.err = {
              message: ' # SKIP disabled by xit or similar'
            };
            run_results_full.tests.push($T._convertMochaEventToTestResult(test));
        }).on('end', function (suite) {
            setHiddenDivContent("run_results_full", JSON.stringify(run_results_full));
        });
    }

this captures both test failures and beforeEach failures

I can try to get a PR up sometime if others think this is useful

How to test behavior dependent on afterScriptsLoaded

Apologies in advance for the wordy post but I wanted to provide enough context. I've posted this as a question on StackExchange but haven't gotten any response there, so forgive me for repeating it here, but I'm having trouble finding enough examples of LTS use cases to help me figure this out. This is also somewhat related to Keith's question in #54 ...

I’m looking for help/examples for setting up tests of a component which calls a load() method via afterScriptsLoaded, then renders data based on the result of the load (which calls a server-side controller) — something like this:

Component

<ltng:require scripts="{!join(',',$Resource.Constants,$Resource.Utils)}" afterScriptsLoaded="{!c.load}"/>

<aura:attribute name="currencyOptions" type="OppActionOverrideController.CurrencyOption[]" description="List of currency options with user's preferred currency set to default"/>
<aura:attribute name="someOtherThing" type="String" description="This is just an example of something else to render"/>

<aura:attribute name="showCurrencyField" type="Boolean" default="false" description="Value set in the load() callback"/>
<aura:attribute name="showSomeOtherField" type="Boolean" default="false" description="Value set in the load() callback"/>

<div class="slds-grid slds-wrap">
    ....
    <aura:if isTrue="{!v.showCurrencyField}">
    <div class="slds-form-element">
        <ui:inputSelect aura:id="selectedCurrency" label="Currency" required="true">
            <aura:iteration items="{!v.currencyOptions}" var="curr">
                <ui:inputSelectOption text="{!curr.isoCode}" label="{!curr.isoCode}" value="{!curr.isDefault}"/>
            </aura:iteration>
        </ui:inputSelect>
    </div>
    </aura:if>

    <aura:if isTrue="{!v.showSomeOtherField}">
        <div aura:id="someOtherField">foobar</div>
    </aura:if>
    ....
</div>

Controller

load: function (component, event, handler) {
    var action = component.get("c.getComponentData");
    action.setCallback(this, function(response) {
        // ....do some validation, if response is successful....
        // set up currency options
        component.set('v.showCurrencyField', true);
        component.set('v.currencyOptions', currencyOptions);

        // set other things
        component.set('v.showSomeOtherField', true);
        component.set('v.someOtherThing', 'hello');
    });
    $A.enqueueAction(action);
}

Test suite

afterEach(function() {
    $T.clearRenderedTestComponents();
});
describe("Rendering the component", function() {
    var getComponentDataPayload = {
        currencyOptions: [
            {isoCode: "USD", isDefault: true},
            {isoCode: "EUR", isDefault: false},
            {isoCode: "GBP", isDefault: false},
        ]
    };
    var renderedComponent = null;

    beforeEach(function(done) {
        renderedComponent = null;
		
        $T.createComponent("c:MyComponent", {}, true)
        .then(function(component) {
            // I assign the component to a separate var so that it can be referenced in specs below, allows me to use a beforeEach instead of having this code in every spec
            renderedComponent = component;

            spyOn($A, "enqueueAction").and.callFake(function(action) {
                var callback = action.getCallback("SUCCESS");
                // The utility function here just takes the payload data and wraps it with the proper getState() and getReturnValue(), etc.
                callback.fn.apply(callback.s, [TestUtils.getMockedServerActionResult(true, "", getComponentDataPayload)]);
                done();
            });
        }).catch(funtion(e) {
            done.fail(e);
        });
    });

    it("renders the currency options", function(done) {
        expect(renderedComponent.find("selectedCurrency")).toBeDefined();
        done();
    });

    it("renders some other field", function(done) {
        expect(renderedComponent.find("someOtherField")).toBeDefined();
        done();
    });
});

The specific problem I’m struggling with is where to place the spyOn (either inside the createComponent callback as above, or before it, or elsewhere) and also where to call done() in the beforeEach. The way the example is defined above, the first spec passes. But when the second spec runs, the scripts are already loaded, so that load() call happens immediately, before the createComponent callback happens (and so the spy is not registered and the done() function inside it is never called). I’ve tried moving the spy outside of the createComponent callback and calling done() in different places, but each results in a condition where either the renderedComponent var is not defined by the time done() is called (and thus the specs fail) or the done() method is never called due to the order that things execute the second time through and I get a timeout.

Is there a better way to structure this spec so that the order of the load call in relation to when the component is done rendering can be more predictable? I prefer to keep my it blocks simple and re-render the component each time, and re-rendering the component with different data to test conditional display is required for this test.

UPDATE
After experimenting a bit more I've tried modifying the structure of the beforeEach to this:

beforeEach(function(done) {
	renderedComponent = null;

	spyOn($A, "enqueueAction").and.callFake(function(action) {
		var callback = action.getCallback("SUCCESS");
		// The utility function here just takes the payload data and wraps it with the proper getState() and getReturnValue(), etc.
    	callback.fn.apply(callback.s, [TestUtils.getMockedServerActionResult(true, "", getComponentDataPayload)]);
	});

	$T.createComponent("c:MyComponent", {}, true)
	.then(function(component) {
		// I assign the component to a separate var so that it can be referenced in specs below, allows me to use a beforeEach instead of having this code in every spec
		renderedComponent = component;

		return $T.waitFor(function() {
			return renderedComponent.find("selectedCurrency") !== undefined;
		});
	}).then(function() {
		done();
	}).catch(function(e) {
		done.fail(e);
	});
});

To summarize the difference from the above version, this moves registering the spy out of the createComponent callback, which ensures it always happens. Then I am using a bit of a hack with waitFor to make sure the pieces of the component under test have indeed been rendered before testing them. This seems to result in a consistent order of operations, but now I am seeing timeouts (using the LTS-defined 3s) with the $T.createComponent, but only when running three or more specs. The first two specs run quickly and without a problem.

I'm hoping that I'm missing something obvious with this setup, does anyone have any ideas or examples of doing something similar?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.