Scenario Based Interview Questions On Apex, Trigger, Batch Apex, Future Method, Test Class Updated 2024

In this blog post we are going to cover interview questions on triggers, batch apex, future method, test class, apex.


Scenario based interview questions on apex trigger in salesforce


1) What is trigger in Salesforce and what are trigger events?

We basically use triggers to perform an operation such as validation(Preventing wrong data entry), update (updating related records).

Following are the events on which trigger fires,

 Before insert

Before update

Before delete

After insert

After update

After delete

After undelete

 2) What are trigger context variables in Salesforce? 

Following are the Trigger context variable available,

 trigger.isbefore()

=> Checks if the trigger is in before mode, If the trigger is in before mode it will return true.

trigger.isafter()

=> Checks if the trigger is in after mode, If the trigger is in after mode it will return true.

trigger.isupdate()

=> Checks if the trigger is in update mode, If the trigger is in update mode it will return true.

trigger.isdelete()

=> Checks if the trigger is in delete mode, If the trigger is in delete mode it will return true.

trigger.isinsert()

=> Checks if the trigger is in insert mode, If the trigger is in insert mode it will return true.

trigger.isundelete()

=> Checks if the trigger is in undelete mode, If the trigger is in undelete mode it will return true.

trigger.isexecuting()

=> Checks if the apex class method is getting called from apex trigger, If getting called return true.

trigger.new()

=> Stores new list of  records.

trigger.newmap()

=> Stores new records with id's

trigger.old()

=> Stores old list of records.

trigger.oldmap()

=> Stores old records with id's.

operationType

=> Returns an enum of type System.TriggerOperation corresponding to the current operation.

Possible values of the System.TriggerOperation enum are: BEFORE_INSERT, BEFORE_UPDATE, BEFORE_DELETE,AFTER_INSERT, AFTER_UPDATE, AFTER_DELETE, and AFTER_UNDELETE. 

 size   

=> The total number of records in a trigger invocation, both old and new.

3) What is the difference between Trigger.new and Trigger.old and Trigger.newmap and Trigger.oldmap ?

Trigger.new returns new records and Trigger.old return data before updates were done.

 Trigger.newmap returns new records with id's and Trigger.oldmap return data before updates were done with id's.

4) Is the id of record changes if we undelete a deleted record?

No, It has the same id.

5) What is the use of trigger.isexecuting?

Suppose we have a method in apex class and we want this method to run only when the method is getting called from apex trigger than we can make use of trigger.isexecuting in apex class to check if the method is getting called from trigger .

6) How to restrict trigger to fire only once(Recursive trigger)? 

Refer article : How to avoid recursive trigger in Salesforce?

7) How many trigger we should write on one object?

 We should always follow the best practice and consider writing one trigger per object. If we have more than one trigger per object on same event say before insert than we cannot guarantee the order of execution.  

8) What is the difference between database.insert and insert?

 Using insert if one record fails entire operation is stopped and none of the record is inserted into database, whereas with databse.insert partial insertion is supported.

9) Is it possible to call batch class from trigger.

Yes.

10) What are the the context variable available with before insert event?

Only Trigger.new is available.

11) What are the the context variable available with after insert event?

Trigger.new and Trigger.newMap.

12) What are the the context variable available with before update event?

Trigger.new, Trigger.old, Trigger.newmap and Trigger.oldmap

13) What are the the context variable available with after update event?

Trigger.new, Trigger.old, Trigger.newmap and Trigger.oldmap

14) What are the the context variable available with before delete event?

Trigger.old and Trigger.oldMap.

15) What are the the context variable available with after delete event?

Trigger.old and Trigger.oldMap.

16) What are the the context variable available with after undelete event?

Trigger.new and Trigger.newMap.

17) What is the condition to call a method from trigger which is making callout?

The callout should be asynchronous.

18) What will you do if a method inside apex class need to be executed only when it is getting called from trigger?

We will use trigger.isexecuting in apex class to check if the method inside apex class is getting called from trigger and will execute the method if getting called from trigger.

19) What is "Trigger Handler Framework Salesforce"?

Refer article: Trigger Handler Framework Salesforce


Scenario based interview questions on future method in salesforce


20Why we cannot pass objects as arguments in future method? Is it possible to call future method from Batch class or another future method?

Object data might change between the time you call the future method and the time it actually executes. and hence we pass record id.

No, we cannot call future method from Batch class or another future method.

21) If downtime occurs and future method was running what will happen?

The Future method execution will be rolled back and will restart after downtime overs.

22) If the future method was queued before a service maintenance what will happen?

It will remains in queue and when maintenance is over and resources are available it will get execute.


Scenario based interview questions on batch apex in salesforce


23) What is batch apex in salesforce? 

 When we want to deal with large number of records we go for batch apex. The code inside batch class runs asynchronously i.e in future context. The governor limit are also more as compared to synchronous code. 

When we use batch apex we implements Database.batchable() interface and we have to include three methods and they are as follows:

1)start 
2)execute 
3)Finish 

  • Start method and finish method are called only once inside batch class. 
  • Start method collects the data for processing. 
  • Execute method performs operations. 
  • The order of execution is not guaranteed in execute method.
  • Finish method generally used for sending emails or calling another batch class when the current batch is completed. 

Syntax:

global class batch implements Database.Batchable < sObject > { 

global (Database.QueryLocator or  Iterable<sObject>)
start(Database.BatchableContext bc) { 

//query on object; 
//return Database.getQueryLocator(query); 

global void execute(Database.batchableContext bc, List < SObject > scope) { 

//some processing. 

global void finish(Database.BatchableContext bc) { 
//job such as sending email or calling another batch class 





For more details visit: Batch class in Salesforce 

24) What is database.stateful interface? 

Batch Apex is stateless.  Each execution of a batch Apex job is considered a discrete transaction. If we implements Database.Stateful we can maintained state across transactions. Using Database.Stateful only instance variable holds values static members does not hold values. If we want to count records as batch proceeds maintaining state is important as after one transaction new transaction will start and members will loose their values.

For more information visit: Database.Stateful in Batch Apex in Salesforce

25) How to write Test class for batch class? 

You need to call batch class from inside of test.starttest() and test.stoptest()
with below syntax,

@istest

public class testclass{

static testmethod void methodname1()
{
test.starttest();

batchClassName obj=new batchClassName ();
Id batchId=Database.executeBatch(obj);

test.stoptest();

}


}

26) Explain the concept of scope size in batch apex?

As we know default scope size is 200 i.e If no size is specified with the optional scope parameter of Database.executeBatch, Salesforce chunks the records returned by the start method into batches of 200 records.

When  an apex job is executed by setting some value for scope size it is not necessary that the number of record processed in one batch iteration will be same as that of scope size specified.

Records from the query locator are retrieved in chunks of given chunk size called retrieveChunkSize .

Chunks size available are 100,200,400.

Selection of chunk size depends on the scope size specified.


If 1 <= scopeSize <= 100, then retrieveChunkSize = 100

If 101 <= scopeSize <= 400, then retrieveChunkSize = 400
If 401 <= scopeSize <= 2000, then retrieveChunkSize = 2000

So Let say if we 285 records to be proceeds and we specify the scope size as 80 than the retrieveChunkSize  will be 100.

In this case the total number of batches will note be 4 i.e (285/80) but in this case it would be 3 retrieve chunks and 6 execute chunks so the total number of batches will be 6.

1. Retrieve chunk 1: retrieve first 100 records
Execute chunk 1: pass first 80 records to execute() method
Execute chunk 2: pass remaining 20 records from this retrieve chunk to execute() method

2. Retrieve chunk 2: retrieve next 100 records

Execute chunk 3: pass first 80 records to execute() method
Execute chunk 4: pass remaining 20 records from this retrieve chunk to execute() method

3. Retrieve chunk 3: retrieve next 85 records

Execute chunk 5: pass first 80 records to execute() method
Execute chunk 6: pass remaining 5 records from this retrieve chunk to execute() method

27) Let say we have 30 records, How many times the executes method will be called for below 2 queries?


A)   updateNameOfAccount obj=new updateNameOfAccount();
       Database.executeBatch(obj);

B)   Final Integer batchsize = 3;
       updateNameOfAccount obj=new updateNameOfAccount();
       Database.executeBatch(obj,batchsize);


In query (A) as batch size is not specified, so by default it will be considered as 200. so retrieve chunks will be 400. All 30 records will be retrieved in single chunk.

so now, 30/200 = 1 batches will be formed and hence execute method will be called 1 time.


In query (B) as the batch size is specified as 3, so retrieve chunk will be 100. All 30 records will be retrieved in single chunk.

so now, 30/3 = 10 batches will be formed and hence execute method will be called 10 times.

28) What is Database.BatchableContext?

All the methods in the Database.Batchable interface require a reference to a Database.BatchableContext object. 

This object is used to track the progress of the batch job.

getJobID returns the ID of the AsyncApexJob object associated with this batch job as a string.

For example,

public void finish(Database.BatchableContext bc){

            AsyncApexJob job = [SELECT Id, Status, NumberOfErrors,

            JobItemsProcessed,

            TotalJobItems, CreatedBy.Email

            FROM AsyncApexJob

            WHERE Id = :bc.getJobId()];

        // call some utility to send email

          Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();

        String[] toAddresses = new String[] {'Testabc@gmail.com'};

        mail.setToAddresses(toAddresses);

        mail.setSubject('Batch Status ' + job.Status + 'Record Processed ' + recordsProcessed );

        mail.setPlainTextBody('Total Jobs Processed: ' + job .TotalJobItems +   'with '+ job .NumberOfErrors + ' failures.');

        Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });

    }

}

29) Can we use public access modifier instead of global access modifier in batch apex?

Yes

30) Explain Database.executeBatch Method?
  • Database.executeBatch method is used begin a batch job.
  • When Database.executeBatch method is called Salesforce adds the process to the queue. Actual execution can be delayed and it depends on service availability.
  • It takes 2 parameters as shown in example below,
      updateNameOfAccount obj=new updateNameOfAccount();
      Database.executeBatch(obj,scope);

Where, obj is an instance of a class that implements the Database.Batchable interface and scope is an optional parameter.

Database.executeBatch method returns the ID of the AsyncApexJob object, which we can use for tracking the progress of the job as shown below.

ID batchprocessid = Database.executeBatch(obj);

31) What is the difference between Database.QueryLocator  or  Iterable<sObject> in below statement?

public (Database.QueryLocator | Iterable<sObject>) start(Database.BatchableContext bc) {}

Database.QueryLocator object is used when using a simple query (SELECT) to generate
the scope of objects in the batch job,If we use a QueryLocator object, the governor limit for
the total number of records retrieved by SOQL queries is bypassed. For example, a batch Apex job
for the Account object can return a QueryLocator for all account records (up to 50 million records) in an org. 

Iterable is used to create a complex scope for the batch job. We can also use the iterable to create our own custom process for iterating through the list. The governor limit for the total number of records retrieved by SOQL queries is still enforced using Iterable.

32) Is it possible to do callouts from batch apex?

Yes

33) Which interface need to be implemented in batch class to make callouts from batch apex?

We have to implement the interface Database.AllowsCallouts in batch apex if we want to do callouts from batch apex.

34) If the batch is executed without the optional scope parameter and If in batch apex suppose we have 600 jobs and there are total 200 records to be proceeds in each transaction, so in total we have 3 transaction. If first transaction succeeds but second fails so in this case the records update done in first transaction are rolled back or not?

It will not be rolled back.


35) What are the parameters in system.schedule(Parameters) represents?

system.schedule('jobName ', expression, instance of schedulable class);

JobName  represents the name for the job.
expression represents time and date at which batch should run.
"instance of schedulable class" represents instance of class  which need to be schedule.

36) What are the parameters in system.schedule(Parameters) represents?

system.schedule('jobName ', expression, instance of schedulable class);

JobName  represents the name for the job,
expression represents time and date at which batch should run,
"instance of schedulable class" represents instance of class  which need to be schedule.


Scenario based interview questions on test class in salesforce


37) What is test class in  Salesforce? 

When we are moving code from sandbox to production org we need to write a test class.

Whatever code we have written we need to ensure that each and every condition is correct
and we can create a dummy data for it.

The code must have 75% coverage to deploy it to production.

Points to remember:

1) Test class does not have access to organization data but if we write @isTest(seeAllData=true),
then we can access data in the test class as well.

2) As every organization have code limit by writing @isTest above test class, the limit will not be considered.

3) Every test class has a method declared with testmethod keyword and is static.

Syntax:

static testmethod void methodname()

{

}

38) What is test.starttest() and test.stoptest()? 

Whatever test we are performing we write the test inside of Test.starttest() and Test.stoptest.

Basically they help to create a fresh set of governing limit.

Each test method can call the start test and stop test only once.

39) What is the use of seeAllData=true ? 

If we are defining a test class with @isTest(SeeAllData=true) then we can access data in test class from the database under all method present in the test class. Under this case annotating a method with @isTest(SeeAllData=false) would be ignored and you can access database data inside this method as well.

Let's understand with an example.

@isTest(SeeAllData=true)

public class testclassexample {

static testmethod void testMethodFirst() {

contact obj = [SELECT Id, Name from contact where name='test' LIMIT 1];

//Accessing contact from database

}

@isTest(SeeAllData=false)

static testmethod void testMethodFirst() {

contact obj1 = [SELECT Id, Name from contact where name='test' LIMIT 1];

//Accessing contact from database although @isTest(SeeAllData=false) is applied for method but it will get ignored as test class is having @isTest(SeeAllData=true).

}

}

40) What is the use of seeAllData=false ? 

@isTest(SeeAllData=false)

If we are defining a test class with @isTest(SeeAllData=false) then we cannot access data in test class from the database under all method present in the test class. Under this case annotating a method with @isTest(SeeAllData=true) would not be ignored and you can access database data inside this method.

Let's understand with an example.

@isTest(SeeAllData=false)

public class testclassexample {

static testmethod void testMethodFirst() {

//You cannot access like this now.

contact obj = [SELECT Id, Name from contact where name='test' LIMIT 1];

//You need to create test data

Contact obj=new contact();

obj.name='test';

insert obj;

}

@isTest(SeeAllData=true)

static testmethod void testMethodFirst() {

contact obj1 = [SELECT Id, Name from contact where name='test' LIMIT 1];

//Accessing contact from database although @isTest(SeeAllData=false) is applied for class but it will get ignored.

}

}

41) What are test class best practices? 

1) We should always considered doing testing with bulk records.

2) We Should test "test cases" for both positive and negative test scenario.

3) Avoid using (SeeAllData=true) in test class because it might happen that the test class pass in sandbox but fails in production if data is not present in production.

4) Avoid using hardcoded id's in  test class.

42) What is @testSetup? 

Method that are annotated with @testSetup are used to create test data and we can this test data inside every method of the test class. The testSetup method is executed first in any test class before other methods.

43) Let say I have a test class in which I have created a testSetup method in which I am creating a contact record. Let say I have two test method inside my test class which is accessing this contact record. If i access this contact record in testmethod1() and made a update to the contact record from testSetup method and now I am accessing this contact in testmethod2(), so will I get the updated contact record or the original unmodified contact record in testmethod2()?

testMethod2() will  gets access to the original unmodified state of  record, this is because changes are rolled back after each test method finishes execution.

44) If the test class is having access to organization data using @isTest(SeeAllData=true) annotation, will the test class be able to support @testSetup method?

@testSetup method are not supported in this case.

44) How many @testSetup method are supported inside a test class?

One test setup method per test class.

45) Why is @TestVisible annotation used in test class?

Using @TestVisible annotation before variable or methods or inner classes inside apex class allows test class to access them. This annotation does not change the visibility of variable or methods or inner classes if accessed by non-test class.

Apex class:

public class apexClassExample{

@TestVisible private static integer rollNo=1;

}

Test class: 

@isTest

public class apexClassExampleTest{

static testmethod void methodName()

{

    Integer rollNo=apexClassExample.rollNo;

}


}

46) What is System.runAs() in test class?

Test class runs in system mode, System.runAs() allow us to run the test in context of current user where user 's record sharing is taken into account. User permission or field level permission are not taken into account.

47) What is the use of test.isrunningtest()? 

Sometimes it may happen that in test class you are not able to satisfy certain condition in apex class so under this case, we can bypass this condition by writing test.isrunningtest() in apex class.

Syntax:

In Apex under condition,

if(a=3 || test.isrunningtest())

{

}


Scenario based interview questions on apex in salesforce


48) Let say user do not have permission on a child object and he is having permission on parent object to read/create/edit/delete parent object, If I create a trigger on parent object to insert a child record after parent record is created, will it create a child record or not after user insert parent record manually?

It will create a child record (Trigger/apex class runs in system mode).

49) If in the above case from trigger I am calling apex class which is in "with sharing" mode and where I am inserting child record after parent is inserted manually by user so will it create a child record?

It will create a child record.(With sharing keyword has nothing to do with user permissions it only takes into account the sharing rules for the user.).

50) Let say if my apex class which is not declared with any keyword "With sharing" or "Without sharing"  is fetching opportunity records and the user with which this class is running does not hold any opportunity records or no opportunity record is shared with user, in this case the class will be able to fetch opportunity records since the apex class runs in system mode though the user have CRUD permissions or does not have CRUD permissions on opportunity.

51) Let say if my apex class is declared with "With Sharing" keyword and is fetching opportunity records and the user with which this class is running does not hold any opportunity records or no opportunity record is shared with user, in this case the class will not be able to fetch opportunity records though the user have CRUD permissions or does not have CRUD permissions on opportunity.

52) What are apex code best practices?

Here are the best Practices we should follow while writing apex code.

a) Bulkify the Code.

Bulkify here simply means writing code that handles more than one record at a time.

Below is an example of poorly written code that handles only one record at a time.

trigger contactTrigger on contact (before insert, before update) {

   //This only handles the first record in the Trigger.new collection, other records are not processed

   Contact con= Trigger.new[0];

   List<Contact> conList = [select id, firstname, lastname 

              from Contact where id= :con.Id];
}

Below is an example of code written to handle bulkification.

trigger contactTrigger on contact (before insert, before update) {

 List<Contact> conList =new List<Contact>();
   for(contact con:trigger.new)
       {
if(con.firstName="Test")
            {   con.booleanField=true;
    conList.add(con);
            }

       }
   update conList;
}

b) Avoid SOQL Queries or DML statements inside FOR Loops.


This is to take Governor Limit in consideration,

Governor limits are calculated at runtime. After the request is initiated (Trigger, Visualforce page, etc.), any Apex code executed in that transaction applies and shares the governor limits. 

SOQL queries per transaction.
100.(synchronous)
SOQL queries per transaction.
200(asynchronous)
dml statements per transaction
150

c) Use single trigger on object.


If we have multiple trigger on one object we cannot control the order of execution.

d) Querying object having more than 50,000 records.


The total number of records that can be queried by soql queries is 50,000 record. If we query more than 50,000 record we exceeds the heap limit.

//A runtime exception is thrown if this query returns enough records to exceed your heap limit.

Account[] accts = [SELECT id FROM account];

To avoid this we should use SOQL query for loop it can process multiple batches of record using call to query and query more.

for (List<Account> acct : [SELECT id, name FROM account

                            WHERE name LIKE 'Test']) {
    // Your logic here

}

For more details please visit --> SOQL List vs SOQL For Loop

e) Avoid hardcoding id's in apex code.

Instead we should use label or some other way to avoid hardcoding id's as these will results in improper processing on records if sandbox and production environment have different id's for the match we are doing in code.

Sample example below to match record type,

  List<RecordType> rtypes = [Select Name, Id From RecordType

                  where sObjectType='Contact' and isActive=true];

     Map<String,String> contactRecordTypes= new Map<String,String>{};

     for(RecordType rt: rtypes)
{

        contactRecordTypes.put(rt.Name,rt.Id);

        }

      for(contact a: Trigger.new)
  {

          if(a.RecordTypeId==contactRecordTypes.get('someRecordTypeName')){            

             
          }

     }


f) Use of the Limits Apex Methods.


Apex has a system class called Limits that let us identify the amount of resources used and amount of resource available to avoid hitting governor limit in a particular context.

System.debug('Total Number of SOQL Queries allowed in this Apex code context: ' +  Limits.getLimitQueries());

System.debug('Total Number of records that can be queried  in this Apex code context: ' +  Limits.getLimitDmlRows());

System.debug('Total Number of DML statements allowed in this Apex code context: ' +  Limits.getLimitDmlStatements() );

System.debug('Total Number of CPU usage time (in ms) allowed in this Apex code context: ' +  Limits.getLimitCpuTime());

System.debug('1. Number of Queries used in this Apex code so far: ' + Limits.getQueries());

System.debug('2. Number of rows queried in this Apex code so far: ' + Limits.getDmlRows());

System.debug('3. Number of DML statements used so far: ' +  Limits.getDmlStatements());  
System.debug('4. Amount of CPU time (in ms) used so far: ' + Limits.getCpuTime());

System.debug('Final heap size: ' +  Limits.getHeapSize());

g) Using @future
  • Methods with the future annotation cannot be used in Visualforce controllers in either getMethodName or setMethodName methods, nor in the constructor.
  • Methods with the future annotation cannot take sObjects or objects as arguments it always takes id's as argument.

Trigger:

trigger accountAsyncTrigger on Account (after insert, after update) {
  for(Account a: Trigger.new){
    // Invoke the @future method for each Account
    // This is inefficient and will easily exceed the governor limit of
    // at most 50 @future invocation per Apex transaction
    someClass.processAccount(a.id);
   }    
}

Apex:

global class someClass{


  @future
  public static void processAccount(Id accountId) {
// some code here
         }
}


Best way for future method invocation,

trigger accountAsyncTrigger on Account (after insert, after update) {
    //By passing the @future method a set of Ids, it only needs to be
    //invoked once to handle all of the data.
    someClass.processAccount(Trigger.newMap.keySet());
}

53) How to call Apex from a Process builder in Salesforce?

To call an apex method from process builder we need to define the method with @InvocableMethod in apex class. When a method is define with the mentioned annotation we can call this method from process builder using action type as Apex.

54) Is it possible to edit apex class in production?

No. we can edit in sandbox.

55) What is heap size limit error and how to avoid it?


56) What is the significance of governor limit in salesforce?

Governor limits are enforced to ensure that code runs correctly without any error. It is necessary to enforce governor limit since apex runs in a multitenant environment, multitenant here simply means a single instance of software runs on a server and serves multiple users at a time. The Apex runtime engine strictly enforces limits to ensure efficient performance.

57) List of the important governor limit in salesforce?

Some of the important limits are mentioned below.

SOQL queries per transaction  100(synchronous)

100 Select statement per apex transaction.

SOQL queries per transaction  200(asynchronous)

200 Select statement per apex transaction.

Number of record retrieve by SOQL query  50,000

DML statements per transaction  150

Number of records proceeds by DML statement  10000

Total number of SOSL query  20

Number of record retrieve by SOSL Statement  2000

Number of future method call per Apex transaction  50 (synchronous)

Number of future method call per Apex transaction  0 in batch and future contexts; 50 in queueable context

Number of Apex jobs in queue  50

Maximum CPU time on the Salesforce servers  10,000 milliseconds       

Maximum CPU time on the Salesforce servers → 60,000 milliseconds

Maximum execution time for each Apex transaction → 10 mins for both synchronous and asynchronous

Total number of callouts (HTTP requests or web services calls) in a transaction  100 for both synchronous and asynchronous.

Maximum cumulative timeout for all callouts (HTTP requests or Web services calls) in a transaction → 120 seconds for both synchronous and asynchronous.

Heap size limit  6 MB ( synchronous)

Heap size limit  12 MB ( asynchronous)

58) What are some of the best practices to avoid hitting governor limit?

1) Avoid writing for loop inside the method.

2) Use SOQL For Loop instead of a SOQL List For Loop to avoid heap size limit error.


3) Use Test.startTest() method inside test method to reset governor limits.

 
4) Do not update setup objects like user role with other objects in the same transaction.



For interview questions on AURA, LWC please visit below links.




14 comments:

  1. Helped me in getting my basics right. Please add more of such QAs

    ReplyDelete
  2. It is Very helpful to me,hope you can add more questions like this

    ReplyDelete
  3. all are useful questions.These questions are helpful to me.Thanks a lot

    ReplyDelete
  4. Really Yours was Unique resource than all resource in Latest Concepts. Please can you upload LG related Project based Scenarios in Different MENU like this. Really awesome blog.Thanks for proving.
    Your efforts will pay my huge Applaus.

    ReplyDelete
  5. These questions helped me allot please add more questions if possible on lightning and LWC.

    Thank you so much Sir:)

    ReplyDelete
  6. Thank you ,its very useful and helped me allot

    ReplyDelete
  7. Best set of questions , Really helpful.

    ReplyDelete
  8. Questions are really helpful and updated as well. Thank you!!

    ReplyDelete
  9. Thank you for the questions. Please add more on LWC

    ReplyDelete
  10. keep doing good work, thanks

    ReplyDelete