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

Rpp 89645 testCaseId, attributes, description reporting #19

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
44 changes: 44 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,47 @@ test('should contain logs with attachments',({ task }) => {
expect(true).toBe(true);
});
```

##### testCaseId
Add testCaseId to ReportPortal for the current test. Should be called inside of corresponding test.<br/>
`ReportingApi.testCaseId(task: vitest.Task, data: string);`<br/>
**required**: `task`, `data`<br/>
Example:
```javascript
test('should contain testCaseId',({ task }) => {
ReportingApi.testCaseId(task, 'C123456');

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

##### description
Add description to ReportPortal for the current test. In case the user call the method more than one time, the existing description will be extended. Should be called inside of corresponding test.<br/>
`ReportingApi.description(task: vitest.Task, data: string);`<br/>
**required**: `task`, `data`<br/>
Example:
```javascript
test('should contain description',({ task }) => {
ReportingApi.description(task, 'Test Description');

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

##### attributes
Send file to ReportPortal for the current test. Should be called inside of corresponding test.<br/>
`ReportingApi.attributes(task: vitest.Task, data: Attribute[]);`<br/>
**required**: `task`, `data`<br/>
where `Attribute` type is `{ value: string; key?: string; system?: boolean; }`<br/>
Example:
```javascript
test('should contain attributes',({ task }) => {
ReportingApi.attributes(task,
[
{ key: 'attrKey1', value: 'attrValue1'},
{ value: 'attrValue2'}
]);

expect(true).toBe(true);
});
```
42 changes: 42 additions & 0 deletions src/__tests__/attributesReporting.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { ReportingApi } from '../reportingApi';
import * as vitest from 'vitest';
import { getTask } from './mocks/data';
import { RPTaskMeta } from '../models';

describe('test attributes reporting', () => {
let task: vitest.Task;

beforeEach(() => {
task = getTask();
});

test('should add attributes to task meta', () => {
const data = [
{ key: 'key1', value: 'value1' },
{ key: 'key2', value: 'value2' },
];
ReportingApi.attributes(task, data);

expect((task.meta as RPTaskMeta).rpMeta.test.attributes).toEqual(data);
});

test('should append attributes to existing attributes in task meta', () => {
const existingAttributes = [{ key: 'existingKey', value: 'existingValue' }];
const rpMeta: RPTaskMeta = {
rpMeta: {
test: {
logs: [],
attributes: existingAttributes,
},
},
};
task.meta = rpMeta;
const newAttributes = [{ key: 'newKey', value: 'newValue' }];
ReportingApi.attributes(task, newAttributes);

expect((task.meta as RPTaskMeta).rpMeta.test.attributes).toEqual([
...existingAttributes,
...newAttributes,
]);
});
});
39 changes: 39 additions & 0 deletions src/__tests__/descriptionReporting.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { ReportingApi } from '../reportingApi';
import * as vitest from 'vitest';
import { getTask } from './mocks/data';
import { RPTaskMeta } from '../models';

describe('test description reporting', () => {
let task: vitest.Task;

beforeEach(() => {
task = getTask();
});

test('should add description to task meta', () => {
const description = 'test description';
ReportingApi.description(task, description);

expect((task.meta as RPTaskMeta).rpMeta.test.description).toEqual(description);
});

test('should append data to existing description in task meta', () => {
const existingDescription = 'test description';
const rpMeta: RPTaskMeta = {
rpMeta: {
test: {
logs: [],
attributes: [],
description: existingDescription,
},
},
};
task.meta = rpMeta;
const newDescription = 'new test description';
ReportingApi.description(task, newDescription);

expect((task.meta as RPTaskMeta).rpMeta.test.description).toEqual(
existingDescription + '\n' + newDescription,
);
});
});
40 changes: 40 additions & 0 deletions src/__tests__/mocks/RPClientMock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { ReportPortalConfig } from '../../models';

const mockedDate = Date.now();
export class RPClientMock {
private config: ReportPortalConfig;

constructor(config?: ReportPortalConfig) {
this.config = config;
}

public startLaunch = jest.fn().mockReturnValue({
promise: Promise.resolve('ok'),
tempId: 'tempLaunchId',
});

public finishLaunch = jest.fn().mockReturnValue({
promise: Promise.resolve('ok'),
});

public startTestItem = jest.fn().mockReturnValue({
promise: Promise.resolve('ok'),
tempId: 'tempTestItemId',
});

public finishTestItem = jest.fn().mockReturnValue({
promise: Promise.resolve('ok'),
});

public sendLog = jest.fn().mockReturnValue({
promise: Promise.resolve('ok'),
});

public helpers = {
now: (): number => mockedDate,
};

public checkConnect = jest.fn().mockReturnValue({
promise: Promise.resolve('ok'),
});
}
10 changes: 10 additions & 0 deletions src/__tests__/mocks/configMock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { ReportPortalConfig } from '../../models';

export const config: ReportPortalConfig = {
apiKey: 'reportportalApiKey',
endpoint: 'https://reportportal.server/api/v1',
project: 'ProjectName',
launch: 'LaunchName',
description: 'Launch description',
attributes: [],
};
13 changes: 13 additions & 0 deletions src/__tests__/mocks/data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import * as vitest from 'vitest';

export function getTask(): vitest.Task {
return {
id: 'id',
name: 'task',
type: 'suite',
mode: 'run',
tasks: [],
meta: {},
projectName: 'testProject',
};
}
56 changes: 56 additions & 0 deletions src/__tests__/onTaskUpdate.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { RPReporter } from '../reporter';
import { config } from './mocks/configMock';
import { RPClientMock } from './mocks/RPClientMock';
import * as vitest from 'vitest';
import { RPTaskMeta } from '../models';
import { STATUSES, TASK_STATUS } from '../constants';

describe('onTaskUpdate', () => {
let reporter: RPReporter;
const testTaskId = 'testTaskId';
const testItemId = 'testId';
beforeEach(() => {
reporter = new RPReporter(config);
reporter.client = new RPClientMock(config);
reporter.launchId = 'tempLaunchId';
reporter.testItems.set(testTaskId, {
id: testItemId,
});
});

describe('finishing test with attributes, testCaseId, description in rpMeta ', () => {
it('test with attributes, description, testCaseId', () => {
const attributes = [
{
key: 'key1',
value: 'value1',
},
];
const description = 'test_description';
const testCaseId = 'testCaseId';
const taskMeta: RPTaskMeta = {
rpMeta: {
test: {
logs: [],
attributes,
description,
testCaseId,
},
},
};
const packs: vitest.TaskResultPack[] = [[testTaskId, { state: TASK_STATUS.pass }, taskMeta]];
const finishTestItemRQ = {
status: STATUSES.PASSED,
attributes,
description,
testCaseId,
endTime: reporter.client.helpers.now(),
};

reporter.onTaskUpdate(packs);

expect(reporter.client.finishTestItem).toBeCalledTimes(1);
expect(reporter.client.finishTestItem).toBeCalledWith(testItemId, finishTestItemRQ);
});
});
});
36 changes: 36 additions & 0 deletions src/__tests__/testCaseIdReporting.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { ReportingApi } from '../reportingApi';
import * as vitest from 'vitest';
import { getTask } from './mocks/data';
import { RPTaskMeta } from '../models';

describe('test case id reporting', () => {
let task: vitest.Task;

beforeEach(() => {
task = getTask();
});

test('should set test case id to task meta', () => {
const testCaseId = 'test_case_id';
ReportingApi.testCaseId(task, testCaseId);

expect((task.meta as RPTaskMeta).rpMeta.test.testCaseId).toEqual(testCaseId);
});

test('should overwrite test case id in task meta', () => {
const rpMeta: RPTaskMeta = {
rpMeta: {
test: {
logs: [],
attributes: [],
testCaseId: 'old_test_case_id',
},
},
};
task.meta = rpMeta;
const newTestCaseId = 'new_test_case_id';
ReportingApi.testCaseId(task, newTestCaseId);

expect((task.meta as RPTaskMeta).rpMeta.test.testCaseId).toEqual(newTestCaseId);
});
});
9 changes: 9 additions & 0 deletions src/models/reporting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,23 @@ export interface RPTaskMeta extends TaskMeta {
rpMeta: {
test: {
logs: LogRQ[];
attributes: Attribute[];
testCaseId?: string;
description?: string;
};
};
}

export interface ReportingApi {
attachment: (context: Task, data: Attachment, description?: string) => void;
attributes: (context: Task, data: Attribute[]) => void;
testCaseId: (context: Task, data: string) => void;
description: (context: Task, data: string) => void;
}

export interface GlobalReportingApi {
attachment: (data: Attachment, description?: string) => void;
attributes: (data: Attribute[]) => void;
testCaseId: (data: string) => void;
description: (data: string) => void;
}
8 changes: 5 additions & 3 deletions src/reporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,14 +174,16 @@ export class RPReporter implements Reporter {
continue;
}

const finishTestItemObj = this.getFinishTestItemObj(taskResult);

if (isRPTaskMeta(meta)) {
meta.rpMeta.test.logs.forEach((logRq) => {
const { logs, attributes, testCaseId, description } = meta.rpMeta.test;
logs.forEach((logRq) => {
this.sendLog(testItemId, logRq);
});
Object.assign(finishTestItemObj, { attributes, testCaseId, description });
}

const finishTestItemObj = this.getFinishTestItemObj(taskResult);

if (taskResult?.errors?.length) {
const error = taskResult.errors[0];

Expand Down
31 changes: 29 additions & 2 deletions src/reportingApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const injectRPTaskMeta = (task: vitest.Task) => {
rpMeta: {
test: {
logs: [],
attributes: [],
},
},
};
Expand All @@ -26,11 +27,37 @@ const attachment = (task: vitest.Task, data: Models.Attachment, description?: st
});
};

const attributes = (task: vitest.Task, data: Models.Attribute[]) => {
injectRPTaskMeta(task);
const rpMeta = (task.meta as Models.RPTaskMeta).rpMeta;
rpMeta.test.attributes = [...rpMeta.test.attributes, ...data];
};

const testCaseId = (task: vitest.Task, data: string) => {
injectRPTaskMeta(task);
(task.meta as Models.RPTaskMeta).rpMeta.test.testCaseId = data;
};

const description = (task: vitest.Task, data: string) => {
injectRPTaskMeta(task);
const rpMeta = (task.meta as Models.RPTaskMeta).rpMeta;
if (rpMeta.test.description) {
rpMeta.test.description = `${rpMeta.test.description}\n${data}`;
} else {
rpMeta.test.description = data;
}
};

export const ReportingApi: Models.ReportingApi = {
attachment,
attributes,
testCaseId,
description,
};

export const bindReportingApi = (task: vitest.Task): Models.GlobalReportingApi => ({
attachment: (data: Models.Attachment, description?: string) =>
attachment(task, data, description),
attachment: (data: Models.Attachment, message?: string) => attachment(task, data, message),
attributes: (data: Models.Attribute[]) => attributes(task, data),
testCaseId: (data: string) => testCaseId(task, data),
description: (data: string) => description(task, data),
});
Loading