Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EPMRPP-78272 || Implement attaching data using attach #123

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"parserOptions": {
"ecmaVersion": 2018,
"sourceType": "module",
"project": "./tsconfig.eslint.json"
"project": "./tsconfig.eslint.json"
},
"rules": {
"no-plusplus": 0,
Expand All @@ -33,6 +33,7 @@
"@typescript-eslint/ban-ts-comment": 0,
"@typescript-eslint/no-implied-eval": 0,
"dot-notation": 0,
"@typescript-eslint/naming-convention": 0
"@typescript-eslint/naming-convention": 0,
"consistent-return": "warn"
}
}
2 changes: 2 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Ignore all md files
*.md
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
### Added
- `ReportingApi` from `@reportportal/agent-js-playwright/promises` methods (***addAttributes, setDescription, setTestCaseId, setStatus***, and all methods for setting custom statuses for test or suite) now using ***testInfo.attach*** method to attach custom data to test case.

## [5.1.4] - 2023-10-05
## Changed
Expand Down
58 changes: 34 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,9 @@ As an alternative to this approach the [`ReportingAPI`](#log) methods can be use

This reporter provides Reporting API to use it directly in tests to send some additional data to the report.

To start using the `ReportingApi` in tests, just import it from `'@reportportal/agent-js-playwright'`:
To start using the `ReportingApi` in tests, just import it from `'@reportportal/agent-js-playwright/promises'`:
```javascript
import { ReportingApi } from '@reportportal/agent-js-playwright';
import { ReportingApi } from '@reportportal/agent-js-playwright/promises'
```

#### Reporting API methods
Expand All @@ -143,13 +143,15 @@ If you want to add a data to the suite, you must pass the suite name as the last

##### addAttributes
Add attributes (tags) to the current test. Should be called inside of corresponding test.<br/>
`ReportingApi.addAttributes(attributes: Array<Attribute>, suite?: string);`<br/>
`ReportingApi.addAttributes(attributes: Array<Attribute>, suite?: string):Promise<void>;`<br/>
**required**: `attributes`<br/>
**optional**: `suite`<br/>
Example:
```javascript
test('should have the correct attributes', () => {
ReportingApi.addAttributes([
import { ReportingApi } from '@reportportal/agent-js-playwright/promises'

test('should have the correct attributes', async () => {
await ReportingApi.addAttributes([
{
key: 'testKey',
value: 'testValue',
Expand All @@ -164,14 +166,16 @@ test('should have the correct attributes', () => {

##### setTestCaseId
Set test case id to the current test ([About test case id](https://reportportal.io/docs/Test-case-ID%3Ewhat-is-it-test-case-id)). Should be called inside of corresponding test.<br/>
`ReportingApi.setTestCaseId(id: string, suite?: string);`<br/>
`ReportingApi.setTestCaseId(id: string, suite?: string):Promise<void>;`<br/>
**required**: `id`<br/>
**optional**: `suite`<br/>
If `testCaseId` not specified, it will be generated automatically based on [codeRef](https://reportportal.io/docs/Test-case-ID%3Ewhat-does-happen-if-you-do-not-report-items-with-test-case-id-).<br/>
Example:
```javascript
test('should have the correct testCaseId', () => {
ReportingApi.setTestCaseId('itemTestCaseId');
import { ReportingApi } from '@reportportal/agent-js-playwright/promises'

test('should have the correct testCaseId', async () => {
await ReportingApi.setTestCaseId('itemTestCaseId');
expect(true).toBe(true);
});
```
Expand Down Expand Up @@ -270,37 +274,43 @@ test('should contain logs with attachments', () => {

##### setStatus
Assign corresponding status to the current test item. Should be called inside of corresponding test.<br/>
`ReportingApi.setStatus(status: string, suite?: string);`<br/>
`ReportingApi.setStatus(status: string, suite?: string):Promise<void>;`<br/>
**required**: `status`<br/>
**optional**: `suite`<br/>
where `status` must be one of the following: *passed*, *failed*, *stopped*, *skipped*, *interrupted*, *cancelled*<br/>
Example:
```javascript
test('should have status FAILED', () => {
ReportingApi.setStatus('failed');
import { ReportingApi } from '@reportportal/agent-js-playwright/promises'

test('should have status FAILED', async () => {
await ReportingApi.setStatus('failed');

expect(true).toBe(true);
});
```

##### setStatusFailed, setStatusPassed, setStatusSkipped, setStatusStopped, setStatusInterrupted, setStatusCancelled
Assign corresponding status to the current test item. Should be called inside of corresponding test.<br/>
`ReportingApi.setStatusFailed(suite?: string);`<br/>
`ReportingApi.setStatusPassed(suite?: string);`<br/>
`ReportingApi.setStatusSkipped(suite?: string);`<br/>
`ReportingApi.setStatusStopped(suite?: string);`<br/>
`ReportingApi.setStatusInterrupted(suite?: string);`<br/>
`ReportingApi.setStatusCancelled(suite?: string);`<br/>
`ReportingApi.setStatusFailed(suite?: string):Promise<void>;`<br/>
`ReportingApi.setStatusPassed(suite?: string):Promise<void>;`<br/>
`ReportingApi.setStatusSkipped(suite?: string):Promise<void>;`<br/>
`ReportingApi.setStatusStopped(suite?: string):Promise<void>;`<br/>
`ReportingApi.setStatusInterrupted(suite?: string):Promise<void>;`<br/>
`ReportingApi.setStatusCancelled(suite?: string):Promise<void>;`<br/>
**optional**: `suite`<br/>
Example:
```javascript
test('should call ReportingApi to set statuses', () => {
ReportingAPI.setStatusFailed();
ReportingAPI.setStatusPassed();
ReportingAPI.setStatusSkipped();
ReportingAPI.setStatusStopped();
ReportingAPI.setStatusInterrupted();
ReportingAPI.setStatusCancelled();
import { ReportingApi } from '@reportportal/agent-js-playwright/promises'

test('should call ReportingApi to set statuses', async () => {
await Promise.all[
ReportingAPI.setStatusFailed(),
ReportingAPI.setStatusPassed(),
ReportingAPI.setStatusSkipped(),
ReportingAPI.setStatusStopped(),
ReportingAPI.setStatusInterrupted(),
ReportingAPI.setStatusCancelled(),
]
});
```

Expand Down
25 changes: 23 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,29 @@
"name": "@reportportal/agent-js-playwright",
"version": "5.1.4",
"description": "Agent to integrate Playwright with ReportPortal.",
"main": "build/index.js",
"types": "build/index.d.ts",
"exports": {
".": {
"node": "./build/index.js",
"import": "./build/index.js",
"require": "./build/index.js",
"default": "./build/index.js"
},
"./promises": {
"node": "./build/promises/index.js",
"default": "./build/promises/index.js",
"require": "./build/promises/index.js",
"import": "./build/promises/index.js"
}
},
"typesVersions": {
"*": {
"promises": [
"./build/promises/index.d.ts"
]
}
},
"types": "./build/index.d.ts",
"main": "./build/index.js",
"scripts": {
"build": "npm run clean && tsc",
"clean": "rimraf ./build",
Expand Down
192 changes: 192 additions & 0 deletions src/__tests__/promises/reportingApi.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
/*
* Copyright 2021 EPAM Systems
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

import { ReportingApi } from '../../promises';
import * as utils from '../../utils';
import { LOG_LEVELS, STATUSES } from '../../constants';

const reportingApiStatusMethods = [
{ method: 'setStatusPassed', status: 'passed' },
{ method: 'setStatusFailed', status: 'failed' },
{ method: 'setStatusSkipped', status: 'skipped' },
{ method: 'setStatusStopped', status: 'stopped' },
{ method: 'setStatusInterrupted', status: 'interrupted' },
{ method: 'setStatusCancelled', status: 'cancelled' },
{ method: 'setStatusInfo', status: 'info' },
{ method: 'setStatusWarn', status: 'warn' },
];

const reportingApiLaunchStatusMethods = [
{ method: 'setLaunchStatusPassed', status: 'passed' },
{ method: 'setLaunchStatusFailed', status: 'failed' },
{ method: 'setLaunchStatusSkipped', status: 'skipped' },
{ method: 'setLaunchStatusStopped', status: 'stopped' },
{ method: 'setLaunchStatusInterrupted', status: 'interrupted' },
{ method: 'setLaunchStatusCancelled', status: 'cancelled' },
{ method: 'setLaunchStatusInfo', status: 'info' },
{ method: 'setLaunchStatusWarn', status: 'warn' },
];

const reportingApiLogMethods = [
{ method: 'trace', level: 'TRACE' },
{ method: 'debug', level: 'DEBUG' },
{ method: 'info', level: 'INFO' },
{ method: 'warn', level: 'WARN' },
{ method: 'error', level: 'ERROR' },
{ method: 'fatal', level: 'FATAL' },
];

const reportingApiLaunchLogMethods = [
{ method: 'launchTrace', level: 'TRACE' },
{ method: 'launchDebug', level: 'DEBUG' },
{ method: 'launchInfo', level: 'INFO' },
{ method: 'launchWarn', level: 'WARN' },
{ method: 'launchError', level: 'ERROR' },
{ method: 'launchFatal', level: 'FATAL' },
];

describe('reportingApi', () => {
beforeEach(() => {
jest.clearAllMocks();
});

test('addAttributes should call sendEventToReporter with params', () => {
const attrs = [
{
key: 'key',
value: 'value',
},
];
const suite = 'suite';
const spySendEventToReporter = jest.spyOn(utils, 'sendEventToReporter');
ReportingApi.addAttributes(attrs, suite);

expect(spySendEventToReporter).toHaveBeenCalledTimes(1);
});

test('setDescription should call sendEventToReporter with params', () => {
const description = 'description';
const suite = 'suite';
const spySendEventToReporter = jest.spyOn(utils, 'sendEventToReporter');
ReportingApi.setDescription(description, suite);

expect(spySendEventToReporter).toHaveBeenCalledTimes(1);
});

test('setTestCaseId should call sendEventToReporter with params', () => {
const testCaseId = 'TestCaseIdForTheSuite';
const suite = 'suite';
const spySendEventToReporter = jest.spyOn(utils, 'sendEventToReporter');
ReportingApi.setTestCaseId(testCaseId, suite);

expect(spySendEventToReporter).toHaveBeenCalledTimes(1);
});

describe('Item status reporting', () => {
reportingApiStatusMethods.map(({ method, status }) => {
test(`${method} should call sendEventToReporter with ${status} status`, () => {
const suite = 'suite';
const spySendEventToReporter = jest.spyOn(utils, 'sendEventToReporter');
// @ts-ignore
ReportingApi[method](suite);

expect(spySendEventToReporter).toHaveBeenCalledTimes(1);
});
});

test('ReportingApi.setStatus should call sendEventToReporter with provided status', () => {
const suite = 'suite';
const spySendEventToReporter = jest.spyOn(utils, 'sendEventToReporter');
ReportingApi.setStatus(STATUSES.PASSED, suite);

expect(spySendEventToReporter).toHaveBeenCalledTimes(1);
});
});

describe('Launch status reporting', () => {
reportingApiLaunchStatusMethods.map(({ method, status }) => {
test(`${method} should call sendEventToReporter with ${status} status`, () => {
const spySendEventToReporter = jest.spyOn(utils, 'sendEventToReporter');
// @ts-ignore
ReportingApi[method]();

expect(spySendEventToReporter).toHaveBeenCalledTimes(1);
});
});

test('ReportingApi.setLaunchStatus should call sendEventToReporter with provided status', () => {
const spySendEventToReporter = jest.spyOn(utils, 'sendEventToReporter');
const status = 'PASSED';
ReportingApi.setLaunchStatus(status);

expect(spySendEventToReporter).toHaveBeenCalledTimes(1);
});
});

describe('Logs reporting', () => {
const file = {
name: 'filename',
type: 'image/png',
content: Buffer.from([1, 2, 3, 4, 5, 6, 7]).toString('base64'),
};
const suite = 'suite';

reportingApiLogMethods.map(({ method, level }) => {
test(`${method} should call ReportingApi.log with ${level} level`, () => {
const spyLogFunc = jest.spyOn(ReportingApi, 'log');

// @ts-ignore
ReportingApi[method]('message', file, suite);

expect(spyLogFunc).toHaveBeenCalledTimes(1);
});
});

test('ReportingApi.log should call sendEventToReporter with params', () => {
const spySendEventToReporter = jest.spyOn(utils, 'sendEventToReporter');
ReportingApi.log(LOG_LEVELS.INFO, 'message', file, suite);

expect(spySendEventToReporter).toHaveBeenCalledTimes(1);
});
});

describe('Launch logs reporting', () => {
const file = {
name: 'filename',
type: 'image/png',
content: Buffer.from([1, 2, 3, 4, 5, 6, 7]).toString('base64'),
};

reportingApiLaunchLogMethods.map(({ method, level }) => {
test(`${method} should call ReportingApi.launchLog with ${level} level`, () => {
const spyLogFunc = jest.spyOn(ReportingApi, 'launchLog');

// @ts-ignore
ReportingApi[method]('message', file);

expect(spyLogFunc).toHaveBeenCalledTimes(1);
});
});

test('ReportingApi.launchLog should call sendEventToReporter with params', () => {
const spySendEventToReporter = jest.spyOn(utils, 'sendEventToReporter');
ReportingApi.launchLog(LOG_LEVELS.INFO, 'message', file);

expect(spySendEventToReporter).toHaveBeenCalledTimes(1);
});
});
});
2 changes: 2 additions & 0 deletions src/__tests__/reporter/finishSuiteReporting.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ describe('finish suites on finish all of their children', () => {
const testCase = {
title: 'testTitle',
id: 'testItemId',
//@ts-ignore
results: [{ attachments: [] }],
parent: {
title: rootSuite,
project: () => ({ name: rootSuite }),
Expand Down
Loading
Loading