Artillery.io Login and capture response and cookies before each VU runs - artillery

Using Artillery.io load tester I am trying to login each VU Before running the Scenarios flow (I do not want the login requests to be part of the scenario results)
I tried moving the login flow to the beforeScenario but that doesn't seem to run
config:
target: '{{ $processEnvironment.URL }}'
scenarios:
- name: 'Warm Up'
beforeScenario:
flow:
- post:
url: '/login'
json:
username: 'admin'
password: 'password'
capture:
- json: '$.user._id'
as: 'userId'
flow:
- post:
url: '/api/graphql'
json:
- operationName: 'apiRequest'
query: 'query aQuery($userId: ID!) { aQuery: testQuery(userId: $userId) { id name } }'
variables:
userId: '{{ userId }}'
Is there any way to achieve this?

Not sure if you have figured this out but i used the "before" section that comes before the scenario and calls a function to helper function that login
and saves the access_token
before:
flow:
- function: "login"
scenarios:
- name: "Create"
- flow:
- post:
url: ""
headers:
Authorization: "Bearer {{access_token}}"

Before your "scenarios" section, you must use something like this (just an example):
before:
flow:
- log: "Running the Authorization before virtual users run"
- post:
url: "/users/login"
json:
username: "{{user}}"
password: "{{password}}"
capture:
json: "$.data.token"
as: "accessToken"
strict: false
expect:
- statusCode: 200

Related

How to pass login parameters in the artillery.io request

I have started using 'Artillery.io for load testing. Here how to pass authentication parameters like email, password in the load-test.yml, the below throws 401 an unauthorised error while sending the request. Could someone guide me on how to pass authentication parameters like email and password
config:
target: 'https://test-url.com'
phases:
- duration: 70
arrivalRate: 10
defaults:
headers:
Content-Type: application/json
scenarios:
- flow:
- get:
url: /findAMembership
headers:
Content-Type: application/json
- post:
url: /auth
body: '{"username":"test#test.com", "password": "some_testpassword"}'
headers:
Content-Type: application/json
There are something to do with your script that makes it much easier to read, troubleshoot and maybe solve your problem.
First, about the 401 problem, I think your request does not meet the authentication endpoint requirements. Please check the endpoint. (like how to do the auth in a normal way?)
I assume that the endpoint accepts an json request (username and password) and response a Bearer token, you can try this (use json instead of body, and define the key-value):
- post:
url: "/auth"
json:
username: "test#test.com"
password: "some_testpassword"
headers:
Content-Type: "application/json" # no need this, you have specified the default Content-Type
capture:
json: "$.token"
as: "token" # Should have this, read below
And just a note, you sent an auth request and do not capture anything from it, which makes no sense. Remember to capture the response (like Bearer token, etc.) for chaining requests that need the authentication. Read more
If you want to read the users from file, you can specify a payload path, and it's fields. This also allowed you to test scenarios where you have several users, and/or failed attempts.
config:
target: "<TARGET>"
payload:
- path: "./users.csv"
fields:
- "username"
- "password"
order: sequence
skipHeader: true
- path: "./products.csv"
fields:
- "id"
order: sequence
skipHeader: true
phases:
- duration: 60
arrivalRate: 20
scenarios:
- flow:
- post:
url: "/login"
json:
username: "{{ username }}"
password: "{{ password }}"
This way the username and passwords will be read from the specified CSV- file and POSTed to the <TARGET>/login endpoint with the json body object
{
username: <READ USERNAME>
password: <READ PASSWORD>
}
An example CSV- file may look like
username,password
some1#example.com,super1
email#example.com,secret

Selenoid: Chrome Browser starts for few seconds and goes down

Details:
1. The browser comes up for a flash of a second and shuts down causing the next test step which is to set the cookie to fail.
Error:
UnableToSetCookieError: unable to set cookie
(Session info: chrome=77.0.3865.75)
at Object.throwDecodedError (/usr/app/node_modules/selenium-webdriver/lib/error.js:550:15)
at parseHttpResponse (/usr/app/node_modules/selenium-webdriver/lib/http.js:563:13)
at Executor.execute (/usr/app/node_modules/selenium-webdriver/lib/http.js:489:26)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
at async thenableWebDriverProxy.execute (/usr/app/node_modules/selenium-webdriver/lib/webdriver.js:699:17)
at async loginWithRoles (/usr/app/features/support/pages/common.js:16:3)
The code which sets the cookie is:
await driver.get(TARGET_HOST)
await driver.manage().addCookie({
name: 'token',
value: tokenValue,
httpOnly: true,
domain: TARGET_HOST_DOMAIN,
path: '/',
secure: false
})
await driver.get(TARGET_HOST)
return driver.manage().window().setRect({width: 1920, height: 3000})
These tests have been running fine until 13-09-2019. This coincides with the date when selenoid/chrome:latest was updated.
I am using the below docker images in the compose file:
aerokube/selenoid:latest-release
selenoid/video-recorder:latest-release
selenoid/chrome:latest
Selenium-webdriver: 4.0.0-alpha.4
Any tips to debug would be helpful
I resolved this issue by not adding domain while setting the cookies.
The code to set cookies looks like this now:
await driver.get(TARGET_HOST)
await driver.manage().addCookie({
name: 'token',
value: tokenValue,
httpOnly: true,
path: '/',
secure: false
})
await driver.get(TARGET_HOST)
See: https://bugs.chromium.org/p/chromedriver/issues/detail?id=3141

Symfony API Rest login and register

I'm finishing developing a API rest with common endpoints using FOSUserBundle, FOSResBundle and FOSoAuthBundle.
In a parallel way, I'm developing another symfony app to consume the services but I'm having several doubts about how to register and login users via API endpoints. My idea is to have 2 controllers refered it's routes (such as /login and /register) and do this actions via api endpoint.
with FOSUserbundle this actions are simple but don't know how to 'consume' trough APIRest service.
I know it's only half an answer but I currently do this with login, but not registration (I don't need it).
I am using Symfony 4 and flex, but it should work on 3.4 I think. I am also using json.
Bundles
Bundles I use for this (on top of fosuser etc):
jms/serializer-bundle
lexik/jwt-authentication-bundle
friendsofsymfony/rest-bundle
Config
Fos Rest
fos_rest:
body_listener: true
param_fetcher_listener: force
format_listener:
enabled: true
rules:
- { path: ^/, priorities: [ json ], fallback_format: json, prefer_extension: true }
view:
view_response_listener: 'force'
formats:
json: true
xml: false
rss: false
mime_types:
json: ['application/json', 'application/x-json']
routing_loader:
default_format: json
include_format: false
exception:
enabled: true
Fos User
fos_user:
db_driver: orm
firewall_name: api
user_class: App\Entity\User
from_email:
address: admin#example.com
sender_name: Admin
JMS Serializer
jms_serializer:
visitors:
xml:
format_output: '%kernel.debug%'
Lexik JWT
You need you generate tokens and put their location in your .env file. More info and a guide here.
lexik_jwt_authentication:
private_key_path: '%kernel.project_dir%/%env(JWT_PRIVATE_KEY_PATH)%'
public_key_path: '%kernel.project_dir%/%env(JWT_PUBLIC_KEY_PATH)%'
pass_phrase: '%env(JWT_PASSPHRASE)%'
token_ttl: 3600 #whatever you like
token_extractors:
authorization_header: ~
cookie: ~
query_parameter: ~
Security
security:
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
encoders:
FOS\UserBundle\Model\UserInterface: sha512 #probably use bcrypt
providers:
fos_userbundle:
id: fos_user.user_provider.username_email
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: ROLE_ADMIN
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
api_login:
pattern: ^/login
stateless: true
anonymous: true
form_login:
check_path: /login
require_previous_session: false
username_parameter: username
password_parameter: password
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
api:
pattern: ^/
stateless: true
guard:
authenticators:
- lexik_jwt_authentication.jwt_token_authenticator
access_control:
- { path: ^/, role: IS_AUTHENTICATED_FULLY }
Routes
login:
type: rest
resource: App\Controller\LoginController
Controller
I made a loginController that is really just a placeholder to override the route
<?php
namespace App\Controller;
use FOS\RestBundle\Controller\Annotations;
use FOS\RestBundle\Controller\FOSRestController;
use FOS\RestBundle\Routing\ClassResourceInterface;
use FOS\RestBundle\Controller\Annotations\RouteResource;
/**
* #RouteResource("login", pluralize=false)
*/
class LoginController extends FOSRestController implements ClassResourceInterface
{
public function postAction()
{
throw new \DomainException('You should never see this');
}
}
Testing it
You can fire a POST request to /login and it should return a token!
{
"username": "my_user",
"password": "passw0rd"
}
Registration
I haven't actually done this but I have a simple enough idea...
Open a route to registration in your security.yaml
security:
firewalls:
api_register:
pattern: ^/register
anonymous: true
access_control:
- { path: ^/register$, role: IS_AUTHENTICATED_ANONYMOUSLY }
Register the route
registration:
type: rest
resource: App\Controller\RegistrationController
Write the controller method
Get the request data
User the FosUserManager to create a new user
- https://symfony.com/doc/current/bundles/FOSUserBundle/user_manager.html

login form POST parameters in Backbone JS

I am trying to build a sign in system using Backbone JS.
Here is a brief description of the API:
HTTP Method: POST
Request type: JSON
Parameters:
a) user[email]
b) user[password]
Response:
1)- Success:
a- :status => OK
2) Failure:
:status => :unauthorized
I'm trying to use
this.model.save({
email: this.$el.find("#email").val(),
password: this.$el.find("#password").val()
},
but the problem is that the parameters are of the type user[email] and user[password].
How do I solve this?
this.model.save({
'user[email]': this.$el.find("#email").val(),
'user[password]': this.$el.find("#password").val() });
make sure the values are not empty.

Why my request POST by $resource is an OPTIONS

The code I'm using is the following, in coffeescipt :
request_with_token =
get:
method: "JSONP",
params:
token: app["token"]
save:
method: "POST",
params:
token: app["token"]
$rootScope.API = "http://0.0.0.0:5200/1.0"
$scope.ajaxAccountUpdate = $resource($rootScope.API + "/account/update.json",
{ callback: "JSON_CALLBACK" }, request_with_token )
user = $scope.user
$scope.ajaxAccountUpdate.save user, (resource) ->
$scope.show_message(resource)
But in my Log I have an OPTIONS instead a POST
[07/Feb/2013 16:50:48] "OPTIONS /1.0/account/update?callback=JSON_CALLBACK&token=mytoken HTTP/1.1" 200 -
Thanks
Probably because you're making a request to a different website from where the HTML is served, resulting in a 'Cross-Origin Resource Sharing' CORS pre-flight check. This is a security feature:
For more information: http://www.html5rocks.com/en/tutorials/cors/

Resources