Reputation: 1547
I'm working on an ecommerce project on protractor and I can't honestly figure out what went wrong with the IT case. I got the following error
Failed: item.element is not a function[0m
Stack:
TypeError: item.element is not a function
I've been pulling my hair out for the last day but the console isn't clear about the specific problem. Cause I've checked and can't see the issue.
Question: what is this? How do I fix this?
The code from the course is as messy as hell, so I will tidy it up for you.
code
describe('Ecommerce Angular Project', function () {
it('Customer Shopping cart', function () {
// write your code here!!!
function selectItem(product) {
//chain the locators so that you can pick a specific item regardless of where it is located
element.all(by.tagName("app-card")).then(function (item) {
item.element(by.css("h4 a")).getText().then(function (text) {
if (text == "Samsung Note 8") {
// add to cart button if loop is correct.
item.element(By.css("button[class*='btn-info']")).click();
} //end of if Loop
})//END: this promise add to cart button for samsung
})//end of command to find samsung 8
}
it('Customer registration', function () {
// write your code here!!!
//Scenario 3: Go Shop page and add items to shopping cart
//Given I am on the home page
//when I select the shop link
//Then I am taken to the shop page
//When I am in the shop page I select a mobile phone
//Then the shopping cart will show 1 item added
//When I add another mobile phone to the shopping cart
//Then the shopping cart will show 2 items added
element(by.linkText("Shop")).click();
//Select 2 items for shopping cart
selectItem("Samsung Note 8");
selectItem("iphone X");
// I want to display the results and confirm there are only 2 items in the shopping cart
element(by.partialLinkText("Checkout")).getText().then(function (text) {
// I want to show both items in the console on a separate line confirm that it 2 items
var res = text.split("(");
expect(res[1].trim().charAt(0)).toBe("2");
})//END: this function will display items in console from shopping bag
}) //end of customer registration & shopping it block
})//end of describe block
Message from console
(note there were IT cases in this spec file and they passed but once, so ignore those message, but when came the IT scenario that's were things went very wrong)
(node:10145) [DEP0022] DeprecationWarning: os.tmpDir() is deprecated. Use os.tmpdir() instead.
[16:34:32] I/launcher - Running 1 instances of WebDriver
[16:34:32] I/hosted - Using the selenium server at http://localhost:4444/wd/hub
Started
[16:34:36] W/element - more than one element found for locator By(css selector, *[name="name"]) - the first result will be used
×
Success! The Form has been submitted successfully!.
[16:34:37] W/element - more than one element found for locator By(css selector, *[name="name"]) - the first result will be used
[16:34:37] W/element - more than one element found for locator By(css selector, *[name="name"]) - the first result will be used
Name should be at least 2 characters
[31mF[0m
Failures:
1) Ecommerce Angular Project Customer registration
Message:
[31m Failed: item.element is not a function[0m
Stack:
TypeError: item.element is not a function
at /Users/xxx/Documents/JSworkspace/LocatorTraining/ecommerceAutomation.js:10:12
at ManagedPromise.invokeCallback_ (/Users/xxx/Documents/JSworkspace/LocatorTraining/protractor/node_modules/selenium-webdriver/lib/promise.js:1376:14)
at TaskQueue.execute_ (/Users/xxx/Documents/JSworkspace/LocatorTraining/protractor/node_modules/selenium-webdriver/lib/promise.js:3084:14)
at TaskQueue.executeNext_ (/Users/xxx/Documents/JSworkspace/LocatorTraining/protractor/node_modules/selenium-webdriver/lib/promise.js:3067:27)
at asyncRun (/Users/xxx/Documents/JSworkspace/LocatorTraining/protractor/node_modules/selenium-webdriver/lib/promise.js:2927:27)
at /Users/xxx/Documents/JSworkspace/LocatorTraining/protractor/node_modules/selenium-webdriver/lib/promise.js:668:7
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)
From: Task: Run it("Customer registration") in control flow
at UserContext.<anonymous> (/Users/xxx/Documents/JSworkspace/LocatorTraining/protractor/node_modules/jasminewd2/index.js:94:19)
From asynchronous test:
Error
at Suite.<anonymous> (/Users/xxx/Documents/JSworkspace/LocatorTraining/ecommerceAutomation.js:27:2)
at Object.<anonymous> (/Users/xxx/Documents/JSworkspace/LocatorTraining/ecommerceAutomation.js:1:63)
at Module._compile (module.js:652:30)
at Object.Module._extensions..js (module.js:663:10)
at Module.load (module.js:565:32)
at tryModuleLoad (module.js:505:12)
1 spec, 1 failure
Finished in 3.801 seconds
[16:34:38] I/launcher - 0 instance(s) of WebDriver still running
[16:34:38] I/launcher - chrome #01 failed 1 test(s)
[16:34:38] I/launcher - overall: 1 failed spec(s)
[16:34:38] E/launcher - Process exited with error code 1
Upvotes: 0
Views: 2587
Reputation: 13712
element.all()
returns ElementArrayFinder
, you can think it as an array of element. Therefore the item
in the then()
represents an array, rather than a single element.
element.all(by.tagName("app-card")).then(function (item) {
item.element(...)
...
})
You can't call .element()
on an array
object. But you can call .element()
on single element as following:
element.all(by.tagName("app-card")).then(function (items) {
items[0].element(...) // items[0] is single element.
...
})
For your case, the function selectItem
should change as following:
function selectItem(product) {
//chain the locators so that you can pick a specific item regardless of where it is located
element.all(by.tagName("app-card")).filter(function(item){
return item.element(by.css("h4 a")).getText().then(function(txt){
return txt === product;
});
}).then(function(items){
if(items.length > 0) {
items[0].element(by.css("button[class*='btn-info']")).click();
}
else {
console.error('Not find product: ' + product);
}
}).catch(function(err){
console.error(err);
});
}
Upvotes: 2