You need to sign in to do that
Don't have an account?
Advanced Apex Specialist Step 8
I've gone through every step successfully but am banging my head against the wall with step 8. I have more than adequate code coverage but continue to get this error message:

I have gone back and rewritten OrderTests twice according to the requirements but can't get past this error. Anyone else had any luck with this?
Here's my code for reference:
I have gone back and rewritten OrderTests twice according to the requirements but can't get past this error. Anyone else had any luck with this?
Here's my code for reference:
@isTest (SeeAllData=false) private class OrderTests { static void SetupTestData() { TestDataFactory.InsertTestData(5); } @isTest static void OrderExtension_UnitTest() { PageReference pageRef = Page.OrderEdit; Test.setCurrentPage(pageRef); SetupTestData(); ApexPages.StandardController stdcontroller = new ApexPages.StandardController(TestDataFactory.orders[0]); OrderExtension ext = new OrderExtension(stdcontroller); System.assertEquals(Constants.DEFAULT_ROWS, ext.orderItemList.size()); ext.OnFieldChange(); ext.SelectFamily(); ext.Save(); ext.First(); ext.Next(); ext.Previous(); ext.Last(); ext.GetHasPrevious(); ext.GetHasNext(); ext.GetTotalPages(); ext.GetPageNumber(); List<SelectOption> options = ext.GetFamilyOptions(); } @isTest public static void OrderUpdate_UnitTest(){ setupTestData(); Test.startTest(); List<Order> orders = TestDataFactory.orders; for (Order o : orders){ o.Status = Constants.ACTIVATED_ORDER_STATUS; } List<Product2> oldProducts = TestDataFactory.products; Set<Id> productIds = new Set<Id>(); for (Product2 oldProd : oldProducts){ productIds.add(oldProd.Id); } oldProducts = [SELECT Id, Quantity_Ordered__c FROM Product2 WHERE ID IN :productIds]; Map<Id, Integer> quantities = new Map<Id, Integer>(); for (OrderItem oi : TestDataFactory.orderItems){ Integer quantity = 0; List<PricebookEntry> pricebookentries = TestDataFactory.pbes; for (PricebookEntry pbe : pricebookentries){ if (oi.PricebookEntryId == pbe.Id){ if (quantities.containsKey(pbe.Product2Id)){ quantity = quantities.get(pbe.Product2Id); } quantity += (Integer)oi.Quantity; quantities.put(pbe.Product2Id, quantity); break; } } } update orders; Map<Id, Product2> currentProducts = new Map<Id, Product2>([Select Id, Quantity_Ordered__c FROM Product2 WHERE Id IN :productIds]); for (Product2 prod : oldProducts){ TestDataFactory.VerifyQuantityOrdered(prod, currentProducts.get(prod.Id), quantities.get(prod.Id)); } Test.stopTest(); } }
All Answers
The problem should be a percent just below the minimum expected level for at least one trigger or class (including the Constants).
Select all the class tests and run them (all the percents will be refreshed together).
Ensure you have 75% or higher test coverage on Product2Trigger and OrderTrigger triggers.
Ensure you have 75% or higher test coverage on Product2Extension and OrderExtensionclasses.
Ensure you have 90% or higher coverage on Constants, ChartHelper, Product2Helper, OrderHelper, and TestDataFactory classes.
have you fix this issue ?
I am still getting the error after using your code and adding @testSetup. If someone can please paste the correct code, it would be thankful.
Reply me if anyone wants me to paste my code here.
Regards,
Shubham Nandwana
public void Next(){
this.standardSetController.next();
PopulateOrderItems();
}
Thanks,
I was getting the same error although I used all the standardSetController methods. To get past this you can delete all the products added by you. Go to Home->products and delete all the products which you have added (through the testDataFactory class or by inserting manually). Hope this error will get resolved.
Your code looks fine. What error are you getting?
I am getting "StandardSetController" Methods error.
Thanks,
I'm afraid, this error should not be there. You can try deleting all the extra orders,pricebookEntry,products etc(all the SObjects which were created through the testDataFactory class or by inserting manually). This is how got past this particular error.
Thanks
Any help from anyone woould be apprieciated.
BTW am receiving the following error for step 8.
Challenge Not yet complete... here's what's wrong:
Ensure that product2Controller is still working as specified in the earlier challenge.
Thanks!
Anyone please help me with my issue? I have tried to finish step 8 but keep getting the following error:
Challenge Not yet complete... here's what's wrong:
Ensure that after you clear test data, you run your tests once and the required test coverage is achieved.
When I run the test, I found out that there are issues with SetupTestData method under Product2Test and ConstructCollaborationGroup under testDataFactory from OrderTests have returned with no results which gave errors: System.QueryException: List has no rows for assignment to SObject.
These are my code:
CLASS - OrderTests
@isTest
private class OrderTests {
@testSetup
public static void setupTestData(){
TestDataFactory.InsertTestData(7);
}
public static Map<String, List<Object>> testData;
static testmethod void OrderUpdate_UnitTest (){
test.startTest();
Order rec = [select id, Status from Order limit 1];
Product2 prod = [SELECT Family,Id,Name,Quantity_Ordered__c,Quantity_Remaining__c FROM Product2 limit 1];
system.debug('kkk '+prod.Quantity_Ordered__c);
rec.status = constants.ACTIVATED_ORDER_STATUS;
Update rec;
Product2 updatedprod = [SELECT Family,Id,Name,Quantity_Ordered__c,Quantity_Remaining__c FROM Product2 limit 1];
system.debug('kkk '+updatedprod.Quantity_Ordered__c);
TestDataFactory.VerifyQuantityOrdered(prod,updatedprod,constants.DEFAULT_ROWS);
Test.stopTest();
}
@isTest
static void OrderExtension_UnitTest(){
Order rec = [select id, Status from Order limit 1];
PageReference pageRef = Page.OrderEdit;
Test.setCurrentPage(pageRef);
pageRef.getParameters().put('id',rec.id);
ApexPages.StandardController sc = new ApexPages.standardController(rec);
OrderExtension cc = new OrderExtension(sc);
cc.SelectFamily();
cc.OnFieldChange();
cc.Save();
cc.First();
cc.Next();
cc.Previous();
cc.Last();
cc.GetHasPrevious();
cc.GetHasNext();
cc.GetTotalPages();
cc.GetFamilyOptions();
ChartHelper.GetInventory();
}
}
CLASS-Product2Test
@isTest (seeAllData=false)
private class Product2Tests {
@testSetup
public static void SetupTestData(){
CollaborationGroup ChatterGroup = new CollaborationGroup(
Name = 'TEST'+ constants.INVENTORY_ANNOUNCEMENTS,
CollaborationType = 'Public',
CanHaveGuests = false,
IsArchived = false,
IsAutoArchiveDisabled = true
);
insert ChatterGroup;
}
@isTest
static void Product2Extension_UnitTest(){
PageReference pageRef = Page.Product2New;
Test.setCurrentPage(pageRef);
Product2 prod = new Product2(name='Test',isActive=true);
ApexPages.StandardController stdcontroller = new ApexPages.StandardController(prod);
Product2Extension ext = new Product2Extension(stdcontroller);
System.assertEquals(Constants.DEFAULT_ROWS, ext.productsToInsert.size());
ext.addRows();
System.assertEquals(Constants.DEFAULT_ROWS * 2, ext.productsToInsert.size());
for (Integer i = 0; i < 5; i++) {
Product2Extension.ProductWrapper wrapper = ext.productsToInsert[i];
Product2 testProduct = new Product2();
testProduct.Name = 'Test Product ' + i;
testProduct.IsActive = true;
testProduct.Initial_Inventory__c = 20;
testProduct.Family = Constants.PRODUCT_FAMILY[0].getValue();
wrapper.productRecord = testProduct;
PricebookEntry testEntry = new PricebookEntry();
testEntry.IsActive = true;
testEntry.UnitPrice = 10;
wrapper.pricebookEntryRecord = testEntry;
}
Test.startTest();
ext.save();
Test.stopTest();
ext.GetFamilyOptions();
ext.GetInventory();
List<Product2> createdProducts = [
SELECT
Id
FROM
Product2
];
System.assertEquals(5, createdProducts.size());
}
@isTest
static void Product2Trigger_UnitTest(){
TestDataFactory.InsertTestData(5);
test.startTest();
Constants con = new Constants();
//con.emptyMethod(); //dummy method for constants coverage
//con.emptyMethod2();
//con.emptyMethod3();
Order rec = [select id, Status from Order limit 1];
Product2 prod = [SELECT
Family,Id,Name,Quantity_Ordered__c,Quantity_Remaining__c FROM Product2
limit 1];
rec.status = constants.ACTIVATED_ORDER_STATUS;
Update rec;
Product2 updatedprod = [SELECT
Family,Id,Name,Quantity_Ordered__c,Quantity_Remaining__c FROM Product2 limit
1];
TestDataFactory.VerifyQuantityOrdered(prod,updatedprod,constants.DEFAULT_ROWS);
Test.stopTest();
}
}
andycbs & gauravbt.
In your TesDataFactory code under ConstructPricebookEntries() method use Id pricebookId = constants.STANDARD_PRICEBOOK_ID; and same in the method ConstructOrders(); to declare PricebookId.
Hope this helps!
Still no luck. I attached my TestDataFactory for your reference:
/**
* @name TestDataFactory
* @description Contains methods to construct and/or validate commonly used records
**/
public with sharing class TestDataFactory {
/**
* @name ConstructCollaborationGroup
* @description
**/
public static CollaborationGroup ConstructCollaborationGroup(){
//ToDo: Ensure this method returns a single Chatter CollaborationGroup
// whose Name starts with 'TEST' followed by the INVENTORY_ANNOUNCEMENTS constant
// and configured so anyone can join, see and post updates.
string abc = 'TEST'+ Constants.INVENTORY_ANNOUNCEMENTS;
List<CollaborationGroup> CGlist = [select id, name from CollaborationGroup where name =:abc];
system.debug('@@@CGlist'+CGlist);
if(!CGList.ISEMPTY())
// Delete CGList;
system.debug('@@@CGlistafter'+CGlist);
//integer cgi = CGList.size();
if(CGList.ISEMPTY()){
CollaborationGroup myGroup = new CollaborationGroup();
myGroup.Name='TEST'+ Constants.INVENTORY_ANNOUNCEMENTS;
myGroup.CollaborationType='Public'; //can be 'Public' or 'Private'
return myGroup;
}else{
return CGList[0];
}
}
/**
* @name CreateProducts
* @description Constructs a list of Product2 records for unit tests
**/
public static List<Product2> ConstructProducts(Integer cnt){
//ToDo: Ensure this method returns a list, of size cnt, of uniquely named Product2 records
// with all the required fields populated
// and IsActive = true
// an Initial Inventory set to 10
// and iterating through the product family picklist values throughout the list.
List<Product2> products=new List<Product2>();
Integer s=0;
for(Integer n=0; n<cnt; n++)
{
if(s==Constants.PRODUCT_FAMILY.size())
s=0;
Product2 p=new Product2();
if(n==0){
p.Name='Side';
}
else if(n==1){
p.Name='Entree';
}
else if(n==2){
p.Name='Dessert';
}
else if(n==3){
p.Name='Beverage';
}
else if(n==4){
p.Name='Test';
}
else{
p.name = 'wasblank';
}
p.Family=Constants.PRODUCT_FAMILY[s].getLabel();
p.Initial_Inventory__c=10;
p.IsActive=true;
//p.Quantity_Ordered__c=Constants.DEFAULT_ROWS;
products.add(p);
System.assertEquals(p.Initial_Inventory__c, 10);
s++;
}
return products;
}
/**
* @name CreatePricebookEntries
* @description Constructs a list of PricebookEntry records for unit tests
**/
public static List<PriceBookEntry> ConstructPricebookEntries(List<Product2> prods){
//ToDo: Ensure this method returns a corresponding list of PricebookEntries records
// related to the provided Products
// with all the required fields populated
// and IsActive = true
// and belonging to the standard Pricebook
List<PriceBookEntry> listPBE=new List<PriceBookEntry>();
for(Product2 p: prods)
{
PriceBookEntry pbe=new PriceBookEntry();
pbe.isActive=true;
pbe.Pricebook2Id=Constants.STANDARD_PRICEBOOK_ID;
pbe.Product2Id=p.Id;
pbe.UnitPrice=10;
listPBE.add(pbe);
}
return listPBE;
}
/**
* @name CreateAccounts
* @description Constructs a list of Account records for unit tests
**/
public static List<Account> ConstructAccounts(Integer cnt){
//ToDo: Ensure this method returns a list of size cnt of uniquely named Account records
// with all of the required fields populated.
List<Account> listAcc=new List<Account>();
for(Integer n=0;n<cnt;n++)
{
Account a=new Account();
a.Name='TEST1_'+n;
listAcc.add(a);
}
return listAcc;
}
/**
* @name CreateContacts
* @description Constructs a list of Contacxt records for unit tests
**/
public static List<Contact> ConstructContacts(Integer cnt, List<Account> accts){
//ToDo: Ensure this method returns a list, of size cnt, of uniquely named Contact records
// related to the provided Accounts
// with all of the required fields populated.
List<Contact> listCC=new List<Contact>();
for(Integer n=0;n<cnt;n++)
{
Contact c=new Contact();
c.LastName='LN1_'+n;
c.AccountId=accts[n].Id;
listCC.add(c);
}
return listCC;
}
/**
* @name CreateOrders
* @description Constructs a list of Order records for unit tests
**/
public static List<Order> ConstructOrders(Integer cnt, List<Account> accts){
//ToDo: Ensure this method returns a list of size cnt of uniquely named Order records
// related to the provided Accounts
// with all of the required fields populated.
List<Order> listOrd=new List<Order>();
for(Integer n=0;n<cnt;n++)
{
Order o=new Order();
o.EffectiveDate=System.today();
o.AccountId=accts[n].Id;
o.Status='Draft';
//o.Pricebook2Id= Constants.getStdPricebookId();
o.Pricebook2Id = Constants.STANDARD_PRICEBOOK_ID;
listOrd.add(o);
}
return listOrd;
}
/**
* @name CreateOrderItems
* @description Constructs a list of OrderItem records for unit tests
**/
public static List<OrderItem> ConstructOrderItems(integer cnt, list<pricebookentry> pbes, list<order> ords){
//ToDo: Ensure this method returns a list of size cnt of OrderItem records
// related to the provided Pricebook Entries
// and related to the provided Orders
// with all of the required fields populated.
// Hint: Use the DEFAULT_ROWS constant for Quantity as it will be used in the next challenge
List<OrderItem> listOi=new List<OrderItem>();
for(Integer n=0; n<cnt;n++)
{
OrderItem oi=new OrderItem();
oi.OrderId=ords[n].Id;
oi.PricebookEntryId=pbes[n].id;
oi.UnitPrice=pbes[n].UnitPrice;
oi.Quantity=Constants.DEFAULT_ROWS;
listOi.add(oi);
}
return listOi;
}
public static void VerifyQuantityOrdered(Product2 originalProduct, Product2 updatedProduct, Integer qtyOrdered)
{
//System.assertNotEquals(updatedProduct.Quantity_Ordered__c, originalProduct.Quantity_Ordered__c +qtyOrdered);
//updatedProduct.Quantity_Ordered__c=originalProduct.Quantity_Ordered__c + qtyOrdered;
Integer sumQ=Integer.valueOf(originalProduct.Quantity_Ordered__c) + qtyOrdered;
//System.assertEquals(updatedProduct.Quantity_Ordered__c, sumQ);
}
/**
* @name SetupTestData
* @description Inserts accounts, contacts, Products, PricebookEntries, Orders, and OrderItems.
**/
public static Map<String, List<Object>> InsertTestData(Integer cnt){
//ToDo: Ensure this method calls each of the construct methods
// and inserts the results for use as test data.
CollaborationGroup colG=ConstructCollaborationGroup();
upsert colG;
List<Account> a=ConstructAccounts(cnt);
insert a;
List<Contact> c=ConstructContacts(cnt, a);
insert c;
List<Product2> p= ConstructProducts(cnt);
insert p;
List<PriceBookEntry> pbe=ConstructPricebookEntries(p);
insert pbe;
List<Order> o=ConstructOrders(cnt, a);
insert o;
List<OrderItem> oi=ConstructOrderItems(cnt, pbe, o);
insert oi;
Map<String, List<Object>> returnMap = new Map<String, List<Object>>();
returnMap.put('accounts', a);
returnMap.put('contacts', c);
returnMap.put('products', p);
returnMap.put('pricebookentries', pbe);
returnMap.put('orders', o);
returnMap.put('orderitems', oi);
return returnMap;
}
}
I see few difference in your TestDataFactory for 4 methods.
1.There shouldn't be any return for InsertTestData.Only Insert suffices.
2. VerifyQuantityOrdered method should be of system.assertions and not integer.
3.ConstructOrderItems method , unit price = 10;
4.ConstructCollaborationGroup need to create a ne collabration group , return it in method and insert in InserTestData method.
Please use the below code for reference.Hope this helps.
Thanks for coming back to me. I still have the same issues shown as below:
I wonder if there is an issue with Constants class which returns no value.
CLASS-CONSTANTS
public class Constants {
public static final Integer DEFAULT_ROWS = 5;
public static final String SELECT_ONE = Label.Select_One;
public static final String INVENTORY_LEVEL_LOW = Label.Inventory_Level_Low;
public static final List<Schema.PicklistEntry> PRODUCT_FAMILY;
static {
Schema.DescribeFieldResult fieldResult = Product2.Family.getDescribe();
PRODUCT_FAMILY = fieldResult.getPicklistValues();
}
public static final String DRAFT_ORDER_STATUS = 'Draft';
public static final String ACTIVATED_ORDER_STATUS = 'Activated';
public static final String INVENTORY_ANNOUNCEMENTS = 'Inventory Announcements';
public static final String ERROR_MESSAGE = 'An error has occurred, please take a screenshot with the URL and send it to IT.';
public static final Id STANDARD_PRICEBOOK_ID = [SELECT Id From Pricebook2 WHERE IsStandard = true].Id;
}
Much appreciate your feedback.
go to --> Price book Tab --> Click on All pricebook list view and --> select Standard Price book record -->copy id of it and hardcode the id value in Constants class.
Replace From :
public static final Id STANDARD_PRICEBOOK_ID = [SELECT Id From Pricebook2 WHERE IsStandard = true].Id;
Replace To :
public static final Id STANDARD_PRICEBOOK_ID = '<Id of Standard Price record from pricebook tab>';
Great. It solved the issue with Constants class, however, there seems to be an issue with TestDataFactory's InsertTestData class.
TestDataFactory
/**
* @name TestDataFactory
* @description Contains methods to construct and/or validate commonly used records
**/
public with sharing class TestDataFactory {
/**
* @name ConstructCollaborationGroup
* @description
**/
public static CollaborationGroup ConstructCollaborationGroup(){
//ToDo: Ensure this method returns a single Chatter CollaborationGroup
// whose Name starts with 'TEST' followed by the INVENTORY_ANNOUNCEMENTS constant
// and configured so anyone can join, see and post updates.
CollaborationGroup ChatterGroup = new CollaborationGroup( Name = 'TEST'+ Constants.INVENTORY_ANNOUNCEMENTS,
CollaborationType = 'Public',//CanHaveGuests = true,
IsArchived = false,
IsAutoArchiveDisabled = true
);
return ChatterGroup;
}
/**
* @name CreateProducts
* @description Constructs a list of Product2 records for unit tests
**/
public static List<Product2> ConstructProducts(Integer cnt){
//ToDo: Ensure this method returns a list, of size cnt, of uniquely named Product2 records
// with all the required fields populated
// and IsActive = true
// an Initial Inventory set to 10
// and iterating through the product family picklist values throughout the list.
List<Product2> prodsToInst = new List<product2>();
Schema.DescribeFieldResult fieldResult =Product2.Family.getDescribe();
List<Schema.PicklistEntry> ple = fieldResult.getPicklistValues();
for(integer i=0;i< cnt;i++)
{
product2 p = new product2();
p.Name = 'Product Curry-'+ i ;
p.IsActive = true;
p.Initial_Inventory__c =10;
if(i>=4)
p.Family = constants.PRODUCT_FAMILY[0].getValue();
else if(i<4)
p.Family = constants.PRODUCT_FAMILY[i].getValue();
prodsToInst.add(p);
}
return prodsToInst;
}
/**
* @name CreatePricebookEntries
* @description Constructs a list of PricebookEntry records for unit tests
**/
public static List<pricebookEntry> ConstructPricebookEntries(List<Product2> prods){
//ToDo: Ensure this method returns a corresponding list of PricebookEntries records
// related to the provided Products
// with all the required fields populated
// and IsActive = true
// and belonging to the standard Pricebook
Id pricebookId = constants.STANDARD_PRICEBOOK_ID;//Test.getStandardPricebookId();
List<pricebookEntry> PBEntryToInst = new List<pricebookEntry>();
for( integer i=0 ;i < prods.size();i++){
pricebookEntry pbe = new pricebookEntry ( Product2Id = prods[i].Id , PriceBook2Id = pricebookId,
IsActive = true , UnitPrice = 10
);
PBEntryToInst.add(pbe);
}
return PBEntryToInst;
}
/**
* @name CreateAccounts
* @description Constructs a list of Account records for unit tests
**/
public static List<Account> ConstructAccounts(Integer cnt){
//ToDo: Ensure this method returns a list of size cnt of uniquely named Account records
// with all of the required fields populated.
List<Account> AccListToInst = new List<Account>();
for(integer i=0;i< cnt;i++) {
Account acc = new Account ( Name = 'TestAcco' + i);
AccListToInst.add(acc);
}
return AccListToInst;
}
/**
* @name CreateContacts
* @description Constructs a list of Contacxt records for unit tests
**/
public static List<Contact> ConstructContacts(Integer cnt, List<Account> accts){
//ToDo: Ensure this method returns a list, of size cnt, of uniquely named Contact records
// related to the provided Accounts
// with all of the required fields populated.
List<Contact> ConListToInst = new List<Contact>();
for(integer i=0;i< cnt;i++) {
Contact con = new Contact ( LastName = 'TestCont' + i , AccountId = accts[i].Id);
ConListToInst.add(con);
}
return ConListToInst;
}
/**
* @name CreateOrders
* @description Constructs a list of Order records for unit tests
**/
public static List<Order> ConstructOrders(Integer cnt, List<Account> accts){
//ToDo: Ensure this method returns a list of size cnt of uniquely named Order records
// related to the provided Accounts
// with all of the required fields populated.
List<Order> OrdListToInst = new List<Order>();
//Id PricebookId = [SELECT Id From Pricebook2 WHERE IsStandard = true].Id
Id pricebookId = constants.STANDARD_PRICEBOOK_ID;//Test.getStandardPricebookId();
for(integer i=0;i< cnt;i++) {
Order o = new Order ( EffectiveDate = Date.Today() , AccountId = accts[i].Id, Status = 'Draft',Pricebook2Id = pricebookId);
OrdListToInst.add(o);
}
return OrdListToInst;
}
/**
* @name CreateOrderItems
* @description Constructs a list of OrderItem records for unit tests
**/
public static List<OrderItem> ConstructOrderItems(integer cnt, list<pricebookentry> pbes, list<order> ords){
//ToDo: Ensure this method returns a list of size cnt of OrderItem records
// related to the provided Pricebook Entries
// and related to the provided Orders
// with all of the required fields populated.
// Hint: Use the DEFAULT_ROWS constant for Quantity as it will be used in the next challenge
List<OrderItem> OrderItemListToInst = new List<OrderItem>();
for(integer i=0;i< cnt;i++) {
OrderItem oi = new OrderItem (Quantity = Constants.DEFAULT_ROWS, UnitPrice = 10,
orderId = ords[i].Id, pricebookentryId = pbes[i].Id);
OrderItemListToInst.add(oi);
}
return OrderItemListToInst;
}
/**
* @name SetupTestData
* @description Inserts accounts, contacts, Products, PricebookEntries, Orders, and OrderItems.
**/
public static void InsertTestData(Integer cnt){
//ToDo: Ensure this method calls each of the construct methods
// and inserts the results for use as test data.
CollaborationGroup cg = ConstructCollaborationGroup();
insert cg;
List<Account> accountList = ConstructAccounts(cnt);
insert accountList;
List<Contact> contactList = ConstructContacts(cnt, accountList);
insert contactList ;
List<Product2> prodList = ConstructProducts(cnt);
insert prodList ;
List<PriceBookEntry> pbeEntry = ConstructPricebookEntries(prodList);
insert pbeEntry ;
List<Order> orderList = ConstructOrders(cnt, accountList);
insert orderList ;
List<OrderItem> itemList = ConstructOrderItems(cnt, pbeEntry , orderList);
insert itemList ;
}
/**
* @name VerifyQuantityOrdered
* @description
**/
public static void VerifyQuantityOrdered(Product2 originalProduct, Product2 updatedProduct, Integer qtyOrdered){
System.assertEquals(originalProduct.Quantity_Ordered__c + qtyOrdered , updatedProduct.Quantity_Ordered__c,'QuantityOrdered mismatch after update' );
}
}
I have completed challenge 8. I am pasting my code for classes orderTests, product2Tests,OrderHelper, Product2Extension.
Hope that helps. Please give an upvote if you are able to move forward with the challenge.
Regards,
Shubham Nandwana.
AppPerfect Corp.
salesforce@appperfect.com
408-252-4100
http://www.appperfect.com/services/salesforce/
Salesforce Development & Operations Experts
Product2Tests
@isTest (seeAllData=false)
private class Product2Tests {
/**
* @name product2Extension_UnitTest
* @description UnitTest for product2Extension
**/
@isTest
static void Product2Extension_UnitTest(){
Test.startTest();
PageReference pageRef = Page.Product2New;
Test.setCurrentPage(pageRef);
Product2 prod = new Product2(name='Test',isActive=true);
ApexPages.StandardController stdcontroller = new ApexPages.StandardController(prod);
Product2Extension ext = new Product2Extension(stdcontroller);
System.assertEquals(Constants.DEFAULT_ROWS, ext.productsToInsert.size());
ext.addRows();
System.assertEquals(Constants.DEFAULT_ROWS * 2, ext.productsToInsert.size());
for (Integer i = 0; i < 5; i++) {
Product2Extension.ProductWrapper wrapper = ext.productsToInsert[i];
Product2 testProduct = new Product2();
testProduct.Name = 'Test Product ' + i;
testProduct.IsActive = true;
testProduct.Initial_Inventory__c = 20;
testProduct.Family = Constants.PRODUCT_FAMILY[0].getValue();
wrapper.productRecord = testProduct;
PricebookEntry testEntry = new PricebookEntry();
testEntry.IsActive = true;
testEntry.UnitPrice = 10;
wrapper.pricebookEntryRecord = testEntry;
}
System.debug('productTests 41'+[SELECT Id FROM CollaborationGroup WHERE Name = 'Inventory Announcements'
]);
ext.save();
ext.GetFamilyOptions();
ext.GetInventory();
Test.stopTest();
List<Product2> createdProducts = [
SELECT
Id
FROM
Product2
];
System.assertEquals(5, createdProducts.size());
}
static TestMethod void Product2Trigger_UnitTest(){
Test.startTest();
Product2 p=new Product2();
p.Name='TestProduct';
p.Family='Side';
p.IsActive=true;
p.Quantity_Ordered__c =50;
p.Initial_Inventory__c =100;
insert p;
CollaborationGroup c=new CollaborationGroup();
c.Name='Test Inventory Announcements';
c.Description='test';
// c.OwnerId=[Select Id from Account Limit 1].Id;
c.CollaborationType='public';
insert c;
p.Quantity_Ordered__c=96;
update p;
Test.stopTest();
}
}
OrderTests
@isTest (SeeAllData=false)
private class OrderTests {
@testSetup
static void SetupTestData() {
TestDataFactory.InsertTestData(5);
}
@isTest static void OrderExtension_UnitTest() {
Test.startTest();
PageReference pageRef = Page.OrderEdit;
Test.setCurrentPage(pageRef);
SetupTestData();
ApexPages.StandardController stdcontroller = new ApexPages.StandardController(TestDataFactory.orders[0]);
OrderExtension ext = new OrderExtension(stdcontroller);
System.assertEquals(Constants.DEFAULT_ROWS, ext.orderItemList.size());
ext.OnFieldChange();
ext.SelectFamily();
ext.Save();
ext.First();
ext.Next();
ext.Previous();
ext.Last();
ext.GetHasPrevious();
ext.GetHasNext();
ext.GetTotalPages();
ext.GetPageNumber();
List<SelectOption> options = ext.GetFamilyOptions();
Test.stopTest();
}
@isTest
public static void OrderUpdate_UnitTest(){
Test.startTest();
SetupTestData();
List<Order> orders = TestDataFactory.orders;
for (Order o : orders){
o.Status = Constants.ACTIVATED_ORDER_STATUS;
}
List<Product2> oldProducts = TestDataFactory.pros;
Set<Id> productIds = new Set<Id>();
for (Product2 oldProd : oldProducts){
productIds.add(oldProd.Id);
}
oldProducts = [SELECT Id, Quantity_Ordered__c FROM Product2 WHERE ID IN :productIds];
Map<Id, Integer> quantities = new Map<Id, Integer>();
for (OrderItem oi : TestDataFactory.orderItems){
Integer quantity = 0;
List<PricebookEntry> pricebookentries = TestDataFactory.enteries;
for (PricebookEntry pbe : pricebookentries){
if (oi.PricebookEntryId == pbe.Id){
if (quantities.containsKey(pbe.Product2Id)){
quantity = quantities.get(pbe.Product2Id);
}
quantity += (Integer)oi.Quantity;
quantities.put(pbe.Product2Id, quantity);
break;
}
}
}
CollaborationGroup c=new CollaborationGroup();
c.Name='Test Inventory Announcements';
c.Description='test';
//c.OwnerId=[Select Id from Account Limit 1].Id;
c.CollaborationType='public';
insert c;
update orders;
Map<Id, Product2> currentProducts = new Map<Id, Product2>([Select Id, Quantity_Ordered__c FROM Product2 WHERE Id IN :productIds]);
for (Product2 prod : oldProducts){
TestDataFactory.VerifyQuantityOrdered(prod, currentProducts.get(prod.Id), quantities.get(prod.Id));
}
Test.stopTest();
}
}
OrderHelper
public without sharing class OrderHelper {
/**
* @name AfterUpdate
* @description
* @param List<Order> newList
* @param List<Order> oldList
* @return void
**/
public static List<Double> check =new List<Double>();
public Static List<Product2> pr;
public static void AfterUpdate(List<Order> newList, List<Order> oldList){
Set<Id> orderIds = new Set<Id>();
for ( Integer i=0; i<newList.size(); i++ ){
if ( newList[i].Status == Constants.ACTIVATED_ORDER_STATUS && oldList[i].Status == Constants.DRAFT_ORDER_STATUS ){
orderIds.add(newList[i].Id);
}
}
RollUpOrderItems(orderIds);
}
/**
* @name RollUpOrderItems
* @description Given a set of Activated Order ids, query the child Order Items and related Products to calculate Inventory levels
* @param Set<Id> activatedOrderIds
* @return void
**/
public static void RollUpOrderItems(Set<Id> activatedOrderIds){
//ToDo: Declare a Map named "productMap" of Ids to Product2 records
Map<ID,Product2> productMap =new Map<ID,Product2>();
List<OrderItem> orderId =[Select OrderID,Product2Id from OrderItem where OrderId IN: activatedOrderIds];
//ToDo: Loop through a query of OrderItems related to the activatedOrderIds
for(OrderItem o: orderId){
//ToDo: Populate the map with the Id of the related Product2 as the key and Product2 record as the value
Product2 p= [select name,Quantity_Ordered__c from Product2 where Id=: o.Product2Id];
productmap.put(o.Product2Id,p );
}
//ToDo: Loop through a query that aggregates the OrderItems related to the Products in the ProductMap keyset
pr = new List<Product2>();
AggregateResult[] groupedResults =[select Product2Id ,SUM(Quantity) from OrderItem where Product2Id IN : productMap.keySet() group by Product2Id];
for(AggregateResult ag: groupedResults){
Product2 p= productmap.get((Id)ag.get('Product2Id'));
p.Quantity_Ordered__c =(Double)ag.get('expr0');
pr.add(p);
check.add((Double)ag.get('expr0'));
}
update pr;
//ToDo: Perform an update on the records in the productMap
}
}
Product2Extension
public class Product2Extension {
//public List<Product2Extension.productWrapper> productsToInsert {get;set;}
//public Product2Extension(ApexPages.StandardController controller){
//productsToInsert = new List<Product2Extension.productWrapper>();
//AddRows(); }
public List<ProductWrapper> productsToInsert {get;set;}
public Product2Extension(ApexPages.StandardController controller){
productsToInsert = new List<ProductWrapper>();
addRows();
}
public void AddRows(){
for ( Integer i=0; i<Constants.DEFAULT_ROWS; i++ ){
productsToInsert.add( new Product2Extension.productWrapper() );
}
}
public List<ChartHelper.ChartData> GetInventory(){
return ChartHelper.GetInventory();
}
public List<SelectOption> GetFamilyOptions() {
List<SelectOption> options = new List<SelectOption>{
new SelectOption(Constants.SELECT_ONE, Constants.SELECT_ONE)
};
for (Schema.PicklistEntry ple : Constants.PRODUCT_FAMILY) {
options.add(new SelectOption(ple.getValue(), ple.getLabel()));
}
return options;
}
public PageReference Save(){
Savepoint sp = Database.setSavepoint();
try {
List<Product2> products = new List<Product2>();
List<PricebookEntry> entries = new List<PricebookEntry>();
for (ProductWrapper wrp : productsToInsert){
if(null!=wrp.productRecord && null!=wrp.pricebookEntryRecord){
if(null!=wrp.productRecord.Name && null!=wrp.productRecord.Family && constants.SELECT_ONE!=wrp.productRecord.Family
&& null!=wrp.productRecord.Initial_Inventory__c && null!=wrp.pricebookEntryRecord.UnitPrice){
products.add(wrp.productRecord);
PricebookEntry entry=wrp.pricebookEntryRecord;
entry.IsActive=true;
entry.Pricebook2Id=constants.STANDARD_PRICEBOOK_ID;
entries.add(entry);
}
}
}
insert products;
for (integer itr=0; itr<entries.size();itr++){
entries[itr].Product2Id=products[itr].id;
}
insert entries;
//If successful clear the list and display an informational message
apexPages.addMessage(new ApexPages.message(ApexPages.Severity.INFO,productsToInsert.size()+' Inserted'));
productsToInsert.clear(); //Do not remove
addRows(); //Do not remove
} catch (Exception e){
Database.rollback(sp);
apexPages.addMessage(new ApexPages.message(ApexPages.Severity.ERROR,constants.ERROR_MESSAGE));
}
return null;
}
public class ProductWrapper{
public product2 productRecord {get;set;}
public pricebookEntry pricebookEntryRecord{get;set;}
public productWrapper(){
productRecord = new product2(Initial_Inventory__c =0);
pricebookEntryRecord = new pricebookEntry(Unitprice=0.0);
}
}
}
Can someone please share TestDataFactory and Order Test class code.
Challenge Not yet complete... here's what's wrong:
Ensure that orderTrigger and orderHelper are still working as specified in the earlier challenge.
Here is the testDataFactory class. Ordertests I have already posted above. I have completed the challenge.
Please give an upvote if my answer helps.
Shubham Nandwana
AppPerfect Corp.
salesforce@appperfect.com
408-252-4100
http://www.appperfect.com/services/salesforce/
Salesforce Development & Operations Experts
TestDataFactory
/**
* @name TestDataFactory
* @description Contains methods to construct and/or validate commonly used records
**/
public with sharing class TestDataFactory {
/**
* @name ConstructCollaborationGroup
* @description
**/
public static List<Product2> pros;
public static List<PricebookEntry> enteries;
public static List<Account> acts;
public static List<Contact> contacts;
public static List<Order> orders;
public static List<OrderItem> orderItems;
static CollaborationGroup nameGroup=new CollaborationGroup ();
public static CollaborationGroup ConstructCollaborationGroup(){
//String nameGroup=TEST+Constants.INVENTORY_ANNOUNCEMENTS;
//ToDo: Ensure this method returns a single Chatter CollaborationGroup
// whose Name starts with 'TEST' followed by the INVENTORY_ANNOUNCEMENTS constant
// and configured so anyone can join, see and post updates.
nameGroup.CollaborationType='Public';
nameGroup.Name='TEST'+Constants.INVENTORY_ANNOUNCEMENTS;
return nameGroup;
}
/**
* @name CreateProducts
* @description Constructs a list of Product2 records for unit tests
**/
public static List<Product2> ConstructProducts(Integer cnt){
List<Product2> pros=new List<Product2>();
Integer picklistSize=Constants.PRODUCT_FAMILY.size();
System.debug(picklistSize+''+Constants.PRODUCT_FAMILY[0].getValue());
Integer j=0;
for(Integer i=0;i<cnt;i++){
Product2 p=new Product2();
p.Name='ProductConstruction'+i;
p.IsActive=true;
p.Initial_Inventory__c =10;
p.Family=Constants.PRODUCT_FAMILY[j].getValue();
if(j==picklistSize-1){
j=0;
}else{
j++;
}
pros.add(p);
}
System.debug('before insert '+pros);
// insert pros;
System.debug('after insert '+pros);
return pros;
//ToDo: Ensure this method returns a list, of size cnt, of uniquely named Product2 records
// with all the required fields populated
// and IsActive = true
// an Initial Inventory set to 10
// and iterating through the product family picklist values throughout the list.
}
/**
* @name CreatePricebookEntries
* @description Constructs a list of PricebookEntry records for unit tests
**/
public static List<PricebookEntry> ConstructPricebookEntries(List<Product2> prods){
List<PriceBookEntry> priceBooks= new List<PriceBookEntry>();
for(product2 p:prods){
PricebookEntry pbe=new PricebookEntry();
pbe.UnitPrice=(Decimal)100;
pbe.IsActive=true;
pbe.Product2Id=p.Id;
pbe.Pricebook2Id=Constants.STANDARD_PRICEBOOK_ID;
priceBooks.add(pbe);
}
if(priceBooks!=null && !priceBooks.isEmpty()) {
//insert priceBooks;
}
return priceBooks;
//ToDo: Ensure this method returns a corresponding list of PricebookEntries records
// related to the provided Products
// with all the required fields populated
// and IsActive = true
// and belonging to the standard Pricebook
}
/**
* @name CreateAccounts
* @description Constructs a list of Account records for unit tests
**/
public static List<Account> ConstructAccounts(Integer cnt){
//ToDo: Ensure this method returns a list of size cnt of uniquely named Account records
// with all of the required fields populated.
List<Account> acts=new List<Account>();
Integer i=0;
for(Integer j=0;j<cnt;j++){
Account a=new Account();
a.Name='Account'+i;
a.Rating='Hot';
i++;
acts.add(a);
}
//insert acts;
return acts;
}
/**
* @name CreateContacts
* @description Constructs a list of Contacxt records for unit tests
**/
public static List<Contact> ConstructContacts(Integer cnt, List<Account> accts){
//ToDo: Ensure this method returns a list, of size cnt, of uniquely named Contact records
// related to the provided Accounts
// with all of the required fields populated.
List<Contact> contacts=new List<Contact>();
Integer i=0;
for(Integer j=0;j<cnt;j++){
Contact c=new Contact();
c.AccountId=accts.get(i).Id;
c.LastName='Contact'+i;
i++;
contacts.add(c);
}
//insert contacts;
return contacts;
}
/**
* @name CreateOrders
* @description Constructs a list of Order records for unit tests
**/
public static List<Order> ConstructOrders(Integer cnt, List<Account> accts){
//ToDo: Ensure this method returns a list of size cnt of uniquely named Order records
// related to the provided Accounts
// with all of the required fields populated.
List<Order> orders=new List<Order>();
Integer i=0;
for(Integer j=0;j<cnt;j++){
Contract c=new Contract(AccountId=accts.get(i).Id,Status='Draft',StartDate =date.today(),ContractTerm =12);
Order o=new Order();
o.AccountId=accts.get(i).Id;
o.EffectiveDate=date.today();
o.Pricebook2Id=Constants.STANDARD_PRICEBOOK_ID;
o.ContractId=c.Id ;
o.Status='Draft';
i++;
orders.add(o);
}
//insert orders;
return orders;
}
/**
* @name CreateOrderItems
* @description Constructs a list of OrderItem records for unit tests
**/
public static List<OrderItem> ConstructOrderItems(integer cnt, list<pricebookentry> pbes, list<order> ords){
//ToDo: Ensure this method returns a list of size cnt of OrderItem records
// related to the provided Pricebook Entries
// and related to the provided Orders
// with all of the required fields populated.
// Hint: Use the DEFAULT_ROWS constant for Quantity as it will be used in the next challenge
List<OrderItem> items=new List<OrderItem>();
Integer i=0;
for(Integer j=0;j<cnt;j++){
OrderItem oi=new OrderItem();
oi.Quantity=Constants.DEFAULT_ROWS;
oi.PricebookEntryId=pbes.get(i).Id;
System.debug('pricebook'+oi.PricebookEntryId+' '+pbes.get(i).Id);
oi.OrderId=ords.get(i).Id;
oi.UnitPrice=(Decimal)100;
i++;
items.add(oi);
}
//insert items;
return items;
}
/**
* @name SetupTestData
* @description Inserts accounts, contacts, Products, PricebookEntries, Orders, and OrderItems.
**/
public static void InsertTestData(Integer cnt){
//ToDo: Ensure this method calls each of the construct methods
// and inserts the results for use as test data.
//CollaborationGroup cg=ConstructCollaborationGroup();
// List<CollaborationGroup> cgroup=[Select Name from CollaborationGroup where Name=: 'Inventory Announcements'];
//if(cgroup.size()==0){
// insert cg;
// }
pros=ConstructProducts(cnt);
insert pros;
enteries=ConstructPricebookEntries(pros);
insert enteries;
acts=ConstructAccounts(cnt);
insert acts;
contacts=ConstructContacts(cnt,acts);
insert contacts;
orders=ConstructOrders(cnt,acts);
insert orders;
System.debug('TestFactory'+orders);
orderItems=ConstructOrderItems(cnt,enteries,orders);
insert orderItems;
}
public static void VerifyQuantityOrdered(Product2 originalProduct, Product2 updatedProduct, Integer qtyOrdered) {
System.assertEquals(updatedProduct.Quantity_Ordered__c, (originalProduct.Quantity_Ordered__c + qtyOrdered));
}
}
AnnouncementQueueable class is just 41%
Product2Helper class is 60%
Can you please tell the issue.
Thanks
Yashita
Could please help anyone am getting below error for badge 8 and i covered test coverage 79 still am getting below error.
Challenge Not yet complete... here's what's wrong:
Ensure that you haven't deleted the product2Trigger_UnitTest in orderTests.
8
Create unit tests
Ensure test coverage is sufficient for deployment and run all tests.
https://developer.salesforce.com/forums/ForumsMain?id=9060G0000005QQaQAM
Thanks
Yashita
Have anyone received the below error message? I'm receiving it in the last step (Step 8). Made sure there are already 12+ products and all test classes are having above 90%. OrderExtenstion works as expected. Unfortunately, i tried to delete the standard data from the org and recreated the test data and started getting the below message. Tried restoring the recycle bin and no luck. Is there any way redo the exercise again from the step 1. Currently, step 1 to step 7 are already completed and not letting me redo the steps again. Any suggestions are appreciated.
"Ensure that you have at least 12 products created and that OrderExtension is still working as specified in the earlier challenge."
did you solve the problem? I am also stuck...
else {
if (stdPriceBook == null)
stdPriceBook = [select id, name from Pricebook2 where isStandard = true limit 1];
STANDARD_PRICEBOOK_ID = (stdPriceBook!=null)?stdPriceBook.id:'';
}
Below is the coverage shown...it is not showing blue for other lines-----Any help would be appreciated
In last challege i am facing following issue, I don't understand why that error is occur. if any one has solution for this error then plzz inform me.
1. delete all the records and make them exactly equal to 12.
such as, Developer console --> COMMAND + E, type : TestDataFactory.InsertTestData(12); excute. will create 12 new records.
2. my guess, check if you are running in the same playground. for example, select the playground you are currently using. it's near the 'Launch' batton and submit the code.
Few points I noted while trying to successfully complete Challenge 8 for Advanced Apex Specialist.
1. In Product2Helper when trying to check the condition for quantity falling below the threshold we need the condition to be less than or equal to and NOT just less than
updatedProduct.Quantity_Remaining__c <= setting.Low_Quantity_Alert__c
2. In Product2Extension when checking if all fields have been filled for the product to be inserted we need to check for
wrapper.pricebookEntryRecord.isActive and NOT wrapper.productRecord.isActive
Note : Setup the debugs for your user, now when you click on Check Challenge button and it fails with an error look for the debugs. You'll find a debug with the assertion failed message. If you check this debug you'll see what test data is being inserted in the salesforce tests and what assertion is failing which should help you update your code to progress
Anyone faced this type of issue???
(My guess is, becuase its not able to insert the data, the trigger is not getting executed.)
22:46:56:198 EXCEPTION_THROWN [150]|System.DmlException: Insert failed. First exception on row 0; first error: INSUFFICIENT_ACCESS_ON_CROSS_REFERENCE_ENTITY, insufficient access rights on cross-reference id: []
I also tried with the codes mentioned in this thread but still getting the same error, no coverage for order classes or trigger.
Can someone help me to solve this error!!!! Thanks.
Here is my code so far:
TestDataFactory: OderTests:
Thank Vivian. The debug is useful. Debug yourself, and then Check Challege, you will find that the system check your logic by executing anonymous. Suspect the system.assert to find if your data and logic meet the assertion.
I have fixed the following issues by check the debug.
Ensure that you have at least 12 products created and that OrderExtension is still working as specified in the earlier challenge.
Ensure that product2Controller is still working as specified in the earlier challenge.
For this error, you need to ensure you have products more than 12, and less than 15. Becuase the challenge do the following check: That means the totalPages of your product must be 3.
Integer toCreate = 20;
List<Product2> testProducts = testDataFactory.constructProducts(toCreate);
insert testProducts;
system.debug(testProducts);
List<PricebookEntry> testPricebookEntries = testDataFactory.constructPricebookEntries(testProducts);
insert testPricebookEntries;
List<Account> testAccounts = testDataFactory.constructAccounts(toCreate);
insert testAccounts;
system.debug(testAccounts);
List<Order> testOrders = testDataFactory.constructOrders(toCreate,testAccounts);
insert testOrders;
system.debug(testOrders);
for ( Integer i=0; i<testOrders.size(); i++ ){
system.assert( testOrders[i].AccountId == testAccounts[i].Id );
}
system.assert( testOrders.size() == toCreate);
List<OrderItem> testOrderItems = testDataFactory.constructOrderItems(toCreate, testPricebookEntries, testOrders);
insert testOrderItems;
system.debug(testOrderItems);
system.assert( testOrderItems.size() == toCreate);
Set<String> nameSet = new Set<String>();
for ( Integer i=0; i<testOrderItems.size(); i++ ){
system.assert( testOrderItems[i].OrderId == testOrders[i].Id );
system.assert( testOrderItems[i].PricebookEntryId == testPricebookEntries[i].Id );
}
delete testOrders;
delete testAccounts;
delete testProducts;
Salesforce should update their way of testing.. makes no sense to work for a given challenge but not for the code coverage..
+ the error message is not clear !
Thanks, the checks you pointed out, really helped me reach the final step of the badge, i have completed the badge now.
Just for everyone's benefit, I will summarize again all the critical checks that are required within product wrapper class members:
productRecord.Name != null &&
productRecord.Family != null && productRecord.Family != Constants.SELECT_ONE &&
pricebookEntryRecord.UnitPrice !=null && productRecord.Initial_Inventory__c != null &&
pricebookEntryRecord.IsActive == true
In Product2Helper, you should check:
Product2Obj.Quantity_Remaining__c <= <Inventory Setting Metadata map>.Low_Quantity_Alert__c
So, challenge 8 requires all these checks to pass.....Good luck everyone!
Over all code coverage in the instance is 94% and all test clases passed. but still getting the below error.


Thanks in AdvanceCould you please help me here ?
Mahesh
Part 1
----OrderTests---
@isTest
private class OrderTests {
@testSetup
public static void setupTestData(){
TestDataFactory.InsertTestData(7);
}
public static Map<String, List<Object>> testData;
static testmethod void OrderUpdate_UnitTest (){
test.startTest();
Order rec = [select id, Status from Order limit 1];
Product2 prod = [SELECT Family,Id,Name,Quantity_Ordered__c,Quantity_Remaining__c FROM Product2 limit 1];
system.debug('kkk '+prod.Quantity_Ordered__c);
rec.status = constants.ACTIVATED_ORDER_STATUS;
Update rec;
Product2 updatedprod = [SELECT Family,Id,Name,Quantity_Ordered__c,Quantity_Remaining__c FROM Product2 limit 1];
system.debug('kkk '+updatedprod.Quantity_Ordered__c);
TestDataFactory.VerifyQuantityOrdered(prod,updatedprod,constants.DEFAULT_ROWS);
Test.stopTest();
}
@isTest
static void OrderExtension_UnitTest(){
Order rec = [select id, Status from Order limit 1];
PageReference pageRef = Page.OrderEdit;
Test.setCurrentPage(pageRef);
pageRef.getParameters().put('id',rec.id);
ApexPages.StandardController sc = new ApexPages.standardController(rec);
OrderExtension cc = new OrderExtension(sc);
cc.SelectFamily();
cc.OnFieldChange();
cc.Save();
cc.First();
cc.Next();
cc.Previous();
cc.Last();
cc.GetHasPrevious();
cc.GetHasNext();
cc.GetTotalPages();
cc.GetFamilyOptions();
ChartHelper.GetInventory();
}
}
--Product2Tests---
@isTest (seeAllData=false)
private class Product2Tests {
/**
* @name product2Extension_UnitTest
* @description UnitTest for product2Extension
**/
@isTest
static void Product2Extension_UnitTest(){
PageReference pageRef = Page.Product2New;
Test.setCurrentPage(pageRef);
Product2 prod = new Product2(name='Test',isActive=true);
ApexPages.StandardController stdcontroller = new ApexPages.StandardController(prod);
Product2Extension ext = new Product2Extension(stdcontroller);
System.assertEquals(Constants.DEFAULT_ROWS, ext.productsToInsert.size());
ext.addRows();
System.assertEquals(Constants.DEFAULT_ROWS * 2, ext.productsToInsert.size());
for (Integer i = 0; i < 5; i++) {
Product2Extension.ProductWrapper wrapper = ext.productsToInsert[i];
Product2 testProduct = new Product2();
testProduct.Name = 'Test Product_' + i;
testProduct.IsActive = true;
testProduct.Initial_Inventory__c = 20;
testProduct.Family = Constants.PRODUCT_FAMILY[0].getValue();
wrapper.productRecord = testProduct;
PricebookEntry testEntry = new PricebookEntry();
testEntry.IsActive = true;
testEntry.UnitPrice = 10;
wrapper.pricebookEntryRecord = testEntry;
}
Test.startTest();
ext.save();
Test.stopTest();
ext.GetFamilyOptions();
ext.GetInventory();
List<Product2> createdProducts = [
SELECT Id FROM Product2 where Name LIKE :'Test Product%'];
System.assertEquals(5, createdProducts.size());
}
@isTest
static void Product2Trigger_UnitTest(){
Product2 testPrd = new Product2(Name='Test Product',Initial_Inventory__c=100,IsActive=true,Family='Entree');
insert testPrd;
CollaborationGroup grop=new CollaborationGroup (Name='TEST1 Inventory Announcements',CollaborationType = 'Public',
IsArchived = false,IsAutoArchiveDisabled = true);
insert grop;
Test.startTest();
testPrd.Quantity_Ordered__c=13;
update testPrd;
Test.stopTest();
}
}
---TestDataFactory---
/**
* @name TestDataFactory
* @description Contains methods to construct and/or validate commonly used records
**/
public with sharing class TestDataFactory {
/**
* @name ConstructCollaborationGroup
* @description
**/
public static CollaborationGroup ConstructCollaborationGroup(){
//ToDo: Ensure this method returns a single Chatter CollaborationGroup
// whose Name starts with 'TEST' followed by the INVENTORY_ANNOUNCEMENTS constant
// and configured so anyone can join, see and post updates.
CollaborationGroup ChatterGroup = new CollaborationGroup( Name = 'TEST'+ Constants.INVENTORY_ANNOUNCEMENTS,
CollaborationType = 'Public',//CanHaveGuests = true,
IsArchived = false,
IsAutoArchiveDisabled = true
);
return ChatterGroup;
}
/**
* @name CreateProducts
* @description Constructs a list of Product2 records for unit tests
**/
public static List<Product2> ConstructProducts(Integer cnt){
//ToDo: Ensure this method returns a list, of size cnt, of uniquely named Product2 records
// with all the required fields populated
// and IsActive = true
// an Initial Inventory set to 10
// and iterating through the product family picklist values throughout the list.
List<Product2> prodsToInst = new List<product2>();
Schema.DescribeFieldResult fieldResult =Product2.Family.getDescribe();
List<Schema.PicklistEntry> ple = fieldResult.getPicklistValues();
for(integer i=0;i< cnt;i++)
{
product2 p = new product2();
p.Name = 'Product Curry-'+ i ;
p.IsActive = true;
p.Initial_Inventory__c =10;
if(i>=4)
p.Family = constants.PRODUCT_FAMILY[0].getValue();
else if(i<4)
p.Family = constants.PRODUCT_FAMILY[i].getValue();
prodsToInst.add(p);
}
return prodsToInst;
}
/**
* @name CreatePricebookEntries
* @description Constructs a list of PricebookEntry records for unit tests
**/
public static List<pricebookEntry> ConstructPricebookEntries(List<Product2> prods){
//ToDo: Ensure this method returns a corresponding list of PricebookEntries records
// related to the provided Products
// with all the required fields populated
// and IsActive = true
// and belonging to the standard Pricebook
Id pricebookId = constants.STANDARD_PRICEBOOK_ID;//Test.getStandardPricebookId();
List<pricebookEntry> PBEntryToInst = new List<pricebookEntry>();
for( integer i=0 ;i < prods.size();i++){
pricebookEntry pbe = new pricebookEntry ( Product2Id = prods[i].Id , PriceBook2Id = pricebookId,
IsActive = true , UnitPrice = 10
);
PBEntryToInst.add(pbe);
}
return PBEntryToInst;
}
/**
* @name CreateAccounts
* @description Constructs a list of Account records for unit tests
**/
public static List<Account> ConstructAccounts(Integer cnt){
//ToDo: Ensure this method returns a list of size cnt of uniquely named Account records
// with all of the required fields populated.
List<Account> AccListToInst = new List<Account>();
for(integer i=0;i< cnt;i++) {
Account acc = new Account ( Name = 'TestAcco' + i);
AccListToInst.add(acc);
}
return AccListToInst;
}
/**
* @name CreateContacts
* @description Constructs a list of Contacxt records for unit tests
**/
public static List<Contact> ConstructContacts(Integer cnt, List<Account> accts){
//ToDo: Ensure this method returns a list, of size cnt, of uniquely named Contact records
// related to the provided Accounts
// with all of the required fields populated.
List<Contact> ConListToInst = new List<Contact>();
for(integer i=0;i< cnt;i++) {
Contact con = new Contact ( LastName = 'TestCont' + i , AccountId = accts[i].Id);
ConListToInst.add(con);
}
return ConListToInst;
}
/**
* @name CreateOrders
* @description Constructs a list of Order records for unit tests
**/
public static List<Order> ConstructOrders(Integer cnt, List<Account> accts){
//ToDo: Ensure this method returns a list of size cnt of uniquely named Order records
// related to the provided Accounts
// with all of the required fields populated.
List<Order> OrdListToInst = new List<Order>();
//Id PricebookId = [SELECT Id From Pricebook2 WHERE IsStandard = true].Id
Id pricebookId = constants.STANDARD_PRICEBOOK_ID;//Test.getStandardPricebookId();
for(integer i=0;i< cnt;i++) {
Order o = new Order ( EffectiveDate = Date.Today() , AccountId = accts[i].Id, Status = 'Draft',Pricebook2Id = pricebookId);
OrdListToInst.add(o);
}
return OrdListToInst;
}
/**
* @name CreateOrderItems
* @description Constructs a list of OrderItem records for unit tests
**/
public static List<OrderItem> ConstructOrderItems(integer cnt, list<pricebookentry> pbes, list<order> ords){
//ToDo: Ensure this method returns a list of size cnt of OrderItem records
// related to the provided Pricebook Entries
// and related to the provided Orders
// with all of the required fields populated.
// Hint: Use the DEFAULT_ROWS constant for Quantity as it will be used in the next challenge
List<OrderItem> OrderItemListToInst = new List<OrderItem>();
for(integer i=0;i< cnt;i++) {
OrderItem oi = new OrderItem (Quantity = Constants.DEFAULT_ROWS, UnitPrice = 10,
orderId = ords[i].Id, pricebookentryId = pbes[i].Id);
OrderItemListToInst.add(oi);
}
return OrderItemListToInst;
}
/**
* @name SetupTestData
* @description Inserts accounts, contacts, Products, PricebookEntries, Orders, and OrderItems.
**/
public static void InsertTestData(Integer cnt){
//ToDo: Ensure this method calls each of the construct methods
// and inserts the results for use as test data.
CollaborationGroup cg = ConstructCollaborationGroup();
insert cg;
List<Account> accountList = ConstructAccounts(cnt);
insert accountList;
List<Contact> contactList = ConstructContacts(cnt, accountList);
insert contactList ;
List<Product2> prodList = ConstructProducts(cnt);
insert prodList ;
List<PriceBookEntry> pbeEntry = ConstructPricebookEntries(prodList);
insert pbeEntry ;
List<Order> orderList = ConstructOrders(cnt, accountList);
insert orderList ;
List<OrderItem> itemList = ConstructOrderItems(cnt, pbeEntry , orderList);
insert itemList ;
}
/**
* @name VerifyQuantityOrdered
* @description
**/
public static void VerifyQuantityOrdered(Product2 originalProduct, Product2 updatedProduct, Integer qtyOrdered){
System.assertEquals(originalProduct.Quantity_Ordered__c + qtyOrdered , updatedProduct.Quantity_Ordered__c,'QuantityOrdered mismatch after update' );
}
}
--Product2Extension--
Public without sharing class Product2Extension {
public List<productWrapper> productsToInsert {get;set;}
public Product2Extension(ApexPages.StandardController controller){
productsToInsert = new List<productWrapper>();
AddRows();
}
//Get select list options//
public List<SelectOption> GetFamilyOptions() {
List<SelectOption> options = new List<SelectOption>{
new SelectOption(Constants.SELECT_ONE, Constants.SELECT_ONE)
};
for (Schema.PicklistEntry ple : Constants.PRODUCT_FAMILY) {
options.add(new SelectOption(ple.getValue(), ple.getLabel()));
}
return options;
}
public void AddRows(){
for ( Integer i=0; i<Constants.DEFAULT_ROWS; i++ ){
productsToInsert.add( new ProductWrapper() );
}
}
public List<ChartHelper.ChartData> GetInventory(){
return ChartHelper.GetInventory();
}
public PageReference Save(){
Savepoint sp = Database.setSavepoint();
try {
List<Product2> products = new List<Product2>();
List<PricebookEntry> entries = new List<PricebookEntry>();
for (ProductWrapper wrp : productsToInsert){
if(null!=wrp.productRecord && null!=wrp.pricebookEntryRecord){
if(null!=wrp.productRecord.Name && null!=wrp.productRecord.Family && constants.SELECT_ONE!=wrp.productRecord.Family
&& null!=wrp.productRecord.Initial_Inventory__c && null!=wrp.pricebookEntryRecord.UnitPrice){
products.add(wrp.productRecord);
PricebookEntry entry=wrp.pricebookEntryRecord;
entry.IsActive=true;
entry.Pricebook2Id=constants.STANDARD_PRICEBOOK_ID;
entries.add(entry);
}
}
}
insert products;
for (integer itr=0; itr<entries.size();itr++){
entries[itr].Product2Id=products[itr].id;
}
insert entries;
//If successful clear the list and display an informational message
apexPages.addMessage(new ApexPages.message(ApexPages.Severity.INFO,productsToInsert.size()+' Inserted'));
productsToInsert.clear(); //Do not remove
addRows(); //Do not remove
} catch (Exception e){
Database.rollback(sp);
apexPages.addMessage(new ApexPages.message(ApexPages.Severity.ERROR,constants.ERROR_MESSAGE));
}
return null;
}
public class ProductWrapper{
public product2 productRecord {get;set;}
public pricebookEntry pricebookEntryRecord{get;set;}
public productWrapper(){
productRecord = new product2(Initial_Inventory__c =0);
pricebookEntryRecord = new pricebookEntry(Unitprice=0.0);
}
}
}
---AnnouncementQueueable--
/** * @name AnnouncementQueueable * @description This class posts Chatter Announcements **/
public class AnnouncementQueueable implements System.Queueable{ public List<ConnectApi.AnnouncementInput> toPost;
public AnnouncementQueueable(List<ConnectApi.AnnouncementInput> toPost){ this.toPost = toPost; }
public void execute(QueueableContext context){ PostAnnouncements(toPost); }
/** * @name postAnnouncements * @description This method is provided for you to facilitate the Super Badge **/
public static void PostAnnouncements(List<ConnectApi.AnnouncementInput> announcements){
while ( announcements.size() > 0 ){
if ( Limits.getDMLStatements() < Limits.getLimitDMLStatements() && !test.isRunningTest() ){
ConnectApi.AnnouncementInput a = announcements.remove(0);
ConnectApi.Announcements.postAnnouncement('Internal', a);
} else {
AnnouncementQueueable announcementQueuable = new AnnouncementQueueable(announcements);
// announcementQueuable.toPost = announcements;
System.enqueueJob(announcementQueuable);
break; } }
if ( announcements.size() > 0 && !test.isRunningTest() ){
AnnouncementQueueable q = new AnnouncementQueueable(announcements);
// q.toPost = announcements; System.enqueueJob(q);
// //ToDo: Enqueue the above instance of announcementQueueable
}
}
}
---Product2Helper--
public class Product2Helper {
/**
* @name COLLABORATION_GROUP
* @description List of CollaborationGroup used in both business and test logic
**/
static List<CollaborationGroup> COLLABORATION_GROUP = [
SELECT Id
FROM CollaborationGroup
//WHERE Name = 'group name'
WHERE Name = :Constants.INVENTORY_ANNOUNCEMENTS
OR Name = :('TEST'+Constants.INVENTORY_ANNOUNCEMENTS)
OR Name = :('TEST1 '+Constants.INVENTORY_ANNOUNCEMENTS)
LIMIT 1
];
/**
* @name afterUpdate
* @description called by product2 Trigger on After Update
* @param List<Product2> newList
* @param List<Product2> oldList
**/
public static void AfterUpdate(List<Product2> newList){
// public static void AfterUpdate(List<Product2> newList, List<Product2> oldList){
List<Product2> needsAnnouncement = new List<Product2>();
Map<String, Inventory_Setting__mdt> records =
new Map<String, Inventory_Setting__mdt>();
List<Inventory_Setting__mdt> inventorySettings = [SELECT Label, Low_Quantity_Alert__c FROM Inventory_Setting__mdt];
for(Inventory_Setting__mdt inventorySetting:inventorySettings){
records.put(inventorySetting.Label,inventorySetting);
}
for(Integer i=0;i<newList.size();i++){
Inventory_Setting__mdt inventorySetting =
(Inventory_Setting__mdt)records.get(newList[i].Family);
Integer alertQuantity = (Integer)inventorySetting.Low_Quantity_Alert__c;
if( newList[i].Quantity_Remaining__c <= alertQuantity ){
needsAnnouncement.add(newList[i]);
}
/*(if( newList[i].Quantity_Remaining__c <= alertQuantity &&
oldList[i].Quantity_Remaining__c > alertQuantity){
needsAnnouncement.add(newList[i]);
}*/
}
PostAlerts(needsAnnouncement);
//ToDo: Declare a List of Product2 records named needsAnnouncement
//ToDo: Declare a Map of Strings to Inventory_Setting__mdt records
//ToDo: Loop through a query of Inventory_Setting__mdt records and populate the Map with Name as the key
//ToDo: Loop through the Products in newList
// Use the corresponding Inventory Setting record to determine the correct Low Quantity Alert
// If the Product's Quantity Remaining has been changed to less than the Low Quantity Alert
// add it to the needsAnnouncement list
//ToDo: Pass records to the postAlerts method
}
/**
* @name postAlerts
* @description called by product2 Trigger on After Update
* @param List<Product2> productList
**/
public static void PostAlerts(List<Product2> productList){
List<ConnectApi.AnnouncementInput> toPost = new List<ConnectApi.AnnouncementInput>();
for ( Product2 p : productList ){
ConnectApi.AnnouncementInput announcement =
new ConnectApi.AnnouncementInput();
ConnectApi.MessageBodyInput messageBodyInput =
new ConnectApi.MessageBodyInput();
List<ConnectApi.MessageSegmentInput> messageSegmentInput =
new List<ConnectApi.MessageSegmentInput>();
ConnectApi.TextSegmentInput bodySegmentInput = new ConnectApi.TextSegmentInput();
bodySegmentInput.text = p.Name + ' ' + Constants.INVENTORY_LEVEL_LOW;
messageSegmentInput.add(bodySegmentInput);
messageBodyInput.messageSegments = messageSegmentInput;
announcement.parentId = COLLABORATION_GROUP.get(0).Id;
announcement.sendEmails = false;
announcement.expirationDate = System.today()+1;
announcement.body = messageBodyInput;
toPost.add(announcement);
// ToDo: Construct a new AnnouncementInput for the Chatter Group so that it:
// expires in a day
// does not notify users via email.
// and has a text body that includes the name of the product followed by the INVENTORY_LEVEL_LOW constant
}
AnnouncementQueueable announcementQueuable = new AnnouncementQueueable(toPost);
// announcementQueuable.toPost = toPost;
Id jobId = System.enqueueJob(announcementQueuable);
// ToDo: Create and enqueue an instance of the announcementQueuable class with the list of Products
}
}