Calling one feature file from another feature in cucumber - java

Consider I have below feature files:
Login.feature
Feature: Login on website
Scenario: Login verification on site
Given Navigate to site login page
When User enters username 'admin1'
And User enters password 'admin1'
And User clicks on login button
Then User should not be able to log in successfully
Home.feature
Feature: Welcome Page Verification
Scenario: Verify the page that comes after login
Given Login is successfully done
When The page after login successfully appears
Then The test is done
In Home.feature file, I need to execute Login.feature first and then call home.feature. So when i execute home from my runner test it will in turn execute login and then home.
RunnerTest.java
import org.junit.runner.RunWith;
import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
#RunWith(Cucumber.class)
#CucumberOptions(strict = false, features = {
"src/test/resources/Features/Home.feature",
}, glue = { "tests" }, plugin = "html:target/cucumber-reports", format = { "pretty",
"json:target/cucumber.json" }, tags = { "~#ignore" })
public class RunnerTest {}

You don't need to call the first feature from the second feature. What you need to do is have a step in the second feature that can log you in. It can do this by calling code you've created when implementing your first feature.
The first feature is something you might write when you are implementing login for the first time. In doing this you will steps and code that these steps call to log you in.
The sort of code you should be creating is (sorry all examples are ruby i don't do java)
A test user entity that knows its name, email and password
A method that can user the test user to login
Then you can write a helper method e.g.
def login_as(user)
visit login_path
fill_in :email, with: user.email
fill_in :password, with: user.password
submit_form
end
and now in your second feature you can have something like
Given I am an admin
When I login
and implement these steps as
Given 'I am an admin' do
# note create_user is a method you would have created when doing user
# registration/creation
#i = create_user(type: admin)
end
When "I login" do
login_as #i
end
and somewhere you will have some helper methods
module StepHelperMethods
def create_user
...
return user
end
def login_as(user)
...
end
end
World StepHelperMethods
Your code reuse always happens at a much lower level. Ideally you should be re-using helper methods that you have created previously to make other scenarios work. You can also call steps directly (nested steps) but this is a very bad thing to do.

Try this:
Create a RunnerLogin class to call the Login.feature.
In your steps class, in the method that implements the
Given Login is successfully done, do something like:
#Given("^Login is successfully done$")
public void login_is_successfully_done() {
Thread T1 = new Thread(new Thread(() -> {
JUnitCore jExecFeature = new JUnitCore();
Result result = jExecFeature.run(RunnerLogin.class);
}));
T1.start();
T1.join();
}

Behind every feature there is a method implemented in your step definitions, so you will not need to write your features in that manner, you will just need to call the method that you have already implemented.
The best solution for frequently used functionalities of your application like Login for e.g is to have Helper methods.
You can implement these methods as global and use them in your every step definition file.
public void LoginUserGlobal(String user, String pass) throws Throwable {
LoginPageObjects LP = new LoginPageObjects(driver);
LP.user().sendKeys(user);
LP.pass().sendKeys(pass);
LP.loginButton().click();
}
And if you need to use it in any of your features you will code it like:
#When("^User logs in with \"([^\"]*)\" and \"([^\"]*)\"$")
public void user_logs_in_with_something_and_something(String user, String pass) throws Throwable {
GlobalClassWhereIsYourLoginMethod Lin = new GlobalClassWhereIsYourLoginMethod (driver)
LoginUserGlobal(user,pass);
}
or if it is not so used part of app, you will call it from a step definition method where is already implemented.

Related

Twilio using Gather to get UserID and Password

Currently, I'm testing out features of Twilio. I simply wanted to get two numbers from the user representing a username and password. What happens is because I don’t know what address to put in action, it defaults to the same time and loops the first gather over and over again. Currently, I’m using Spark and ngrok to test my code.
package com.example;
import com.twilio.twiml.VoiceResponse;
import com.twilio.twiml.voice.Gather;
import com.twilio.twiml.voice.Say;
import static spark.Spark.*;
public class Example {
public static void main(String[] args) {
post("/", (request, response) -> {
Say say = new Say.Builder(
"Enter UserID.")
.build();
Gather gather = new Gather.Builder().action("/").say(say).build();
Say say2 = new Say.Builder(
"Enter Password.")
.build();
Gather gather2 = new Gather.Builder().action("/").say(say2).build();
VoiceResponse voiceResponse = new VoiceResponse.Builder()
.gather(gather)
.gather(gather2)
.build();
return voiceResponse.toXml();
});
}
}
I tried changing the action attribute to a random address like /test, I changed the method to POST or GET, but neither seemed to have any effect except in the ngrok dashboard. The problem I'm currently having is I have no clue how to use Spark and the Gather verb together.
It repeats the actions over and over again because of the properties of the gather TwiMl element.
First, you should point to a different endpoint of your application and handle the response at this endpoint. Once you parse the user input at this endpoint, you can return another TwiML response that asks for the second input, which you then need to process at a third endpoint.
With this in mind, I see a second problem with the code above. You ask for both inputs sequentially, meaning you only ask for the second input if the caller ignores the first prompt and remains quiet. Look at "Scenario 1-3" of this page for more details.
I understand that implementing so many endpoints for a simple IVR might be confusing at first. The good news is that this can be much simpler by using Studio.

Why am I getting "Error processing transaction request: intrinsic gas too low" error when trying to add tUSDT to a particular account?

I am trying to send test USDT to a particular account in Java using the following code:
final Web3j web3 = createWeb3If(ethNetworkUrl);
final Credentials credentials = Credentials.create(privateKey);
final ERC20 usdtContract = ERC20.load(usdtContractAddress, web3, credentials, new TestGasProvider());
usdtContract.transfer(exchangeAddress, BigInteger.valueOf(10)).send();
The last statement results in the following exception:
java.lang.RuntimeException: Error processing transaction request: intrinsic gas too low
at org.web3j.tx.TransactionManager.processResponse(TransactionManager.java:176)
at org.web3j.tx.TransactionManager.executeTransaction(TransactionManager.java:81)
at org.web3j.tx.ManagedTransaction.send(ManagedTransaction.java:128)
at org.web3j.tx.Contract.executeTransaction(Contract.java:367)
at org.web3j.tx.Contract.executeTransaction(Contract.java:350)
at org.web3j.tx.Contract.executeTransaction(Contract.java:344)
at org.web3j.tx.Contract.executeTransaction(Contract.java:339)
at org.web3j.tx.Contract.lambda$executeRemoteCallTransaction$3(Contract.java:410)
at org.web3j.protocol.core.RemoteCall.send(RemoteCall.java:42)
at com.dpisarenko.minimalcryptoexchange.delegates.TransferUsdtToExchangeAccount.execute(TransferUsdtToExchangeAccount.java:57)
TestGasProvider is defined as:
public class TestGasProvider extends StaticGasProvider {
public static final BigInteger GAS_PRICE = BigInteger.valueOf(10L);
public static final BigInteger GAS_LIMIT = BigInteger.valueOf(1L);
public TestGasProvider() {
super(GAS_PRICE, GAS_LIMIT);
}
}
usdtContract was deployed using this script, which calls deploy.js:
async function main() {
const USDT = await ethers.getContractFactory("USDT");
const usdt = await USDT.deploy(1000000000000000);
console.log("USDT contract deployed to:", usdt.address);
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
This contract is running on a local testnet set up as described here.
What do I need to change in any of these components (testnet, contract, deploy scripts, Java code) in order to send any amount of USDT to a particular address (without any errors)?
Update 1: If I change TestGasProvider to
public class TestGasProvider extends StaticGasProvider {
public static final BigInteger GAS_PRICE = BigInteger.valueOf(1L);
public static final BigInteger GAS_LIMIT = BigInteger.valueOf(1000000000L);
public TestGasProvider() {
super(GAS_PRICE, GAS_LIMIT);
}
}
I get another error:
java.lang.RuntimeException: Error processing transaction request: exceeds block gas limit
at org.web3j.tx.TransactionManager.processResponse(TransactionManager.java:176)
at org.web3j.tx.TransactionManager.executeTransaction(TransactionManager.java:81)
at org.web3j.tx.ManagedTransaction.send(ManagedTransaction.java:128)
at org.web3j.tx.Contract.executeTransaction(Contract.java:367)
at org.web3j.tx.Contract.executeTransaction(Contract.java:350)
at org.web3j.tx.Contract.executeTransaction(Contract.java:344)
at org.web3j.tx.Contract.executeTransaction(Contract.java:339)
at org.web3j.tx.Contract.lambda$executeRemoteCallTransaction$3(Contract.java:410)
at org.web3j.protocol.core.RemoteCall.send(RemoteCall.java:42)
at com.dpisarenko.minimalcryptoexchange.delegates.TransferUsdtToExchangeAccount.execute(TransferUsdtToExchangeAccount.java:57)
Update 1
I am looking to submit a set of code changes to the branch i16 of the minimal-crypto-exchange project which passes the following test:
Step 1
Set up the environment as described here.
Step 2
Set a breakpoint on line usdtContract.transfer(exchangeAddress, BigInteger.valueOf(10)).send(); in TransferUsdtToExchangeAccount class:
Step 3
Start the process engine application in debug mode. Its Java main method is located here.
Wait until you see the message starting to acquire jobs in the console output:
11:59:16.031 [JobExecutor[org.camunda.bpm.engine.spring.components.jobexecutor.SpringJobExecutor]] INFO org.camunda.bpm.engine.jobexecutor - ENGINE-14018 JobExecutor[org.camunda.bpm.engine.spring.components.jobexecutor.SpringJobExecutor] starting to acquire jobs
Step 4
Login with the credentials demo/demo at http://localhost:8080.
After login you should see a page like this:
Step 5
Click on the tasklist link. You should see a page that looks like this:
Press the "Start process" link. Following screen will appear:
Click on Send USDT to the exchange account process link. Following dialog box will appear:
Enter an arbitrary value into the "business key" field and press the "Start" button.
Step 6
After a couple of seconds, the breakpoint from step 2 will activate.
The problem will be solved if usdtContract.transfer(exchangeAddress, BigInteger.valueOf(10)).send() is executed without errors.
Notes
You are allowed to modify the amount in usdtContract.transfer(exchangeAddress, BigInteger.valueOf(10)).send(); from 10 to something else.
You can also modify the parameters of the Ethereum testnet specified in docker-compose.yml and genesis.json, as well as those of the USDT smart contract which is deployed using this script.
Your solution must work in this controlled environment (i. e. no faucets must be used).
Update 2
I made following changes:
The set-up tutorial now contains step 7 in which ETH is added to the exchange account.
Now a new version of the ETH testnet is being used, major changes being that log output is more verbose and the gas price is set to 1 (see --miner.gasprice 1 in entrypoint.sh).
Modified the code in TransferUsdtToExchangeAccount so that now USDT is transferred not from the exchange account (which has zero balance), but from the buffer account.
Now I am receiving the error
org.web3j.protocol.exceptions.TransactionException: Transaction 0x4bce379a2673c4564b2eb6080607b00d1a8ac232fbddf903f353f4eeda566cae
has failed with status: 0x0. Gas used: 32767.
Revert reason: 'ERC20: transfer amount exceeds allowance'.
My skills with Ethereum are still not sharp enough to give you a proper answer, but I hope you get some guidance.
The error states that you are trying to transfer by a party A certain quantity in the name of another party B, to a third one C, but the amount you are trying to transfer, using transferFrom, is greater than the one party B approved party A to send.
You can check the actual allowance between to parties using the method with the same name of your contract.
Please, consider review this integration test from the web3j library in Github. It is different than yours but I think it could be helpful.
Especially, it states that the actual transferFrom operation should be performed by the beneficiary of the allowance. Please, see the relevant code:
final String aliceAddress = ALICE.getAddress();
final String bobAddress = BOB.getAddress();
ContractGasProvider contractGasProvider = new DefaultGasProvider();
HumanStandardToken contract =
HumanStandardToken.deploy(
web3j,
ALICE,
contractGasProvider,
aliceQty,
"web3j tokens",
BigInteger.valueOf(18),
"w3j$")
.send();
//...
// set an allowance
assertEquals(contract.allowance(aliceAddress, bobAddress).send(), (BigInteger.ZERO));
transferQuantity = BigInteger.valueOf(50);
TransactionReceipt approveReceipt =
contract.approve(BOB.getAddress(), transferQuantity).send();
HumanStandardToken.ApprovalEventResponse approvalEventValues =
contract.getApprovalEvents(approveReceipt).get(0);
assertEquals(approvalEventValues._owner, (aliceAddress));
assertEquals(approvalEventValues._spender, (bobAddress));
assertEquals(approvalEventValues._value, (transferQuantity));
assertEquals(contract.allowance(aliceAddress, bobAddress).send(), (transferQuantity));
// perform a transfer as Bob
transferQuantity = BigInteger.valueOf(25);
// Bob requires his own contract instance
HumanStandardToken bobsContract =
HumanStandardToken.load(
contract.getContractAddress(), web3j, BOB, STATIC_GAS_PROVIDER);
TransactionReceipt bobTransferReceipt =
bobsContract.transferFrom(aliceAddress, bobAddress, transferQuantity).send();
HumanStandardToken.TransferEventResponse bobTransferEventValues =
contract.getTransferEvents(bobTransferReceipt).get(0);
assertEquals(bobTransferEventValues._from, (aliceAddress));
assertEquals(bobTransferEventValues._to, (bobAddress));
assertEquals(bobTransferEventValues._value, (transferQuantity));
//...
This fact is also indicated in this OpenZeppelin forum post.

How do i sign a user up and add attributes with Amplify and Android

When creating a user with Amplify, I am calling amplify.createUser(email, password).
When using Cognito, you can use Auth.SignUp() with an attributes parameter to assign Cognito user pool attributes to the user. Is there anyway to do this with Amplify?
I basically want to sign up a user and set some Cognito user pool attributes at the same time.
This functionality has not yet been implemented in Amplify for Android but is scheduled to be finished in the near future, as noted in this documentation. Please check back to the documentation for updates on availability.
In the meantime though, you can still use Amplify. Just access the underlying AWSMobileClient through the authentication escape hatch, which does support passing custom attributes. See this documentation for more details on how exactly to use AWSMobileClient.
I don't know if this is still relevant, but here is how to accomplish the task with Amplify.
First you build an AuthSignUpOptions object (example of custom attribute and standard attribute below):
AuthSignUpOptions options = AuthSignUpOptions.builder()
.userAttribute(AuthUserAttributeKey.custom("custom:role"), "some_role")
.userAttribute(AuthUserAttributeKey.address(), "some_address")
.build();
Then call Amplify.Auth.signup:
Amplify.Auth.signUp("username", "password", options,
result -> { /* do something */ },
error -> { /* do something */ });
Altogether it looks like this:
AuthSignUpOptions options = AuthSignUpOptions.builder()
.userAttribute(AuthUserAttributeKey.custom("custom:role"), "some_role")
.userAttribute(AuthUserAttributeKey.address(), "some_address")
.build();
Amplify.Auth.signUp(tempUsername.getText().toString(), pin.getText().toString(), options,
result -> { /* do something */ },
error -> { /* do something */ });

Run each cucumber test independently

I'm using cucumber and maven on eclipse and what I'm trying to do is run each test independently. For example I have a library system software that basically allows users to borrow books and do other stuff.
One of the conditions is that users can only borrow a max of two books so I wrote to make sure that the functionality works. This is my feature file:
Scenario: Borrow over max limit
Given "jim#help.ca" logs in to the library system
When "jim#help.ca" order his first book with ISBN "9781611687910"
And "jim#help.ca" orders another book with ISBN "9781442667181"
And "jim#help.ca" tries to order another book with ISBN "1234567890123"
Then jim will get the message that says "The User has reached his/her max number of books"
I wrote a corresponding step definition file and every worked out great. However, in the future I want to use the same username ("jim#help.ca") for borrowing books as though jim#help.ca has not yet borrowed any books. I want each test to be independent of each other.
Is there any way of doing this...maybe there's something I can put into my step definition classes such as a teardown method. I've looked into it but I couldn't fine any solid information about it. If there's a way please help me. Any help is greatly appreciated and I thank you in advance!
Yes, you can do setups and teardowns before and after each scenario, but it's not in the step definition file. What you want to use are hooks.
Hooks run before or after a scenario and can run before/after every scenario or just the ones you and #tag to, for example:
#remove_borrowed_books
Scenario: Borrow over max limit
Unfortunately I have only used cucumber with ruby not java so I can't give you step-by-step instructions, but this should tell you what you need to know https://zsoltfabok.com/blog/2012/09/cucumber-jvm-hooks/
You can use the "#After" hook to achieve this as #Derek has mentioned using for example a Map of books borrowed per username:
private final Map<String, Integer> booksBorrowed = new HashMap<>();
#After
public void tearDown() {
booksBorrowed.clear();
}
#Given("...")
public void givenUserBorrowsBook(String username) {
booksBorrowed.put(username, booksBorrowed.containsKey(username) ? booksBorrowed.get(username) + 1 : 1);
....
}
Or the "#Before" hook to perform the cleanup before each scenario is executed, which is the option I would recommend:
private Map<String, Integer> booksBorrowed;
#Before
public void setUp() {
booksBorrowed = new HashMap<>();
}
If you are planning to run scenarios in parallel then the logic will be more complex as you will need to maintain the relationship between the thread executing a particular scenario and the usernames used on that thread.

Creating Roles Programmatically for each User Group

I want to create a Role for each User Group within my portal so that I can grant specific access to many users at once, depending on what groups they belong to.
Using Liferay API, is there any way to programmatically add a Role for each User Group that exists within the Portal?
This would be more efficient than adding each role individually through the UI.
Something like
for(i = 0; i < userGroups.size(); i++){
roles.add(userGroups[i].getName());
}
If possible, I'd like to then assign the same User Group to that Role within the same method, otherwise the role would know nothing of the associated user group:
roles.assignUserGroup(userGroups[i]);
Anyone accomplished a task similar to this?
Linked Liferay Forum Post http://liferay.com/community/forums/-/message_boards/message/46355079
In short you need to create a Role with a similar name as that of the UserGroups you have and then assign the UserGroup to that Role.
You can do that programmatically with Liferay's API, since that is how liferay also creates the different types of Roles and assigns users, user-groups etc to the role.
You just need to dig into to the source code to do this. Check source code for RoleLocalServiceImpl, UserGroupLocalServiceImpl and GroupLocalServiceImpl.
I am providing the steps for Liferay v6.2, there should not be much change in 6.0 and 6.1:
Fetch all the UserGroups using UserGroupLocalServiceUtil.getUserGroups(companyId)
Loop through it as you have done:
for (UserGroup userGroup : userGroups) {
... // steps to follow
}
Get the name of the UserGroup: userGroup.getName()
Create a Role using RoleLocalServiceUtil.addRole( ... ) and assign the userGroup to role using GroupLocalServiceUtil.addRoleGroups( ... )
for (UserGroup userGroup : userGroups) {
String userGroupName = userGroup.getName();
// for locale specific title (optional, can be null)
Map<Locale, String> titleMap = new HashMap<Locale, String>();
titleMap.put(Locale.ENGLISH, userGroupName);
// for locale specific description (optional, can be null)
Map<Locale, String> descriptionMap = new HashMap<Locale, String>();
titleMap.put(Locale.ENGLISH, "Role created for UserGroup - " + userGroupName);
int type = RoleConstants.TYPE_REGULAR;
// adding the role
Role role = RoleLocalServiceUtil.addRole(userId, Role.class.getName(), 0, userGroupName, titleMap, descriptionMap, type, null, null);
// assigning the UserGroup to the role
GroupLocalServiceUtil.addRoleGroups(role.getRoleId(), new long[]{userGroup.getGroupId()}); // need to pass groupId and not userGroupId
}
Now were would you write this code-snippet? There are various places depending upon what requirement you have:
Custom plugin portlet with a UI to execute this code. (better if required periodically)
Custom plugin action-hook and the code goes inside a StartUpAction, executes the code when the hook is being deployed. Hook should be undeployed or else will run everytime the hook is deployed. (better for one time use)
Custom plugin upgrade hook, executes the code during deployment once based on the upgrade condition. (better for one time use)
Use Beanshell, Server Administration → Script → Select Beanshell → Paste the code-snippet → Execute. You need to have the proper import statements and then just the code-snippet and you are good to go. For an example of Beanshell usage you can check my other answer. (better for one time use)
Even after all this you would still have to take the pains to give permission to each role ;-)
Hope this helps though.

Categories

Resources