Forums

Articles
Create
cancel
Showing results for 
Search instead for 
Did you mean: 

XRAY REST API request from JEST to JIRA cloud Fails

Anmol Fattepur July 21, 2023

I am making a XRAY REST API request from JEST to JIRA cloud as below,

https://adneurope.atlassian.net/api/v2/import/execution

I am also putting JSON Body containing execution results as below,

{
testExecutionKey: 'XAUTO-15',
info: {
summary: 'Execution of automated tests for release v1.3',
description: 'TEST!!!! This execution is automatically created when importing execution results from an external source',
version: 'Beta',
user: 'Anmol Fattepur',
revision: '1.0.42134',
startDate: '2014-08-30T11:47:35+01:00',
finishDate: '2014-08-30T11:53:00+01:00',
testPlanKey: 'DEMO-100',
testEnvironments: ['UAT'],
},
tests: [
{
testKey: 'XAUTO-4',
start: '2014-08-30T11:47:35+01:00',
finish: '2014-08-30T11:50:56+01:00',
comment: 'Successful execution',
status: 'PASSED',
},
],
}

It fails with response as below,

Symbol(Response internals)]: {
url: 'https://adneurope.atlassian.net/api/v2/import/execution',
status: 404,
statusText: 'Not Found',
headers: Headers { [Symbol(map)]: [Object: null prototype] },
counter: 0

1 answer

0 votes
Marc - Devoteam
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
July 21, 2023

Hi @Anmol Fattepur 

As I understand correctly you want to import Test Execution results in Jira Cloud

To import test execution results you would need to call the XRAY API, not the JIRA API

See the XRAY documentation:https://docs.getxray.app/display/XRAYCLOUD/REST+API

Also in documentation, you need to create an API token for the user who needs to execute the action.

Anmol Fattepur July 21, 2023

Hi @Marc - Devoteam

Thanks for your response.

I have referred the XRAY API documentation and the provided REST API endpoint for importing Test Execution results in Jira Cloud is, /api/v2/import/execution 

Using the same suggested endpoint.

However, I am still facing this error.

Please suggest

Marc - Devoteam
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
July 21, 2023

Hi @Anmol Fattepur 

So you used the following url to trigger the API:

https://xray.cloud.getxray.app/api/v2/import/execution

And you made yourself an API in Xray settings, https://docs.getxray.app/display/XRAYCLOUD/Global+Settings%3A+API+Keys ?

Anmol Fattepur July 24, 2023

Hi @Marc - Devoteam ,

Till now I was using below url to trigger the API:

 https://adneurope.atlassian.net/api/v2/import/execution 

And not the one you suggested. However, with little bit of exploration I understood we need to use  https://xray.cloud.getxray.app/api/v2/import/execution and not the one above.

I have also created the API keys.

If possible can you please in brief explain the procedure to achieve my requirement?

Marc - Devoteam
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
July 24, 2023

Hi @Anmol Fattepur ,

The structure for the JSON request can be found here, based on the required format.

https://docs.getxray.app/display/XRAYCLOUD/Import+Execution+Results+-+REST+v2 

So you need to use the Xray API to import test execution results.

You need an Xray API key for the user who is executing the JSON call

This user has to have a Jira account and Xray API as mentioned above and have the right permissions on the Jira project.

Anmol Fattepur July 24, 2023

Hi @Marc - Devoteam ,

I'm still struggling.
I will paste my complete code for your reference as below,

const fetch = require('node-fetch');
const clientId = 'FCBD243AF6EF4D39B52455543919643B';
const clientSecret = '793b48d41eed541adf7c53915b51b9739037aee6a1441d4c7d4d837e624db593';
const apiToken = 'ATATT3xFfGF0lEZDxgDa7rcsHtucHVS56fArATOVvbLEDBXGBKkDj3YuO9pr7yE_lUOVMBfCyCmiJ9idtft0pt9WlHVpGMGCHQ3wYlaLxefrzVSFUj0YWN8TLetE0YlpcyewS-rE5UV8pqMBBtDFkqvhtzYZt26Y6lwD5ai8QgFtjMLrznjkzHQ=5FFF1216';

async function getAccessToken() {

  const headers = {
    'Content-Type': 'application/x-www-form-urlencoded',
  };

  const requestBody = new URLSearchParams();
  requestBody.append('grant_type', 'client_credentials');
  requestBody.append('client_id', clientId);
  requestBody.append('client_secret', clientSecret);

  const response = await fetch(tokenEndpoint, {
    method: 'POST',
    headers: headers,
    body: requestBody,
  });

  const responseData = await response.json();
  return responseData.access_token;
}

async function updateXRAY() {
  const accessToken = await getAccessToken();
  const testExecutionData = {
    info: {
          testExecutionKey: 'XAUTO-25',
          summary: 'Execution of automated tests for release v1.3',
          description: 'TEST!!!! This execution is automatically created when importing execution results from an external source',
          version: 'Beta',
          user: 'Anmol Fattepur',
          revision: '1.0.42134',
          startDate: '2014-08-30T11:47:35+01:00',
          finishDate: '2014-08-30T11:53:00+01:00',
          testPlanKey: 'DEMO-100',
          testEnvironments: ['UAT'],
      },
    tests: [
      {
        testKey: 'XAUTO-4',
        start: '2014-08-30T11:47:35+01:00',
        finish: '2014-08-30T11:50:56+01:00',
        comment: 'Successful execution',
        status: 'PASSED',
      }
    ],
  };

  // Prepare the headers with the API token
  const headers = {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${accessToken}`,
  };

  try {
    const response = await fetch('https://xray.cloud.getxray.app/api/v2/import/execution', {
      method: 'POST',
      headers: headers,
      body: JSON.stringify(testExecutionData),
    });

    if (response.status === 200) {
      console.log('Test execution results successfully imported into Xray!');
    } else {
      console.log('Failed to import test execution results.');
      console.log('Response status code:', response.status);
      const responseData = await response.text();
      console.log('Response data:', responseData);
    }
  } catch (error) {
    console.error('An error occurred during the API request:', error);
  }
}

test('Test importing execution results into Xray', async () => {
  try {
    await updateXRAY();
  } catch (error) {
    console.error('Error during test:', error);
  }
});
Executing this will give error as below,

console.error
Error during test: FetchError {
message: 'invalid json response body at https://xray.cloud.getxray.app/api/v2/token reason: Unexpected token < in JSON at position 0',
type: 'invalid-json'
}

105 | await updateXRAY();
106 | } catch (error) {
> 107 | console.error('Error during test:', error);
| ^
108 | }
109 | });
110 |

at error (routes/ged.test.js:107:13)
at call (routes/ged.test.js:2:1)
at Generator.tryCatch (routes/ged.test.js:2:1)
at Generator._invoke [as throw] (routes/ged.test.js:2:1)
at asyncGeneratorStep (routes/ged.test.js:2:1)
at asyncGeneratorStep (routes/ged.test.js:2:1)

 

Appreciate if you can suggest a code fix?

Marc - Devoteam
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
July 25, 2023

Hi @Anmol Fattepur 

If I look at your input

 {
    info: {
          testExecutionKey: 'XAUTO-25',
          summary: 'Execution of automated tests for release v1.3',
          description: 'TEST!!!! This execution is automatically created when importing execution results from an external source',
          version: 'Beta',
          user: 'Anmol Fattepur',
          revision: '1.0.42134',
          startDate: '2014-08-30T11:47:35+01:00',
          finishDate: '2014-08-30T11:53:00+01:00',
          testPlanKey: 'DEMO-100',
          testEnvironments: ['UAT'],
      },
    tests: [
      {
        testKey: 'XAUTO-4',
        start: '2014-08-30T11:47:35+01:00',
        finish: '2014-08-30T11:50:56+01:00',
        comment: 'Successful execution',
        status: 'PASSED',
      }
    ],
  };

And look at the Xray example

{

    "testExecutionKey": "DEMO-1206",

    "info" : {

        "summary" : "Execution of automated tests for release v1.3",

        "description" : "This execution is automatically created when importing execution results from an external source",

        "version" : "v1.3",

        "user" : "admin",

        "revision" : "1.0.42134",

        "startDate" : "2014-08-30T11:47:35+01:00",

        "finishDate" : "2014-08-30T11:53:00+01:00",

        "testPlanKey" : "DEMO-100",

        "testEnvironments": ["iOS", "Android"]

    },

    "tests" : [

        {

            "testKey" : "DEMO-6",

            "start" : "2014-08-30T11:47:35+01:00",

            "finish" : "2014-08-30T11:50:56+01:00",

            "comment" : "Successful execution",

            "status" : "PASSED"

        }

     ]

}

I highlighted the differences in BOLD (including, closing brackets) and you are using single quotes all over, as the need to be double or they are missing

Anmol Fattepur July 25, 2023

Hi @Marc - Devoteam ,

Thanks for your response.

I have modified the code to match the input as suggested.

Pasting the entire code for your reference again,

 

const fetch = require('node-fetch');
const jwt = require('jsonwebtoken');

const clientId = 'FCBD243AF6EF4D39B52455543919643B';
const clientSecret = '793b48d41eed541adf7c53915b51b9739037aee6a1441d4c7d4d837e624db593';

async function getAccessToken() {

  const payload = {
    iss: clientId,
    sub: clientId,
    exp: Math.floor(Date.now() / 1000) + 60,
  };

  const token = jwt.sign(payload, clientSecret);

  const headers = {
    'Content-Type': 'application/x-www-form-urlencoded',
    'Authorization': `Bearer ${token}`,
  };

  const requestBody = new URLSearchParams();
  requestBody.append('grant_type', 'client_credentials');

  try {
    const response = await fetch(tokenEndpoint, {
      method: 'POST',
      headers: headers,
      body: requestBody,
    });

    if (!response.ok) {
      throw new Error(`Failed to get access token: ${response.statusText}`);
    }

    const responseData = await response.json();
    return responseData.access_token;
  } catch (error) {
    console.error('An error occurred while getting the access token:', error);
    throw error;
  }
  console.log('Response from token endpoint:', response);
  const responseData = await response.json();
  return responseData.access_token;
}

async function updateXRAY() {
  const accessToken = await getAccessToken();
  const testExecutionData = {
    info: {
      "testExecutionKey": "XAUTO-25",
      "info" : {
          "summary" : "Execution of automated tests for release v1.3",
          "description" : "TEST!!!! This execution is automatically created when importing execution results from an external source'",
          "version" : "Beta",
          "user" : "Anmol Fattepur",
          "revision" : "1.0.42134",
          "startDate" : "2014-08-30T11:47:35+01:00",
          "finishDate" : "2014-08-30T11:53:00+01:00",
          "testPlanKey" : "DEMO-100",
          "testEnvironments": ['UAT']
      },
      "tests" : [
          {
              "testKey" : "XAUTO-4",
              "start" : "2014-08-30T11:47:35+01:00",
              "finish" : "2014-08-30T11:50:56+01:00",
              "comment" : "Successful execution",
              "status" : "PASSED"
          }
       ],
  }
};

  const headers = {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${accessToken}`,
  };

  try {
    const response = await fetch('https://xray.cloud.getxray.app/api/v2/import/execution', {
      method: 'POST',
      headers: headers,
      body: JSON.stringify(testExecutionData),
    });

    if (response.status === 200) {
      console.log('Test execution results successfully imported into Xray!');
    } else {
      console.log('Failed to import test execution results.');
      console.log('Response status code:', response.status);
      const responseData = await response.text();
      console.log('Response data:', responseData);
    }
  } catch (error) {
    console.error('An error occurred during the API request:', error);
  }
}

test('Test importing execution results into Xray', async () => {
  try {
    await updateXRAY();
  } catch (error) {
    console.error('Error during test:', error);
  }
});
Executing this code will give error as below,

console.error
An error occurred while getting the access token: Error: Failed to get access token: Unauthorized
at _callee8$ (D:\nodejs\ADN_GED_Confluence\adn-ged-confluence\ged-confluence\routes\ged.test.js:57:13)
at call (D:\nodejs\ADN_GED_Confluence\adn-ged-confluence\ged-confluence\routes\ged.test.js:2:1)
at Generator.tryCatch (D:\nodejs\ADN_GED_Confluence\adn-ged-confluence\ged-confluence\routes\ged.test.js:2:1)
at Generator._invoke [as next] (D:\nodejs\ADN_GED_Confluence\adn-ged-confluence\ged-confluence\routes\ged.test.js:2:1)
at asyncGeneratorStep (D:\nodejs\ADN_GED_Confluence\adn-ged-confluence\ged-confluence\routes\ged.test.js:2:1)
at asyncGeneratorStep (D:\nodejs\ADN_GED_Confluence\adn-ged-confluence\ged-confluence\routes\ged.test.js:2:1)
at processTicksAndRejections (node:internal/process/task_queues:96:5)

61 | return responseData.access_token;
62 | } catch (error) {
> 63 | console.error('An error occurred while getting the access token:', error);
| ^
64 | throw error;
65 | }
66 | console.log('Response from token endpoint:', response);

at error (routes/ged.test.js:63:13)
at call (routes/ged.test.js:2:1)
at Generator.tryCatch (routes/ged.test.js:2:1)
at Generator._invoke [as next] (routes/ged.test.js:2:1)
at asyncGeneratorStep (routes/ged.test.js:2:1)
at asyncGeneratorStep (routes/ged.test.js:2:1)

console.error
Error during test: Error: Failed to get access token: Unauthorized
at _callee8$ (D:\nodejs\ADN_GED_Confluence\adn-ged-confluence\ged-confluence\routes\ged.test.js:57:13)
at call (D:\nodejs\ADN_GED_Confluence\adn-ged-confluence\ged-confluence\routes\ged.test.js:2:1)
at Generator.tryCatch (D:\nodejs\ADN_GED_Confluence\adn-ged-confluence\ged-confluence\routes\ged.test.js:2:1)
at Generator._invoke [as next] (D:\nodejs\ADN_GED_Confluence\adn-ged-confluence\ged-confluence\routes\ged.test.js:2:1)
at asyncGeneratorStep (D:\nodejs\ADN_GED_Confluence\adn-ged-confluence\ged-confluence\routes\ged.test.js:2:1)
at asyncGeneratorStep (D:\nodejs\ADN_GED_Confluence\adn-ged-confluence\ged-confluence\routes\ged.test.js:2:1)
at processTicksAndRejections (node:internal/process/task_queues:96:5)

126 | await updateXRAY();
127 | } catch (error) {
> 128 | console.error('Error during test:', error);
| ^
129 | }
130 | });
131 |

at error (routes/ged.test.js:128:13)
at call (routes/ged.test.js:2:1)
at Generator.tryCatch (routes/ged.test.js:2:1)
at Generator._invoke [as throw] (routes/ged.test.js:2:1)
at asyncGeneratorStep (routes/ged.test.js:2:1)
at asyncGeneratorStep (routes/ged.test.js:2:1)

 

I'm stuck, please suggest some solution

Marc - Devoteam
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
July 25, 2023

Hi @Anmol Fattepur 

I see this:

const testExecutionData = {
    info: {
      "testExecutionKey": "XAUTO-25",
For me this seems to be:
const testExecutionData = {
      "testExecutionKey": "XAUTO-25",
And at the end
],
This should be just ]
Anmol Fattepur July 25, 2023

Hi @Marc - Devoteam ,

I modified again as suggested.

Pasting entire code again for your reference,

 

const fetch = require('node-fetch');
const jwt = require('jsonwebtoken');

const clientId = 'FCBD243AF6EF4D39B52455543919643B';
const clientSecret = '793b48d41eed541adf7c53915b51b9739037aee6a1441d4c7d4d837e624db593';

async function getAccessToken() {

  const payload = {
    iss: clientId,
    sub: clientId,
    exp: Math.floor(Date.now() / 1000) + 60,
  };

  const token = jwt.sign(payload, clientSecret);

  const headers = {
    'Content-Type': 'application/x-www-form-urlencoded',
    'Authorization': `Bearer ${token}`,
  };

  const requestBody = new URLSearchParams();
  requestBody.append('grant_type', 'client_credentials');

  try {
    const response = await fetch(tokenEndpoint, {
      method: 'POST',
      headers: headers,
      body: requestBody,
    });

    if (!response.ok) {
      throw new Error(`Failed to get access token: ${response.statusText}`);
    }

    const responseData = await response.json();
    return responseData.access_token;
  } catch (error) {
    console.error('An error occurred while getting the access token:', error);
    throw error;
  }
  console.log('Response from token endpoint:', response);
  const responseData = await response.json();
  return responseData.access_token;
}

async function updateXRAY() {
  const accessToken = await getAccessToken();
  const testExecutionData = {
      "testExecutionKey": "XAUTO-25",
      "info" : {
          "summary" : "Execution of automated tests for release v1.3",
          "description" : "TEST!!!! This execution is automatically created when importing execution results from an external source'",
          "version" : "Beta",
          "user" : "Anmol Fattepur",
          "revision" : "1.0.42134",
          "startDate" : "2014-08-30T11:47:35+01:00",
          "finishDate" : "2014-08-30T11:53:00+01:00",
          "testPlanKey" : "DEMO-100",
          "testEnvironments": ['UAT']
      },
      "tests" : [
          {
              "testKey" : "XAUTO-4",
              "start" : "2014-08-30T11:47:35+01:00",
              "finish" : "2014-08-30T11:50:56+01:00",
              "comment" : "Successful execution",
              "status" : "PASSED"
          }
       ]
};

  const headers = {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${accessToken}`,
  };

  try {
    const response = await fetch('https://xray.cloud.getxray.app/api/v2/import/execution', {
      method: 'POST',
      headers: headers,
      body: JSON.stringify(testExecutionData),
    });

    if (response.status === 200) {
      console.log('Test execution results successfully imported into Xray!');
    } else {
      console.log('Failed to import test execution results.');
      console.log('Response status code:', response.status);
      const responseData = await response.text();
      console.log('Response data:', responseData);
    }
  } catch (error) {
    console.error('An error occurred during the API request:', error);
  }
}

test('Test importing execution results into Xray', async () => {
  try {
    await updateXRAY();
  } catch (error) {
    console.error('Error during test:', error);
  }
});
I still get the same error message
Marc - Devoteam
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
July 25, 2023

Quick question,

Does your test and test execution already exist in Jira (XAUTO-25 and XAUTO-4)?

Or does only the Test (XAUTO-4) exists?

If the call is to create a new Test Execution you should use the following api call (example):

{

    "info" : {

        "summary" : "Execution of automated tests for release v1.3",

        "description" : "This execution is automatically created when importing execution results from an external source",

        "version" : "Beta",

        "user" : "Anmol Fattepur",

        "revision" : "1.0.42134",

        "startDate" : "2014-08-30T11:47:35+01:00",

        "finishDate" : "2014-08-30T11:53:00+01:00",

        "testEnvironments": ["UAT"]

    },

    "tests" : [

        {

            "testKey" : "XAUTO-4",

            "start" : "2014-08-30T11:47:35+01:00",

            "finish" : "2014-08-30T11:50:56+01:00",

            "actualResult" : "Successful execution",

            "status" : "PASSED"

        }

   ]

}

Marc - Devoteam
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
July 25, 2023

But I see the following error:

An error occurred while getting the access token: Error: Failed to get access token: Unauthorized

So you are not authorised correctly, so this will cause the API call to fail.

SO there is something wrong in the call to authenticate yourself.

Could you first see if your authentication works?

Suggest an answer

Log in or Sign up to answer
DEPLOYMENT TYPE
CLOUD
PRODUCT PLAN
STANDARD
PERMISSIONS LEVEL
Product Admin
TAGS
AUG Leaders

Atlassian Community Events