Skip to content

Commit

Permalink
ADM-718[frontend][stub]feat: Display verification results of ‘board’ (#…
Browse files Browse the repository at this point in the history
…985)

* [kai.zhou][adm-718] feat: remove project key field

* [kai.zhou][adm-718]: feat: add addtional key for form field

* [kai.zhou][adm-718] fix unit test

* [kai.zhou][adm-718]: fix: ignore no coverage function

* [kai.zhou][adm-718]: feat: start integrate info api

* [kai.zhou][adm-718]: fix: fix code typo

* [kai.zhou][adm-718]: feat: update error handle for verify api

* [kai.zhou][adm-718]: feat: refact valid rule

* [kai.zhou][adm-718]: update get info callback

* [kai.zhou][adm-718]: refact board info call in metric page

* [kai.zhou][adm-718]: create new empty content component

* [kai.zhou][adm-718]: test: fix some unit test

* ADM-747: [frontend] feat: handle error (#968)

* ADM-747: [frontend] refactor: refactor notification

* ADM-747: [frontend] refactor: set default title for notification

* ADM-747: [frontend] feat: handle timeout error

* ADM-747: [frontend] feat: handle report error

* ADM-747: [frontend] refactor: rename reportMetricsError

* ADM-747: [frontend] refactor: replace enum with object

* ADM-747: [frontend] feat: handle report error

* ADM-747: [frontend] feat: handle export error

* ADM-747: [frontend] test: add tests for error notifications

* ADM-747: [frontend] refactor: refactor report useEffect

* ADM-747: [frontend] refactor: refactor TimeoutException

* ADM-747: [frontend] refactor: delete useless isServerError

* ADM-747: [frontend] test: add e2e tests for date picker

* ADM-747: [frontend] fix: fix import

* [kai.zhou][adm-718]: refact board info call in metric page

* [kai.zhou][adm-718]: create new empty content component

* [kai.zhou][adm-718]: test: fix some unit test

* [kai.zhou][adm-718]: chroe: format code

* [kai.zhou][adm-718]: refact board info call in metric page

* [kai.zhou][adm-718]: create new empty content component

* [kai.zhou][adm-718]: test: fix some unit test

* [kai.zhou][adm-718]: refact board info call in metric page

* [kai.zhou][adm-718]: test: fix some unit test

* [kai.zhou][adm-718]: chroe: format code

* [kai.zhou][adm-718]: fix failed unit test

* [kai.zhou][adm-718]: add new  stub for jira verify

* [kai.zhou][adm-718]: fix failed unit test

* [kai.zhou][adm-718]: add unit test for useVerifyBoardEffect

* [kai.zhou][adm-718]: fix unit test coverage

* [kai.zhou][adm-718]: update e2e test

* [kai.zhou][adm-718]: update e2e stub

* [kai.zhou][adm-718]: update stub data

* ADM-718:[Frontend] Fix E2E stub data

* ADM-718:[Frontend] Fix E2E stub data

* ADM-718:[Frontend] Fix E2E stub data

* [kai.zhou][adm-718]: fix email fields not post and ignore some e2e script

* [kai.zhou][adm-718]: refact board info call in metric page

* [kai.zhou][adm-718]: create new empty content component

* [kai.zhou][adm-718]: test: fix some unit test

* ADM-747: [frontend] feat: handle error (#968)

* ADM-747: [frontend] refactor: refactor notification

* ADM-747: [frontend] refactor: set default title for notification

* ADM-747: [frontend] feat: handle timeout error

* ADM-747: [frontend] feat: handle report error

* ADM-747: [frontend] refactor: rename reportMetricsError

* ADM-747: [frontend] refactor: replace enum with object

* ADM-747: [frontend] feat: handle report error

* ADM-747: [frontend] feat: handle export error

* ADM-747: [frontend] test: add tests for error notifications

* ADM-747: [frontend] refactor: refactor report useEffect

* ADM-747: [frontend] refactor: refactor TimeoutException

* ADM-747: [frontend] refactor: delete useless isServerError

* ADM-747: [frontend] test: add e2e tests for date picker

* ADM-747: [frontend] fix: fix import

* [kai.zhou][adm-718]: refact board info call in metric page

* [kai.zhou][adm-718]: test: fix some unit test

* [kai.zhou][adm-718]: chroe: format code

* [ADM-740] show not show real done when cycle time by status (#972)

Co-authored-by: wenjing-qi <wenjing.qi@rea-group.com>

* [kai.zhou][adm-718]: refact board info call in metric page

* [kai.zhou][adm-718]: create new empty content component

* [kai.zhou][adm-718]: test: fix some unit test

* [kai.zhou][adm-718]: refact board info call in metric page

* [kai.zhou][adm-718]: test: fix some unit test

* [kai.zhou][adm-718]: chroe: format code

* [kai.zhou][adm-718]: fix failed unit test

* [kai.zhou][adm-718]: fix unit test coverage

* [kai.zhou][adm-718]: fix typo

* [kai.zhou][adm-718]: fix local conflict

* [kai.zhou][adm-718]: fix failed test

* [kai.zhou][adm-718]: fix type

* [kai.zhou][adm-718]: fix code for review

* [kai.zhou][adm-718]: fix test typo

* [kai.zhou][adm-718]: fix code styles

* [kai.zhou][adm-718]: fix failed test

* [kai.zhou][adm-718]: refact email token mix

* [kai.zhou][adm-718]: add new test case

* [kai.zhou][adm-718]: fix code styles

* [kai.zhou][adm-718]: skip e2e test for creat project

* [kai.zhou][adm-718]: fix pr issue

* [kai.zhou][adm-718]: fix codacy issue

* [kai.zhou][adm-718]: fix codacy issue

* [kai.zhou][adm-718]: fix codacy issue

* [kai.zhou][adm-718]: fix codacy issue

* [kai.zhou][adm-718]: fix failed test

* [kai.zhou][adm-718]: refact unit test

* ADM-718:[Frontend] Fix Codacy issue

* ADM-718:[Frontend] Fix rebase issue

* ADM-718:[Frontend] Fix test case

* [kai.zhou][adm-718]: fix not show form error

* [kai.zhou][adm-718]: fix issues about deskcheck

* ADM-718:[Frontend] Fix unit test case

* [kai.zhou]: support reset error message when change form field

* [kai.zhou][adm-718]: fix failed test

* [kai.zhou][adm-718]: fix Classification can not update

* [kai.zhou][adm-718]: refact unit test for classification

* [kai.zhou][adm-718]: fix failed lint

* [kai.zhou][adm-718]: fix lint warning

* ADM-718:[Frontend] Remove some comments for E2E tests

* [kai.zhou][adm-718]: fix form field warning

---------

Co-authored-by: 姜如 <77052266+JiangRu1@users.noreply.github.com>
Co-authored-by: Simon Tal <simon_tal@hotmail.com>
Co-authored-by: gabralia <gabralia@qq.com>
Co-authored-by: wenjing-qi <wenjing.qi@rea-group.com>
  • Loading branch information
5 people authored Feb 1, 2024
1 parent e41ff49 commit 2447ec8
Show file tree
Hide file tree
Showing 60 changed files with 3,745 additions and 6,986 deletions.
12 changes: 4 additions & 8 deletions frontend/__tests__/client/BoardClient.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import {
MOCK_BOARD_URL_FOR_CLASSIC_JIRA,
MOCK_BOARD_URL_FOR_JIRA,
MOCK_BOARD_VERIFY_REQUEST_PARAMS,
MOCK_CLASSIC_JIRA_BOARD_VERIFY_REQUEST_PARAMS,
MOCK_JIRA_BOARD_VERIFY_REQUEST_PARAMS,
VERIFY_ERROR_MESSAGE,
AXIOS_ERROR_MESSAGE,
} from '../fixtures';
Expand All @@ -11,10 +10,7 @@ import { setupServer } from 'msw/node';
import { HttpStatusCode } from 'axios';
import { rest } from 'msw';

const server = setupServer(
rest.post(MOCK_BOARD_URL_FOR_JIRA, (req, res, ctx) => res(ctx.status(HttpStatusCode.Ok))),
rest.post(MOCK_BOARD_URL_FOR_CLASSIC_JIRA, (req, res, ctx) => res(ctx.status(HttpStatusCode.Ok))),
);
const server = setupServer(rest.post(MOCK_BOARD_URL_FOR_JIRA, (req, res, ctx) => res(ctx.status(HttpStatusCode.Ok))));

describe('verify board request', () => {
beforeAll(() => server.listen());
Expand All @@ -26,8 +22,8 @@ describe('verify board request', () => {
expect(result.isBoardVerify).toEqual(true);
});

it('should isBoardVerify is true when select classic jira and board verify response status 200', async () => {
const result = await boardClient.getVerifyBoard(MOCK_CLASSIC_JIRA_BOARD_VERIFY_REQUEST_PARAMS);
it('should isBoardVerify is true when select jira and board verify response status 200', async () => {
const result = await boardClient.getVerifyBoard(MOCK_JIRA_BOARD_VERIFY_REQUEST_PARAMS);

expect(result.isBoardVerify).toEqual(true);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import DateRangeViewer from '@src/components/Common/DateRangeViewer';
import { render, screen } from '@testing-library/react';
import React from 'react';
describe('DateRangeVier', () => {
it('should show date when render component given startDate and endDate', () => {
render(<DateRangeViewer startDate={new Date('2022/1/1').toString()} endDate={new Date('2022/1/2').toString()} />);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import EmptyContent from '@src/components/Common/EmptyContent';
import { render, screen } from '@testing-library/react';

describe('EmptyContent', () => {
it('should show title and message when render EmptyContent given title and message', () => {
render(<EmptyContent title='Fake title' message='there is empty content' />);
expect(screen.getByText(/fake title/i)).toBeInTheDocument();
expect(screen.getByText(/there is empty content/i)).toBeInTheDocument();
});
});
202 changes: 93 additions & 109 deletions frontend/__tests__/containers/ConfigStep/Board.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,48 @@ import {
CONFIG_TITLE,
ERROR_MESSAGE_COLOR,
MOCK_BOARD_URL_FOR_JIRA,
NO_CARD_ERROR_MESSAGE,
RESET,
VERIFIED,
VERIFY,
VERIFY_ERROR_MESSAGE,
VERIFY_FAILED,
FAKE_TOKEN,
} from '../../fixtures';
import { fireEvent, render, screen, waitFor, within } from '@testing-library/react';
import { render, screen, waitFor, within } from '@testing-library/react';
import { Board } from '@src/containers/ConfigStep/Board';
import { setupStore } from '../../utils/setupStoreUtil';
import userEvent from '@testing-library/user-event';
import { Provider } from 'react-redux';
import { setupServer } from 'msw/node';
import { HttpStatusCode } from 'axios';
import { rest } from 'msw';
import React from 'react';

export const fillBoardFieldsInformation = () => {
const fields = ['Board Id', 'Email', 'Project Key', 'Site', 'Token'];
const mockInfo = ['2', 'mockEmail@qq.com', 'mockKey', '1', 'mockToken'];
const fieldInputs = fields.map((label) => screen.getByTestId(label).querySelector('input') as HTMLInputElement);
fieldInputs.map((input, index) => {
fireEvent.change(input, { target: { value: mockInfo[index] } });
});
fieldInputs.map((input, index) => {
expect(input.value).toEqual(mockInfo[index]);
});

export const fillBoardFieldsInformation = async () => {
await userEvent.type(screen.getByLabelText(/board id/i), '1');
await userEvent.type(screen.getByLabelText(/email/i), 'fake@qq.com');
await userEvent.type(screen.getByLabelText(/site/i), 'fake');
await userEvent.type(screen.getByLabelText(/token/i), FAKE_TOKEN);
};

let store = null;

const server = setupServer(rest.post(MOCK_BOARD_URL_FOR_JIRA, (req, res, ctx) => res(ctx.status(200))));
const server = setupServer();

const mockVerifySuccess = (delay = 0) => {
server.use(
rest.post(MOCK_BOARD_URL_FOR_JIRA, (_, res, ctx) =>
res(
ctx.json({
projectKey: 'FAKE',
}),
ctx.delay(delay),
),
),
);
};

describe('Board', () => {
beforeAll(() => server.listen());
beforeAll(() => {
server.listen();
});
afterAll(() => server.close());

store = setupStore();
Expand All @@ -56,7 +64,6 @@ describe('Board', () => {

it('should show board title and fields when render board component ', () => {
setup();

BOARD_FIELDS.map((field) => {
expect(screen.getByLabelText(`${field} *`)).toBeInTheDocument();
});
Expand All @@ -65,17 +72,16 @@ describe('Board', () => {

it('should show default value jira when init board component', () => {
setup();
const boardType = screen.getByText(BOARD_TYPES.JIRA);
const boardType = screen.getByRole('button', {
name: /board/i,
});

expect(boardType).toBeInTheDocument();

const option = screen.queryByText(BOARD_TYPES.CLASSIC_JIRA);
expect(option).not.toBeTruthy();
});

it('should show detail options when click board field', () => {
it('should show detail options when click board field', async () => {
setup();
fireEvent.mouseDown(screen.getByRole('button', { name: CONFIG_TITLE.BOARD }));
await userEvent.click(screen.getByRole('button', { name: /board jira/i }));
const listBox = within(screen.getByRole('listbox'));
const options = listBox.getAllByRole('option');
const optionValue = options.map((li) => li.getAttribute('data-value'));
Expand All @@ -85,149 +91,127 @@ describe('Board', () => {

it('should show board type when select board field value ', async () => {
setup();
await userEvent.click(screen.getByRole('button', { name: /board jira/i }));

fireEvent.mouseDown(screen.getByRole('button', { name: CONFIG_TITLE.BOARD }));
fireEvent.click(screen.getByText(BOARD_TYPES.CLASSIC_JIRA));
await waitFor(() => {
expect(screen.getByRole('option', { name: /jira/i })).toBeInTheDocument();
});

await userEvent.click(screen.getByRole('option', { name: /jira/i }));

await waitFor(() => {
expect(screen.getByText(BOARD_TYPES.CLASSIC_JIRA)).toBeInTheDocument();
expect(
screen.getByRole('button', {
name: /board/i,
}),
).toBeInTheDocument();
});
});

it('should show error message when input a wrong type or empty email ', async () => {
setup();
const EMAil_INVALID_ERROR_MESSAGE = 'Email is invalid!';
const emailInput = screen.getByTestId('Email').querySelector('input') as HTMLInputElement;

fireEvent.change(emailInput, { target: { value: 'wrong type email' } });

expect(screen.getByText(EMAil_INVALID_ERROR_MESSAGE)).toBeVisible();
expect(screen.getByText(EMAil_INVALID_ERROR_MESSAGE)).toHaveStyle(ERROR_MESSAGE_COLOR);
const emailInput = screen.getByRole('textbox', {
name: /email/i,
});

fireEvent.change(emailInput, { target: { value: '' } });
await userEvent.type(emailInput, 'wrong@email');

const EMAIL_REQUIRE_ERROR_MESSAGE = 'Email is required!';
expect(screen.getByText(EMAIL_REQUIRE_ERROR_MESSAGE)).toBeVisible();
});
await waitFor(() => {
expect(screen.getByText(EMAil_INVALID_ERROR_MESSAGE)).toBeVisible();
});

it('should clear other fields information when change board field selection', () => {
setup();
const boardIdInput = screen.getByRole('textbox', {
name: 'Board Id',
}) as HTMLInputElement;
const emailInput = screen.getByRole('textbox', {
name: 'Email',
}) as HTMLInputElement;
expect(screen.getByText(EMAil_INVALID_ERROR_MESSAGE)).toHaveStyle(ERROR_MESSAGE_COLOR);

fireEvent.change(boardIdInput, { target: { value: 2 } });
fireEvent.change(emailInput, { target: { value: 'mockEmail@qq.com' } });
fireEvent.mouseDown(screen.getByRole('button', { name: CONFIG_TITLE.BOARD }));
fireEvent.click(screen.getByText(BOARD_TYPES.CLASSIC_JIRA));
await userEvent.clear(emailInput);

expect(emailInput.value).toEqual('');
expect(boardIdInput.value).toEqual('');
await waitFor(() => {
expect(screen.getByText('Email is required!')).toBeVisible();
});
});

it('should clear all fields information when click reset button', async () => {
setup();
const fieldInputs = BOARD_FIELDS.slice(1, 5).map(
(label) =>
screen.getByRole('textbox', {
name: label,
hidden: true,
}) as HTMLInputElement,
);
fillBoardFieldsInformation();
mockVerifySuccess();
await fillBoardFieldsInformation();

fireEvent.click(screen.getByText(VERIFY));
await waitFor(() => {
fireEvent.click(screen.getByRole('button', { name: RESET }));
expect(screen.getByRole('button', { name: /verify/i })).not.toBeDisabled();
});

fieldInputs.map((input) => {
expect(input.value).toEqual('');
await userEvent.click(screen.getByText(/verify/i));

await waitFor(() => {
expect(screen.getByRole('button', { name: /reset/i })).toBeInTheDocument();
});
expect(screen.getByText(BOARD_TYPES.JIRA)).toBeInTheDocument();
expect(screen.queryByRole('button', { name: RESET })).not.toBeTruthy();
expect(screen.queryByRole('button', { name: VERIFY })).toBeDisabled();
});
expect(screen.queryByRole('button', { name: /verified/i })).toBeDisabled();

it('should enabled verify button when all fields checked correctly given disable verify button', () => {
setup();
const verifyButton = screen.getByRole('button', { name: VERIFY });
await userEvent.click(screen.getByRole('button', { name: /reset/i }));

expect(verifyButton).toBeDisabled();
await waitFor(() => {
expect(screen.getByLabelText(/board id/i)).not.toHaveValue();
});
expect(screen.getByLabelText(/email/i)).not.toHaveValue();
expect(screen.getByLabelText(/site/i)).not.toHaveValue();
expect(screen.getByLabelText(/token/i)).not.toHaveValue();

await userEvent.click(screen.getByRole('button', { name: /board/i }));

fillBoardFieldsInformation();
await waitFor(() => {
expect(screen.getByRole('option', { name: /jira/i })).toBeInTheDocument();
});
await userEvent.click(screen.getByRole('option', { name: /jira/i }));

expect(verifyButton).toBeEnabled();
await waitFor(() => {
expect(screen.getByRole('button', { name: /board jira/i })).toBeInTheDocument();
});
});

it('should show reset button and verified button when verify succeed ', async () => {
mockVerifySuccess();
setup();
fillBoardFieldsInformation();
await fillBoardFieldsInformation();

fireEvent.click(screen.getByText(VERIFY));
await userEvent.click(screen.getByText(VERIFY));

await waitFor(() => {
expect(screen.getByText(RESET)).toBeVisible();
});

await waitFor(() => {
expect(screen.getByText(VERIFIED)).toBeTruthy();
});
expect(screen.getByText(VERIFIED)).toBeInTheDocument();
});

it('should called verifyBoard method once when click verify button', async () => {
mockVerifySuccess();
setup();
fillBoardFieldsInformation();
fireEvent.click(screen.getByRole('button', { name: VERIFY }));
await fillBoardFieldsInformation();
await userEvent.click(screen.getByRole('button', { name: /verify/i }));

await waitFor(() => {
expect(screen.getByText('Verified')).toBeInTheDocument();
});
});

it('should check loading animation when click verify button', async () => {
const { container } = setup();
fillBoardFieldsInformation();
fireEvent.click(screen.getByRole('button', { name: VERIFY }));

await waitFor(() => {
expect(container.getElementsByTagName('span')[0].getAttribute('role')).toEqual('progressbar');
});
});

it('should check noCardPop show and disappear when board verify response status is 204', async () => {
server.use(rest.post(MOCK_BOARD_URL_FOR_JIRA, (req, res, ctx) => res(ctx.status(HttpStatusCode.NoContent))));
mockVerifySuccess(300);
setup();
fillBoardFieldsInformation();

fireEvent.click(screen.getByRole('button', { name: VERIFY }));
await fillBoardFieldsInformation();
await userEvent.click(screen.getByRole('button', { name: VERIFY }));

await waitFor(() => {
expect(screen.getByText(NO_CARD_ERROR_MESSAGE)).toBeInTheDocument();
expect(screen.getByTestId('loading')).toBeInTheDocument();
});

fireEvent.click(screen.getByRole('button', { name: 'Ok' }));
expect(screen.getByText(NO_CARD_ERROR_MESSAGE)).not.toBeVisible();
});

it('should check error notification show and disappear when board verify response status is 401', async () => {
server.use(
rest.post(MOCK_BOARD_URL_FOR_JIRA, (req, res, ctx) =>
res(ctx.status(HttpStatusCode.Unauthorized), ctx.json({ hintInfo: VERIFY_ERROR_MESSAGE.UNAUTHORIZED })),
),
);
server.use(rest.post(MOCK_BOARD_URL_FOR_JIRA, (_, res, ctx) => res(ctx.status(HttpStatusCode.Unauthorized))));
setup();
fillBoardFieldsInformation();
await fillBoardFieldsInformation();

fireEvent.click(screen.getByRole('button', { name: VERIFY }));
await userEvent.click(screen.getByRole('button', { name: /verify/i }));

await waitFor(() => {
expect(
screen.getByText(`${BOARD_TYPES.JIRA} ${VERIFY_FAILED}: ${VERIFY_ERROR_MESSAGE.UNAUTHORIZED}`),
).toBeInTheDocument();
expect(screen.getByText(/email is incorrect/i)).toBeInTheDocument();
});
});
});
Loading

0 comments on commit 2447ec8

Please sign in to comment.