[9.0] [Cases] Improve unit test flakiness (#212489) (#214686)

# Backport

This will backport the following commits from `main` to `9.0`:
- [[Cases] Improve unit test flakiness
(#212489)](https://github.com/elastic/kibana/pull/212489)

<!--- Backport version: 9.6.6 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sorenlouv/backport)

<!--BACKPORT [{"author":{"name":"Christos
Nasikas","email":"christos.nasikas@elastic.co"},"sourceCommit":{"committedDate":"2025-03-14T17:17:13Z","message":"[Cases]
Improve unit test flakiness (#212489)\n\n## Summary\n\nThis PR attempts
(I have lost count of how many there have been so far)\nto stabilize the
flakiness of cases tests.\n\n## Approach\n\nBased on our investigations,
I believe a common factor that causes all\ntests to time out is how we
wrap the tests with the needed providers.\nInstead of figuring out why
they time out (which is very difficult), I\ntried a different approach.
I rewrote how we initialize the testing\ndependencies, mocks, and
providers on tests. To test my theory, I\ncreated a VM instance in
GCloud with the same configuration as the one\nrunning in the CI,
specifically the n2-standard-4 (4 vCPUs, 16 GB\nMemory) machine type. I
ran the tests 100 times, which took almost two\ndays. In 10 of the runs,
a random test was timeouted. I noticed that the\nmachine was stressed
while running the tests, and the CPU frequently\nspiked to 100%,
especially at the beginning of each test. Then, I\nincreased the timeout
for all cases tests to 10 seconds and ran the\ntests again 100 times. No
timeouts occurred. Lastly, I created a VM\ninstance in GCloud with the
same configuration as the one running in the\nCI, specifically the
n2-standard-8 (8 vCPUs, 32 GB Memory) machine type.\nI ran the tests
again 100 times. In 1 of the runs, a random test was\ntimeouted. The
machine on the CI cannot handle the cases tests. I\nbelieve the work in
this PR is a step in the right direction either way,\nand we will
benefit from it. I also believe increasing the timeout is a\ngood
decision as we need it based on the experiments and the research
we\nhave done in the last months.\n\nCPU usage on
n2-standard-4\n\n\nhttps://github.com/user-attachments/assets/36b035df-310f-4906-98ba-688d57b97c7e\n\nCPU
usage on
n2-standard-8\n\n\nhttps://github.com/user-attachments/assets/3b1b6351-d48e-41da-a413-a56e52b54b82\n\n##
RLT eslint rules\nI enabled the [RLT
eslint\nrules](https://testing-library.com/docs/ecosystem-eslint-plugin-testing-library/)\nfor
Cases and resolved any eslint errors. The process revealed small\nbugs
in the tests, which I fixed them.\n\n## Testing utils\n\nI removed the
`appMockRender` and any usage in favor of the
new\n`renderWithTestingProviders` utility function and the
improved\n`TestProviders` component. The `renderWithTestingProviders`
follows
the\nprincipals\n[suggested](https://github.com/testing-library/react-testing-library/issues/780#issuecomment-689053441)\nby
the RLT team. Specifically:\n- The `renderWithTestingProviders` is a
wrapper of the `render` function\nof the RTL library.\n- The
`renderWithTestingProviders` does not create the services or
any\ncomponent inside it.\n- The `renderWithTestingProviders` cannot be
used in `beforeEach`\nfunctions. It should be called separately on each
test.\n- The `renderWithTestingProviders` accepts props to override the
default\nmocks.\n- The `renderWithTestingProviders` passes the
`TestProviders` in the\n`wrapper` argument of the RLT `render`
function.\n- The `TestProviders` component initializes and memoizes all
services\nand dependencies. It accepts props to override the default
mocks.\n- Mock overrides (like core services) should be created and
passed to\n`renderWithTestingProviders` on each test, even if it means
duplication.\nWe favor test isolation.\n\n### Checklist\n\nCheck the PR
satisfies the following conditions. \n\nReviewers should verify this PR
satisfies this list as well.\n\n- [x] [Unit or
functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere
updated or added to match the most common scenarios\n\n##
Issues\n<details>\n<summary>List</summary>\n\nFixes:
https://github.com/elastic/kibana/issues/207712\nFixes:
https://github.com/elastic/kibana/issues/192739\nFixes:
https://github.com/elastic/kibana/issues/174682\nFixes:
https://github.com/elastic/kibana/issues/206366\nFixes:
https://github.com/elastic/kibana/issues/207427\nFixes:
https://github.com/elastic/kibana/issues/175239\nFixes:
https://github.com/elastic/kibana/issues/177334\nFixes:
https://github.com/elastic/kibana/issues/208443\nFixes:
https://github.com/elastic/kibana/issues/187526\nFixes:
https://github.com/elastic/kibana/issues/208310\nFixes:
https://github.com/elastic/kibana/issues/192640\nFixes:
https://github.com/elastic/kibana/issues/207077\nFixes:
https://github.com/elastic/kibana/issues/197304\nFixes:
https://github.com/elastic/kibana/issues/207249\nFixes:
https://github.com/elastic/kibana/issues/202761\nFixes:
https://github.com/elastic/kibana/issues/202115\nFixes:
https://github.com/elastic/kibana/issues/193026\nFixes:
https://github.com/elastic/kibana/issues/177304\nFixes:
https://github.com/elastic/kibana/issues/208415\nFixes:
https://github.com/elastic/kibana/issues/174661\nFixes:
https://github.com/elastic/kibana/issues/201611\nFixes:
https://github.com/elastic/kibana/issues/182364\nFixes:
https://github.com/elastic/kibana/issues/175841\nFixes:
https://github.com/elastic/kibana/issues/207907\nFixes:
https://github.com/elastic/kibana/issues/171177\nFixes:
https://github.com/elastic/kibana/issues/196628\nFixes:
https://github.com/elastic/kibana/issues/194703\nFixes:
https://github.com/elastic/kibana/issues/207241\nFixes:
https://github.com/elastic/kibana/issues/206056\nFixes:
https://github.com/elastic/kibana/issues/207328\nFixes:
https://github.com/elastic/kibana/issues/205953\nFixes:
https://github.com/elastic/kibana/issues/176524\nFixes:
https://github.com/elastic/kibana/issues/176335\nFixes:
https://github.com/elastic/kibana/issues/207404\nFixes:
https://github.com/elastic/kibana/issues/207384\nFixes:
https://github.com/elastic/kibana/issues/208380\nFixes:
https://github.com/elastic/kibana/issues/207248\nFixes:
https://github.com/elastic/kibana/issues/207444\nFixes:
https://github.com/elastic/kibana/issues/175240\nFixes:
https://github.com/elastic/kibana/issues/178001\n\n</details>\n\n---------\n\nCo-authored-by:
kibanamachine
<42973632+kibanamachine@users.noreply.github.com>\nCo-authored-by:
Elastic Machine
<elasticmachine@users.noreply.github.com>","sha":"1054799f9c1139c52d74c9c588f60177182919c7","branchLabelMapping":{"^v9.1.0$":"main","^v8.19.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:ResponseOps","v9.0.0","Feature:Cases","backport:version","v8.18.0","v9.1.0","v8.19.0"],"title":"[Cases]
Improve unit test
flakiness","number":212489,"url":"https://github.com/elastic/kibana/pull/212489","mergeCommit":{"message":"[Cases]
Improve unit test flakiness (#212489)\n\n## Summary\n\nThis PR attempts
(I have lost count of how many there have been so far)\nto stabilize the
flakiness of cases tests.\n\n## Approach\n\nBased on our investigations,
I believe a common factor that causes all\ntests to time out is how we
wrap the tests with the needed providers.\nInstead of figuring out why
they time out (which is very difficult), I\ntried a different approach.
I rewrote how we initialize the testing\ndependencies, mocks, and
providers on tests. To test my theory, I\ncreated a VM instance in
GCloud with the same configuration as the one\nrunning in the CI,
specifically the n2-standard-4 (4 vCPUs, 16 GB\nMemory) machine type. I
ran the tests 100 times, which took almost two\ndays. In 10 of the runs,
a random test was timeouted. I noticed that the\nmachine was stressed
while running the tests, and the CPU frequently\nspiked to 100%,
especially at the beginning of each test. Then, I\nincreased the timeout
for all cases tests to 10 seconds and ran the\ntests again 100 times. No
timeouts occurred. Lastly, I created a VM\ninstance in GCloud with the
same configuration as the one running in the\nCI, specifically the
n2-standard-8 (8 vCPUs, 32 GB Memory) machine type.\nI ran the tests
again 100 times. In 1 of the runs, a random test was\ntimeouted. The
machine on the CI cannot handle the cases tests. I\nbelieve the work in
this PR is a step in the right direction either way,\nand we will
benefit from it. I also believe increasing the timeout is a\ngood
decision as we need it based on the experiments and the research
we\nhave done in the last months.\n\nCPU usage on
n2-standard-4\n\n\nhttps://github.com/user-attachments/assets/36b035df-310f-4906-98ba-688d57b97c7e\n\nCPU
usage on
n2-standard-8\n\n\nhttps://github.com/user-attachments/assets/3b1b6351-d48e-41da-a413-a56e52b54b82\n\n##
RLT eslint rules\nI enabled the [RLT
eslint\nrules](https://testing-library.com/docs/ecosystem-eslint-plugin-testing-library/)\nfor
Cases and resolved any eslint errors. The process revealed small\nbugs
in the tests, which I fixed them.\n\n## Testing utils\n\nI removed the
`appMockRender` and any usage in favor of the
new\n`renderWithTestingProviders` utility function and the
improved\n`TestProviders` component. The `renderWithTestingProviders`
follows
the\nprincipals\n[suggested](https://github.com/testing-library/react-testing-library/issues/780#issuecomment-689053441)\nby
the RLT team. Specifically:\n- The `renderWithTestingProviders` is a
wrapper of the `render` function\nof the RTL library.\n- The
`renderWithTestingProviders` does not create the services or
any\ncomponent inside it.\n- The `renderWithTestingProviders` cannot be
used in `beforeEach`\nfunctions. It should be called separately on each
test.\n- The `renderWithTestingProviders` accepts props to override the
default\nmocks.\n- The `renderWithTestingProviders` passes the
`TestProviders` in the\n`wrapper` argument of the RLT `render`
function.\n- The `TestProviders` component initializes and memoizes all
services\nand dependencies. It accepts props to override the default
mocks.\n- Mock overrides (like core services) should be created and
passed to\n`renderWithTestingProviders` on each test, even if it means
duplication.\nWe favor test isolation.\n\n### Checklist\n\nCheck the PR
satisfies the following conditions. \n\nReviewers should verify this PR
satisfies this list as well.\n\n- [x] [Unit or
functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere
updated or added to match the most common scenarios\n\n##
Issues\n<details>\n<summary>List</summary>\n\nFixes:
https://github.com/elastic/kibana/issues/207712\nFixes:
https://github.com/elastic/kibana/issues/192739\nFixes:
https://github.com/elastic/kibana/issues/174682\nFixes:
https://github.com/elastic/kibana/issues/206366\nFixes:
https://github.com/elastic/kibana/issues/207427\nFixes:
https://github.com/elastic/kibana/issues/175239\nFixes:
https://github.com/elastic/kibana/issues/177334\nFixes:
https://github.com/elastic/kibana/issues/208443\nFixes:
https://github.com/elastic/kibana/issues/187526\nFixes:
https://github.com/elastic/kibana/issues/208310\nFixes:
https://github.com/elastic/kibana/issues/192640\nFixes:
https://github.com/elastic/kibana/issues/207077\nFixes:
https://github.com/elastic/kibana/issues/197304\nFixes:
https://github.com/elastic/kibana/issues/207249\nFixes:
https://github.com/elastic/kibana/issues/202761\nFixes:
https://github.com/elastic/kibana/issues/202115\nFixes:
https://github.com/elastic/kibana/issues/193026\nFixes:
https://github.com/elastic/kibana/issues/177304\nFixes:
https://github.com/elastic/kibana/issues/208415\nFixes:
https://github.com/elastic/kibana/issues/174661\nFixes:
https://github.com/elastic/kibana/issues/201611\nFixes:
https://github.com/elastic/kibana/issues/182364\nFixes:
https://github.com/elastic/kibana/issues/175841\nFixes:
https://github.com/elastic/kibana/issues/207907\nFixes:
https://github.com/elastic/kibana/issues/171177\nFixes:
https://github.com/elastic/kibana/issues/196628\nFixes:
https://github.com/elastic/kibana/issues/194703\nFixes:
https://github.com/elastic/kibana/issues/207241\nFixes:
https://github.com/elastic/kibana/issues/206056\nFixes:
https://github.com/elastic/kibana/issues/207328\nFixes:
https://github.com/elastic/kibana/issues/205953\nFixes:
https://github.com/elastic/kibana/issues/176524\nFixes:
https://github.com/elastic/kibana/issues/176335\nFixes:
https://github.com/elastic/kibana/issues/207404\nFixes:
https://github.com/elastic/kibana/issues/207384\nFixes:
https://github.com/elastic/kibana/issues/208380\nFixes:
https://github.com/elastic/kibana/issues/207248\nFixes:
https://github.com/elastic/kibana/issues/207444\nFixes:
https://github.com/elastic/kibana/issues/175240\nFixes:
https://github.com/elastic/kibana/issues/178001\n\n</details>\n\n---------\n\nCo-authored-by:
kibanamachine
<42973632+kibanamachine@users.noreply.github.com>\nCo-authored-by:
Elastic Machine
<elasticmachine@users.noreply.github.com>","sha":"1054799f9c1139c52d74c9c588f60177182919c7"}},"sourceBranch":"main","suggestedTargetBranches":["9.0"],"targetPullRequestStates":[{"branch":"9.0","label":"v9.0.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"8.18","label":"v8.18.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"url":"https://github.com/elastic/kibana/pull/214676","number":214676,"state":"OPEN"},{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/212489","number":212489,"mergeCommit":{"message":"[Cases]
Improve unit test flakiness (#212489)\n\n## Summary\n\nThis PR attempts
(I have lost count of how many there have been so far)\nto stabilize the
flakiness of cases tests.\n\n## Approach\n\nBased on our investigations,
I believe a common factor that causes all\ntests to time out is how we
wrap the tests with the needed providers.\nInstead of figuring out why
they time out (which is very difficult), I\ntried a different approach.
I rewrote how we initialize the testing\ndependencies, mocks, and
providers on tests. To test my theory, I\ncreated a VM instance in
GCloud with the same configuration as the one\nrunning in the CI,
specifically the n2-standard-4 (4 vCPUs, 16 GB\nMemory) machine type. I
ran the tests 100 times, which took almost two\ndays. In 10 of the runs,
a random test was timeouted. I noticed that the\nmachine was stressed
while running the tests, and the CPU frequently\nspiked to 100%,
especially at the beginning of each test. Then, I\nincreased the timeout
for all cases tests to 10 seconds and ran the\ntests again 100 times. No
timeouts occurred. Lastly, I created a VM\ninstance in GCloud with the
same configuration as the one running in the\nCI, specifically the
n2-standard-8 (8 vCPUs, 32 GB Memory) machine type.\nI ran the tests
again 100 times. In 1 of the runs, a random test was\ntimeouted. The
machine on the CI cannot handle the cases tests. I\nbelieve the work in
this PR is a step in the right direction either way,\nand we will
benefit from it. I also believe increasing the timeout is a\ngood
decision as we need it based on the experiments and the research
we\nhave done in the last months.\n\nCPU usage on
n2-standard-4\n\n\nhttps://github.com/user-attachments/assets/36b035df-310f-4906-98ba-688d57b97c7e\n\nCPU
usage on
n2-standard-8\n\n\nhttps://github.com/user-attachments/assets/3b1b6351-d48e-41da-a413-a56e52b54b82\n\n##
RLT eslint rules\nI enabled the [RLT
eslint\nrules](https://testing-library.com/docs/ecosystem-eslint-plugin-testing-library/)\nfor
Cases and resolved any eslint errors. The process revealed small\nbugs
in the tests, which I fixed them.\n\n## Testing utils\n\nI removed the
`appMockRender` and any usage in favor of the
new\n`renderWithTestingProviders` utility function and the
improved\n`TestProviders` component. The `renderWithTestingProviders`
follows
the\nprincipals\n[suggested](https://github.com/testing-library/react-testing-library/issues/780#issuecomment-689053441)\nby
the RLT team. Specifically:\n- The `renderWithTestingProviders` is a
wrapper of the `render` function\nof the RTL library.\n- The
`renderWithTestingProviders` does not create the services or
any\ncomponent inside it.\n- The `renderWithTestingProviders` cannot be
used in `beforeEach`\nfunctions. It should be called separately on each
test.\n- The `renderWithTestingProviders` accepts props to override the
default\nmocks.\n- The `renderWithTestingProviders` passes the
`TestProviders` in the\n`wrapper` argument of the RLT `render`
function.\n- The `TestProviders` component initializes and memoizes all
services\nand dependencies. It accepts props to override the default
mocks.\n- Mock overrides (like core services) should be created and
passed to\n`renderWithTestingProviders` on each test, even if it means
duplication.\nWe favor test isolation.\n\n### Checklist\n\nCheck the PR
satisfies the following conditions. \n\nReviewers should verify this PR
satisfies this list as well.\n\n- [x] [Unit or
functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere
updated or added to match the most common scenarios\n\n##
Issues\n<details>\n<summary>List</summary>\n\nFixes:
https://github.com/elastic/kibana/issues/207712\nFixes:
https://github.com/elastic/kibana/issues/192739\nFixes:
https://github.com/elastic/kibana/issues/174682\nFixes:
https://github.com/elastic/kibana/issues/206366\nFixes:
https://github.com/elastic/kibana/issues/207427\nFixes:
https://github.com/elastic/kibana/issues/175239\nFixes:
https://github.com/elastic/kibana/issues/177334\nFixes:
https://github.com/elastic/kibana/issues/208443\nFixes:
https://github.com/elastic/kibana/issues/187526\nFixes:
https://github.com/elastic/kibana/issues/208310\nFixes:
https://github.com/elastic/kibana/issues/192640\nFixes:
https://github.com/elastic/kibana/issues/207077\nFixes:
https://github.com/elastic/kibana/issues/197304\nFixes:
https://github.com/elastic/kibana/issues/207249\nFixes:
https://github.com/elastic/kibana/issues/202761\nFixes:
https://github.com/elastic/kibana/issues/202115\nFixes:
https://github.com/elastic/kibana/issues/193026\nFixes:
https://github.com/elastic/kibana/issues/177304\nFixes:
https://github.com/elastic/kibana/issues/208415\nFixes:
https://github.com/elastic/kibana/issues/174661\nFixes:
https://github.com/elastic/kibana/issues/201611\nFixes:
https://github.com/elastic/kibana/issues/182364\nFixes:
https://github.com/elastic/kibana/issues/175841\nFixes:
https://github.com/elastic/kibana/issues/207907\nFixes:
https://github.com/elastic/kibana/issues/171177\nFixes:
https://github.com/elastic/kibana/issues/196628\nFixes:
https://github.com/elastic/kibana/issues/194703\nFixes:
https://github.com/elastic/kibana/issues/207241\nFixes:
https://github.com/elastic/kibana/issues/206056\nFixes:
https://github.com/elastic/kibana/issues/207328\nFixes:
https://github.com/elastic/kibana/issues/205953\nFixes:
https://github.com/elastic/kibana/issues/176524\nFixes:
https://github.com/elastic/kibana/issues/176335\nFixes:
https://github.com/elastic/kibana/issues/207404\nFixes:
https://github.com/elastic/kibana/issues/207384\nFixes:
https://github.com/elastic/kibana/issues/208380\nFixes:
https://github.com/elastic/kibana/issues/207248\nFixes:
https://github.com/elastic/kibana/issues/207444\nFixes:
https://github.com/elastic/kibana/issues/175240\nFixes:
https://github.com/elastic/kibana/issues/178001\n\n</details>\n\n---------\n\nCo-authored-by:
kibanamachine
<42973632+kibanamachine@users.noreply.github.com>\nCo-authored-by:
Elastic Machine
<elasticmachine@users.noreply.github.com>","sha":"1054799f9c1139c52d74c9c588f60177182919c7"}},{"branch":"8.x","label":"v8.19.0","branchLabelMappingKey":"^v8.19.0$","isSourceBranch":false,"url":"https://github.com/elastic/kibana/pull/214675","number":214675,"state":"OPEN"}]}]
BACKPORT-->

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
Christos Nasikas 2025-03-17 16:50:53 +02:00 committed by GitHub
parent 0ce508ea46
commit 542d800c42
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
254 changed files with 4063 additions and 4807 deletions

View file

@ -209,6 +209,7 @@ enabled:
- x-pack/test/functional_execution_context/config.ts
- x-pack/test/functional_with_es_ssl/apps/cases/group1/config.ts
- x-pack/test/functional_with_es_ssl/apps/cases/group2/config.ts
- x-pack/test/functional_with_es_ssl/apps/cases/basic/config.ts
- x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/config.ts
- x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/config.ts
- x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/shared/config.ts

View file

@ -1340,6 +1340,10 @@ module.exports = {
'react/display-name': ['error', { ignoreTranspilerName: true }],
},
},
{
files: ['x-pack/platform/plugins/shared/cases/**/*.{test,mock,test_helper}.tsx'],
extends: ['plugin:testing-library/react'],
},
/**
* Lists overrides. These rules below are maintained and owned by

View file

@ -1751,7 +1751,7 @@
"eslint-plugin-react": "^7.32.2",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-perf": "^3.3.1",
"eslint-plugin-testing-library": "^6.4.0",
"eslint-plugin-testing-library": "^7.1.1",
"eslint-traverse": "^1.0.0",
"exit-hook": "^2.2.0",
"expect": "^29.7.0",

View file

@ -270,24 +270,6 @@ describe('schema', () => {
]
`);
});
it.skip('fails when page number is negative', () => {
expect(PathReporter.report(paginationSchema({ maxPerPage: 3 }).decode({ page: -1 })))
.toMatchInlineSnapshot(`
Array [
"The provided page value is too low. The minimum allowed page value is 0.",
]
`);
});
it.skip('fails when perPage number is negative', () => {
expect(PathReporter.report(paginationSchema({ maxPerPage: 3 }).decode({ perPage: -1 })))
.toMatchInlineSnapshot(`
Array [
"The provided perPage value is too low. The minimum allowed perPage value is 0.",
]
`);
});
});
describe('limitedNumberSchema', () => {

View file

@ -14,4 +14,5 @@ module.exports = {
collectCoverageFrom: [
'<rootDir>/x-pack/platform/plugins/shared/cases/{common,public,server}/**/*.{ts,tsx}',
],
testTimeout: 10000,
};

View file

@ -9,32 +9,19 @@ import type { PublicAppInfo } from '@kbn/core-application-browser';
import { AppStatus } from '@kbn/core-application-browser';
import { renderHook } from '@testing-library/react';
import { BehaviorSubject, Subject } from 'rxjs';
import type { AppMockRenderer } from '../../mock';
import { createAppMockRenderer } from '../../mock';
import { useApplication } from './use_application';
import { TestProviders } from '../../mock';
import { coreMock } from '@kbn/core/public/mocks';
import React from 'react';
describe('useApplication', () => {
let appMockRender: AppMockRenderer;
beforeEach(() => {
jest.clearAllMocks();
appMockRender = createAppMockRenderer();
});
const getApp = (props: Partial<PublicAppInfo> = {}): PublicAppInfo => ({
id: 'testAppId',
title: 'Test title',
status: AppStatus.accessible,
visibleIn: ['globalSearch'],
appRoute: `/app/some-id`,
keywords: [],
deepLinks: [],
...props,
});
it('returns the appId and the appTitle correctly', () => {
const { result } = renderHook(() => useApplication(), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
expect(result.current).toEqual({
@ -44,20 +31,26 @@ describe('useApplication', () => {
});
it('returns undefined appId and appTitle if the currentAppId observable is not defined', () => {
appMockRender.coreStart.application.currentAppId$ = new Subject();
const coreStart = coreMock.createStart();
coreStart.application.applications$ = getApplicationObservable();
coreStart.application.currentAppId$ = new Subject();
const { result } = renderHook(() => useApplication(), {
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} coreStart={coreStart} />,
});
expect(result.current).toEqual({});
});
it('returns undefined appTitle if the applications observable is not defined', () => {
appMockRender.coreStart.application.applications$ = new Subject();
it('returns undefined appTitle if the applications observable is not defined', async () => {
const coreStart = coreMock.createStart();
coreStart.application.applications$ = new Subject();
coreStart.application.currentAppId$ = getCurrentApplicationObservable();
const { result } = renderHook(() => useApplication(), {
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} coreStart={coreStart} />,
});
expect(result.current).toEqual({
@ -67,12 +60,14 @@ describe('useApplication', () => {
});
it('returns the label as appTitle', () => {
appMockRender.coreStart.application.applications$ = new BehaviorSubject(
new Map([['testAppId', getApp({ category: { id: 'test-label-id', label: 'Test label' } })]])
);
const coreStart = coreMock.createStart();
coreStart.application.currentAppId$ = getCurrentApplicationObservable();
coreStart.application.applications$ = getApplicationObservable({
category: { id: 'test-label-id', label: 'Test label' },
});
const { result } = renderHook(() => useApplication(), {
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} coreStart={coreStart} />,
});
expect(result.current).toEqual({
@ -82,12 +77,15 @@ describe('useApplication', () => {
});
it('returns the title as appTitle if the categories label is missing', () => {
appMockRender.coreStart.application.applications$ = new BehaviorSubject(
new Map([['testAppId', getApp({ title: 'Test title' })]])
);
const coreStart = coreMock.createStart();
coreStart.application.currentAppId$ = getCurrentApplicationObservable();
coreStart.application.applications$ = getApplicationObservable({
title: 'Test title',
category: undefined,
});
const { result } = renderHook(() => useApplication(), {
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} coreStart={coreStart} />,
});
expect(result.current).toEqual({
@ -97,12 +95,35 @@ describe('useApplication', () => {
});
it('gets the value from the default value of the currentAppId observable if it exists', () => {
appMockRender.coreStart.application.currentAppId$ = new BehaviorSubject('new-test-id');
const coreStart = coreMock.createStart();
coreStart.application.currentAppId$ = new BehaviorSubject('new-test-id');
const { result } = renderHook(() => useApplication(), {
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} coreStart={coreStart} />,
});
expect(result.current).toEqual({ appId: 'new-test-id' });
});
});
const getApplicationObservable = (props: Partial<PublicAppInfo> = {}) =>
new BehaviorSubject<Map<string, PublicAppInfo>>(
new Map([
[
'testAppId',
{
id: 'testAppId',
title: 'test-title',
category: { id: 'test-label-id', label: 'Test' },
status: AppStatus.accessible,
visibleIn: ['globalSearch'],
appRoute: `/app/some-id`,
keywords: [],
deepLinks: [],
...props,
},
],
])
);
const getCurrentApplicationObservable = () => new BehaviorSubject<string>('testAppId');

View file

@ -7,29 +7,32 @@
/* eslint-disable no-console */
import React, { useMemo } from 'react';
import type { ReactElement } from 'react';
import React, { useMemo, useCallback } from 'react';
import { MemoryRouter } from 'react-router-dom';
import { render as reactRender, waitFor } from '@testing-library/react';
import type { RenderOptions, RenderResult } from '@testing-library/react';
import { render } from '@testing-library/react';
import type { RenderOptions } from '@testing-library/react';
import type { ILicense } from '@kbn/licensing-plugin/public';
import type { ScopedFilesClient } from '@kbn/files-plugin/public';
import type { FilesClient, ScopedFilesClient } from '@kbn/files-plugin/public';
import { createMockFilesClient } from '@kbn/shared-ux-file-mocks';
import { QueryClient } from '@tanstack/react-query';
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
import { FilesContext } from '@kbn/shared-ux-file-context';
import type { DeeplyMockedKeys } from '@kbn/utility-types-jest';
import { coreMock } from '@kbn/core/public/mocks';
import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
import type { CoreStart } from '@kbn/core/public';
import type { BaseFilesClient } from '@kbn/shared-ux-file-types';
import type { CasesFeatures, CasesPermissions } from '../../../common/ui/types';
import type { StartServices } from '../../types';
import type { ReleasePhase } from '../../components/types';
import { SECURITY_SOLUTION_OWNER } from '../../../common/constants';
import type { CasesContextProps } from '../../components/cases_context';
import { CasesProvider } from '../../components/cases_context';
import { createStartServicesMock } from '../lib/kibana/kibana_react.mock';
import { ExternalReferenceAttachmentTypeRegistry } from '../../client/attachment_framework/external_reference_registry';
import { PersistableStateAttachmentTypeRegistry } from '../../client/attachment_framework/persistable_state_registry';
import { allCasesPermissions } from './permissions';
import type { CasesPublicStartDependencies } from '../../types';
interface TestProviderProps {
children: React.ReactNode;
@ -40,179 +43,142 @@ interface TestProviderProps {
externalReferenceAttachmentTypeRegistry?: ExternalReferenceAttachmentTypeRegistry;
persistableStateAttachmentTypeRegistry?: PersistableStateAttachmentTypeRegistry;
license?: ILicense;
services?: CasesPublicStartDependencies;
queryClient?: QueryClient;
coreStart?: CoreStart;
filesClient?: BaseFilesClient;
}
type UiRender = (ui: React.ReactElement, options?: RenderOptions) => RenderResult;
window.scrollTo = jest.fn();
const mockGetFilesClient = () => {
const mockedFilesClient = createMockFilesClient() as unknown as DeeplyMockedKeys<
ScopedFilesClient<unknown>
>;
const getMockedFilesClient = (): BaseFilesClient => {
const mockedFilesClient = createMockFilesClient();
mockedFilesClient.getFileKind.mockImplementation(() => ({
id: 'test',
maxSizeBytes: 10000,
http: {},
}));
return () => mockedFilesClient;
return mockedFilesClient;
};
export const mockedTestProvidersOwner = [SECURITY_SOLUTION_OWNER];
export const createTestQueryClient = () =>
new QueryClient({
defaultOptions: {
queries: {
retry: false,
},
},
logger: {
log: console.log,
warn: console.warn,
error: () => {},
},
});
/** A utility for wrapping children in the providers required to run most tests */
const TestProvidersComponent: React.FC<TestProviderProps> = ({
children,
features,
owner = mockedTestProvidersOwner,
permissions = allCasesPermissions(),
releasePhase = 'ga',
externalReferenceAttachmentTypeRegistry = new ExternalReferenceAttachmentTypeRegistry(),
persistableStateAttachmentTypeRegistry = new PersistableStateAttachmentTypeRegistry(),
owner,
permissions,
releasePhase,
externalReferenceAttachmentTypeRegistry,
persistableStateAttachmentTypeRegistry,
license,
coreStart,
services,
queryClient,
filesClient,
}) => {
const coreStart = useMemo(() => coreMock.createStart(), []);
const services = useMemo(() => createStartServicesMock({ license }), [license]);
const finalCoreStart = useMemo(() => coreStart ?? coreMock.createStart(), [coreStart]);
const finalServices = useMemo(
() => ({ ...createStartServicesMock({ license }), ...coreStart, ...services }),
[coreStart, license, services]
);
const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: false,
},
},
logger: {
log: console.log,
warn: console.warn,
error: () => {},
},
});
const defaultQueryClient = useMemo(() => createTestQueryClient(), []);
const getFilesClient = mockGetFilesClient();
const casesProviderValue = {
externalReferenceAttachmentTypeRegistry,
persistableStateAttachmentTypeRegistry,
features,
owner,
permissions,
getFilesClient,
};
const finalQueryClient = useMemo(
() => queryClient ?? defaultQueryClient,
[defaultQueryClient, queryClient]
);
const defaultPermissions = useMemo(() => allCasesPermissions(), []);
const finalFilesClient = useMemo(
() => filesClient ?? getMockedFilesClient(),
[filesClient]
) as FilesClient;
const getFilesClientFinal = useCallback(
() => finalFilesClient as unknown as ScopedFilesClient,
[finalFilesClient]
);
const defaultExternalReferenceAttachmentTypeRegistry = useMemo(
() => new ExternalReferenceAttachmentTypeRegistry(),
[]
);
const defaultPersistableStateAttachmentTypeRegistry = useMemo(
() => new PersistableStateAttachmentTypeRegistry(),
[]
);
const casesProviderValue: CasesContextProps = useMemo(
() => ({
externalReferenceAttachmentTypeRegistry:
externalReferenceAttachmentTypeRegistry ?? defaultExternalReferenceAttachmentTypeRegistry,
persistableStateAttachmentTypeRegistry:
persistableStateAttachmentTypeRegistry ?? defaultPersistableStateAttachmentTypeRegistry,
features,
owner: owner ?? mockedTestProvidersOwner,
permissions: permissions ?? defaultPermissions,
releasePhase: releasePhase ?? 'ga',
getFilesClient: getFilesClientFinal,
}),
[
defaultExternalReferenceAttachmentTypeRegistry,
defaultPermissions,
defaultPersistableStateAttachmentTypeRegistry,
externalReferenceAttachmentTypeRegistry,
features,
getFilesClientFinal,
owner,
permissions,
persistableStateAttachmentTypeRegistry,
releasePhase,
]
);
return (
<KibanaRenderContextProvider {...coreStart}>
<KibanaContextProvider services={services}>
<KibanaRenderContextProvider {...finalCoreStart}>
<KibanaContextProvider services={finalServices}>
<MemoryRouter>
<CasesProvider value={casesProviderValue} queryClient={queryClient}>
<FilesContext client={createMockFilesClient()}>{children}</FilesContext>
<CasesProvider value={casesProviderValue} queryClient={finalQueryClient}>
<FilesContext client={finalFilesClient}>{children}</FilesContext>
</CasesProvider>
</MemoryRouter>
</KibanaContextProvider>
</KibanaRenderContextProvider>
);
};
TestProvidersComponent.displayName = 'TestProviders';
export const TestProviders = React.memo(TestProvidersComponent);
export interface AppMockRenderer {
externalReferenceAttachmentTypeRegistry: ExternalReferenceAttachmentTypeRegistry;
persistableStateAttachmentTypeRegistry: PersistableStateAttachmentTypeRegistry;
render: UiRender;
coreStart: StartServices;
queryClient: QueryClient;
AppWrapper: React.FC<{ children: React.ReactNode }>;
getFilesClient: () => ScopedFilesClient;
clearQueryCache: () => Promise<void>;
}
export const testQueryClient = new QueryClient({
defaultOptions: {
queries: {
retry: false,
},
},
/**
* React query prints the errors in the console even though
* all tests are passings. We turn them off for testing.
*/
logger: {
log: console.log,
warn: console.warn,
error: () => {},
},
});
export const createAppMockRenderer = ({
features,
owner = mockedTestProvidersOwner,
permissions = allCasesPermissions(),
releasePhase = 'ga',
externalReferenceAttachmentTypeRegistry = new ExternalReferenceAttachmentTypeRegistry(),
persistableStateAttachmentTypeRegistry = new PersistableStateAttachmentTypeRegistry(),
license,
}: Omit<TestProviderProps, 'children'> = {}): AppMockRenderer => {
const coreStart = coreMock.createStart();
const services = createStartServicesMock({ license });
const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: false,
},
},
logger: {
log: console.log,
warn: console.warn,
error: () => {},
},
});
const getFilesClient = mockGetFilesClient();
const casesProviderValue = {
externalReferenceAttachmentTypeRegistry,
persistableStateAttachmentTypeRegistry,
features,
owner,
permissions,
releasePhase,
getFilesClient,
};
const AppWrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => (
<KibanaRenderContextProvider {...coreStart}>
<KibanaContextProvider services={services}>
<MemoryRouter>
<CasesProvider value={casesProviderValue} queryClient={queryClient}>
{children}
</CasesProvider>
</MemoryRouter>
</KibanaContextProvider>
</KibanaRenderContextProvider>
);
AppWrapper.displayName = 'AppWrapper';
const memoizedAppWrapper = React.memo(AppWrapper);
const render: UiRender = (ui, options) => {
return reactRender(ui, {
wrapper: memoizedAppWrapper,
...options,
});
};
const clearQueryCache = async () => {
queryClient.getQueryCache().clear();
await waitFor(() => expect(queryClient.isFetching()).toBe(0));
};
return {
coreStart: services,
queryClient,
render,
AppWrapper,
externalReferenceAttachmentTypeRegistry,
persistableStateAttachmentTypeRegistry,
getFilesClient,
clearQueryCache,
};
type CustomRenderOptions = Omit<RenderOptions, 'wrapper'> & {
wrapperProps?: Omit<TestProviderProps, 'children'>;
};
export const renderWithTestingProviders = (ui: ReactElement, options?: CustomRenderOptions) => {
const { wrapperProps, ...renderOptions } = options ?? {};
return render(ui, {
wrapper: (props) => <TestProviders {...props} {...wrapperProps} />,
...renderOptions,
});
};

View file

@ -7,15 +7,14 @@
import { renderHook, act } from '@testing-library/react';
import { Subject } from 'rxjs';
import type { AppMockRenderer } from './mock/test_providers';
import { createAppMockRenderer } from './mock/test_providers';
import { TestProviders } from './mock/test_providers';
import { useCasesLocalStorage } from './use_cases_local_storage';
import React from 'react';
import { coreMock } from '@kbn/core/public/mocks';
describe('useCasesLocalStorage', () => {
const initialValue = { foo: 'bar' };
let appMockRender: AppMockRenderer;
beforeEach(() => {
localStorage.clear();
});
@ -24,13 +23,9 @@ describe('useCasesLocalStorage', () => {
const lsKey = 'myKey';
const ownerLSKey = `securitySolution.${lsKey}`;
beforeEach(() => {
appMockRender = createAppMockRenderer();
});
it('initialize the local storage correctly', async () => {
const { result } = renderHook(() => useCasesLocalStorage(lsKey, initialValue), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
expect(result.current[0]).toEqual(initialValue);
@ -41,7 +36,7 @@ describe('useCasesLocalStorage', () => {
localStorage.setItem(ownerLSKey, '{"foo":"new value"}');
const { result } = renderHook(() => useCasesLocalStorage(lsKey, initialValue), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
expect(result.current[0]).toEqual({ foo: 'new value' });
@ -50,7 +45,7 @@ describe('useCasesLocalStorage', () => {
it('persists to the local storage correctly', async () => {
const { result } = renderHook(() => useCasesLocalStorage(lsKey, initialValue), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
act(() => {
@ -65,7 +60,7 @@ describe('useCasesLocalStorage', () => {
localStorage.setItem(ownerLSKey, 'test');
const { result } = renderHook(() => useCasesLocalStorage(lsKey, initialValue), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
expect(result.current[0]).toEqual(initialValue);
@ -73,9 +68,10 @@ describe('useCasesLocalStorage', () => {
});
it('supports multiple owners correctly', async () => {
appMockRender = createAppMockRenderer({ owner: ['securitySolution', 'observability'] });
const { result } = renderHook(() => useCasesLocalStorage(lsKey, initialValue), {
wrapper: appMockRender.AppWrapper,
wrapper: (props) => (
<TestProviders {...props} owner={['securitySolution', 'observability']} />
),
});
expect(result.current[0]).toEqual(initialValue);
@ -87,13 +83,9 @@ describe('useCasesLocalStorage', () => {
const lsKey = 'myKey';
const ownerLSKey = `testAppId.${lsKey}`;
beforeEach(() => {
appMockRender = createAppMockRenderer({ owner: [] });
});
it('initialize the local storage correctly', async () => {
const { result } = renderHook(() => useCasesLocalStorage(lsKey, initialValue), {
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} owner={[]} />,
});
expect(result.current[0]).toEqual(initialValue);
@ -104,7 +96,7 @@ describe('useCasesLocalStorage', () => {
localStorage.setItem(ownerLSKey, '{"foo":"new value"}');
const { result } = renderHook(() => useCasesLocalStorage(lsKey, initialValue), {
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} owner={[]} />,
});
expect(result.current[0]).toEqual({ foo: 'new value' });
@ -113,7 +105,7 @@ describe('useCasesLocalStorage', () => {
it('persists to the local storage correctly', async () => {
const { result } = renderHook(() => useCasesLocalStorage(lsKey, initialValue), {
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} owner={[]} />,
});
act(() => {
@ -128,7 +120,7 @@ describe('useCasesLocalStorage', () => {
localStorage.setItem(ownerLSKey, 'test');
const { result } = renderHook(() => useCasesLocalStorage(lsKey, initialValue), {
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} owner={[]} />,
});
expect(result.current[0]).toEqual(initialValue);
@ -136,10 +128,11 @@ describe('useCasesLocalStorage', () => {
});
it('returns the initial value and not persist to local storage if the appId is not defined', async () => {
appMockRender.coreStart.application.currentAppId$ = new Subject();
const coreStart = coreMock.createStart();
coreStart.application.currentAppId$ = new Subject();
const { result } = renderHook(() => useCasesLocalStorage(lsKey, initialValue), {
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} owner={[]} coreStart={coreStart} />,
});
expect(result.current[0]).toEqual(initialValue);

View file

@ -6,14 +6,13 @@
*/
import { useKibana, useToasts } from './lib/kibana';
import type { AppMockRenderer } from './mock';
import { createAppMockRenderer, TestProviders } from './mock';
import { TestProviders, renderWithTestingProviders } from './mock';
import { CaseToastSuccessContent, useCasesToast } from './use_cases_toast';
import { alertComment, basicComment, mockCase } from '../containers/mock';
import React from 'react';
import userEvent from '@testing-library/user-event';
import type { SupportedCaseAttachment } from '../types';
import { getByTestId, queryByTestId, screen, renderHook } from '@testing-library/react';
import { screen, renderHook, getByTestId, queryByTestId } from '@testing-library/react';
import { OWNER_INFO } from '../../common/constants';
import { useApplication } from './lib/kibana/use_application';
@ -49,6 +48,7 @@ describe('Use cases toast hook', () => {
const mockParams = successMock.mock.calls[0][0];
const el = document.createElement('div');
mockParams.text(el);
// eslint-disable-next-line testing-library/prefer-screen-queries
const button = getByTestId(el, 'toaster-content-case-view-link');
await userEvent.click(button);
}
@ -149,11 +149,9 @@ describe('Use cases toast hook', () => {
});
describe('Toast content', () => {
let appMockRender: AppMockRenderer;
const onViewCaseClick = jest.fn();
beforeEach(() => {
appMockRender = createAppMockRenderer();
onViewCaseClick.mockReset();
});
@ -197,34 +195,30 @@ describe('Use cases toast hook', () => {
});
it('renders a correct successful message content', () => {
const result = appMockRender.render(
renderWithTestingProviders(
<CaseToastSuccessContent content={'my content'} onViewCaseClick={onViewCaseClick} />
);
expect(result.getByTestId('toaster-content-sync-text')).toHaveTextContent('my content');
expect(result.getByTestId('toaster-content-case-view-link')).toHaveTextContent('View case');
expect(screen.getByTestId('toaster-content-sync-text')).toHaveTextContent('my content');
expect(screen.getByTestId('toaster-content-case-view-link')).toHaveTextContent('View case');
expect(onViewCaseClick).not.toHaveBeenCalled();
});
it('renders a correct successful message without content', () => {
const result = appMockRender.render(
<CaseToastSuccessContent onViewCaseClick={onViewCaseClick} />
);
expect(result.queryByTestId('toaster-content-sync-text')).toBeFalsy();
expect(result.getByTestId('toaster-content-case-view-link')).toHaveTextContent('View case');
renderWithTestingProviders(<CaseToastSuccessContent onViewCaseClick={onViewCaseClick} />);
expect(screen.queryByTestId('toaster-content-sync-text')).toBeFalsy();
expect(screen.getByTestId('toaster-content-case-view-link')).toHaveTextContent('View case');
expect(onViewCaseClick).not.toHaveBeenCalled();
});
it('Calls the onViewCaseClick when clicked', async () => {
const result = appMockRender.render(
<CaseToastSuccessContent onViewCaseClick={onViewCaseClick} />
);
renderWithTestingProviders(<CaseToastSuccessContent onViewCaseClick={onViewCaseClick} />);
await userEvent.click(result.getByTestId('toaster-content-case-view-link'));
await userEvent.click(screen.getByTestId('toaster-content-case-view-link'));
expect(onViewCaseClick).toHaveBeenCalled();
});
it('hides the view case link when onViewCaseClick is not defined', () => {
appMockRender.render(<CaseToastSuccessContent />);
<CaseToastSuccessContent />;
expect(screen.queryByTestId('toaster-content-case-view-link')).not.toBeInTheDocument();
});
@ -301,6 +295,7 @@ describe('Use cases toast hook', () => {
const mockParams = successMock.mock.calls[0][0];
const el = document.createElement('div');
mockParams.text(el);
// eslint-disable-next-line testing-library/prefer-screen-queries
const button = queryByTestId(el, 'toaster-content-case-view-link');
expect(button).toBeNull();

View file

@ -6,20 +6,13 @@
*/
import { renderHook, act } from '@testing-library/react';
import type { AppMockRenderer } from './mock';
import { createAppMockRenderer } from './mock';
import { useIsUserTyping } from './use_is_user_typing';
import { TestProviders } from './mock';
describe('useIsUserTyping', () => {
let appMockRender: AppMockRenderer;
beforeEach(() => {
appMockRender = createAppMockRenderer();
});
it('set isUserTyping=false on init', () => {
const { result } = renderHook(() => useIsUserTyping(), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
expect(result.current.isUserTyping).toBe(false);
@ -27,7 +20,7 @@ describe('useIsUserTyping', () => {
it('set isUserTyping to true with setIsUserTyping', () => {
const { result } = renderHook(() => useIsUserTyping(), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
act(() => {
@ -39,7 +32,7 @@ describe('useIsUserTyping', () => {
it('set isUserTyping to true onContentChange', () => {
const { result } = renderHook(() => useIsUserTyping(), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
act(() => {
@ -51,7 +44,7 @@ describe('useIsUserTyping', () => {
it('does not set isUserTyping to true onContentChange when the value is empty', () => {
const { result } = renderHook(() => useIsUserTyping(), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
act(() => {
@ -63,7 +56,7 @@ describe('useIsUserTyping', () => {
it('set isUserTyping to false onDebounce', () => {
const { result } = renderHook(() => useIsUserTyping(), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
act(() => {

View file

@ -7,8 +7,8 @@
import React from 'react';
import userEvent from '@testing-library/user-event';
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
import { renderWithTestingProviders } from '../../../common/mock';
import { basicCase } from '../../../containers/mock';
import { EditAssigneesFlyout } from './edit_assignees_flyout';
import { screen, waitFor } from '@testing-library/react';
@ -23,8 +23,6 @@ const useBulkGetUserProfilesMock = useBulkGetUserProfiles as jest.Mock;
const useSuggestUserProfilesMock = useSuggestUserProfiles as jest.Mock;
describe('EditAssigneesFlyout', () => {
let appMock: AppMockRenderer;
const props = {
selectedCases: [basicCase],
onClose: jest.fn(),
@ -33,14 +31,13 @@ describe('EditAssigneesFlyout', () => {
beforeEach(() => {
jest.clearAllMocks();
appMock = createAppMockRenderer();
useBulkGetUserProfilesMock.mockReturnValue({ data: userProfilesMap, isLoading: false });
useSuggestUserProfilesMock.mockReturnValue({ data: userProfiles, isLoading: false });
});
it('renders correctly', async () => {
appMock.render(<EditAssigneesFlyout {...props} />);
renderWithTestingProviders(<EditAssigneesFlyout {...props} />);
expect(await screen.findByTestId('cases-edit-assignees-flyout')).toBeInTheDocument();
expect(await screen.findByTestId('cases-edit-assignees-flyout-title')).toBeInTheDocument();
@ -49,7 +46,7 @@ describe('EditAssigneesFlyout', () => {
});
it('calls onClose when pressing the cancel button', async () => {
appMock.render(<EditAssigneesFlyout {...props} />);
renderWithTestingProviders(<EditAssigneesFlyout {...props} />);
await userEvent.click(await screen.findByTestId('cases-edit-assignees-flyout-cancel'));
@ -59,7 +56,7 @@ describe('EditAssigneesFlyout', () => {
});
it('calls onSaveAssignees when pressing the save selection button', async () => {
appMock.render(<EditAssigneesFlyout {...props} />);
renderWithTestingProviders(<EditAssigneesFlyout {...props} />);
expect(await screen.findByText('Damaged Raccoon')).toBeInTheDocument();
@ -75,13 +72,15 @@ describe('EditAssigneesFlyout', () => {
});
it('shows the case title when selecting one case', async () => {
appMock.render(<EditAssigneesFlyout {...props} />);
renderWithTestingProviders(<EditAssigneesFlyout {...props} />);
expect(await screen.findByText(basicCase.title)).toBeInTheDocument();
});
it('shows the number of total selected cases in the title when selecting multiple cases', async () => {
appMock.render(<EditAssigneesFlyout {...props} selectedCases={[basicCase, basicCase]} />);
renderWithTestingProviders(
<EditAssigneesFlyout {...props} selectedCases={[basicCase, basicCase]} />
);
expect(await screen.findByText('Selected cases: 2')).toBeInTheDocument();
});

View file

@ -6,9 +6,9 @@
*/
import React from 'react';
import { act, waitFor } from '@testing-library/react';
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
import { act, waitFor, screen } from '@testing-library/react';
import { renderWithTestingProviders } from '../../../common/mock';
import { EditAssigneesSelectable } from './edit_assignees_selectable';
import { basicCase } from '../../../containers/mock';
import userEvent, { type UserEvent } from '@testing-library/user-event';
@ -19,7 +19,6 @@ jest.mock('../../../containers/user_profiles/api');
describe('EditAssigneesSelectable', () => {
let user: UserEvent;
let appMock: AppMockRenderer;
/**
* Case has the following tags: Damaged Raccoon
@ -62,46 +61,46 @@ describe('EditAssigneesSelectable', () => {
user = userEvent.setup({
advanceTimers: jest.advanceTimersByTime,
});
appMock = createAppMockRenderer();
jest.clearAllMocks();
});
it('renders correctly', async () => {
const result = appMock.render(<EditAssigneesSelectable {...props} />);
renderWithTestingProviders(<EditAssigneesSelectable {...props} />);
await waitFor(() => {
expect(result.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
expect(screen.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
});
expect(result.getByPlaceholderText('Find a user')).toBeInTheDocument();
expect(result.getByText('Selected: 1')).toBeInTheDocument();
expect(screen.getByPlaceholderText('Find a user')).toBeInTheDocument();
expect(screen.getByText('Selected: 1')).toBeInTheDocument();
for (const userProfile of userProfiles) {
// @ts-ignore: full name exists
expect(result.getByText(userProfile.user.full_name)).toBeInTheDocument();
expect(screen.getByText(userProfile.user.full_name)).toBeInTheDocument();
}
});
it('renders the selected assignees label correctly', async () => {
const result = appMock.render(<EditAssigneesSelectable {...propsMultipleCases} />);
renderWithTestingProviders(<EditAssigneesSelectable {...propsMultipleCases} />);
await waitFor(() => {
expect(result.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
expect(screen.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
});
expect(result.getByText('Selected: 2')).toBeInTheDocument();
expect(screen.getByText('Selected: 2')).toBeInTheDocument();
for (const userProfile of userProfilesMap.values()) {
// @ts-ignore: full name exists
expect(result.getByText(userProfile.user.full_name)).toBeInTheDocument();
expect(screen.getByText(userProfile.user.full_name)).toBeInTheDocument();
}
});
it('renders the assignees icons correctly', async () => {
const result = appMock.render(<EditAssigneesSelectable {...propsMultipleCases} />);
renderWithTestingProviders(<EditAssigneesSelectable {...propsMultipleCases} />);
await waitFor(() => {
expect(result.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
expect(screen.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
});
for (const [uid, icon] of [
@ -110,20 +109,20 @@ describe('EditAssigneesSelectable', () => {
[userProfiles[2].uid, 'empty'],
]) {
const iconDataTestSubj = `cases-actions-assignees-edit-selectable-assignee-${uid}-icon-${icon}`;
expect(result.getByTestId(iconDataTestSubj)).toBeInTheDocument();
expect(screen.getByTestId(iconDataTestSubj)).toBeInTheDocument();
}
});
it('selects and unselects correctly assignees with one case', async () => {
const result = appMock.render(<EditAssigneesSelectable {...props} />);
renderWithTestingProviders(<EditAssigneesSelectable {...props} />);
await waitFor(() => {
expect(result.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
expect(screen.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
});
for (const userProfile of userProfiles) {
// @ts-ignore: full name exists
await user.click(result.getByText(userProfile.user.full_name));
await user.click(screen.getByText(userProfile.user.full_name));
}
expect(props.onChangeAssignees).toBeCalledTimes(3);
@ -137,15 +136,15 @@ describe('EditAssigneesSelectable', () => {
});
it('selects and unselects correctly assignees with multiple cases', async () => {
const result = appMock.render(<EditAssigneesSelectable {...propsMultipleCases} />);
renderWithTestingProviders(<EditAssigneesSelectable {...propsMultipleCases} />);
await waitFor(() => {
expect(result.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
expect(screen.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
});
for (const userProfile of userProfiles) {
// @ts-ignore: full name exists
await user.click(result.getByText(userProfile.user.full_name));
await user.click(screen.getByText(userProfile.user.full_name));
}
expect(propsMultipleCases.onChangeAssignees).toBeCalledTimes(3);
@ -159,15 +158,15 @@ describe('EditAssigneesSelectable', () => {
});
it('renders the icons correctly after selecting and deselecting assignees', async () => {
const result = appMock.render(<EditAssigneesSelectable {...propsMultipleCases} />);
renderWithTestingProviders(<EditAssigneesSelectable {...propsMultipleCases} />);
await waitFor(() => {
expect(result.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
expect(screen.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
});
for (const userProfile of userProfiles) {
// @ts-ignore: full name exists
await user.click(result.getByText(userProfile.user.full_name));
await user.click(screen.getByText(userProfile.user.full_name));
}
for (const [uid, icon] of [
@ -176,7 +175,7 @@ describe('EditAssigneesSelectable', () => {
[userProfiles[2].uid, 'check'],
]) {
const iconDataTestSubj = `cases-actions-assignees-edit-selectable-assignee-${uid}-icon-${icon}`;
expect(result.getByTestId(iconDataTestSubj)).toBeInTheDocument();
expect(screen.getByTestId(iconDataTestSubj)).toBeInTheDocument();
}
expect(propsMultipleCases.onChangeAssignees).toBeCalledTimes(3);
@ -194,13 +193,13 @@ describe('EditAssigneesSelectable', () => {
const reversedUserProfiles = [...userProfiles].reverse();
spyOnBulkGetUserProfiles.mockResolvedValueOnce(reversedUserProfiles);
const result = appMock.render(<EditAssigneesSelectable {...props} />);
renderWithTestingProviders(<EditAssigneesSelectable {...props} />);
await waitFor(() => {
expect(result.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
expect(screen.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
});
const allUsersInView = result.getAllByRole('option');
const allUsersInView = screen.getAllByRole('option');
expect(allUsersInView.length).toBe(3);
expect(allUsersInView[0].textContent?.includes('Damaged Raccoon')).toBe(true);
@ -213,23 +212,23 @@ describe('EditAssigneesSelectable', () => {
const searchedUserDataTestSubj =
'cases-actions-assignees-edit-selectable-assignee-u_IbBVXpDtrjOByJ-syBdr425fLGqwpzY_xdQqCFAFXLI_0';
const result = appMock.render(<EditAssigneesSelectable {...props} />);
renderWithTestingProviders(<EditAssigneesSelectable {...props} />);
await waitFor(() => {
expect(result.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
expect(screen.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
});
await user.type(result.getByPlaceholderText('Find a user'), 's');
await user.type(screen.getByPlaceholderText('Find a user'), 's');
act(() => {
jest.advanceTimersByTime(1000);
});
await waitFor(() => {
expect(result.getByTestId(searchedUserDataTestSubj));
expect(screen.getByTestId(searchedUserDataTestSubj));
});
const searchResults = result.getAllByRole('option');
const searchResults = screen.getAllByRole('option');
expect(searchResults.length).toBe(2);
expect(searchResults[0].textContent?.includes('Physical Dinosaur')).toBe(true);
@ -241,50 +240,50 @@ describe('EditAssigneesSelectable', () => {
const searchedUserDataTestSubj =
'cases-actions-assignees-edit-selectable-assignee-u_IbBVXpDtrjOByJ-syBdr425fLGqwpzY_xdQqCFAFXLI_0';
const result = appMock.render(<EditAssigneesSelectable {...props} />);
renderWithTestingProviders(<EditAssigneesSelectable {...props} />);
await waitFor(() => {
expect(result.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
expect(screen.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
});
await user.type(result.getByPlaceholderText('Find a user'), 's');
await user.type(screen.getByPlaceholderText('Find a user'), 's');
act(() => {
jest.advanceTimersByTime(1000);
});
await waitFor(() => {
expect(result.getByTestId(searchedUserDataTestSubj));
expect(screen.getByTestId(searchedUserDataTestSubj));
});
// selects
await user.click(result.getByTestId(searchedUserDataTestSubj));
await user.click(screen.getByTestId(searchedUserDataTestSubj));
// deselect
await user.click(result.getByTestId(searchedUserDataTestSubj));
await user.click(screen.getByTestId(searchedUserDataTestSubj));
// clear search results
await user.click(result.getByTestId('clearSearchButton'));
await user.click(screen.getByTestId('clearSearchButton'));
await waitFor(() => {
expect(result.getByText('Damaged Raccoon'));
expect(screen.getByText('Damaged Raccoon'));
});
expect(result.queryByTestId(searchedUserDataTestSubj)).not.toBeInTheDocument();
expect(screen.queryByTestId(searchedUserDataTestSubj)).not.toBeInTheDocument();
});
it('does not show the same user in search results if it is already in the initial user profile mapping', async () => {
const result = appMock.render(<EditAssigneesSelectable {...props} />);
renderWithTestingProviders(<EditAssigneesSelectable {...props} />);
await waitFor(() => {
expect(result.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
expect(screen.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
});
await user.type(result.getByPlaceholderText('Find a user'), 's');
await user.type(screen.getByPlaceholderText('Find a user'), 's');
act(() => {
jest.advanceTimersByTime(1000);
});
const searchResults = result.getAllByTestId(
const searchResults = screen.getAllByTestId(
// Physical Dinosaur
'cases-actions-assignees-edit-selectable-assignee-u_A_tM4n0wPkdiQ9smmd8o0Hr_h61XQfu8aRPh9GMoRoc_0-icon-empty'
);
@ -297,23 +296,23 @@ describe('EditAssigneesSelectable', () => {
const searchedUserDataTestSubj =
'cases-actions-assignees-edit-selectable-assignee-u_IbBVXpDtrjOByJ-syBdr425fLGqwpzY_xdQqCFAFXLI_0';
const result = appMock.render(<EditAssigneesSelectable {...props} />);
renderWithTestingProviders(<EditAssigneesSelectable {...props} />);
await waitFor(() => {
expect(result.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
expect(screen.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
});
await user.type(result.getByPlaceholderText('Find a user'), 's');
await user.type(screen.getByPlaceholderText('Find a user'), 's');
act(() => {
jest.advanceTimersByTime(1000);
});
await waitFor(() => {
expect(result.getByTestId(searchedUserDataTestSubj));
expect(screen.getByTestId(searchedUserDataTestSubj));
});
await user.click(result.getByTestId(searchedUserDataTestSubj));
await user.click(screen.getByTestId(searchedUserDataTestSubj));
expect(props.onChangeAssignees).toBeCalledWith({
selectedItems: [
'u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0',
@ -324,20 +323,20 @@ describe('EditAssigneesSelectable', () => {
});
it('shows deselected users from the initial user profile mapping', async () => {
const result = appMock.render(<EditAssigneesSelectable {...props} />);
renderWithTestingProviders(<EditAssigneesSelectable {...props} />);
await waitFor(() => {
expect(result.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
expect(screen.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
});
// @ts-ignore: full name exists
await user.click(result.getByText(userProfiles[0].user.full_name));
await user.click(screen.getByText(userProfiles[0].user.full_name));
// @ts-ignore: full name exists
expect(result.getByText(userProfiles[0].user.full_name)).toBeInTheDocument();
expect(screen.getByText(userProfiles[0].user.full_name)).toBeInTheDocument();
// ensures that the icon is set to empty
expect(
result.getByTestId(
screen.getByTestId(
'cases-actions-assignees-edit-selectable-assignee-u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0-icon-empty'
)
).toBeInTheDocument();
@ -353,10 +352,10 @@ describe('EditAssigneesSelectable', () => {
const searchedUserDataTestSubj =
'cases-actions-assignees-edit-selectable-assignee-u_IbBVXpDtrjOByJ-syBdr425fLGqwpzY_xdQqCFAFXLI_0';
const result = appMock.render(<EditAssigneesSelectable {...props} />);
renderWithTestingProviders(<EditAssigneesSelectable {...props} />);
await waitFor(() => {
expect(result.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
expect(screen.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
});
act(() => {
@ -364,20 +363,20 @@ describe('EditAssigneesSelectable', () => {
});
await waitFor(() => {
expect(result.getByText('Damaged Raccoon'));
expect(screen.getByText('Damaged Raccoon'));
});
expect(result.queryByTestId(searchedUserDataTestSubj)).not.toBeInTheDocument();
expect(screen.queryByTestId(searchedUserDataTestSubj)).not.toBeInTheDocument();
});
it('shows the no matching component', async () => {
const result = appMock.render(<EditAssigneesSelectable {...props} />);
renderWithTestingProviders(<EditAssigneesSelectable {...props} />);
await waitFor(() => {
expect(result.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
expect(screen.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
});
await user.type(result.getByPlaceholderText('Find a user'), 'not-exists');
await user.type(screen.getByPlaceholderText('Find a user'), 'not-exists');
act(() => {
jest.advanceTimersByTime(1000);
@ -385,42 +384,42 @@ describe('EditAssigneesSelectable', () => {
await waitFor(() => {
expect(
result.getAllByTestId('case-user-profiles-assignees-popover-no-matches')[0]
screen.getAllByTestId('case-user-profiles-assignees-popover-no-matches')[0]
).toBeInTheDocument();
});
});
it('shows unknown users', async () => {
const selectedCases = [{ ...basicCase, assignees: [{ uid: '123' }, { uid: '456' }] }];
const result = appMock.render(
renderWithTestingProviders(
<EditAssigneesSelectable {...props} selectedCases={selectedCases} />
);
await waitFor(() => {
expect(result.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
expect(screen.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
});
await waitFor(() => {
const unknownUsers = result.getAllByText('Unknown');
const unknownUsers = screen.getAllByText('Unknown');
expect(unknownUsers.length).toBe(2);
});
});
it('selects unknown users', async () => {
const selectedCases = [{ ...basicCase, assignees: [{ uid: '123' }] }, basicCase];
const result = appMock.render(
renderWithTestingProviders(
<EditAssigneesSelectable {...props} selectedCases={selectedCases} />
);
await waitFor(() => {
expect(result.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
expect(screen.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
});
await waitFor(() => {
expect(result.getByText('Unknown')).toBeInTheDocument();
expect(screen.getByText('Unknown')).toBeInTheDocument();
});
await user.click(result.getByText('Unknown'));
await user.click(screen.getByText('Unknown'));
expect(props.onChangeAssignees).toBeCalledWith({
selectedItems: ['123'],
@ -430,15 +429,15 @@ describe('EditAssigneesSelectable', () => {
it('deselects unknown users', async () => {
const selectedCases = [{ ...basicCase, assignees: [{ uid: '123' }] }];
const result = appMock.render(
renderWithTestingProviders(
<EditAssigneesSelectable {...props} selectedCases={selectedCases} />
);
await waitFor(() => {
expect(result.getByText('Unknown')).toBeInTheDocument();
expect(screen.getByText('Unknown')).toBeInTheDocument();
});
await user.click(result.getByText('Unknown'));
await user.click(screen.getByText('Unknown'));
expect(props.onChangeAssignees).toBeCalledWith({
selectedItems: [],
@ -447,14 +446,14 @@ describe('EditAssigneesSelectable', () => {
});
it('remove all assignees', async () => {
const result = appMock.render(<EditAssigneesSelectable {...propsMultipleCases} />);
renderWithTestingProviders(<EditAssigneesSelectable {...propsMultipleCases} />);
await waitFor(() => {
expect(result.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
expect(screen.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
});
expect(result.getByRole('button', { name: 'Remove all assignees' })).toBeInTheDocument();
await user.click(result.getByRole('button', { name: 'Remove all assignees' }));
expect(screen.getByRole('button', { name: 'Remove all assignees' })).toBeInTheDocument();
await user.click(screen.getByRole('button', { name: 'Remove all assignees' }));
expect(propsMultipleCases.onChangeAssignees).toBeCalledTimes(1);
expect(propsMultipleCases.onChangeAssignees).toBeCalledWith({
@ -468,15 +467,15 @@ describe('EditAssigneesSelectable', () => {
it('renders even with no assignee set yet', async () => {
const selectedCases = [{ ...basicCase, assignees: [] }];
const result = appMock.render(
renderWithTestingProviders(
<EditAssigneesSelectable {...props} selectedCases={selectedCases} />
);
await waitFor(() => {
expect(result.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
expect(screen.getByTestId('cases-actions-assignees-edit-selectable')).toBeInTheDocument();
});
expect(result.getByPlaceholderText('Find a user')).toBeInTheDocument();
expect(result.getByText('Selected: 0')).toBeInTheDocument();
expect(screen.getByPlaceholderText('Find a user')).toBeInTheDocument();
expect(screen.getByText('Selected: 0')).toBeInTheDocument();
});
});

View file

@ -5,23 +5,22 @@
* 2.0.
*/
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
import { act, waitFor, renderHook } from '@testing-library/react';
import { useAssigneesAction } from './use_assignees_action';
import * as api from '../../../containers/api';
import { basicCase } from '../../../containers/mock';
import { TestProviders } from '../../../common/mock';
import { coreMock } from '@kbn/core/public/mocks';
import React from 'react';
jest.mock('../../../containers/api');
describe('useAssigneesAction', () => {
let appMockRender: AppMockRenderer;
const onAction = jest.fn();
const onActionSuccess = jest.fn();
beforeEach(() => {
appMockRender = createAppMockRenderer();
jest.clearAllMocks();
});
@ -34,7 +33,7 @@ describe('useAssigneesAction', () => {
isDisabled: false,
}),
{
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
}
);
@ -59,7 +58,7 @@ describe('useAssigneesAction', () => {
const { result } = renderHook(
() => useAssigneesAction({ onAction, onActionSuccess, isDisabled: false }),
{
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
}
);
@ -78,24 +77,27 @@ describe('useAssigneesAction', () => {
await waitFor(() => {
expect(result.current.isFlyoutOpen).toBe(false);
expect(onActionSuccess).toHaveBeenCalled();
expect(updateSpy).toHaveBeenCalledWith({
cases: [
{
assignees: [{ uid: 'u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0' }, { uid: '1' }],
id: basicCase.id,
version: basicCase.version,
},
],
});
});
expect(onActionSuccess).toHaveBeenCalled();
expect(updateSpy).toHaveBeenCalledWith({
cases: [
{
assignees: [{ uid: 'u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0' }, { uid: '1' }],
id: basicCase.id,
version: basicCase.version,
},
],
});
});
it('shows the success toaster correctly when updating one case', async () => {
const coreStart = coreMock.createStart();
const { result } = renderHook(
() => useAssigneesAction({ onAction, onActionSuccess, isDisabled: false }),
{
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} coreStart={coreStart} />,
}
);
@ -110,7 +112,7 @@ describe('useAssigneesAction', () => {
});
await waitFor(() => {
expect(appMockRender.coreStart.notifications.toasts.addSuccess).toHaveBeenCalledWith({
expect(coreStart.notifications.toasts.addSuccess).toHaveBeenCalledWith({
title: 'Edited case',
className: 'eui-textBreakWord',
});
@ -118,10 +120,12 @@ describe('useAssigneesAction', () => {
});
it('shows the success toaster correctly when updating multiple cases', async () => {
const coreStart = coreMock.createStart();
const { result } = renderHook(
() => useAssigneesAction({ onAction, onActionSuccess, isDisabled: false }),
{
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} coreStart={coreStart} />,
}
);
@ -136,7 +140,7 @@ describe('useAssigneesAction', () => {
});
await waitFor(() => {
expect(appMockRender.coreStart.notifications.toasts.addSuccess).toHaveBeenCalledWith({
expect(coreStart.notifications.toasts.addSuccess).toHaveBeenCalledWith({
title: 'Edited 2 cases',
className: 'eui-textBreakWord',
});

View file

@ -5,22 +5,21 @@
* 2.0.
*/
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
import { waitFor, renderHook } from '@testing-library/react';
import { useCopyIDAction } from './use_copy_id_action';
import { basicCase } from '../../../containers/mock';
import { TestProviders } from '../../../common/mock';
import React from 'react';
import { coreMock } from '@kbn/core/public/mocks';
jest.mock('../../../containers/api');
describe('useCopyIDAction', () => {
let appMockRender: AppMockRenderer;
const onActionSuccess = jest.fn();
const originalClipboard = global.window.navigator.clipboard;
beforeEach(() => {
appMockRender = createAppMockRenderer();
jest.clearAllMocks();
Object.defineProperty(navigator, 'clipboard', {
value: {
@ -38,7 +37,7 @@ describe('useCopyIDAction', () => {
it('renders a copy ID action with one case', async () => {
const { result } = renderHook(() => useCopyIDAction({ onActionSuccess }), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
expect(result.current.getAction(basicCase)).toMatchInlineSnapshot(`
@ -59,7 +58,7 @@ describe('useCopyIDAction', () => {
it('copies the id of the selected case to the clipboard', async () => {
const { result } = renderHook(() => useCopyIDAction({ onActionSuccess }), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
const action = result.current.getAction(basicCase);
@ -68,13 +67,16 @@ describe('useCopyIDAction', () => {
await waitFor(() => {
expect(onActionSuccess).toHaveBeenCalled();
expect(navigator.clipboard.writeText).toHaveBeenCalledWith(basicCase.id);
});
expect(navigator.clipboard.writeText).toHaveBeenCalledWith(basicCase.id);
});
it('shows the success toaster correctly when copying the case id', async () => {
const coreStart = coreMock.createStart();
const { result } = renderHook(() => useCopyIDAction({ onActionSuccess }), {
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} coreStart={coreStart} />,
});
const action = result.current.getAction(basicCase);
@ -83,10 +85,11 @@ describe('useCopyIDAction', () => {
await waitFor(() => {
expect(onActionSuccess).toHaveBeenCalled();
expect(appMockRender.coreStart.notifications.toasts.addSuccess).toHaveBeenCalledWith({
title: 'Copied case ID to clipboard',
className: 'eui-textBreakWord',
});
});
expect(coreStart.notifications.toasts.addSuccess).toHaveBeenCalledWith({
title: 'Copied case ID to clipboard',
className: 'eui-textBreakWord',
});
});
});

View file

@ -5,23 +5,22 @@
* 2.0.
*/
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
import { act, waitFor, renderHook } from '@testing-library/react';
import { useDeleteAction } from './use_delete_action';
import * as api from '../../../containers/api';
import { basicCase } from '../../../containers/mock';
import { TestProviders } from '../../../common/mock';
import { coreMock } from '@kbn/core/public/mocks';
import React from 'react';
jest.mock('../../../containers/api');
describe('useDeleteAction', () => {
let appMockRender: AppMockRenderer;
const onAction = jest.fn();
const onActionSuccess = jest.fn();
beforeEach(() => {
appMockRender = createAppMockRenderer();
jest.clearAllMocks();
});
@ -29,7 +28,7 @@ describe('useDeleteAction', () => {
const { result } = renderHook(
() => useDeleteAction({ onAction, onActionSuccess, isDisabled: false }),
{
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
}
);
@ -57,7 +56,7 @@ describe('useDeleteAction', () => {
const { result } = renderHook(
() => useDeleteAction({ onAction, onActionSuccess, isDisabled: false }),
{
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
}
);
@ -87,7 +86,7 @@ describe('useDeleteAction', () => {
const { result } = renderHook(
() => useDeleteAction({ onAction, onActionSuccess, isDisabled: false }),
{
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
}
);
@ -106,16 +105,17 @@ describe('useDeleteAction', () => {
await waitFor(() => {
expect(result.current.isModalVisible).toBe(false);
expect(onActionSuccess).toHaveBeenCalled();
expect(deleteSpy).toHaveBeenCalledWith({ caseIds: ['basic-case-id'] });
});
expect(onActionSuccess).toHaveBeenCalled();
expect(deleteSpy).toHaveBeenCalledWith({ caseIds: ['basic-case-id'] });
});
it('closes the modal', async () => {
const { result } = renderHook(
() => useDeleteAction({ onAction, onActionSuccess, isDisabled: false }),
{
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
}
);
@ -137,10 +137,12 @@ describe('useDeleteAction', () => {
});
it('shows the success toaster correctly when delete one case', async () => {
const coreStart = coreMock.createStart();
const { result } = renderHook(
() => useDeleteAction({ onAction, onActionSuccess, isDisabled: false }),
{
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} coreStart={coreStart} />,
}
);
@ -155,7 +157,7 @@ describe('useDeleteAction', () => {
});
await waitFor(() => {
expect(appMockRender.coreStart.notifications.toasts.addSuccess).toHaveBeenCalledWith({
expect(coreStart.notifications.toasts.addSuccess).toHaveBeenCalledWith({
title: 'Deleted case',
className: 'eui-textBreakWord',
});
@ -163,10 +165,12 @@ describe('useDeleteAction', () => {
});
it('shows the success toaster correctly when delete multiple case', async () => {
const coreStart = coreMock.createStart();
const { result } = renderHook(
() => useDeleteAction({ onAction, onActionSuccess, isDisabled: false }),
{
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} coreStart={coreStart} />,
}
);
@ -181,7 +185,7 @@ describe('useDeleteAction', () => {
});
await waitFor(() => {
expect(appMockRender.coreStart.notifications.toasts.addSuccess).toHaveBeenCalledWith({
expect(coreStart.notifications.toasts.addSuccess).toHaveBeenCalledWith({
title: 'Deleted 2 cases',
className: 'eui-textBreakWord',
});

View file

@ -5,25 +5,23 @@
* 2.0.
*/
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
import { act, waitFor, renderHook } from '@testing-library/react';
import { useSeverityAction } from './use_severity_action';
import * as api from '../../../containers/api';
import { basicCase } from '../../../containers/mock';
import { CaseSeverity } from '../../../../common/types/domain';
import { TestProviders } from '../../../common/mock';
import React from 'react';
import { coreMock } from '@kbn/core/public/mocks';
jest.mock('../../../containers/api');
// FLAKY: https://github.com/elastic/kibana/issues/207712
describe.skip('useSeverityAction', () => {
let appMockRender: AppMockRenderer;
describe('useSeverityAction', () => {
const onAction = jest.fn();
const onActionSuccess = jest.fn();
beforeEach(() => {
appMockRender = createAppMockRenderer();
jest.clearAllMocks();
});
@ -36,7 +34,7 @@ describe.skip('useSeverityAction', () => {
isDisabled: false,
}),
{
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
}
);
@ -84,7 +82,7 @@ describe.skip('useSeverityAction', () => {
const { result } = renderHook(
() => useSeverityAction({ onAction, onActionSuccess, isDisabled: false }),
{
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
}
);
@ -103,10 +101,11 @@ describe.skip('useSeverityAction', () => {
await waitFor(() => {
expect(onAction).toHaveBeenCalled();
expect(onActionSuccess).toHaveBeenCalled();
expect(updateSpy).toHaveBeenCalledWith({
cases: [{ severity, id: basicCase.id, version: basicCase.version }],
});
});
expect(onActionSuccess).toHaveBeenCalled();
expect(updateSpy).toHaveBeenCalledWith({
cases: [{ severity, id: basicCase.id, version: basicCase.version }],
});
}
});
@ -121,10 +120,12 @@ describe.skip('useSeverityAction', () => {
it.each(singleCaseTests)(
'shows the success toaster correctly when updating the severity of the case: %s',
async (_, index, expectedMessage) => {
const coreStart = coreMock.createStart();
const { result } = renderHook(
() => useSeverityAction({ onAction, onActionSuccess, isDisabled: false }),
{
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} coreStart={coreStart} />,
}
);
@ -136,7 +137,7 @@ describe.skip('useSeverityAction', () => {
});
await waitFor(() => {
expect(appMockRender.coreStart.notifications.toasts.addSuccess).toHaveBeenCalledWith({
expect(coreStart.notifications.toasts.addSuccess).toHaveBeenCalledWith({
title: expectedMessage,
className: 'eui-textBreakWord',
});
@ -154,10 +155,12 @@ describe.skip('useSeverityAction', () => {
it.each(multipleCasesTests)(
'shows the success toaster correctly when updating the severity of the case: %s',
async (_, index, expectedMessage) => {
const coreStart = coreMock.createStart();
const { result } = renderHook(
() => useSeverityAction({ onAction, onActionSuccess, isDisabled: false }),
{
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} coreStart={coreStart} />,
}
);
@ -169,7 +172,7 @@ describe.skip('useSeverityAction', () => {
});
await waitFor(() => {
expect(appMockRender.coreStart.notifications.toasts.addSuccess).toHaveBeenCalledWith({
expect(coreStart.notifications.toasts.addSuccess).toHaveBeenCalledWith({
title: expectedMessage,
className: 'eui-textBreakWord',
});
@ -188,7 +191,7 @@ describe.skip('useSeverityAction', () => {
const { result } = renderHook(
() => useSeverityAction({ onAction, onActionSuccess, isDisabled: false }),
{
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
}
);
@ -202,7 +205,7 @@ describe.skip('useSeverityAction', () => {
const { result } = renderHook(
() => useSeverityAction({ onAction, onActionSuccess, isDisabled: true }),
{
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
}
);

View file

@ -5,8 +5,6 @@
* 2.0.
*/
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
import { act, waitFor, renderHook } from '@testing-library/react';
import { useStatusAction } from './use_status_action';
@ -15,18 +13,19 @@ import { basicCase } from '../../../containers/mock';
import { CaseStatuses } from '../../../../common/types/domain';
import { useUserPermissions } from '../../user_actions/use_user_permissions';
import { useShouldDisableStatus } from './use_should_disable_status';
import { TestProviders } from '../../../common/mock';
import { coreMock } from '@kbn/core/public/mocks';
import React from 'react';
jest.mock('../../user_actions/use_user_permissions');
jest.mock('./use_should_disable_status');
jest.mock('../../../containers/api');
describe('useStatusAction', () => {
let appMockRender: AppMockRenderer;
const onAction = jest.fn();
const onActionSuccess = jest.fn();
beforeEach(() => {
appMockRender = createAppMockRenderer();
jest.clearAllMocks();
(useShouldDisableStatus as jest.Mock).mockReturnValue(() => false);
@ -45,7 +44,7 @@ describe('useStatusAction', () => {
isDisabled: false,
}),
{
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
}
);
@ -85,7 +84,7 @@ describe('useStatusAction', () => {
const { result } = renderHook(
() => useStatusAction({ onAction, onActionSuccess, isDisabled: false }),
{
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
}
);
@ -103,10 +102,11 @@ describe('useStatusAction', () => {
await waitFor(() => {
expect(onAction).toHaveBeenCalled();
expect(onActionSuccess).toHaveBeenCalled();
expect(updateSpy).toHaveBeenCalledWith({
cases: [{ status, id: basicCase.id, version: basicCase.version }],
});
});
expect(onActionSuccess).toHaveBeenCalled();
expect(updateSpy).toHaveBeenCalledWith({
cases: [{ status, id: basicCase.id, version: basicCase.version }],
});
}
});
@ -120,10 +120,12 @@ describe('useStatusAction', () => {
it.each(singleCaseTests)(
'shows the success toaster correctly when updating the status of the case: %s',
async (_, index, expectedMessage) => {
const coreStart = coreMock.createStart();
const { result } = renderHook(
() => useStatusAction({ onAction, onActionSuccess, isDisabled: false }),
{
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} coreStart={coreStart} />,
}
);
@ -135,7 +137,7 @@ describe('useStatusAction', () => {
});
await waitFor(() => {
expect(appMockRender.coreStart.notifications.toasts.addSuccess).toHaveBeenCalledWith({
expect(coreStart.notifications.toasts.addSuccess).toHaveBeenCalledWith({
title: expectedMessage,
className: 'eui-textBreakWord',
});
@ -152,10 +154,12 @@ describe('useStatusAction', () => {
it.each(multipleCasesTests)(
'shows the success toaster correctly when updating the status of the case: %s',
async (_, index, expectedMessage) => {
const coreStart = coreMock.createStart();
const { result } = renderHook(
() => useStatusAction({ onAction, onActionSuccess, isDisabled: false }),
{
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} coreStart={coreStart} />,
}
);
@ -167,7 +171,7 @@ describe('useStatusAction', () => {
});
await waitFor(() => {
expect(appMockRender.coreStart.notifications.toasts.addSuccess).toHaveBeenCalledWith({
expect(coreStart.notifications.toasts.addSuccess).toHaveBeenCalledWith({
title: expectedMessage,
className: 'eui-textBreakWord',
});
@ -187,7 +191,7 @@ describe('useStatusAction', () => {
const { result } = renderHook(
() => useStatusAction({ onAction, onActionSuccess, isDisabled: false }),
{
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
}
);
@ -201,7 +205,7 @@ describe('useStatusAction', () => {
const { result } = renderHook(
() => useStatusAction({ onAction, onActionSuccess, isDisabled: true }),
{
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
}
);
@ -219,7 +223,7 @@ describe('useStatusAction', () => {
const { result } = renderHook(
() => useStatusAction({ onAction, onActionSuccess, isDisabled: false }),
{
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
}
);
@ -235,7 +239,7 @@ describe('useStatusAction', () => {
const { result } = renderHook(
() => useStatusAction({ onAction, onActionSuccess, isDisabled: false }),
{
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
}
);

View file

@ -9,8 +9,7 @@ import React from 'react';
import userEvent from '@testing-library/user-event';
import { waitFor, screen } from '@testing-library/react';
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
import { renderWithTestingProviders } from '../../../common/mock';
import { basicCase, tags } from '../../../containers/mock';
import { useGetTags } from '../../../containers/use_get_tags';
import { EditTagsFlyout } from './edit_tags_flyout';
@ -20,8 +19,6 @@ jest.mock('../../../containers/use_get_tags');
const useGetTagsMock = useGetTags as jest.Mock;
describe('EditTagsFlyout', () => {
let appMock: AppMockRenderer;
/**
* Case one has the following tags: coke, pepsi, one
* Case two has the following tags: one, three
@ -37,11 +34,10 @@ describe('EditTagsFlyout', () => {
beforeEach(() => {
jest.clearAllMocks();
appMock = createAppMockRenderer();
});
it('renders correctly', async () => {
appMock.render(<EditTagsFlyout {...props} />);
renderWithTestingProviders(<EditTagsFlyout {...props} />);
expect(await screen.findByTestId('cases-edit-tags-flyout')).toBeInTheDocument();
expect(await screen.findByTestId('cases-edit-tags-flyout-title')).toBeInTheDocument();
@ -50,7 +46,7 @@ describe('EditTagsFlyout', () => {
});
it('calls onClose when pressing the cancel button', async () => {
appMock.render(<EditTagsFlyout {...props} />);
renderWithTestingProviders(<EditTagsFlyout {...props} />);
await userEvent.click(await screen.findByTestId('cases-edit-tags-flyout-cancel'));
@ -60,7 +56,7 @@ describe('EditTagsFlyout', () => {
});
it('calls onSaveTags when pressing the save selection button', async () => {
appMock.render(<EditTagsFlyout {...props} />);
renderWithTestingProviders(<EditTagsFlyout {...props} />);
expect(await screen.findByText('coke')).toBeInTheDocument();
@ -76,13 +72,15 @@ describe('EditTagsFlyout', () => {
});
it('shows the case title when selecting one case', async () => {
appMock.render(<EditTagsFlyout {...props} />);
renderWithTestingProviders(<EditTagsFlyout {...props} />);
expect(await screen.findByText(basicCase.title)).toBeInTheDocument();
});
it('shows the number of total selected cases in the title when selecting multiple cases', async () => {
appMock.render(<EditTagsFlyout {...props} selectedCases={[basicCase, basicCase]} />);
renderWithTestingProviders(
<EditTagsFlyout {...props} selectedCases={[basicCase, basicCase]} />
);
expect(await screen.findByText('Selected cases: 2')).toBeInTheDocument();
});

View file

@ -6,16 +6,14 @@
*/
import React from 'react';
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
import { renderWithTestingProviders } from '../../../common/mock';
import { EditTagsSelectable } from './edit_tags_selectable';
import { basicCase } from '../../../containers/mock';
import userEvent from '@testing-library/user-event';
import { waitFor } from '@testing-library/react';
import { waitFor, screen } from '@testing-library/react';
describe('EditTagsSelectable', () => {
let appMock: AppMockRenderer;
/**
* Case has the following tags: coke, pepsi
* All available tags are: one, two, coke, pepsi
@ -43,38 +41,37 @@ describe('EditTagsSelectable', () => {
};
beforeEach(() => {
appMock = createAppMockRenderer();
jest.clearAllMocks();
});
it('renders correctly', async () => {
const result = appMock.render(<EditTagsSelectable {...props} />);
renderWithTestingProviders(<EditTagsSelectable {...props} />);
expect(result.getByTestId('cases-actions-tags-edit-selectable')).toBeInTheDocument();
expect(result.getByPlaceholderText('Search')).toBeInTheDocument();
expect(result.getByText(`Total tags: ${props.tags.length}`)).toBeInTheDocument();
expect(result.getByText('Selected: 2')).toBeInTheDocument();
expect(result.getByText('Select all')).toBeInTheDocument();
expect(result.getByText('Select none')).toBeInTheDocument();
expect(screen.getByTestId('cases-actions-tags-edit-selectable')).toBeInTheDocument();
expect(screen.getByPlaceholderText('Search')).toBeInTheDocument();
expect(screen.getByText(`Total tags: ${props.tags.length}`)).toBeInTheDocument();
expect(screen.getByText('Selected: 2')).toBeInTheDocument();
expect(screen.getByText('Select all')).toBeInTheDocument();
expect(screen.getByText('Select none')).toBeInTheDocument();
for (const tag of props.tags) {
expect(result.getByText(tag)).toBeInTheDocument();
expect(screen.getByText(tag)).toBeInTheDocument();
}
});
it('renders the selected tags label correctly', async () => {
const result = appMock.render(<EditTagsSelectable {...propsMultipleCases} />);
renderWithTestingProviders(<EditTagsSelectable {...propsMultipleCases} />);
expect(result.getByText('Total tags: 5')).toBeInTheDocument();
expect(result.getByText('Selected: 4')).toBeInTheDocument();
expect(screen.getByText('Total tags: 5')).toBeInTheDocument();
expect(screen.getByText('Selected: 4')).toBeInTheDocument();
for (const tag of props.tags) {
expect(result.getByText(tag)).toBeInTheDocument();
expect(screen.getByText(tag)).toBeInTheDocument();
}
});
it('renders the tags icons correctly', async () => {
const result = appMock.render(<EditTagsSelectable {...propsMultipleCases} />);
renderWithTestingProviders(<EditTagsSelectable {...propsMultipleCases} />);
for (const [tag, icon] of [
['one', 'check'],
@ -84,15 +81,15 @@ describe('EditTagsSelectable', () => {
['pepsi', 'asterisk'],
]) {
const iconDataTestSubj = `cases-actions-tags-edit-selectable-tag-${tag}-icon-${icon}`;
expect(result.getByTestId(iconDataTestSubj)).toBeInTheDocument();
expect(screen.getByTestId(iconDataTestSubj)).toBeInTheDocument();
}
});
it('selects and unselects correctly tags with one case', async () => {
const result = appMock.render(<EditTagsSelectable {...props} />);
renderWithTestingProviders(<EditTagsSelectable {...props} />);
for (const tag of props.tags) {
await userEvent.click(result.getByText(tag));
await userEvent.click(screen.getByText(tag));
}
expect(props.onChangeTags).toBeCalledTimes(props.tags.length);
@ -103,10 +100,10 @@ describe('EditTagsSelectable', () => {
});
it('selects and unselects correctly tags with multiple cases', async () => {
const result = appMock.render(<EditTagsSelectable {...propsMultipleCases} />);
renderWithTestingProviders(<EditTagsSelectable {...propsMultipleCases} />);
for (const tag of propsMultipleCases.tags) {
await userEvent.click(result.getByText(tag));
await userEvent.click(screen.getByText(tag));
}
expect(propsMultipleCases.onChangeTags).toBeCalledTimes(propsMultipleCases.tags.length);
@ -117,10 +114,10 @@ describe('EditTagsSelectable', () => {
});
it('renders the icons correctly after selecting and deselecting tags', async () => {
const result = appMock.render(<EditTagsSelectable {...propsMultipleCases} />);
renderWithTestingProviders(<EditTagsSelectable {...propsMultipleCases} />);
for (const tag of propsMultipleCases.tags) {
await userEvent.click(result.getByText(tag));
await userEvent.click(screen.getByText(tag));
}
for (const [tag, icon] of [
@ -131,7 +128,7 @@ describe('EditTagsSelectable', () => {
['pepsi', 'check'],
]) {
const iconDataTestSubj = `cases-actions-tags-edit-selectable-tag-${tag}-icon-${icon}`;
expect(result.getByTestId(iconDataTestSubj)).toBeInTheDocument();
expect(screen.getByTestId(iconDataTestSubj)).toBeInTheDocument();
}
expect(propsMultipleCases.onChangeTags).toBeCalledTimes(propsMultipleCases.tags.length);
@ -142,17 +139,17 @@ describe('EditTagsSelectable', () => {
});
it('adds a new tag correctly', async () => {
const result = appMock.render(<EditTagsSelectable {...props} />);
renderWithTestingProviders(<EditTagsSelectable {...props} />);
await userEvent.type(result.getByPlaceholderText('Search'), 'not-exist', { delay: 1 });
await userEvent.type(screen.getByPlaceholderText('Search'), 'not-exist', { delay: 1 });
await waitFor(() => {
expect(
result.getByTestId('cases-actions-tags-edit-selectable-add-new-tag')
screen.getByTestId('cases-actions-tags-edit-selectable-add-new-tag')
).toBeInTheDocument();
});
const addNewTagButton = result.getByTestId('cases-actions-tags-edit-selectable-add-new-tag');
const addNewTagButton = screen.getByTestId('cases-actions-tags-edit-selectable-add-new-tag');
await userEvent.click(addNewTagButton);
@ -164,10 +161,10 @@ describe('EditTagsSelectable', () => {
});
it('selects all tags correctly', async () => {
const result = appMock.render(<EditTagsSelectable {...propsMultipleCases} />);
renderWithTestingProviders(<EditTagsSelectable {...propsMultipleCases} />);
expect(result.getByText('Select all')).toBeInTheDocument();
await userEvent.click(result.getByText('Select all'));
expect(screen.getByText('Select all')).toBeInTheDocument();
await userEvent.click(screen.getByText('Select all'));
expect(propsMultipleCases.onChangeTags).toBeCalledTimes(1);
expect(propsMultipleCases.onChangeTags).nthCalledWith(1, {
@ -177,10 +174,10 @@ describe('EditTagsSelectable', () => {
});
it('unselects all tags correctly', async () => {
const result = appMock.render(<EditTagsSelectable {...propsMultipleCases} />);
renderWithTestingProviders(<EditTagsSelectable {...propsMultipleCases} />);
expect(result.getByText('Select all')).toBeInTheDocument();
await userEvent.click(result.getByText('Select none'));
expect(screen.getByText('Select all')).toBeInTheDocument();
await userEvent.click(screen.getByText('Select none'));
expect(propsMultipleCases.onChangeTags).toBeCalledTimes(1);
expect(propsMultipleCases.onChangeTags).nthCalledWith(1, {
@ -190,24 +187,24 @@ describe('EditTagsSelectable', () => {
});
it('unselects correctly with the new item presented', async () => {
const result = appMock.render(<EditTagsSelectable {...propsMultipleCases} />);
renderWithTestingProviders(<EditTagsSelectable {...propsMultipleCases} />);
/**
* Tag with label "one" exist. Searching for "on" will show both the
* "add new tag" item and the "one" tag
*/
await userEvent.type(result.getByPlaceholderText('Search'), 'on', { delay: 1 });
await userEvent.type(screen.getByPlaceholderText('Search'), 'on', { delay: 1 });
await waitFor(() => {
expect(
result.getByTestId('cases-actions-tags-edit-selectable-add-new-tag')
screen.getByTestId('cases-actions-tags-edit-selectable-add-new-tag')
).toBeInTheDocument();
});
const iconDataTestSubj = 'cases-actions-tags-edit-selectable-tag-one-icon-check';
expect(result.getByTestId(iconDataTestSubj)).toBeInTheDocument();
expect(screen.getByTestId(iconDataTestSubj)).toBeInTheDocument();
await userEvent.click(result.getByTestId(iconDataTestSubj));
await userEvent.click(screen.getByTestId(iconDataTestSubj));
expect(propsMultipleCases.onChangeTags).toBeCalledTimes(1);
expect(propsMultipleCases.onChangeTags).nthCalledWith(1, {
@ -217,25 +214,25 @@ describe('EditTagsSelectable', () => {
});
it('adds a partial match correctly and does not show the no match label', async () => {
const result = appMock.render(<EditTagsSelectable {...props} />);
renderWithTestingProviders(<EditTagsSelectable {...props} />);
/**
* Tag with label "one" exist. Searching for "on" will show both the
* "add new tag" item and the "one" tag
*/
await userEvent.type(result.getByPlaceholderText('Search'), 'on', { delay: 1 });
await userEvent.type(screen.getByPlaceholderText('Search'), 'on', { delay: 1 });
await waitFor(() => {
expect(
result.getByTestId('cases-actions-tags-edit-selectable-add-new-tag')
screen.getByTestId('cases-actions-tags-edit-selectable-add-new-tag')
).toBeInTheDocument();
});
expect(
result.queryByTestId('cases-actions-tags-edit-selectable-no-match-label')
screen.queryByTestId('cases-actions-tags-edit-selectable-no-match-label')
).not.toBeInTheDocument();
const addNewTagButton = result.getByTestId('cases-actions-tags-edit-selectable-add-new-tag');
const addNewTagButton = screen.getByTestId('cases-actions-tags-edit-selectable-add-new-tag');
await userEvent.click(addNewTagButton);
@ -247,46 +244,46 @@ describe('EditTagsSelectable', () => {
});
it('do not show the new item option on exact match', async () => {
const result = appMock.render(<EditTagsSelectable {...props} />);
renderWithTestingProviders(<EditTagsSelectable {...props} />);
await userEvent.type(result.getByPlaceholderText('Search'), 'one', { delay: 1 });
await userEvent.type(screen.getByPlaceholderText('Search'), 'one', { delay: 1 });
expect(
result.queryByTestId('cases-actions-tags-edit-selectable-add-new-tag')
screen.queryByTestId('cases-actions-tags-edit-selectable-add-new-tag')
).not.toBeInTheDocument();
});
it('does not show the no match label when the initial tags are empty', async () => {
const result = appMock.render(<EditTagsSelectable {...props} tags={[]} />);
renderWithTestingProviders(<EditTagsSelectable {...props} tags={[]} />);
expect(
result.queryByTestId('cases-actions-tags-edit-selectable-no-match-label')
screen.queryByTestId('cases-actions-tags-edit-selectable-no-match-label')
).not.toBeInTheDocument();
});
it('shows the no match label when there is no match', async () => {
const result = appMock.render(<EditTagsSelectable {...props} />);
renderWithTestingProviders(<EditTagsSelectable {...props} />);
await userEvent.type(result.getByPlaceholderText('Search'), 'not-exist', { delay: 1 });
await userEvent.type(screen.getByPlaceholderText('Search'), 'not-exist', { delay: 1 });
expect(
result.getByTestId('cases-actions-tags-edit-selectable-no-match-label')
screen.getByTestId('cases-actions-tags-edit-selectable-no-match-label')
).toBeInTheDocument();
});
it('shows the no match label and the add new item when there is space in the search term', async () => {
const result = appMock.render(<EditTagsSelectable {...props} />);
renderWithTestingProviders(<EditTagsSelectable {...props} />);
await userEvent.type(result.getByPlaceholderText('Search'), 'test tag', { delay: 1 });
await userEvent.type(screen.getByPlaceholderText('Search'), 'test tag', { delay: 1 });
await waitFor(() => {
expect(
result.getByTestId('cases-actions-tags-edit-selectable-add-new-tag')
screen.getByTestId('cases-actions-tags-edit-selectable-add-new-tag')
).toBeInTheDocument();
});
expect(
result.getByTestId('cases-actions-tags-edit-selectable-no-match-label')
screen.getByTestId('cases-actions-tags-edit-selectable-no-match-label')
).toBeInTheDocument();
});
});

View file

@ -5,23 +5,22 @@
* 2.0.
*/
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
import { act, waitFor, renderHook } from '@testing-library/react';
import { useTagsAction } from './use_tags_action';
import * as api from '../../../containers/api';
import { basicCase } from '../../../containers/mock';
import { TestProviders } from '../../../common/mock';
import { coreMock } from '@kbn/core/public/mocks';
import React from 'react';
jest.mock('../../../containers/api');
describe('useTagsAction', () => {
let appMockRender: AppMockRenderer;
const onAction = jest.fn();
const onActionSuccess = jest.fn();
beforeEach(() => {
appMockRender = createAppMockRenderer();
jest.clearAllMocks();
});
@ -34,7 +33,7 @@ describe('useTagsAction', () => {
isDisabled: false,
}),
{
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
}
);
@ -59,7 +58,7 @@ describe('useTagsAction', () => {
const { result } = renderHook(
() => useTagsAction({ onAction, onActionSuccess, isDisabled: false }),
{
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
}
);
@ -78,18 +77,20 @@ describe('useTagsAction', () => {
await waitFor(() => {
expect(result.current.isFlyoutOpen).toBe(false);
expect(onActionSuccess).toHaveBeenCalled();
expect(updateSpy).toHaveBeenCalledWith({
cases: [{ tags: ['coke', 'one'], id: basicCase.id, version: basicCase.version }],
});
});
expect(onActionSuccess).toHaveBeenCalled();
expect(updateSpy).toHaveBeenCalledWith({
cases: [{ tags: ['coke', 'one'], id: basicCase.id, version: basicCase.version }],
});
});
it('shows the success toaster correctly when updating one case', async () => {
const coreStart = coreMock.createStart();
const { result } = renderHook(
() => useTagsAction({ onAction, onActionSuccess, isDisabled: false }),
{
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} coreStart={coreStart} />,
}
);
@ -104,7 +105,7 @@ describe('useTagsAction', () => {
});
await waitFor(() => {
expect(appMockRender.coreStart.notifications.toasts.addSuccess).toHaveBeenCalledWith({
expect(coreStart.notifications.toasts.addSuccess).toHaveBeenCalledWith({
title: 'Edited case',
className: 'eui-textBreakWord',
});
@ -112,10 +113,11 @@ describe('useTagsAction', () => {
});
it('shows the success toaster correctly when updating multiple cases', async () => {
const coreStart = coreMock.createStart();
const { result } = renderHook(
() => useTagsAction({ onAction, onActionSuccess, isDisabled: false }),
{
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} coreStart={coreStart} />,
}
);
@ -130,7 +132,7 @@ describe('useTagsAction', () => {
});
await waitFor(() => {
expect(appMockRender.coreStart.notifications.toasts.addSuccess).toHaveBeenCalledWith({
expect(coreStart.notifications.toasts.addSuccess).toHaveBeenCalledWith({
title: 'Edited 2 cases',
className: 'eui-textBreakWord',
});

View file

@ -5,22 +5,22 @@
* 2.0.
*/
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
import { act, waitFor, renderHook } from '@testing-library/react';
import { useItemsAction } from './use_items_action';
import * as api from '../../containers/api';
import { basicCase } from '../../containers/mock';
import { TestProviders } from '../../common/mock';
import React from 'react';
import { coreMock } from '@kbn/core/public/mocks';
jest.mock('../../containers/api');
describe('useItemsAction', () => {
let appMockRender: AppMockRenderer;
const onAction = jest.fn();
const onActionSuccess = jest.fn();
const successToasterTitle = jest.fn().mockReturnValue('My toaster title');
const fieldSelector = jest.fn().mockReturnValue(basicCase.tags);
const fieldSelector = jest.fn().mockImplementation((item) => item.tags);
const itemsTransformer = jest.fn().mockImplementation((items) => items);
const props = {
@ -34,14 +34,13 @@ describe('useItemsAction', () => {
};
beforeEach(() => {
appMockRender = createAppMockRenderer();
jest.clearAllMocks();
});
describe('flyout', () => {
it('opens the flyout', async () => {
const { result } = renderHook(() => useItemsAction(props), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
expect(result.current.isFlyoutOpen).toBe(false);
@ -55,7 +54,7 @@ describe('useItemsAction', () => {
it('closes the flyout', async () => {
const { result } = renderHook(() => useItemsAction(props), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
expect(result.current.isFlyoutOpen).toBe(false);
@ -72,8 +71,9 @@ describe('useItemsAction', () => {
await waitFor(() => {
expect(result.current.isFlyoutOpen).toBe(false);
expect(onAction).toHaveBeenCalled();
});
expect(onAction).toHaveBeenCalled();
});
});
@ -82,7 +82,7 @@ describe('useItemsAction', () => {
const updateSpy = jest.spyOn(api, 'updateCases');
const { result } = renderHook(() => useItemsAction(props), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
act(() => {
@ -101,24 +101,25 @@ describe('useItemsAction', () => {
await waitFor(() => {
expect(result.current.isFlyoutOpen).toBe(false);
expect(onActionSuccess).toHaveBeenCalled();
expect(fieldSelector).toHaveBeenCalled();
expect(itemsTransformer).toHaveBeenCalled();
expect(updateSpy).toHaveBeenCalledWith({
cases: [
{
[props.fieldKey]: ['coke', 'one'],
id: basicCase.id,
version: basicCase.version,
},
],
});
});
expect(onActionSuccess).toHaveBeenCalled();
expect(fieldSelector).toHaveBeenCalled();
expect(itemsTransformer).toHaveBeenCalled();
expect(updateSpy).toHaveBeenCalledWith({
cases: [
{
[props.fieldKey]: ['coke', 'one'],
id: basicCase.id,
version: basicCase.version,
},
],
});
});
it('calls fieldSelector correctly', async () => {
const { result } = renderHook(() => useItemsAction(props), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
act(() => {
@ -137,13 +138,14 @@ describe('useItemsAction', () => {
await waitFor(() => {
expect(result.current.isFlyoutOpen).toBe(false);
expect(fieldSelector).toHaveBeenCalledWith(basicCase);
});
expect(fieldSelector).toHaveBeenCalledWith(basicCase);
});
it('calls itemsTransformer correctly', async () => {
const { result } = renderHook(() => useItemsAction(props), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
act(() => {
@ -162,15 +164,16 @@ describe('useItemsAction', () => {
await waitFor(() => {
expect(result.current.isFlyoutOpen).toBe(false);
expect(itemsTransformer).toHaveBeenCalledWith(['coke', 'one']);
});
expect(itemsTransformer).toHaveBeenCalledWith(['coke', 'one']);
});
it('removes duplicates', async () => {
const updateSpy = jest.spyOn(api, 'updateCases');
const { result } = renderHook(() => useItemsAction(props), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
act(() => {
@ -189,22 +192,25 @@ describe('useItemsAction', () => {
await waitFor(() => {
expect(result.current.isFlyoutOpen).toBe(false);
expect(onActionSuccess).toHaveBeenCalled();
expect(updateSpy).toHaveBeenCalledWith({
cases: [
{
[props.fieldKey]: ['coke', 'one'],
id: basicCase.id,
version: basicCase.version,
},
],
});
});
expect(onActionSuccess).toHaveBeenCalled();
expect(updateSpy).toHaveBeenCalledWith({
cases: [
{
[props.fieldKey]: ['coke', 'one'],
id: basicCase.id,
version: basicCase.version,
},
],
});
});
it('shows the success toaster correctly when updating a case', async () => {
const coreStart = coreMock.createStart();
const { result } = renderHook(() => useItemsAction(props), {
wrapper: appMockRender.AppWrapper,
wrapper: (wrapperProps) => <TestProviders {...wrapperProps} coreStart={coreStart} />,
});
act(() => {
@ -219,7 +225,7 @@ describe('useItemsAction', () => {
});
await waitFor(() => {
expect(appMockRender.coreStart.notifications.toasts.addSuccess).toHaveBeenCalledWith({
expect(coreStart.notifications.toasts.addSuccess).toHaveBeenCalledWith({
title: 'My toaster title',
className: 'eui-textBreakWord',
});
@ -230,7 +236,7 @@ describe('useItemsAction', () => {
const updateSpy = jest.spyOn(api, 'updateCases');
const { result } = renderHook(() => useItemsAction(props), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
act(() => {
@ -246,16 +252,17 @@ describe('useItemsAction', () => {
await waitFor(() => {
expect(result.current.isFlyoutOpen).toBe(false);
expect(onActionSuccess).not.toHaveBeenCalled();
expect(updateSpy).not.toHaveBeenCalled();
});
expect(onActionSuccess).toHaveBeenCalled();
expect(updateSpy).toHaveBeenCalledWith({ cases: [] });
});
it('do not update if the selected items are the same but with different order', async () => {
const updateSpy = jest.spyOn(api, 'updateCases');
const { result } = renderHook(() => useItemsAction(props), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
act(() => {
@ -271,16 +278,17 @@ describe('useItemsAction', () => {
await waitFor(() => {
expect(result.current.isFlyoutOpen).toBe(false);
expect(onActionSuccess).not.toHaveBeenCalled();
expect(updateSpy).not.toHaveBeenCalled();
});
expect(onActionSuccess).toHaveBeenCalled();
expect(updateSpy).toHaveBeenCalledWith({ cases: [] });
});
it('do not update if the selected items are the same', async () => {
const updateSpy = jest.spyOn(api, 'updateCases');
const { result } = renderHook(() => useItemsAction(props), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
act(() => {
@ -296,16 +304,17 @@ describe('useItemsAction', () => {
await waitFor(() => {
expect(result.current.isFlyoutOpen).toBe(false);
expect(onActionSuccess).not.toHaveBeenCalled();
expect(updateSpy).not.toHaveBeenCalled();
});
expect(onActionSuccess).toHaveBeenCalled();
expect(updateSpy).toHaveBeenCalledWith({ cases: [] });
});
it('do not update if selecting and unselecting the same item', async () => {
const updateSpy = jest.spyOn(api, 'updateCases');
const { result } = renderHook(() => useItemsAction(props), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
act(() => {
@ -321,16 +330,17 @@ describe('useItemsAction', () => {
await waitFor(() => {
expect(result.current.isFlyoutOpen).toBe(false);
expect(onActionSuccess).not.toHaveBeenCalled();
expect(updateSpy).not.toHaveBeenCalled();
});
expect(onActionSuccess).toHaveBeenCalled();
expect(updateSpy).toHaveBeenCalledWith({ cases: [] });
});
it('do not update with empty items and no selection', async () => {
const updateSpy = jest.spyOn(api, 'updateCases');
const { result } = renderHook(() => useItemsAction(props), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
act(() => {
@ -346,9 +356,10 @@ describe('useItemsAction', () => {
await waitFor(() => {
expect(result.current.isFlyoutOpen).toBe(false);
expect(onActionSuccess).not.toHaveBeenCalled();
expect(updateSpy).not.toHaveBeenCalled();
});
expect(onActionSuccess).toHaveBeenCalled();
expect(updateSpy).toHaveBeenCalledWith({ cases: [] });
});
});
});

View file

@ -5,16 +5,14 @@
* 2.0.
*/
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
import { renderHook, act } from '@testing-library/react';
import { useItemsState } from './use_items_state';
import { basicCase } from '../../containers/mock';
import type { ItemSelectableOption } from './types';
import { TestProviders } from '../../common/mock';
describe('useItemsState', () => {
let appMockRender: AppMockRenderer;
const onChangeItems = jest.fn();
const fieldSelector = jest.fn();
const itemToSelectableOption = jest
@ -30,7 +28,6 @@ describe('useItemsState', () => {
};
beforeEach(() => {
appMockRender = createAppMockRenderer();
fieldSelector.mockReturnValueOnce(['one', 'two']);
fieldSelector.mockReturnValueOnce(['one', 'three']);
jest.clearAllMocks();
@ -38,7 +35,7 @@ describe('useItemsState', () => {
it('inits the state correctly', async () => {
const { result } = renderHook(() => useItemsState(props), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
expect(result.current.state).toMatchInlineSnapshot(`
@ -84,7 +81,7 @@ describe('useItemsState', () => {
it('inits the options correctly', async () => {
const { result } = renderHook(() => useItemsState(props), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
expect(result.current.options).toMatchInlineSnapshot(`
@ -128,7 +125,7 @@ describe('useItemsState', () => {
it('inits the totalSelectedItems correctly', async () => {
const { result } = renderHook(() => useItemsState(props), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
expect(result.current.totalSelectedItems).toBe(3);
@ -136,7 +133,7 @@ describe('useItemsState', () => {
it('selects all items correctly', async () => {
const { result } = renderHook(() => useItemsState(props), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
act(() => {
@ -234,7 +231,7 @@ describe('useItemsState', () => {
it('unselects all items correctly', async () => {
const { result } = renderHook(() => useItemsState(props), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
act(() => {
@ -328,7 +325,7 @@ describe('useItemsState', () => {
it('selects and unselects correctly', async () => {
const { result } = renderHook(() => useItemsState(props), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
const newOptions = [
@ -425,7 +422,7 @@ describe('useItemsState', () => {
it('changes the label of the new item correctly', async () => {
const { result } = renderHook(() => useItemsState(props), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
const newOptions = [
@ -445,7 +442,7 @@ describe('useItemsState', () => {
it('keeps the data of the option', async () => {
const { result } = renderHook(() => useItemsState(props), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
const newOptions = [
@ -473,7 +470,7 @@ describe('useItemsState', () => {
it('does not add the new item as unselected', async () => {
const { result } = renderHook(() => useItemsState(props), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
const newOptions = [
@ -493,7 +490,7 @@ describe('useItemsState', () => {
it('does not add non dirty items as unselected', async () => {
const { result } = renderHook(() => useItemsState(props), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
const newOptions = [{ key: 'two', label: 'two', checked: 'on' }] as ItemSelectableOption[];
@ -514,7 +511,7 @@ describe('useItemsState', () => {
it('calls itemToSelectableOption correctly', async () => {
renderHook(() => useItemsState(props), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
expect(itemToSelectableOption).toHaveBeenNthCalledWith(1, {
@ -535,7 +532,7 @@ describe('useItemsState', () => {
it('calls itemToSelectableOption with data correctly', async () => {
const { result } = renderHook(() => useItemsState(props), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
const newOptions = [
@ -558,7 +555,7 @@ describe('useItemsState', () => {
}));
const { result } = renderHook(() => useItemsState(props), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
for (const option of result.current.options) {
@ -575,7 +572,7 @@ describe('useItemsState', () => {
const validIcons = ['check', 'asterisk', 'empty'];
const { result } = renderHook(() => useItemsState(props), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
for (const option of result.current.options) {
@ -586,7 +583,7 @@ describe('useItemsState', () => {
it('calls fieldSelector correctly', async () => {
renderHook(() => useItemsState(props), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
expect(fieldSelector).toHaveBeenCalledWith(basicCase);

View file

@ -13,8 +13,7 @@ import { noop } from 'lodash/fp';
import {
onlyCreateCommentPermissions,
noCreateCommentCasesPermissions,
TestProviders,
createAppMockRenderer,
renderWithTestingProviders,
} from '../../common/mock';
import { AttachmentType } from '../../../common/types/domain';
@ -25,7 +24,7 @@ import { AddComment } from '.';
import { CasesTimelineIntegrationProvider } from '../timeline_context';
import { timelineIntegrationMock } from '../__mock__/timeline';
import type { CaseAttachmentWithoutOwner } from '../../types';
import type { AppMockRenderer } from '../../common/mock';
import { useCreateAttachments } from '../../containers/use_create_attachments';
jest.mock('../../containers/use_create_attachments');
@ -59,11 +58,9 @@ const appId = 'securitySolution';
const draftKey = `cases.${appId}.${addCommentProps.caseId}.${addCommentProps.id}.markdownEditor`;
describe('AddComment ', () => {
let appMockRender: AppMockRenderer;
beforeEach(() => {
jest.clearAllMocks();
appMockRender = createAppMockRenderer();
useCreateAttachmentsMock.mockReturnValue({
isLoading: false,
mutate: createAttachmentsMock,
@ -75,7 +72,7 @@ describe('AddComment ', () => {
});
it('renders correctly', () => {
appMockRender.render(<AddComment {...addCommentProps} />);
renderWithTestingProviders(<AddComment {...addCommentProps} />);
expect(screen.getByTestId('add-comment')).toBeInTheDocument();
});
@ -86,7 +83,7 @@ describe('AddComment ', () => {
mutateAsync: createAttachmentsMock,
});
appMockRender.render(<AddComment {...{ ...addCommentProps, showLoading: true }} />);
renderWithTestingProviders(<AddComment {...{ ...addCommentProps, showLoading: true }} />);
fireEvent.change(screen.getByLabelText('caseComment'), {
target: { value: sampleData.comment },
@ -104,11 +101,9 @@ describe('AddComment ', () => {
isLoading: true,
}));
appMockRender.render(
<TestProviders permissions={noCreateCommentCasesPermissions()}>
<AddComment {...{ ...addCommentProps }} />
</TestProviders>
);
renderWithTestingProviders(<AddComment {...{ ...addCommentProps }} />, {
wrapperProps: { permissions: noCreateCommentCasesPermissions() },
});
expect(screen.queryByTestId('loading-spinner')).not.toBeInTheDocument();
expect(screen.queryByTestId('add-comment-form-wrapper')).not.toBeInTheDocument();
@ -120,18 +115,16 @@ describe('AddComment ', () => {
isLoading: true,
}));
appMockRender.render(
<TestProviders permissions={onlyCreateCommentPermissions()}>
<AddComment {...{ ...addCommentProps }} />
</TestProviders>
);
renderWithTestingProviders(<AddComment {...{ ...addCommentProps }} />, {
wrapperProps: { permissions: onlyCreateCommentPermissions() },
});
expect(screen.queryByTestId('loading-spinner')).not.toBeInTheDocument();
expect(screen.queryByTestId('add-comment-form-wrapper')).toBeInTheDocument();
expect(screen.getByTestId('add-comment-form-wrapper')).toBeInTheDocument();
});
it('should post comment on submit click', async () => {
appMockRender.render(<AddComment {...addCommentProps} />);
renderWithTestingProviders(<AddComment {...addCommentProps} />);
const markdown = screen.getByTestId('euiMarkdownEditorTextArea');
await userEvent.type(markdown, sampleData.comment);
@ -163,7 +156,7 @@ describe('AddComment ', () => {
const sampleQuote = 'what a cool quote \n with new lines';
const ref = React.createRef<AddCommentRefObject>();
appMockRender.render(<AddComment {...addCommentProps} ref={ref} />);
renderWithTestingProviders(<AddComment {...addCommentProps} ref={ref} />);
await userEvent.click(await screen.findByTestId('euiMarkdownEditorTextArea'));
await userEvent.paste(sampleData.comment);
@ -187,7 +180,7 @@ describe('AddComment ', () => {
const mockTimelineIntegration = { ...timelineIntegrationMock };
mockTimelineIntegration.hooks.useInsertTimeline = useInsertTimelineMock;
appMockRender.render(
renderWithTestingProviders(
<CasesTimelineIntegrationProvider timelineIntegration={mockTimelineIntegration}>
<AddComment {...addCommentProps} />
</CasesTimelineIntegrationProvider>
@ -204,60 +197,52 @@ describe('AddComment ', () => {
describe('errors', () => {
it('shows an error when comment is empty', async () => {
appMockRender.render(<AddComment {...addCommentProps} />);
renderWithTestingProviders(<AddComment {...addCommentProps} />);
const markdown = screen.getByTestId('euiMarkdownEditorTextArea');
await userEvent.type(markdown, 'test');
await userEvent.clear(markdown);
await waitFor(() => {
expect(screen.getByText('Empty comments are not allowed.')).toBeInTheDocument();
expect(screen.getByTestId('submit-comment')).toHaveAttribute('disabled');
});
expect(await screen.findByText('Empty comments are not allowed.')).toBeInTheDocument();
expect(screen.getByTestId('submit-comment')).toHaveAttribute('disabled');
});
it('shows an error when comment is of empty characters', async () => {
appMockRender.render(<AddComment {...addCommentProps} />);
renderWithTestingProviders(<AddComment {...addCommentProps} />);
const markdown = screen.getByTestId('euiMarkdownEditorTextArea');
await userEvent.clear(markdown);
await userEvent.type(markdown, ' ');
await waitFor(() => {
expect(screen.getByText('Empty comments are not allowed.')).toBeInTheDocument();
expect(screen.getByTestId('submit-comment')).toHaveAttribute('disabled');
});
expect(await screen.findByText('Empty comments are not allowed.')).toBeInTheDocument();
expect(screen.getByTestId('submit-comment')).toHaveAttribute('disabled');
});
it('shows an error when comment is too long', async () => {
const longComment = 'a'.repeat(MAX_COMMENT_LENGTH + 1);
appMockRender.render(<AddComment {...addCommentProps} />);
renderWithTestingProviders(<AddComment {...addCommentProps} />);
const markdown = screen.getByTestId('euiMarkdownEditorTextArea');
await userEvent.click(markdown);
await userEvent.paste(longComment);
await waitFor(() => {
expect(
screen.getByText(
'The length of the comment is too long. The maximum length is 30000 characters.'
)
).toBeInTheDocument();
expect(screen.getByTestId('submit-comment')).toHaveAttribute('disabled');
});
expect(
await screen.findByText(
'The length of the comment is too long. The maximum length is 30000 characters.'
)
).toBeInTheDocument();
expect(screen.getByTestId('submit-comment')).toHaveAttribute('disabled');
});
});
});
describe('draft comment ', () => {
let appMockRenderer: AppMockRenderer;
beforeEach(() => {
appMockRenderer = createAppMockRenderer();
jest.clearAllMocks();
});
@ -274,7 +259,7 @@ describe('draft comment ', () => {
});
it('should clear session storage on submit', async () => {
appMockRenderer.render(<AddComment {...addCommentProps} />);
renderWithTestingProviders(<AddComment {...addCommentProps} />);
fireEvent.change(screen.getByLabelText('caseComment'), {
target: { value: sampleData.comment },
@ -292,25 +277,27 @@ describe('draft comment ', () => {
await waitFor(() => {
expect(onCommentSaving).toBeCalled();
expect(createAttachmentsMock).toBeCalledWith(
{
caseId: addCommentProps.caseId,
attachments: [
{
comment: sampleData.comment,
type: AttachmentType.user,
},
],
caseOwner: SECURITY_SOLUTION_OWNER,
},
{ onSuccess: expect.any(Function) }
);
});
expect(createAttachmentsMock).toBeCalledWith(
{
caseId: addCommentProps.caseId,
attachments: [
{
comment: sampleData.comment,
type: AttachmentType.user,
},
],
caseOwner: SECURITY_SOLUTION_OWNER,
},
{ onSuccess: expect.any(Function) }
);
await waitFor(() => {
expect(screen.getByLabelText('caseComment').textContent).toBe('');
expect(sessionStorage.getItem(draftKey)).toBe('');
});
expect(screen.getByLabelText('caseComment').textContent).toBe('');
});
describe('existing storage key', () => {
@ -323,7 +310,7 @@ describe('draft comment ', () => {
});
it('should have draft comment same as existing session storage', async () => {
appMockRenderer.render(<AddComment {...addCommentProps} />);
renderWithTestingProviders(<AddComment {...addCommentProps} />);
expect(screen.getByLabelText('caseComment')).toHaveValue('value set in storage');
});

View file

@ -7,23 +7,22 @@
import React from 'react';
import moment from 'moment-timezone';
import { render, waitFor, screen, within, renderHook } from '@testing-library/react';
import { waitFor, screen, within, renderHook } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl';
import type { AppMockRenderer } from '../../common/mock';
import {
createAppMockRenderer,
TestProviders,
noCreateCasesPermissions,
noDeleteCasesPermissions,
readCasesPermissions,
TestProviders,
renderWithTestingProviders,
} from '../../common/mock';
import { useGetCasesMockState, connectorsMock } from '../../containers/mock';
import { SortFieldCase } from '../../../common/ui/types';
import { CaseSeverity, CaseStatuses } from '../../../common/types/domain';
import { SECURITY_SOLUTION_OWNER } from '../../../common/constants';
import { getEmptyCellValue } from '../empty_value';
import { useKibana } from '../../common/lib/kibana';
import { AllCasesList } from './all_cases_list';
import { useCasesColumns } from './use_cases_columns';
@ -128,13 +127,10 @@ const patchGetComputedStyle = () => {
});
};
// FLAKY: https://github.com/elastic/kibana/issues/192739
describe.skip('AllCasesListGeneric', () => {
describe('AllCasesListGeneric', () => {
const onRowClick = jest.fn();
const updateCaseProperty = jest.fn();
const emptyTag = getEmptyCellValue().props.children;
const defaultGetCases = {
...useGetCasesMockState,
};
@ -152,8 +148,6 @@ describe.skip('AllCasesListGeneric', () => {
const removeMsFromDate = (value: string) => moment(value).format('YYYY-MM-DDTHH:mm:ss[Z]');
let appMockRenderer: AppMockRenderer;
beforeAll(() => {
patchGetComputedStyle();
mockKibana();
@ -167,7 +161,7 @@ describe.skip('AllCasesListGeneric', () => {
beforeEach(() => {
jest.clearAllMocks();
appMockRenderer = createAppMockRenderer();
useGetCasesMock.mockReturnValue(defaultGetCases);
useGetTagsMock.mockReturnValue({ data: ['coke', 'pepsi'], isLoading: false });
useGetCategoriesMock.mockReturnValue({ data: ['twix', 'snickers'], isLoading: false });
@ -189,7 +183,7 @@ describe.skip('AllCasesListGeneric', () => {
it('should render AllCasesList', async () => {
useLicenseMock.mockReturnValue({ isAtLeastPlatinum: () => true });
appMockRenderer.render(<AllCasesList />);
renderWithTestingProviders(<AllCasesList />);
const caseDetailsLinks = await screen.findAllByTestId('case-details-link');
@ -198,15 +192,20 @@ describe.skip('AllCasesListGeneric', () => {
expect(
(await screen.findAllByTestId('case-user-profile-avatar-damaged_raccoon'))[0]
).toHaveTextContent('DR');
expect((await screen.findAllByTestId('case-table-column-tags-coke'))[0]).toHaveAttribute(
'title',
useGetCasesMockState.data.cases[0].tags[0]
);
const createdAtColumn = screen.getAllByTestId('case-table-column-createdAt')[0];
expect(
(await screen.findAllByTestId('case-table-column-createdAt'))[0].querySelector(
'.euiToolTipAnchor'
within(createdAtColumn).getByText(
removeMsFromDate(useGetCasesMockState.data.cases[0].createdAt)
)
).toHaveTextContent(removeMsFromDate(useGetCasesMockState.data.cases[0].createdAt));
).toBeInTheDocument();
expect(await screen.findByTestId('case-table-case-count')).toHaveTextContent(
`Showing 10 of ${useGetCasesMockState.data.total} cases`
);
@ -218,7 +217,7 @@ describe.skip('AllCasesListGeneric', () => {
it("should show a tooltip with the assignee's email when hover over the assignee avatar", async () => {
useLicenseMock.mockReturnValue({ isAtLeastPlatinum: () => true });
appMockRenderer.render(<AllCasesList />);
renderWithTestingProviders(<AllCasesList />);
await userEvent.hover(
(
@ -230,7 +229,7 @@ describe.skip('AllCasesListGeneric', () => {
});
it('should show a tooltip with all tags when hovered', async () => {
appMockRenderer.render(<AllCasesList />);
renderWithTestingProviders(<AllCasesList />);
await userEvent.hover((await screen.findAllByTestId('case-table-column-tags'))[0]);
@ -261,16 +260,13 @@ describe.skip('AllCasesListGeneric', () => {
},
});
appMockRenderer.render(<AllCasesList />);
renderWithTestingProviders(<AllCasesList />);
const checkIt = async (columnName: string, key: number) => {
const column = (await screen.findByTestId('cases-table')).querySelectorAll(
'tbody .euiTableRowCell'
);
expect(column[key].querySelector('.euiTableRowCell--hideForDesktop')).toHaveTextContent(
columnName
);
expect(column[key].querySelector('span')).toHaveTextContent(emptyTag);
const column = screen.getByText(columnName);
expect(column).toBeInTheDocument();
expect(within(column).getByText('-')).toBeInTheDocument();
};
const { result } = renderHook(() => useCasesColumns(defaultColumnArgs), {
@ -292,7 +288,7 @@ describe.skip('AllCasesListGeneric', () => {
cases: [],
},
});
appMockRenderer.render(<AllCasesList isSelectorView={false} />);
renderWithTestingProviders(<AllCasesList isSelectorView={false} />);
await userEvent.click(await screen.findByTestId('cases-table-add-case'));
await waitFor(() => {
expect(onRowClick).not.toHaveBeenCalled();
@ -300,7 +296,7 @@ describe.skip('AllCasesListGeneric', () => {
});
it('should tableHeaderSortButton AllCasesList', async () => {
appMockRenderer.render(<AllCasesList />);
renderWithTestingProviders(<AllCasesList />);
await userEvent.click((await screen.findAllByTestId('tableHeaderSortButton'))[0]);
@ -316,7 +312,7 @@ describe.skip('AllCasesListGeneric', () => {
});
it('renders the columns correctly', async () => {
appMockRenderer.render(<AllCasesList isSelectorView={false} />);
renderWithTestingProviders(<AllCasesList isSelectorView={false} />);
const casesTable = within(await screen.findByTestId('cases-table'));
@ -334,51 +330,60 @@ describe.skip('AllCasesListGeneric', () => {
});
it('should not render table utility bar when isSelectorView=true', async () => {
appMockRenderer.render(<AllCasesList isSelectorView={true} />);
renderWithTestingProviders(<AllCasesList isSelectorView={true} />);
expect(screen.queryByTestId('case-table-selected-case-count')).not.toBeInTheDocument();
expect(screen.queryByTestId('case-table-bulk-actions')).not.toBeInTheDocument();
});
it('should not render table utility bar when the user does not have permissions to delete', async () => {
render(
<TestProviders permissions={noDeleteCasesPermissions()}>
<AllCasesList isSelectorView={true} />
</TestProviders>
);
renderWithTestingProviders(<AllCasesList isSelectorView={true} />, {
wrapperProps: { permissions: noDeleteCasesPermissions() },
});
expect(screen.queryByTestId('case-table-selected-case-count')).not.toBeInTheDocument();
expect(screen.queryByTestId('case-table-bulk-actions')).not.toBeInTheDocument();
});
it('should render metrics when isSelectorView=false', async () => {
appMockRenderer.render(<AllCasesList isSelectorView={false} />);
renderWithTestingProviders(<AllCasesList isSelectorView={false} />);
expect(await screen.findByTestId('cases-metrics-stats')).toBeInTheDocument();
});
it('should not render metrics when isSelectorView=true', async () => {
appMockRenderer.render(<AllCasesList isSelectorView={true} />);
renderWithTestingProviders(<AllCasesList isSelectorView={true} />);
expect(screen.queryByTestId('case-table-selected-case-count')).not.toBeInTheDocument();
expect(screen.queryByTestId('cases-metrics-stats')).not.toBeInTheDocument();
});
it('should call onRowClick with no cases and isSelectorView=true when create case is clicked', async () => {
appMockRenderer.render(<AllCasesList isSelectorView={true} onRowClick={onRowClick} />);
renderWithTestingProviders(<AllCasesList isSelectorView={true} onRowClick={onRowClick} />);
await userEvent.click(await screen.findByTestId('cases-table-add-case-filter-bar'));
const isCreateCase = true;
await waitFor(() => {
expect(onRowClick).toHaveBeenCalled();
expect(onRowClick).toBeCalledWith(undefined, isCreateCase);
});
expect(onRowClick).toBeCalledWith(undefined, isCreateCase);
});
it('should not render the create new case link when the user does not have create privileges', async () => {
renderWithTestingProviders(<AllCasesList />, {
wrapperProps: { permissions: noCreateCasesPermissions() },
});
await screen.findByTestId('cases-table');
expect(screen.queryByTestId('cases-table-add-case')).not.toBeInTheDocument();
});
it('should call onRowClick when clicking a case with modal=true', async () => {
const theCase = defaultGetCases.data.cases[0];
appMockRenderer.render(<AllCasesList isSelectorView={true} onRowClick={onRowClick} />);
renderWithTestingProviders(<AllCasesList isSelectorView={true} onRowClick={onRowClick} />);
await userEvent.click(await screen.findByTestId(`cases-table-row-select-${theCase.id}`));
@ -388,7 +393,7 @@ describe.skip('AllCasesListGeneric', () => {
});
it('should NOT call onRowClick when clicking a case with modal=true', async () => {
appMockRenderer.render(<AllCasesList isSelectorView={false} />);
renderWithTestingProviders(<AllCasesList isSelectorView={false} />);
await userEvent.click(await screen.findByTestId('cases-table-row-1'));
@ -398,7 +403,7 @@ describe.skip('AllCasesListGeneric', () => {
});
it('should sort by status', async () => {
appMockRenderer.render(<AllCasesList isSelectorView={false} />);
renderWithTestingProviders(<AllCasesList isSelectorView={false} />);
// 0 is the status filter button label
await userEvent.click((await screen.findAllByTitle('Status'))[1]);
@ -417,7 +422,7 @@ describe.skip('AllCasesListGeneric', () => {
});
it('should render Name, Category, CreatedOn and Severity columns when isSelectorView=true', async () => {
appMockRenderer.render(<AllCasesList isSelectorView={true} />);
renderWithTestingProviders(<AllCasesList isSelectorView={true} />);
expect(await screen.findByTitle('Name')).toBeInTheDocument();
expect(await screen.findByTitle('Category')).toBeInTheDocument();
@ -427,7 +432,7 @@ describe.skip('AllCasesListGeneric', () => {
});
it('should sort by severity', async () => {
appMockRenderer.render(<AllCasesList isSelectorView={false} />);
renderWithTestingProviders(<AllCasesList isSelectorView={false} />);
// 0 is the severity filter button label
await userEvent.click((await screen.findAllByTitle('Severity'))[1]);
@ -446,7 +451,7 @@ describe.skip('AllCasesListGeneric', () => {
});
it('should sort by title', async () => {
appMockRenderer.render(<AllCasesList isSelectorView={false} />);
renderWithTestingProviders(<AllCasesList isSelectorView={false} />);
await userEvent.click(await screen.findByTitle('Name'));
@ -464,7 +469,7 @@ describe.skip('AllCasesListGeneric', () => {
});
it('should sort by updatedOn', async () => {
appMockRenderer.render(<AllCasesList isSelectorView={false} />);
renderWithTestingProviders(<AllCasesList isSelectorView={false} />);
await userEvent.click(await screen.findByTitle('Updated on'));
@ -482,7 +487,7 @@ describe.skip('AllCasesListGeneric', () => {
});
it('should sort by category', async () => {
appMockRenderer.render(<AllCasesList isSelectorView={false} />);
renderWithTestingProviders(<AllCasesList isSelectorView={false} />);
await userEvent.click(await screen.findByTitle('Category'));
@ -500,7 +505,7 @@ describe.skip('AllCasesListGeneric', () => {
});
it('should filter by category', async () => {
appMockRenderer.render(<AllCasesList isSelectorView={false} />);
renderWithTestingProviders(<AllCasesList isSelectorView={false} />);
await userEvent.click(await screen.findByTestId('options-filter-popover-button-category'));
await waitForEuiPopoverOpen();
@ -519,7 +524,7 @@ describe.skip('AllCasesListGeneric', () => {
});
it('should show the correct count on stats', async () => {
appMockRenderer.render(<AllCasesList isSelectorView={false} />);
renderWithTestingProviders(<AllCasesList isSelectorView={false} />);
await userEvent.click(await screen.findByTestId('options-filter-popover-button-status'));
@ -535,23 +540,21 @@ describe.skip('AllCasesListGeneric', () => {
});
it('shows Solution column if there are no set owners', async () => {
render(
<TestProviders owner={[]}>
<AllCasesList isSelectorView={false} />
</TestProviders>
);
renderWithTestingProviders(<AllCasesList isSelectorView={false} />, {
wrapperProps: { owner: [] },
});
expect((await screen.findAllByText('Solution'))[0]).toBeInTheDocument();
});
it('hides Solution column if there is a set owner', async () => {
appMockRenderer.render(<AllCasesList isSelectorView={false} />);
renderWithTestingProviders(<AllCasesList isSelectorView={false} />);
expect(screen.queryByText('Solution')).not.toBeInTheDocument();
});
it('should deselect cases when refreshing', async () => {
appMockRenderer.render(<AllCasesList />);
renderWithTestingProviders(<AllCasesList />);
const allCheckbox = await screen.findByTestId('checkboxSelectAll');
await userEvent.click(allCheckbox);
@ -575,7 +578,7 @@ describe.skip('AllCasesListGeneric', () => {
selectedCases: [],
});
appMockRenderer.render(<AllCasesList />);
renderWithTestingProviders(<AllCasesList />);
const allCheckbox = await screen.findByTestId('checkboxSelectAll');
@ -598,36 +601,28 @@ describe.skip('AllCasesListGeneric', () => {
});
it('should hide the alerts column if the alert feature is disabled', async () => {
render(
<TestProviders features={{ alerts: { enabled: false } }}>
<AllCasesList />
</TestProviders>
);
renderWithTestingProviders(<AllCasesList />, {
wrapperProps: { features: { alerts: { enabled: false } } },
});
expect(await screen.findByTestId('cases-table')).toBeInTheDocument();
expect(screen.queryAllByTestId('case-table-column-alertsCount').length).toBe(0);
});
it('should show the alerts column if the alert feature is enabled', async () => {
const { findAllByTestId } = render(
<TestProviders features={{ alerts: { enabled: true } }}>
<AllCasesList />
</TestProviders>
);
renderWithTestingProviders(<AllCasesList />, {
wrapperProps: { features: { alerts: { enabled: true } } },
});
const alertCounts = await findAllByTestId('case-table-column-alertsCount');
const alertCounts = await screen.findAllByTestId('case-table-column-alertsCount');
expect(alertCounts.length).toBeGreaterThan(0);
});
it('should show the alerts column if the alert object is empty', async () => {
const { findAllByTestId } = render(
<TestProviders features={{ alerts: {} }}>
<AllCasesList />
</TestProviders>
);
renderWithTestingProviders(<AllCasesList />, { wrapperProps: { features: { alerts: {} } } });
const alertCounts = await findAllByTestId('case-table-column-alertsCount');
const alertCounts = await screen.findAllByTestId('case-table-column-alertsCount');
expect(alertCounts.length).toBeGreaterThan(0);
});
@ -635,7 +630,7 @@ describe.skip('AllCasesListGeneric', () => {
it('should clear the filters correctly', async () => {
useLicenseMock.mockReturnValue({ isAtLeastPlatinum: () => true });
appMockRenderer.render(<AllCasesList />);
renderWithTestingProviders(<AllCasesList />);
await userEvent.click(await screen.findByTestId('options-filter-popover-button-category'));
await waitForEuiPopoverOpen();
@ -650,11 +645,9 @@ describe.skip('AllCasesListGeneric', () => {
describe('Solutions', () => {
it('should hide the solutions filter if the owner is provided', async () => {
render(
<TestProviders owner={[SECURITY_SOLUTION_OWNER]}>
<AllCasesList />
</TestProviders>
);
renderWithTestingProviders(<AllCasesList />, {
wrapperProps: { owner: [SECURITY_SOLUTION_OWNER] },
});
expect(screen.queryByTestId('options-filter-popover-button-owner')).not.toBeInTheDocument();
});
@ -666,7 +659,7 @@ describe.skip('AllCasesListGeneric', () => {
describe('Bulk actions', () => {
it('Renders bulk action', async () => {
appMockRenderer.render(<AllCasesList />);
renderWithTestingProviders(<AllCasesList />);
expect(await screen.findByTestId('cases-table')).toBeInTheDocument();
@ -680,7 +673,7 @@ describe.skip('AllCasesListGeneric', () => {
it.each([[CaseStatuses.open], [CaseStatuses['in-progress']], [CaseStatuses.closed]])(
'Bulk update status: %s',
async (status) => {
appMockRenderer.render(<AllCasesList />);
renderWithTestingProviders(<AllCasesList />);
expect(await screen.findByTestId('cases-table')).toBeInTheDocument();
@ -716,7 +709,7 @@ describe.skip('AllCasesListGeneric', () => {
[CaseSeverity.HIGH],
[CaseSeverity.CRITICAL],
])('Bulk update severity: %s', async (severity) => {
appMockRenderer.render(<AllCasesList />);
renderWithTestingProviders(<AllCasesList />);
expect(await screen.findByTestId('cases-table')).toBeInTheDocument();
@ -746,7 +739,7 @@ describe.skip('AllCasesListGeneric', () => {
});
it('Bulk delete', async () => {
appMockRenderer.render(<AllCasesList />);
renderWithTestingProviders(<AllCasesList />);
expect(await screen.findByTestId('cases-table')).toBeInTheDocument();
@ -779,8 +772,9 @@ describe.skip('AllCasesListGeneric', () => {
});
it('should disable the checkboxes when the user has read only permissions', async () => {
appMockRenderer = createAppMockRenderer({ permissions: readCasesPermissions() });
appMockRenderer.render(<AllCasesList />);
renderWithTestingProviders(<AllCasesList />, {
wrapperProps: { permissions: readCasesPermissions() },
});
expect(await screen.findByTestId('checkboxSelectAll')).toBeDisabled();
@ -805,7 +799,7 @@ describe.skip('AllCasesListGeneric', () => {
];
it('should render row actions', async () => {
appMockRenderer.render(<AllCasesList />);
renderWithTestingProviders(<AllCasesList />);
for (const theCase of defaultGetCases.data.cases) {
expect(
@ -815,7 +809,7 @@ describe.skip('AllCasesListGeneric', () => {
});
it.each(statusTests)('update the status of a case: %s', async (status) => {
appMockRenderer.render(<AllCasesList />);
renderWithTestingProviders(<AllCasesList />);
const openCase = useGetCasesMockState.data.cases[0];
const inProgressCase = useGetCasesMockState.data.cases[1];
const theCase = status === CaseStatuses.open ? inProgressCase : openCase;
@ -838,7 +832,7 @@ describe.skip('AllCasesListGeneric', () => {
});
it.each(severityTests)('update the severity of a case: %s', async (severity) => {
appMockRenderer.render(<AllCasesList />);
renderWithTestingProviders(<AllCasesList />);
const lowCase = useGetCasesMockState.data.cases[0];
const mediumCase = useGetCasesMockState.data.cases[1];
const theCase = severity === CaseSeverity.LOW ? mediumCase : lowCase;
@ -864,7 +858,7 @@ describe.skip('AllCasesListGeneric', () => {
});
it('should delete a case', async () => {
appMockRenderer.render(<AllCasesList />);
renderWithTestingProviders(<AllCasesList />);
const theCase = defaultGetCases.data.cases[0];
await userEvent.click(
@ -885,7 +879,7 @@ describe.skip('AllCasesListGeneric', () => {
});
it('should disable row actions when bulk selecting all cases', async () => {
appMockRenderer.render(<AllCasesList />);
renderWithTestingProviders(<AllCasesList />);
await userEvent.click(await screen.findByTestId('checkboxSelectAll'));
@ -897,7 +891,7 @@ describe.skip('AllCasesListGeneric', () => {
});
it('should disable row actions when selecting a case', async () => {
appMockRenderer.render(<AllCasesList />);
renderWithTestingProviders(<AllCasesList />);
const caseToSelect = defaultGetCases.data.cases[0];
await userEvent.click(await screen.findByTestId(`checkboxSelectRow-${caseToSelect.id}`));
@ -914,7 +908,7 @@ describe.skip('AllCasesListGeneric', () => {
it('should hide the assignees column on basic license', async () => {
useLicenseMock.mockReturnValue({ isAtLeastPlatinum: () => false });
appMockRenderer.render(<AllCasesList />);
renderWithTestingProviders(<AllCasesList />);
expect(await screen.findByTestId('cases-table')).toBeTruthy();
expect(screen.queryAllByTestId('case-table-column-assignee').length).toBe(0);
@ -923,7 +917,7 @@ describe.skip('AllCasesListGeneric', () => {
it('should show the assignees column on platinum license', async () => {
useLicenseMock.mockReturnValue({ isAtLeastPlatinum: () => true });
appMockRenderer.render(<AllCasesList />);
renderWithTestingProviders(<AllCasesList />);
expect(await screen.findByTestId('cases-table')).toBeTruthy();
expect(screen.queryAllByTestId('case-table-column-assignee').length).toBeGreaterThan(0);
@ -932,7 +926,7 @@ describe.skip('AllCasesListGeneric', () => {
it('should hide the assignees filters on basic license', async () => {
useLicenseMock.mockReturnValue({ isAtLeastPlatinum: () => false });
appMockRenderer.render(<AllCasesList />);
renderWithTestingProviders(<AllCasesList />);
expect(await screen.findByTestId('cases-table')).toBeTruthy();
expect(screen.queryAllByTestId('options-filter-popover-button-assignees').length).toBe(0);
@ -941,7 +935,7 @@ describe.skip('AllCasesListGeneric', () => {
it('should show the assignees filters on platinum license', async () => {
useLicenseMock.mockReturnValue({ isAtLeastPlatinum: () => true });
appMockRenderer.render(<AllCasesList />);
renderWithTestingProviders(<AllCasesList />);
expect(await screen.findByTestId('cases-table')).toBeTruthy();
expect(
@ -952,7 +946,7 @@ describe.skip('AllCasesListGeneric', () => {
it('should reset the assignees when deactivating the filter', async () => {
useLicenseMock.mockReturnValue({ isAtLeastPlatinum: () => true });
appMockRenderer.render(<AllCasesList />);
renderWithTestingProviders(<AllCasesList />);
// Opens assignees filter and checks an option
const assigneesButton = await screen.findByTestId(
@ -993,13 +987,13 @@ describe.skip('AllCasesListGeneric', () => {
describe('Columns Popover', () => {
it('renders the columns popover correctly', async () => {
appMockRenderer.render(<AllCasesList isSelectorView={false} />);
renderWithTestingProviders(<AllCasesList isSelectorView={false} />);
expect(await screen.findByTestId('column-selection-popover-button')).toBeInTheDocument();
});
it('does not render the columns popover when isSelectorView=true', () => {
appMockRenderer.render(<AllCasesList isSelectorView={true} />);
renderWithTestingProviders(<AllCasesList isSelectorView={true} />);
expect(screen.queryByTestId('column-selection-popover-button')).not.toBeInTheDocument();
});

View file

@ -8,26 +8,22 @@
import React from 'react';
import { screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
import { userProfiles, userProfilesMap } from '../../containers/user_profiles/api.mock';
import type { AssigneesColumnProps } from './assignees_column';
import { AssigneesColumn } from './assignees_column';
import { renderWithTestingProviders } from '../../common/mock';
// Failing: See https://github.com/elastic/kibana/issues/192674
describe.skip('AssigneesColumn', () => {
describe('AssigneesColumn', () => {
const defaultProps: AssigneesColumnProps = {
assignees: userProfiles,
userProfiles: userProfilesMap,
compressedDisplayLimit: 2,
};
let appMockRender: AppMockRenderer;
beforeEach(() => {
jest.clearAllMocks();
appMockRender = createAppMockRenderer();
});
it('renders a long dash if the assignees is an empty array', async () => {
@ -36,7 +32,7 @@ describe.skip('AssigneesColumn', () => {
assignees: [],
};
appMockRender.render(<AssigneesColumn {...props} />);
renderWithTestingProviders(<AssigneesColumn {...props} />);
expect(
screen.queryByTestId('case-table-column-assignee-damaged_raccoon')
@ -51,7 +47,7 @@ describe.skip('AssigneesColumn', () => {
...defaultProps,
};
appMockRender.render(<AssigneesColumn {...props} />);
renderWithTestingProviders(<AssigneesColumn {...props} />);
expect(screen.getByTestId('case-table-column-assignee-damaged_raccoon')).toBeInTheDocument();
expect(screen.getByTestId('case-table-column-assignee-physical_dinosaur')).toBeInTheDocument();
@ -63,7 +59,7 @@ describe.skip('AssigneesColumn', () => {
compressedDisplayLimit: 5,
};
appMockRender.render(<AssigneesColumn {...props} />);
renderWithTestingProviders(<AssigneesColumn {...props} />);
expect(screen.getByTestId('case-table-column-assignee-damaged_raccoon')).toBeInTheDocument();
expect(screen.getByTestId('case-table-column-assignee-physical_dinosaur')).toBeInTheDocument();
@ -76,7 +72,7 @@ describe.skip('AssigneesColumn', () => {
compressedDisplayLimit: 2,
};
appMockRender.render(<AssigneesColumn {...props} />);
renderWithTestingProviders(<AssigneesColumn {...props} />);
expect(screen.getByTestId('case-table-column-expand-button')).toBeInTheDocument();
expect(screen.getByText('+1 more')).toBeInTheDocument();
@ -88,7 +84,7 @@ describe.skip('AssigneesColumn', () => {
compressedDisplayLimit: 5,
};
appMockRender.render(<AssigneesColumn {...props} />);
renderWithTestingProviders(<AssigneesColumn {...props} />);
expect(screen.queryByTestId('case-table-column-expand-button')).not.toBeInTheDocument();
});
@ -99,7 +95,7 @@ describe.skip('AssigneesColumn', () => {
compressedDisplayLimit: userProfiles.length,
};
appMockRender.render(<AssigneesColumn {...props} />);
renderWithTestingProviders(<AssigneesColumn {...props} />);
expect(screen.queryByTestId('case-table-column-expand-button')).not.toBeInTheDocument();
});
@ -110,7 +106,7 @@ describe.skip('AssigneesColumn', () => {
compressedDisplayLimit: 2,
};
appMockRender.render(<AssigneesColumn {...props} />);
renderWithTestingProviders(<AssigneesColumn {...props} />);
expect(screen.queryByTestId('case-table-column-assignee-wet_dingo')).not.toBeInTheDocument();
@ -118,11 +114,9 @@ describe.skip('AssigneesColumn', () => {
expect(screen.getByText('+1 more')).toBeInTheDocument();
await userEvent.click(screen.getByTestId('case-table-column-expand-button'));
expect(await screen.findByText('show less')).toBeInTheDocument();
await waitFor(() => {
expect(screen.getByText('show less')).toBeInTheDocument();
expect(screen.getByTestId('case-table-column-assignee-wet_dingo')).toBeInTheDocument();
});
expect(screen.getByTestId('case-table-column-assignee-wet_dingo')).toBeInTheDocument();
});
it('shows more avatars and then hides them when the expand row button is clicked multiple times', async () => {
@ -131,7 +125,7 @@ describe.skip('AssigneesColumn', () => {
compressedDisplayLimit: 2,
};
appMockRender.render(<AssigneesColumn {...props} />);
renderWithTestingProviders(<AssigneesColumn {...props} />);
expect(screen.queryByTestId('case-table-column-assignee-wet_dingo')).not.toBeInTheDocument();
@ -140,16 +134,14 @@ describe.skip('AssigneesColumn', () => {
await userEvent.click(screen.getByTestId('case-table-column-expand-button'));
await waitFor(() => {
expect(screen.getByText('show less')).toBeInTheDocument();
expect(screen.getByTestId('case-table-column-assignee-wet_dingo')).toBeInTheDocument();
});
expect(await screen.findByText('show less')).toBeInTheDocument();
expect(screen.getByTestId('case-table-column-assignee-wet_dingo')).toBeInTheDocument();
await waitFor(() => {});
await userEvent.click(screen.getByTestId('case-table-column-expand-button'));
await waitFor(() => {
expect(screen.getByText('+1 more')).toBeInTheDocument();
expect(screen.queryByTestId('case-table-column-assignee-wet_dingo')).not.toBeInTheDocument();
});
expect(await screen.findByText('+1 more')).toBeInTheDocument();
expect(screen.queryByTestId('case-table-column-assignee-wet_dingo')).not.toBeInTheDocument();
});
});

View file

@ -10,27 +10,23 @@ import userEvent from '@testing-library/user-event';
import { screen, fireEvent, waitFor, within } from '@testing-library/react';
import { waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
import type { AssigneesFilterPopoverProps } from './assignees_filter';
import { AssigneesFilterPopover } from './assignees_filter';
import { userProfiles } from '../../containers/user_profiles/api.mock';
import { MAX_ASSIGNEES_FILTER_LENGTH } from '../../../common/constants';
import { useSuggestUserProfiles } from '../../containers/user_profiles/use_suggest_user_profiles';
import { renderWithTestingProviders } from '../../common/mock';
jest.mock('../../containers/user_profiles/use_suggest_user_profiles');
const useSuggestUserProfilesMock = useSuggestUserProfiles as jest.Mock;
describe('AssigneesFilterPopover', () => {
let appMockRender: AppMockRenderer;
let defaultProps: AssigneesFilterPopoverProps;
beforeEach(() => {
jest.clearAllMocks();
appMockRender = createAppMockRenderer();
defaultProps = {
currentUserProfile: undefined,
selectedAssignees: [],
@ -44,7 +40,7 @@ describe('AssigneesFilterPopover', () => {
const onSelectionChange = jest.fn();
const props = { ...defaultProps, onSelectionChange };
appMockRender.render(<AssigneesFilterPopover {...props} />);
renderWithTestingProviders(<AssigneesFilterPopover {...props} />);
await userEvent.click(await screen.findByTestId('options-filter-popover-button-assignees'));
@ -66,7 +62,7 @@ describe('AssigneesFilterPopover', () => {
it('calls onSelectionChange with a single user when different users are selected', async () => {
const onSelectionChange = jest.fn();
const props = { ...defaultProps, onSelectionChange };
appMockRender.render(<AssigneesFilterPopover {...props} />);
renderWithTestingProviders(<AssigneesFilterPopover {...props} />);
await userEvent.click(await screen.findByTestId('options-filter-popover-button-assignees'));
expect(await screen.findByText('wet_dingo@elastic.co'));
@ -84,15 +80,16 @@ describe('AssigneesFilterPopover', () => {
filterId: 'assignees',
selectedOptionKeys: ['u_9xDEQqUqoYCnFnPPLq5mIRHKL8gBTo_NiKgOnd5gGk0_0'],
});
expect(onSelectionChange).toHaveBeenCalledWith({
filterId: 'assignees',
selectedOptionKeys: ['u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0'],
});
});
expect(onSelectionChange).toHaveBeenCalledWith({
filterId: 'assignees',
selectedOptionKeys: ['u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0'],
});
});
it('does not show the assigned users total if there are no assigned users', async () => {
appMockRender.render(<AssigneesFilterPopover {...defaultProps} />);
renderWithTestingProviders(<AssigneesFilterPopover {...defaultProps} />);
await userEvent.click(await screen.findByTestId('options-filter-popover-button-assignees'));
expect(await screen.findByText('Damaged Raccoon')).toBeInTheDocument();
@ -107,7 +104,7 @@ describe('AssigneesFilterPopover', () => {
...defaultProps,
selectedAssignees: [userProfiles[0].uid],
};
appMockRender.render(<AssigneesFilterPopover {...props} />);
renderWithTestingProviders(<AssigneesFilterPopover {...props} />);
await userEvent.click(await screen.findByTestId('options-filter-popover-button-assignees'));
expect(await screen.findByText('1 filter selected')).toBeInTheDocument();
@ -122,7 +119,7 @@ describe('AssigneesFilterPopover', () => {
...defaultProps,
selectedAssignees: [userProfiles[0].uid, userProfiles[1].uid],
};
appMockRender.render(<AssigneesFilterPopover {...props} />);
renderWithTestingProviders(<AssigneesFilterPopover {...props} />);
await userEvent.click(await screen.findByTestId('options-filter-popover-button-assignees'));
expect(await screen.findByText('2 filters selected')).toBeInTheDocument();
@ -134,7 +131,7 @@ describe('AssigneesFilterPopover', () => {
});
it('shows three users when initially rendered', async () => {
appMockRender.render(<AssigneesFilterPopover {...defaultProps} />);
renderWithTestingProviders(<AssigneesFilterPopover {...defaultProps} />);
await userEvent.click(await screen.findByTestId('options-filter-popover-button-assignees'));
expect(await screen.findByText('Wet Dingo')).toBeInTheDocument();
@ -151,7 +148,7 @@ describe('AssigneesFilterPopover', () => {
currentUserProfile: userProfiles[2],
};
appMockRender.render(<AssigneesFilterPopover {...props} />);
renderWithTestingProviders(<AssigneesFilterPopover {...props} />);
await userEvent.click(await screen.findByTestId('options-filter-popover-button-assignees'));
expect(await screen.findByText('Wet Dingo')).toBeInTheDocument();
@ -166,7 +163,7 @@ describe('AssigneesFilterPopover', () => {
});
it('does not show the number of filters', async () => {
appMockRender.render(<AssigneesFilterPopover {...defaultProps} />);
renderWithTestingProviders(<AssigneesFilterPopover {...defaultProps} />);
await userEvent.click(await screen.findByTestId('options-filter-popover-button-assignees'));
expect(await screen.findByText('Wet Dingo')).toBeInTheDocument();
@ -182,7 +179,7 @@ describe('AssigneesFilterPopover', () => {
currentUserProfile: userProfiles[2],
};
appMockRender.render(<AssigneesFilterPopover {...props} />);
renderWithTestingProviders(<AssigneesFilterPopover {...props} />);
await userEvent.click(await screen.findByTestId('options-filter-popover-button-assignees'));
expect(await screen.findByText('Wet Dingo')).toBeInTheDocument();
@ -195,7 +192,7 @@ describe('AssigneesFilterPopover', () => {
it('filters cases with no assignees', async () => {
const onSelectionChange = jest.fn();
const props = { ...defaultProps, onSelectionChange };
appMockRender.render(<AssigneesFilterPopover {...props} />);
renderWithTestingProviders(<AssigneesFilterPopover {...props} />);
await userEvent.click(await screen.findByTestId('options-filter-popover-button-assignees'));
expect(await screen.findByPlaceholderText('Search users')).toBeInTheDocument();
@ -214,7 +211,7 @@ describe('AssigneesFilterPopover', () => {
it('filters cases with no assignees and users', async () => {
const onSelectionChange = jest.fn();
const props = { ...defaultProps, onSelectionChange };
appMockRender.render(<AssigneesFilterPopover {...props} />);
renderWithTestingProviders(<AssigneesFilterPopover {...props} />);
await userEvent.click(await screen.findByTestId('options-filter-popover-button-assignees'));
expect(await screen.findByPlaceholderText('Search users')).toBeInTheDocument();
@ -230,21 +227,22 @@ describe('AssigneesFilterPopover', () => {
filterId: 'assignees',
selectedOptionKeys: [null],
});
expect(onSelectionChange).toHaveBeenCalledWith({
filterId: 'assignees',
selectedOptionKeys: ['u_9xDEQqUqoYCnFnPPLq5mIRHKL8gBTo_NiKgOnd5gGk0_0'],
});
expect(onSelectionChange).toHaveBeenCalledWith({
filterId: 'assignees',
selectedOptionKeys: ['u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0'],
});
});
expect(onSelectionChange).toHaveBeenCalledWith({
filterId: 'assignees',
selectedOptionKeys: ['u_9xDEQqUqoYCnFnPPLq5mIRHKL8gBTo_NiKgOnd5gGk0_0'],
});
expect(onSelectionChange).toHaveBeenCalledWith({
filterId: 'assignees',
selectedOptionKeys: ['u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0'],
});
});
it('hides no assignee filtering when searching', async () => {
const onSelectionChange = jest.fn();
const props = { ...defaultProps, onSelectionChange };
appMockRender.render(<AssigneesFilterPopover {...props} />);
renderWithTestingProviders(<AssigneesFilterPopover {...props} />);
await userEvent.click(await screen.findByTestId('options-filter-popover-button-assignees'));
expect(await screen.findByPlaceholderText('Search users')).toBeInTheDocument();
@ -263,7 +261,7 @@ describe('AssigneesFilterPopover', () => {
...defaultProps,
selectedAssignees: maxAssignees,
};
appMockRender.render(<AssigneesFilterPopover {...props} />);
renderWithTestingProviders(<AssigneesFilterPopover {...props} />);
await userEvent.click(await screen.findByTestId('options-filter-popover-button-assignees'));
expect(

View file

@ -7,8 +7,8 @@
import { screen, within } from '@testing-library/react';
import React from 'react';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
import { renderWithTestingProviders } from '../../common/mock';
import { useGetCasesMetrics } from '../../containers/use_get_cases_metrics';
import { CasesMetrics } from './cases_metrics';
@ -18,8 +18,6 @@ jest.mock('../../containers/use_get_cases_metrics');
const useGetCasesMetricsMock = useGetCasesMetrics as jest.Mock;
describe('Cases metrics', () => {
let appMockRenderer: AppMockRenderer;
beforeEach(() => {
useGetCasesMetricsMock.mockReturnValue({
isLoading: false,
@ -28,12 +26,10 @@ describe('Cases metrics', () => {
status: { open: 20, inProgress: 40, closed: 130 },
},
});
appMockRenderer = createAppMockRenderer();
});
it('renders the correct stats', async () => {
appMockRenderer.render(<CasesMetrics />);
renderWithTestingProviders(<CasesMetrics />);
expect(await screen.findByTestId('cases-metrics-stats')).toBeInTheDocument();
@ -53,4 +49,20 @@ describe('Cases metrics', () => {
within(await screen.findByTestId('mttrStatsHeader')).getByText('2ms')
).toBeInTheDocument();
});
it('should render the loading spinner when loading stats', async () => {
useGetCasesMetricsMock.mockReturnValue({
isLoading: true,
data: {
mttr: 2000,
status: { open: 20, inProgress: 40, closed: 130 },
},
});
renderWithTestingProviders(<CasesMetrics />);
expect(screen.getByTestId('openStatsHeader-loading-spinner')).toBeInTheDocument();
expect(screen.getByTestId('inProgressStatsHeader-loading-spinner')).toBeInTheDocument();
expect(screen.getByTestId('closedStatsHeader-loading-spinner')).toBeInTheDocument();
});
});

View file

@ -10,23 +10,14 @@ import { screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
import { renderWithTestingProviders } from '../../common/mock';
import { ColumnsPopover } from './columns_popover';
// FLAKY: https://github.com/elastic/kibana/issues/174682
describe.skip('ColumnsPopover', () => {
let appMockRenderer: AppMockRenderer;
describe('ColumnsPopover', () => {
beforeEach(() => {
appMockRenderer = createAppMockRenderer();
jest.clearAllMocks();
});
afterEach(async () => {
await appMockRenderer.clearQueryCache();
});
const selectedColumns = [
{ field: 'title', name: 'Title', isChecked: true },
{ field: 'category', name: 'Category', isChecked: false },
@ -34,7 +25,7 @@ describe.skip('ColumnsPopover', () => {
];
it('renders correctly a list of selected columns', async () => {
appMockRenderer.render(
renderWithTestingProviders(
<ColumnsPopover selectedColumns={selectedColumns} onSelectedColumnsChange={() => {}} />
);
@ -56,7 +47,7 @@ describe.skip('ColumnsPopover', () => {
it('clicking a switch calls onSelectedColumnsChange with the right params', async () => {
const onSelectedColumnsChange = jest.fn();
appMockRenderer.render(
renderWithTestingProviders(
<ColumnsPopover
selectedColumns={selectedColumns}
onSelectedColumnsChange={onSelectedColumnsChange}
@ -81,7 +72,7 @@ describe.skip('ColumnsPopover', () => {
it('clicking Show All calls onSelectedColumnsChange with the right params', async () => {
const onSelectedColumnsChange = jest.fn();
appMockRenderer.render(
renderWithTestingProviders(
<ColumnsPopover
selectedColumns={selectedColumns}
onSelectedColumnsChange={onSelectedColumnsChange}
@ -106,7 +97,7 @@ describe.skip('ColumnsPopover', () => {
it('clicking Hide All calls onSelectedColumnsChange with the right params', async () => {
const onSelectedColumnsChange = jest.fn();
appMockRenderer.render(
renderWithTestingProviders(
<ColumnsPopover
selectedColumns={selectedColumns}
onSelectedColumnsChange={onSelectedColumnsChange}
@ -126,7 +117,7 @@ describe.skip('ColumnsPopover', () => {
});
it('searching for text changes the column list correctly', async () => {
appMockRenderer.render(
renderWithTestingProviders(
<ColumnsPopover selectedColumns={selectedColumns} onSelectedColumnsChange={() => {}} />
);
@ -143,7 +134,7 @@ describe.skip('ColumnsPopover', () => {
it('searching for text does not change the list of selected columns', async () => {
const onSelectedColumnsChange = jest.fn();
appMockRenderer.render(
renderWithTestingProviders(
<ColumnsPopover
selectedColumns={selectedColumns}
onSelectedColumnsChange={onSelectedColumnsChange}
@ -161,7 +152,7 @@ describe.skip('ColumnsPopover', () => {
});
it('searching for text hides the drag and drop icons', async () => {
appMockRenderer.render(
renderWithTestingProviders(
<ColumnsPopover selectedColumns={selectedColumns} onSelectedColumnsChange={() => {}} />
);
@ -172,13 +163,11 @@ describe.skip('ColumnsPopover', () => {
await userEvent.click(await screen.findByTestId('column-selection-popover-search'));
await userEvent.paste('Foobar');
expect(
await screen.queryByTestId('column-selection-popover-draggable-icon')
).not.toBeInTheDocument();
expect(screen.queryByTestId('column-selection-popover-draggable-icon')).not.toBeInTheDocument();
});
it('searching for text disables hideAll and showAll buttons', async () => {
appMockRenderer.render(
renderWithTestingProviders(
<ColumnsPopover selectedColumns={selectedColumns} onSelectedColumnsChange={() => {}} />
);

View file

@ -6,52 +6,45 @@
*/
import React from 'react';
import { screen } from '@testing-library/react';
import type { AppMockRenderer } from '../../common/mock';
import { buildCasesPermissions, createAppMockRenderer } from '../../common/mock';
import { buildCasesPermissions, renderWithTestingProviders } from '../../common/mock';
import { CasesTableHeader } from './header';
describe('CasesTableHeader', () => {
let appMockRender: AppMockRenderer;
beforeEach(() => {
jest.clearAllMocks();
appMockRender = createAppMockRenderer();
});
it('displays the create new case button when the user has create privileges', () => {
appMockRender = createAppMockRenderer({
permissions: buildCasesPermissions({ update: false, create: true }),
renderWithTestingProviders(<CasesTableHeader actionsErrors={[]} />, {
wrapperProps: { permissions: buildCasesPermissions({ update: false, create: true }) },
});
const result = appMockRender.render(<CasesTableHeader actionsErrors={[]} />);
expect(result.getByTestId('createNewCaseBtn')).toBeInTheDocument();
expect(screen.getByTestId('createNewCaseBtn')).toBeInTheDocument();
});
it('does not display the create new case button when the user does not have create privileges', () => {
appMockRender = createAppMockRenderer({
permissions: buildCasesPermissions({ create: false }),
renderWithTestingProviders(<CasesTableHeader actionsErrors={[]} />, {
wrapperProps: { permissions: buildCasesPermissions({ create: false }) },
});
const result = appMockRender.render(<CasesTableHeader actionsErrors={[]} />);
expect(result.queryByTestId('createNewCaseBtn')).not.toBeInTheDocument();
expect(screen.queryByTestId('createNewCaseBtn')).not.toBeInTheDocument();
});
it('displays the configure button when the user has update privileges', () => {
appMockRender = createAppMockRenderer({
permissions: buildCasesPermissions({ create: false, update: true }),
renderWithTestingProviders(<CasesTableHeader actionsErrors={[]} />, {
wrapperProps: { permissions: buildCasesPermissions({ create: false, update: true }) },
});
const result = appMockRender.render(<CasesTableHeader actionsErrors={[]} />);
expect(result.getByTestId('configure-case-button')).toBeInTheDocument();
expect(screen.getByTestId('configure-case-button')).toBeInTheDocument();
});
it('does not display the configure button when the user does not have settings privileges', () => {
appMockRender = createAppMockRenderer({
permissions: buildCasesPermissions({ settings: false }),
renderWithTestingProviders(<CasesTableHeader actionsErrors={[]} />, {
wrapperProps: { permissions: buildCasesPermissions({ settings: false }) },
});
const result = appMockRender.render(<CasesTableHeader actionsErrors={[]} />);
expect(result.queryByTestId('configure-case-button')).not.toBeInTheDocument();
expect(screen.queryByTestId('configure-case-button')).not.toBeInTheDocument();
});
});

View file

@ -1,162 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import React from 'react';
import { waitFor } from '@testing-library/react';
import { AllCases } from '.';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer, noCreateCasesPermissions } from '../../common/mock';
import { useGetActionLicense } from '../../containers/use_get_action_license';
import { connectorsMock, useGetCasesMockState } from '../../containers/mock';
import { useGetSupportedActionConnectors } from '../../containers/configure/use_get_supported_action_connectors';
import { useGetTags } from '../../containers/use_get_tags';
import { useGetCategories } from '../../containers/use_get_categories';
import { useGetCases } from '../../containers/use_get_cases';
import { useGetCurrentUserProfile } from '../../containers/user_profiles/use_get_current_user_profile';
import { userProfiles, userProfilesMap } from '../../containers/user_profiles/api.mock';
import { useBulkGetUserProfiles } from '../../containers/user_profiles/use_bulk_get_user_profiles';
jest.mock('../../common/lib/kibana');
jest.mock('../../containers/use_get_tags');
jest.mock('../../containers/use_get_categories');
jest.mock('../../containers/use_get_action_license', () => {
return {
useGetActionLicense: jest.fn(),
};
});
jest.mock('../../containers/configure/use_get_supported_action_connectors');
jest.mock('../../containers/api');
jest.mock('../../containers/use_get_cases');
jest.mock('../../containers/user_profiles/use_get_current_user_profile');
jest.mock('../../containers/user_profiles/use_bulk_get_user_profiles');
jest.mock('../../api');
const useGetConnectorsMock = useGetSupportedActionConnectors as jest.Mock;
const useGetCasesMock = useGetCases as jest.Mock;
const useGetActionLicenseMock = useGetActionLicense as jest.Mock;
const useGetCurrentUserProfileMock = useGetCurrentUserProfile as jest.Mock;
const useBulkGetUserProfilesMock = useBulkGetUserProfiles as jest.Mock;
describe('AllCases', () => {
const refetchCases = jest.fn();
const setFilters = jest.fn();
const setQueryParams = jest.fn();
const setSelectedCases = jest.fn();
const defaultGetCases = {
...useGetCasesMockState,
refetchCases,
setFilters,
setQueryParams,
setSelectedCases,
};
const defaultActionLicense = {
data: null,
isLoading: false,
isError: false,
};
beforeAll(() => {
jest.useFakeTimers();
(useGetTags as jest.Mock).mockReturnValue({ data: ['coke', 'pepsi'], refetch: jest.fn() });
(useGetCategories as jest.Mock).mockReturnValue({
data: ['beverages', 'snacks'],
refetch: jest.fn(),
});
useGetConnectorsMock.mockImplementation(() => ({ data: connectorsMock, isLoading: false }));
useGetActionLicenseMock.mockReturnValue(defaultActionLicense);
useGetCasesMock.mockReturnValue(defaultGetCases);
useGetCurrentUserProfileMock.mockReturnValue({ data: userProfiles[0], isLoading: false });
useBulkGetUserProfilesMock.mockReturnValue({ data: userProfilesMap });
});
afterAll(() => {
jest.useRealTimers();
});
let appMockRender: AppMockRenderer;
beforeEach(() => {
appMockRender = createAppMockRenderer();
});
afterEach(() => {
jest.clearAllMocks();
});
// FLAKY: https://github.com/elastic/kibana/issues/162852
describe.skip('empty table', () => {
beforeEach(() => {
useGetCasesMock.mockReturnValue({
...defaultGetCases,
data: {
...defaultGetCases.data,
cases: [],
total: 0,
},
});
});
it('should render the create new case link when the user has create privileges', async () => {
const result = appMockRender.render(<AllCases />);
await waitFor(() => {
expect(result.getByTestId('cases-table-add-case')).toBeInTheDocument();
});
});
it('should not render the create new case link when the user does not have create privileges', async () => {
appMockRender = createAppMockRenderer({ permissions: noCreateCasesPermissions() });
const result = appMockRender.render(<AllCases />);
await waitFor(() => {
expect(result.queryByTestId('cases-table-add-case')).not.toBeInTheDocument();
});
});
});
it('should render the stats', async () => {
useGetCasesMock.mockReturnValue({
...defaultGetCases,
});
const result = appMockRender.render(<AllCases />);
await waitFor(() => {
expect(result.getByTestId('openStatsHeader')).toBeInTheDocument();
expect(result.getByText('20')).toBeInTheDocument();
});
await waitFor(() => {
expect(result.getByTestId('inProgressStatsHeader')).toBeInTheDocument();
expect(result.getByText('40')).toBeInTheDocument();
});
await waitFor(() => {
expect(result.getByTestId('closedStatsHeader')).toBeInTheDocument();
expect(result.getByText('130')).toBeInTheDocument();
});
});
it('should render the loading spinner when loading stats', async () => {
const result = appMockRender.render(<AllCases />);
await waitFor(() => {
expect(result.getByTestId('openStatsHeader-loading-spinner')).toBeInTheDocument();
expect(result.getByTestId('inProgressStatsHeader-loading-spinner')).toBeInTheDocument();
expect(result.getByTestId('closedStatsHeader-loading-spinner')).toBeInTheDocument();
});
});
it('should render the case callouts', async () => {
const result = appMockRender.render(<AllCases />);
await waitFor(() => {
expect(result.getByTestId('case-callouts')).toBeInTheDocument();
});
});
});

View file

@ -11,7 +11,7 @@ import userEvent from '@testing-library/user-event';
import { waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl';
// Failing: See https://github.com/elastic/kibana/issues/183663
describe.skip('multi select filter', () => {
describe('multi select filter', () => {
it('should render the amount of options available', async () => {
const onChange = jest.fn();
const props = {

View file

@ -7,47 +7,42 @@
import React from 'react';
import { screen } from '@testing-library/react';
import type { AppMockRenderer } from '../../common/mock';
import {
createAppMockRenderer,
noCasesSettingsPermission,
noCreateCasesPermissions,
buildCasesPermissions,
renderWithTestingProviders,
} from '../../common/mock';
import { NavButtons } from './nav_buttons';
describe('NavButtons', () => {
let appMockRenderer: AppMockRenderer;
beforeEach(() => {
appMockRenderer = createAppMockRenderer();
});
it('shows the configure case button', () => {
appMockRenderer.render(<NavButtons actionsErrors={[]} />);
renderWithTestingProviders(<NavButtons actionsErrors={[]} />);
expect(screen.getByTestId('configure-case-button')).toBeInTheDocument();
});
it('does not render the case create button with no create permissions', () => {
appMockRenderer = createAppMockRenderer({ permissions: noCreateCasesPermissions() });
appMockRenderer.render(<NavButtons actionsErrors={[]} />);
renderWithTestingProviders(<NavButtons actionsErrors={[]} />, {
wrapperProps: { permissions: noCreateCasesPermissions() },
});
expect(screen.queryByTestId('createNewCaseBtn')).not.toBeInTheDocument();
});
it('does not render the case configure button with no settings permissions', () => {
appMockRenderer = createAppMockRenderer({ permissions: noCasesSettingsPermission() });
appMockRenderer.render(<NavButtons actionsErrors={[]} />);
renderWithTestingProviders(<NavButtons actionsErrors={[]} />, {
wrapperProps: { permissions: noCasesSettingsPermission() },
});
expect(screen.queryByTestId('configure-case-button')).not.toBeInTheDocument();
});
it('does not render any button with no create and no settings permissions', () => {
appMockRenderer = createAppMockRenderer({
permissions: buildCasesPermissions({ create: false, settings: false }),
renderWithTestingProviders(<NavButtons actionsErrors={[]} />, {
wrapperProps: { permissions: buildCasesPermissions({ create: false, settings: false }) },
});
appMockRenderer.render(<NavButtons actionsErrors={[]} />);
expect(screen.queryByTestId('createNewCaseBtn')).not.toBeInTheDocument();
expect(screen.queryByTestId('configure-case-button')).not.toBeInTheDocument();

View file

@ -8,22 +8,19 @@
import React from 'react';
import userEvent from '@testing-library/user-event';
import { screen } from '@testing-library/react';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
import { TableSearch } from './search';
import { renderWithTestingProviders } from '../../common/mock';
describe('TableSearch', () => {
const onFilterOptionsChange = jest.fn();
let appMockRender: AppMockRenderer;
beforeEach(() => {
appMockRender = createAppMockRenderer();
jest.clearAllMocks();
});
it('renders with empty value correctly', async () => {
appMockRender.render(
renderWithTestingProviders(
<TableSearch filterOptionsSearch="" onFilterOptionsChange={onFilterOptionsChange} />
);
@ -31,7 +28,7 @@ describe('TableSearch', () => {
});
it('renders with initial value correctly', async () => {
appMockRender.render(
renderWithTestingProviders(
<TableSearch filterOptionsSearch="My search" onFilterOptionsChange={onFilterOptionsChange} />
);
@ -39,7 +36,7 @@ describe('TableSearch', () => {
});
it('calls onFilterOptionsChange correctly', async () => {
appMockRender.render(
renderWithTestingProviders(
<TableSearch filterOptionsSearch="" onFilterOptionsChange={onFilterOptionsChange} />
);
@ -49,7 +46,7 @@ describe('TableSearch', () => {
});
it('calls onFilterOptionsChange if the search term is empty', async () => {
appMockRender.render(
renderWithTestingProviders(
<TableSearch filterOptionsSearch="" onFilterOptionsChange={onFilterOptionsChange} />
);
@ -59,7 +56,7 @@ describe('TableSearch', () => {
});
it('calls onFilterOptionsChange when clearing the search bar', async () => {
appMockRender.render(
renderWithTestingProviders(
<TableSearch filterOptionsSearch="My search" onFilterOptionsChange={onFilterOptionsChange} />
);

View file

@ -8,10 +8,10 @@
import React from 'react';
import { AllCasesSelectorModal } from '.';
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
import { renderWithTestingProviders } from '../../../common/mock';
import userEvent from '@testing-library/user-event';
import { waitFor } from '@testing-library/react';
import { waitFor, screen } from '@testing-library/react';
import { useGetTags } from '../../../containers/use_get_tags';
import { useGetCategories } from '../../../containers/use_get_categories';
@ -26,11 +26,9 @@ const defaultProps = {
};
describe('AllCasesSelectorModal', () => {
let appMockRenderer: AppMockRenderer;
beforeEach(() => {
jest.clearAllMocks();
appMockRenderer = createAppMockRenderer();
(useGetTags as jest.Mock).mockReturnValue({ data: ['coke', 'pepsi'], refetch: jest.fn() });
(useGetCategories as jest.Mock).mockReturnValue({
data: ['beverages', 'snacks'],
@ -39,61 +37,61 @@ describe('AllCasesSelectorModal', () => {
});
it('renders', () => {
const res = appMockRenderer.render(<AllCasesSelectorModal {...defaultProps} />);
renderWithTestingProviders(<AllCasesSelectorModal {...defaultProps} />);
expect(res.getByTestId('all-cases-modal')).toBeInTheDocument();
expect(screen.getByTestId('all-cases-modal')).toBeInTheDocument();
});
it('Closing modal when pressing the x icon', async () => {
const res = appMockRenderer.render(<AllCasesSelectorModal {...defaultProps} />);
renderWithTestingProviders(<AllCasesSelectorModal {...defaultProps} />);
await userEvent.click(res.getByLabelText('Closes this modal window'));
await userEvent.click(screen.getByLabelText('Closes this modal window'));
expect(res.queryByTestId('all-cases-modal')).toBeFalsy();
expect(screen.queryByTestId('all-cases-modal')).toBeFalsy();
});
it('Closing modal when pressing the cancel button', async () => {
const res = appMockRenderer.render(<AllCasesSelectorModal {...defaultProps} />);
renderWithTestingProviders(<AllCasesSelectorModal {...defaultProps} />);
await userEvent.click(res.getByTestId('all-cases-modal-cancel-button'));
await userEvent.click(screen.getByTestId('all-cases-modal-cancel-button'));
expect(res.queryByTestId('all-cases-modal')).toBeFalsy();
expect(screen.queryByTestId('all-cases-modal')).toBeFalsy();
});
it('should not show bulk actions and row actions on the modal', async () => {
const res = appMockRenderer.render(<AllCasesSelectorModal {...defaultProps} />);
renderWithTestingProviders(<AllCasesSelectorModal {...defaultProps} />);
await waitFor(() => {
expect(res.getByTestId('cases-table')).toBeInTheDocument();
expect(screen.getByTestId('cases-table')).toBeInTheDocument();
});
expect(res.queryByTestId('case-table-bulk-actions-link-icon')).toBeFalsy();
expect(res.queryByText('Actions')).toBeFalsy();
expect(screen.queryByTestId('case-table-bulk-actions-link-icon')).toBeFalsy();
expect(screen.queryByText('Actions')).toBeFalsy();
});
it('should show the select button', async () => {
const res = appMockRenderer.render(<AllCasesSelectorModal {...defaultProps} />);
renderWithTestingProviders(<AllCasesSelectorModal {...defaultProps} />);
await waitFor(() => {
expect(res.getByTestId('cases-table')).toBeInTheDocument();
expect(screen.getByTestId('cases-table')).toBeInTheDocument();
});
expect(res.getAllByTestId(/cases-table-row-select/).length).toBeGreaterThan(0);
expect(screen.getAllByTestId(/cases-table-row-select/).length).toBeGreaterThan(0);
});
it('should hide the metrics', async () => {
const res = appMockRenderer.render(<AllCasesSelectorModal {...defaultProps} />);
renderWithTestingProviders(<AllCasesSelectorModal {...defaultProps} />);
await waitFor(() => {
expect(res.getByTestId('cases-table')).toBeInTheDocument();
expect(screen.getByTestId('cases-table')).toBeInTheDocument();
});
expect(res.queryByTestId('cases-metrics-stats')).toBeFalsy();
expect(screen.queryByTestId('cases-metrics-stats')).toBeFalsy();
});
it('should show the create case button', async () => {
const res = appMockRenderer.render(<AllCasesSelectorModal {...defaultProps} />);
renderWithTestingProviders(<AllCasesSelectorModal {...defaultProps} />);
await waitFor(() => {
expect(res.getByTestId('cases-table')).toBeInTheDocument();
expect(screen.getByTestId('cases-table')).toBeInTheDocument();
});
expect(res.getByTestId('cases-table-add-case-filter-bar')).toBeInTheDocument();
expect(screen.getByTestId('cases-table-add-case-filter-bar')).toBeInTheDocument();
});
});

View file

@ -5,15 +5,14 @@
* 2.0.
*/
import { waitFor, renderHook, act } from '@testing-library/react';
import { waitFor, renderHook, act, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import type { FC, PropsWithChildren } from 'react';
import React from 'react';
import AllCasesSelectorModal from '.';
import type { CaseUI } from '../../../../common';
import { CaseStatuses } from '../../../../common/types/domain';
import type { AppMockRenderer } from '../../../common/mock';
import { allCasesPermissions, createAppMockRenderer } from '../../../common/mock';
import { allCasesPermissions, renderWithTestingProviders } from '../../../common/mock';
import { useCasesToast } from '../../../common/use_cases_toast';
import { alertComment } from '../../../containers/mock';
import { useCreateAttachments } from '../../../containers/use_create_attachments';
@ -63,7 +62,7 @@ describe('use cases add to existing case modal hook', () => {
});
const dispatch = jest.fn();
let appMockRender: AppMockRenderer;
const wrapper: FC<PropsWithChildren<unknown>> = ({ children }) => {
return (
<CasesContext.Provider
@ -88,7 +87,6 @@ describe('use cases add to existing case modal hook', () => {
};
beforeEach(() => {
appMockRender = createAppMockRenderer();
dispatch.mockReset();
AllCasesSelectorModalMock.mockReset();
onSuccess.mockReset();
@ -146,13 +144,14 @@ describe('use cases add to existing case modal hook', () => {
return null;
});
const result = appMockRender.render(<TestComponent />);
await userEvent.click(result.getByTestId('open-modal'));
renderWithTestingProviders(<TestComponent />);
await userEvent.click(screen.getByTestId('open-modal'));
await waitFor(() => {
expect(getAttachments).toHaveBeenCalledTimes(1);
expect(getAttachments).toHaveBeenCalledWith({ theCase: { id: 'test', owner: 'cases' } });
});
expect(getAttachments).toHaveBeenCalledWith({ theCase: { id: 'test', owner: 'cases' } });
});
it('should show a toaster info when no attachments are defined and noAttachmentsToaster is defined', async () => {
@ -168,10 +167,10 @@ describe('use cases add to existing case modal hook', () => {
showInfoToast: mockedToastInfo,
});
const result = appMockRender.render(
renderWithTestingProviders(
<TestComponent noAttachmentsToaster={{ title: 'My title', content: 'My content' }} />
);
await userEvent.click(result.getByTestId('open-modal'));
await userEvent.click(screen.getByTestId('open-modal'));
await waitFor(() => {
expect(mockedToastInfo).toHaveBeenCalledWith('My title', 'My content');
@ -191,8 +190,8 @@ describe('use cases add to existing case modal hook', () => {
showInfoToast: mockedToastInfo,
});
const result = appMockRender.render(<TestComponent />);
await userEvent.click(result.getByTestId('open-modal'));
renderWithTestingProviders(<TestComponent />);
await userEvent.click(screen.getByTestId('open-modal'));
await waitFor(() => {
expect(mockedToastInfo).toHaveBeenCalledWith('No attachments added to the case', undefined);
@ -215,16 +214,17 @@ describe('use cases add to existing case modal hook', () => {
return null;
});
const result = appMockRender.render(<TestComponent />);
await userEvent.click(result.getByTestId('open-modal'));
renderWithTestingProviders(<TestComponent />);
await userEvent.click(screen.getByTestId('open-modal'));
await waitFor(() => {
expect(mockBulkCreateAttachments).toHaveBeenCalledTimes(1);
expect(mockBulkCreateAttachments).toHaveBeenCalledWith({
caseId: 'test',
caseOwner: 'cases',
attachments: [alertComment],
});
});
expect(mockBulkCreateAttachments).toHaveBeenCalledWith({
caseId: 'test',
caseOwner: 'cases',
attachments: [alertComment],
});
expect(mockedToastSuccess).toHaveBeenCalled();
});
@ -246,8 +246,8 @@ describe('use cases add to existing case modal hook', () => {
return null;
});
const result = appMockRender.render(<TestComponent />);
await userEvent.click(result.getByTestId('open-modal'));
renderWithTestingProviders(<TestComponent />);
await userEvent.click(screen.getByTestId('open-modal'));
await waitFor(() => {
expect(onSuccess).toHaveBeenCalled();
@ -269,9 +269,9 @@ describe('use cases add to existing case modal hook', () => {
return null;
});
const result = appMockRender.render(<TestComponent />);
renderWithTestingProviders(<TestComponent />);
await userEvent.click(result.getByTestId('open-modal'));
await userEvent.click(screen.getByTestId('open-modal'));
// give a small delay for the reducer to run
act(() => {
@ -297,8 +297,8 @@ describe('use cases add to existing case modal hook', () => {
return null;
});
const result = appMockRender.render(<TestComponent />);
await userEvent.click(result.getByTestId('open-modal'));
renderWithTestingProviders(<TestComponent />);
await userEvent.click(screen.getByTestId('open-modal'));
await waitFor(() => {
expect(mockBulkCreateAttachments).toHaveBeenCalledWith({

View file

@ -7,28 +7,24 @@
import { CaseSeverity } from '../../../common/types/domain';
import React from 'react';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
import userEvent from '@testing-library/user-event';
import { screen, waitFor, within } from '@testing-library/react';
import { waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl';
import { SeverityFilter } from './severity_filter';
import { renderWithTestingProviders } from '../../common/mock';
// Failing: See https://github.com/elastic/kibana/issues/176336
describe.skip('Severity form field', () => {
describe('Severity form field', () => {
const onChange = jest.fn();
let appMockRender: AppMockRenderer;
const props = {
selectedOptionKeys: [],
onChange,
};
beforeEach(() => {
appMockRender = createAppMockRenderer();
});
it('renders', async () => {
appMockRender.render(<SeverityFilter {...props} />);
renderWithTestingProviders(<SeverityFilter {...props} />);
const popoverButton = await screen.findByTestId('options-filter-popover-button-severity');
expect(popoverButton).toBeInTheDocument();
@ -50,9 +46,13 @@ describe.skip('Severity form field', () => {
});
it('selects the correct value when changed', async () => {
appMockRender.render(<SeverityFilter {...props} />);
renderWithTestingProviders(<SeverityFilter {...props} />);
await userEvent.click(await screen.findByRole('button', { name: 'Severity' }));
const popoverButton = await screen.findByTestId('options-filter-popover-button-severity');
expect(popoverButton).toBeInTheDocument();
expect(popoverButton).not.toBeDisabled();
await userEvent.click(popoverButton);
await waitForEuiPopoverOpen();

View file

@ -9,41 +9,35 @@ import React from 'react';
import { screen } from '@testing-library/react';
import { waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
import { renderWithTestingProviders } from '../../common/mock';
import { SECURITY_SOLUTION_OWNER, OBSERVABILITY_OWNER } from '../../../common/constants';
import { SolutionFilter } from './solution_filter';
import userEvent from '@testing-library/user-event';
describe('SolutionFilter ', () => {
let appMockRender: AppMockRenderer;
const onChange = jest.fn();
const solutions = [SECURITY_SOLUTION_OWNER, OBSERVABILITY_OWNER];
beforeEach(() => {
appMockRender = createAppMockRenderer();
jest.clearAllMocks();
});
it('renders button correctly', () => {
const { getByTestId } = appMockRender.render(
renderWithTestingProviders(
<SolutionFilter onChange={onChange} selectedOptionKeys={[]} availableSolutions={solutions} />
);
expect(getByTestId('options-filter-popover-button-owner')).toBeInTheDocument();
expect(screen.getByTestId('options-filter-popover-button-owner')).toBeInTheDocument();
});
describe('when the owner is a single solution', () => {
beforeEach(() => {
// by default, the owner will be the same but we set it explicitly here to make it clear
appMockRender = createAppMockRenderer({ owner: [SECURITY_SOLUTION_OWNER] });
jest.clearAllMocks();
});
// Flaky: https://github.com/elastic/kibana/issues/175239
it.skip('renders options correctly', async () => {
appMockRender.render(
it('renders options correctly', async () => {
renderWithTestingProviders(
<SolutionFilter
onChange={onChange}
selectedOptionKeys={[]}
@ -64,7 +58,7 @@ describe('SolutionFilter ', () => {
});
it('should call onChange with selected solution id when no option selected yet', async () => {
const { getByTestId } = appMockRender.render(
renderWithTestingProviders(
<SolutionFilter
onChange={onChange}
selectedOptionKeys={[]}
@ -72,11 +66,11 @@ describe('SolutionFilter ', () => {
/>
);
await userEvent.click(getByTestId('options-filter-popover-button-owner'));
await userEvent.click(screen.getByTestId('options-filter-popover-button-owner'));
await waitForEuiPopoverOpen();
await userEvent.click(getByTestId(`options-filter-popover-item-${solutions[0]}`));
await userEvent.click(screen.getByTestId(`options-filter-popover-item-${solutions[0]}`));
expect(onChange).toHaveBeenCalledWith({
filterId: 'owner',
@ -85,7 +79,7 @@ describe('SolutionFilter ', () => {
});
it('should call onChange with [owner] when the last solution option selected is deselected', async () => {
const { getByTestId } = appMockRender.render(
renderWithTestingProviders(
<SolutionFilter
onChange={onChange}
selectedOptionKeys={[solutions[0]]}
@ -93,11 +87,11 @@ describe('SolutionFilter ', () => {
/>
);
await userEvent.click(getByTestId('options-filter-popover-button-owner'));
await userEvent.click(screen.getByTestId('options-filter-popover-button-owner'));
await waitForEuiPopoverOpen();
await userEvent.click(getByTestId(`options-filter-popover-item-${solutions[0]}`));
await userEvent.click(screen.getByTestId(`options-filter-popover-item-${solutions[0]}`));
expect(onChange).toHaveBeenCalledWith({
filterId: 'owner',
@ -108,44 +102,44 @@ describe('SolutionFilter ', () => {
describe('when no owner set', () => {
beforeEach(() => {
appMockRender = createAppMockRenderer({ owner: [] });
jest.clearAllMocks();
});
it('renders options correctly', async () => {
const { getByTestId } = appMockRender.render(
renderWithTestingProviders(
<SolutionFilter
onChange={onChange}
selectedOptionKeys={[]}
availableSolutions={solutions}
/>
/>,
{ wrapperProps: { owner: [] } }
);
expect(getByTestId('options-filter-popover-button-owner')).toBeInTheDocument();
expect(screen.getByTestId('options-filter-popover-button-owner')).toBeInTheDocument();
await userEvent.click(getByTestId('options-filter-popover-button-owner'));
await userEvent.click(screen.getByTestId('options-filter-popover-button-owner'));
await waitForEuiPopoverOpen();
expect(getByTestId(`options-filter-popover-item-${solutions[0]}`)).toBeInTheDocument();
expect(getByTestId(`options-filter-popover-item-${solutions[1]}`)).toBeInTheDocument();
expect(screen.getByTestId(`options-filter-popover-item-${solutions[0]}`)).toBeInTheDocument();
expect(screen.getByTestId(`options-filter-popover-item-${solutions[1]}`)).toBeInTheDocument();
});
// Flaky: https://github.com/elastic/kibana/issues/175240
it.skip('should call onChange with selected solution id when no option selected yet', async () => {
const { getByTestId } = appMockRender.render(
it('should call onChange with selected solution id when no option selected yet', async () => {
renderWithTestingProviders(
<SolutionFilter
onChange={onChange}
selectedOptionKeys={[]}
availableSolutions={solutions}
/>
/>,
{ wrapperProps: { owner: [] } }
);
await userEvent.click(getByTestId('options-filter-popover-button-owner'));
await userEvent.click(screen.getByTestId('options-filter-popover-button-owner'));
await waitForEuiPopoverOpen();
await userEvent.click(getByTestId(`options-filter-popover-item-${solutions[0]}`));
await userEvent.click(screen.getByTestId(`options-filter-popover-item-${solutions[0]}`));
expect(onChange).toHaveBeenCalledWith({
filterId: 'owner',
@ -154,19 +148,20 @@ describe('SolutionFilter ', () => {
});
it('should call onChange with [all solutions] when the last solution option selected is deselected', async () => {
const { getByTestId } = appMockRender.render(
renderWithTestingProviders(
<SolutionFilter
onChange={onChange}
selectedOptionKeys={[solutions[0]]}
availableSolutions={solutions}
/>
/>,
{ wrapperProps: { owner: [] } }
);
await userEvent.click(getByTestId('options-filter-popover-button-owner'));
await userEvent.click(screen.getByTestId('options-filter-popover-button-owner'));
await waitForEuiPopoverOpen();
await userEvent.click(getByTestId(`options-filter-popover-item-${solutions[0]}`));
await userEvent.click(screen.getByTestId(`options-filter-popover-item-${solutions[0]}`));
expect(onChange).toHaveBeenCalledWith({
filterId: 'owner',

View file

@ -19,8 +19,7 @@ const LABELS = {
inProgress: i18n.STATUS_IN_PROGRESS,
};
// FLAKY: https://github.com/elastic/kibana/issues/177334
describe.skip('StatusFilter', () => {
describe('StatusFilter', () => {
const onChange = jest.fn();
const defaultProps = {
selectedOptionKeys: [],

View file

@ -4,15 +4,14 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import React from 'react';
import { renderHook } from '@testing-library/react';
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
import type { FilterConfig, FilterConfigRenderParams } from './types';
import { useFilterConfig } from './use_filter_config';
import type { FilterOptions } from '../../../../common/ui';
import { CUSTOM_FIELD_KEY_PREFIX } from '../constants';
import { CustomFieldTypes } from '../../../../common/types/domain';
import { TestProviders } from '../../../common/mock';
const emptyFilterOptions: FilterOptions = {
search: '',
@ -51,10 +50,7 @@ describe('useFilterConfig', () => {
},
];
let appMockRender: AppMockRenderer;
beforeEach(() => {
appMockRender = createAppMockRenderer();
localStorage.clear();
});
@ -64,9 +60,7 @@ describe('useFilterConfig', () => {
it('should remove a selected option if the filter is deleted', async () => {
const { rerender } = renderHook(useFilterConfig, {
wrapper: ({ children }: React.PropsWithChildren) => (
<appMockRender.AppWrapper>{children}</appMockRender.AppWrapper>
),
wrapper: TestProviders,
initialProps: {
systemFilterConfig: filters,
onFilterOptionsChange,
@ -106,9 +100,7 @@ describe('useFilterConfig', () => {
);
const { result } = renderHook(useFilterConfig, {
wrapper: ({ children }: React.PropsWithChildren) => (
<appMockRender.AppWrapper>{children}</appMockRender.AppWrapper>
),
wrapper: TestProviders,
initialProps: {
systemFilterConfig: filters,
onFilterOptionsChange,

View file

@ -14,8 +14,8 @@ import { waitForComponentToUpdate } from '../../common/test_utils';
import { CaseStatuses, CustomFieldTypes, CaseSeverity } from '../../../common/types/domain';
import { SECURITY_SOLUTION_OWNER, OBSERVABILITY_OWNER } from '../../../common/constants';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
import { renderWithTestingProviders } from '../../common/mock';
import { DEFAULT_FILTER_OPTIONS } from '../../containers/constants';
import type { CasesTableFiltersProps } from './table_filters';
import { CasesTableFilters } from './table_filters';
@ -48,7 +48,6 @@ const props: CasesTableFiltersProps = {
};
describe('CasesTableFilters ', () => {
let appMockRender: AppMockRenderer;
// eslint-disable-next-line prefer-object-spread
const originalGetComputedStyle = Object.assign({}, window.getComputedStyle);
@ -88,7 +87,6 @@ describe('CasesTableFilters ', () => {
});
beforeEach(() => {
appMockRender = createAppMockRenderer();
(useGetTags as jest.Mock).mockReturnValue({ data: ['coke', 'pepsi'], isLoading: false });
(useGetCategories as jest.Mock).mockReturnValue({
data: ['twix', 'snickers'],
@ -105,18 +103,18 @@ describe('CasesTableFilters ', () => {
});
it('should render the case status filter dropdown', async () => {
appMockRender.render(<CasesTableFilters {...props} />);
renderWithTestingProviders(<CasesTableFilters {...props} />);
expect(await screen.findByTestId('options-filter-popover-button-status')).toBeInTheDocument();
});
it('should render the case severity filter dropdown', async () => {
appMockRender.render(<CasesTableFilters {...props} />);
renderWithTestingProviders(<CasesTableFilters {...props} />);
expect(await screen.findByTestId('options-filter-popover-button-severity')).toBeTruthy();
});
it('should call onFilterChange when the severity filter changes', async () => {
appMockRender.render(<CasesTableFilters {...props} />);
renderWithTestingProviders(<CasesTableFilters {...props} />);
await userEvent.click(await screen.findByTestId('options-filter-popover-button-severity'));
await waitForEuiPopoverOpen();
await userEvent.click(await screen.findByTestId('options-filter-popover-item-high'));
@ -125,7 +123,7 @@ describe('CasesTableFilters ', () => {
});
it('should call onFilterChange when selected tags change', async () => {
appMockRender.render(<CasesTableFilters {...props} />);
renderWithTestingProviders(<CasesTableFilters {...props} />);
await userEvent.click(await screen.findByTestId('options-filter-popover-button-tags'));
await waitForEuiPopoverOpen();
@ -135,7 +133,7 @@ describe('CasesTableFilters ', () => {
});
it('should call onFilterChange when selected category changes', async () => {
appMockRender.render(<CasesTableFilters {...props} />);
renderWithTestingProviders(<CasesTableFilters {...props} />);
await userEvent.click(await screen.findByTestId('options-filter-popover-button-category'));
await waitForEuiPopoverOpen();
@ -149,13 +147,11 @@ describe('CasesTableFilters ', () => {
license: { type: 'platinum' },
});
appMockRender = createAppMockRenderer({ license });
const { getByTestId, getByText } = appMockRender.render(<CasesTableFilters {...props} />);
await userEvent.click(getByTestId('options-filter-popover-button-assignees'));
renderWithTestingProviders(<CasesTableFilters {...props} />, { wrapperProps: { license } });
await userEvent.click(screen.getByTestId('options-filter-popover-button-assignees'));
await waitForEuiPopoverOpen();
await userEvent.click(getByText('Physical Dinosaur'));
await userEvent.click(screen.getByText('Physical Dinosaur'));
expect(onFilterChanged.mock.calls[0][0]).toMatchInlineSnapshot(`
Object {
@ -179,7 +175,7 @@ describe('CasesTableFilters ', () => {
});
it('should call onFilterChange when search changes', async () => {
appMockRender.render(<CasesTableFilters {...props} />);
renderWithTestingProviders(<CasesTableFilters {...props} />);
await userEvent.type(await screen.findByTestId('search-cases'), 'My search{enter}');
@ -189,7 +185,7 @@ describe('CasesTableFilters ', () => {
});
it('should change the initial value of search when the state changes', async () => {
const { rerender } = appMockRender.render(
const { rerender } = renderWithTestingProviders(
<CasesTableFilters
{...props}
filterOptions={{ ...props.filterOptions, search: 'My search' }}
@ -209,7 +205,7 @@ describe('CasesTableFilters ', () => {
});
it('should call onFilterChange when changing status', async () => {
appMockRender.render(<CasesTableFilters {...props} />);
renderWithTestingProviders(<CasesTableFilters {...props} />);
await userEvent.click(await screen.findByTestId('options-filter-popover-button-status'));
await waitForEuiPopoverOpen();
@ -222,7 +218,7 @@ describe('CasesTableFilters ', () => {
});
it('should show in progress status only when "in p" is searched in the filter', async () => {
appMockRender.render(<CasesTableFilters {...props} />);
renderWithTestingProviders(<CasesTableFilters {...props} />);
await userEvent.click(await screen.findByTestId('options-filter-popover-button-status'));
await waitForEuiPopoverOpen();
@ -250,9 +246,9 @@ describe('CasesTableFilters ', () => {
license: { type: 'platinum' },
});
appMockRender = createAppMockRenderer({ license });
appMockRender.render(<CasesTableFilters {...overrideProps} />);
renderWithTestingProviders(<CasesTableFilters {...overrideProps} />, {
wrapperProps: { license },
});
await userEvent.click(await screen.findByTestId('options-filter-popover-button-assignees'));
await waitForEuiPopoverOpen();
@ -281,35 +277,32 @@ describe('CasesTableFilters ', () => {
describe('Solution filter', () => {
it('shows Solution filter when provided more than 1 availableSolutions', async () => {
appMockRender = createAppMockRenderer({
owner: [SECURITY_SOLUTION_OWNER, OBSERVABILITY_OWNER],
});
appMockRender.render(
renderWithTestingProviders(
<CasesTableFilters
{...props}
availableSolutions={[SECURITY_SOLUTION_OWNER, OBSERVABILITY_OWNER]}
/>
/>,
{ wrapperProps: { owner: [SECURITY_SOLUTION_OWNER, OBSERVABILITY_OWNER] } }
);
expect(await screen.findByTestId('options-filter-popover-button-owner')).toBeInTheDocument();
});
it('does not show Solution filter when provided less than 1 availableSolutions', () => {
appMockRender = createAppMockRenderer({
owner: [],
renderWithTestingProviders(<CasesTableFilters {...props} availableSolutions={[]} />, {
wrapperProps: { owner: [] },
});
appMockRender.render(<CasesTableFilters {...props} availableSolutions={[]} />);
expect(screen.queryByTestId('options-filter-popover-button-owner')).not.toBeInTheDocument();
});
it('does not select a solution on initial render', async () => {
appMockRender = createAppMockRenderer({
owner: [SECURITY_SOLUTION_OWNER, OBSERVABILITY_OWNER],
});
appMockRender.render(
renderWithTestingProviders(
<CasesTableFilters
{...props}
availableSolutions={[SECURITY_SOLUTION_OWNER, OBSERVABILITY_OWNER]}
/>
/>,
{ wrapperProps: { owner: [SECURITY_SOLUTION_OWNER, OBSERVABILITY_OWNER] } }
);
expect(await screen.findByTestId('options-filter-popover-button-owner')).not.toHaveAttribute(
@ -318,10 +311,6 @@ describe('CasesTableFilters ', () => {
});
it('should reset the filter when deactivated', async () => {
appMockRender = createAppMockRenderer({
owner: [SECURITY_SOLUTION_OWNER, OBSERVABILITY_OWNER],
});
const overrideProps = {
...props,
filterOptions: {
@ -330,11 +319,12 @@ describe('CasesTableFilters ', () => {
},
};
appMockRender.render(
renderWithTestingProviders(
<CasesTableFilters
{...overrideProps}
availableSolutions={[SECURITY_SOLUTION_OWNER, OBSERVABILITY_OWNER]}
/>
/>,
{ wrapperProps: { owner: [SECURITY_SOLUTION_OWNER, OBSERVABILITY_OWNER] } }
);
await userEvent.click(screen.getByRole('button', { name: 'More' }));
@ -348,10 +338,6 @@ describe('CasesTableFilters ', () => {
});
it('should check all options when all options are selected', async () => {
appMockRender = createAppMockRenderer({
owner: [SECURITY_SOLUTION_OWNER, OBSERVABILITY_OWNER],
});
const overrideProps = {
...props,
filterOptions: {
@ -360,11 +346,12 @@ describe('CasesTableFilters ', () => {
},
};
appMockRender.render(
renderWithTestingProviders(
<CasesTableFilters
{...overrideProps}
availableSolutions={[SECURITY_SOLUTION_OWNER, OBSERVABILITY_OWNER]}
/>
/>,
{ wrapperProps: { owner: [SECURITY_SOLUTION_OWNER, OBSERVABILITY_OWNER] } }
);
await userEvent.click(await screen.findByTestId('options-filter-popover-button-owner'));
@ -381,7 +368,7 @@ describe('CasesTableFilters ', () => {
describe('assignees filter', () => {
it('should hide the assignees filters on basic license', async () => {
appMockRender.render(<CasesTableFilters {...props} />);
renderWithTestingProviders(<CasesTableFilters {...props} />);
expect(screen.queryByTestId('options-filter-popover-button-assignees')).toBeNull();
});
@ -391,8 +378,9 @@ describe('CasesTableFilters ', () => {
license: { type: 'platinum' },
});
appMockRender = createAppMockRenderer({ license });
appMockRender.render(<CasesTableFilters {...props} />);
renderWithTestingProviders(<CasesTableFilters {...props} />, {
wrapperProps: { license },
});
expect(
await screen.findByTestId('options-filter-popover-button-assignees')
@ -411,8 +399,9 @@ describe('CasesTableFilters ', () => {
license: { type: 'platinum' },
});
appMockRender = createAppMockRenderer({ license });
appMockRender.render(<CasesTableFilters {...overrideProps} />);
renderWithTestingProviders(<CasesTableFilters {...overrideProps} />, {
wrapperProps: { license },
});
// deactivate the assignees filter
await userEvent.click(screen.getByRole('button', { name: 'More' }));
@ -428,25 +417,28 @@ describe('CasesTableFilters ', () => {
describe('create case button', () => {
it('should not render the create case button when isSelectorView is false and onCreateCasePressed are not passed', () => {
appMockRender.render(<CasesTableFilters {...props} />);
renderWithTestingProviders(<CasesTableFilters {...props} />);
expect(screen.queryByTestId('cases-table-add-case-filter-bar')).not.toBeInTheDocument();
});
it('should render the create case button when isSelectorView is true and onCreateCasePressed are passed', async () => {
const onCreateCasePressed = jest.fn();
appMockRender.render(
renderWithTestingProviders(
<CasesTableFilters
{...props}
isSelectorView={true}
onCreateCasePressed={onCreateCasePressed}
/>
);
expect(await screen.findByTestId('cases-table-add-case-filter-bar')).toBeInTheDocument();
});
it('should call the onCreateCasePressed when create case is clicked', async () => {
const onCreateCasePressed = jest.fn();
appMockRender.render(
renderWithTestingProviders(
<CasesTableFilters
{...props}
isSelectorView={true}
@ -488,7 +480,7 @@ describe('CasesTableFilters ', () => {
});
it('should render its options', async () => {
appMockRender.render(<CasesTableFilters {...props} />);
renderWithTestingProviders(<CasesTableFilters {...props} />);
await userEvent.click(await screen.findByTestId('options-filter-popover-button-toggleKey'));
await waitForEuiPopoverOpen();
@ -500,7 +492,7 @@ describe('CasesTableFilters ', () => {
});
it('should call onFilterChange when On option changes', async () => {
appMockRender.render(<CasesTableFilters {...props} />);
renderWithTestingProviders(<CasesTableFilters {...props} />);
await userEvent.click(await screen.findByTestId('options-filter-popover-button-toggleKey'));
await waitForEuiPopoverOpen();
@ -519,7 +511,7 @@ describe('CasesTableFilters ', () => {
});
it('should call onFilterChange when Off option changes', async () => {
appMockRender.render(<CasesTableFilters {...props} />);
renderWithTestingProviders(<CasesTableFilters {...props} />);
await userEvent.click(await screen.findByTestId('options-filter-popover-button-toggleKey'));
await waitForEuiPopoverOpen();
@ -550,7 +542,8 @@ describe('CasesTableFilters ', () => {
},
},
};
appMockRender.render(<CasesTableFilters {...customProps} />);
renderWithTestingProviders(<CasesTableFilters {...customProps} />);
await userEvent.click(await screen.findByTestId('options-filter-popover-button-toggleKey'));
await waitForEuiPopoverOpen();
@ -586,7 +579,7 @@ describe('CasesTableFilters ', () => {
},
},
};
appMockRender.render(<CasesTableFilters {...customProps} />);
renderWithTestingProviders(<CasesTableFilters {...customProps} />);
await userEvent.click(await screen.findByTestId('options-filter-popover-button-filters'));
await userEvent.click(await screen.findByRole('option', { name: 'Toggle' }));
@ -622,12 +615,12 @@ describe('CasesTableFilters ', () => {
});
it('should not render the more button when in selector view', async () => {
appMockRender.render(<CasesTableFilters {...props} isSelectorView />);
renderWithTestingProviders(<CasesTableFilters {...props} isSelectorView />);
expect(screen.queryByRole('button', { name: 'More' })).not.toBeInTheDocument();
});
it('should render all options in the popover, including custom fields', async () => {
appMockRender.render(<CasesTableFilters {...props} />);
renderWithTestingProviders(<CasesTableFilters {...props} />);
expect(screen.getByRole('button', { name: 'More' })).toBeInTheDocument();
await userEvent.click(screen.getByRole('button', { name: 'More' }));
@ -640,7 +633,7 @@ describe('CasesTableFilters ', () => {
});
it('should not add text type custom fields', async () => {
appMockRender.render(<CasesTableFilters {...props} />);
renderWithTestingProviders(<CasesTableFilters {...props} />);
await userEvent.click(screen.getByRole('button', { name: 'More' }));
await waitForEuiPopoverOpen();
@ -649,7 +642,7 @@ describe('CasesTableFilters ', () => {
});
it('when a filter gets activated, it should be rendered at the end of the list', async () => {
appMockRender.render(<CasesTableFilters {...props} />);
renderWithTestingProviders(<CasesTableFilters {...props} />);
await userEvent.click(screen.getByRole('button', { name: 'More' }));
await waitFor(() => expect(screen.getAllByRole('option')).toHaveLength(5));
@ -665,7 +658,7 @@ describe('CasesTableFilters ', () => {
});
it('when a filter gets activated, it should be updated in the local storage', async () => {
appMockRender.render(<CasesTableFilters {...props} />);
renderWithTestingProviders(<CasesTableFilters {...props} />);
await userEvent.click(screen.getByRole('button', { name: 'More' }));
await waitFor(() => expect(screen.getAllByRole('option')).toHaveLength(5));
@ -702,7 +695,7 @@ describe('CasesTableFilters ', () => {
});
it('when a filter gets deactivated, it should be removed from the list', async () => {
appMockRender.render(<CasesTableFilters {...props} />);
renderWithTestingProviders(<CasesTableFilters {...props} />);
await userEvent.click(screen.getByRole('button', { name: 'More' }));
await waitFor(() => expect(screen.getAllByRole('option')).toHaveLength(5));
@ -726,7 +719,7 @@ describe('CasesTableFilters ', () => {
status: [CaseStatuses.open],
},
};
appMockRender.render(<CasesTableFilters {...customProps} />);
renderWithTestingProviders(<CasesTableFilters {...customProps} />);
await userEvent.click(await screen.findByRole('button', { name: 'More' }));
await userEvent.click(await screen.findByRole('option', { name: 'Status' }));
@ -744,7 +737,7 @@ describe('CasesTableFilters ', () => {
});
it('when a filter gets deactivated, it should be updated in the local storage', async () => {
appMockRender.render(<CasesTableFilters {...props} />);
renderWithTestingProviders(<CasesTableFilters {...props} />);
await userEvent.click(screen.getByRole('button', { name: 'More' }));
await waitFor(() => expect(screen.getAllByRole('option')).toHaveLength(5));
@ -797,7 +790,7 @@ describe('CasesTableFilters ', () => {
JSON.stringify(previousState)
);
appMockRender.render(<CasesTableFilters {...props} />);
renderWithTestingProviders(<CasesTableFilters {...props} />);
const filterBar = await screen.findByTestId('cases-table-filters');
let allFilters: HTMLElement[];
@ -827,7 +820,7 @@ describe('CasesTableFilters ', () => {
JSON.stringify(previousState)
);
appMockRender.render(<CasesTableFilters {...props} />);
renderWithTestingProviders(<CasesTableFilters {...props} />);
const filterBar = await screen.findByTestId('cases-table-filters');
let allFilters: HTMLElement[];
@ -857,7 +850,7 @@ describe('CasesTableFilters ', () => {
},
}));
appMockRender.render(<CasesTableFilters {...props} />);
renderWithTestingProviders(<CasesTableFilters {...props} />);
await userEvent.click(screen.getByRole('button', { name: 'More' }));
await waitFor(() => {
@ -883,7 +876,7 @@ describe('CasesTableFilters ', () => {
});
it('when a filter is active and is not last in the list, it should move the filter to last position after deactivating and activating', async () => {
appMockRender.render(<CasesTableFilters {...props} />);
renderWithTestingProviders(<CasesTableFilters {...props} />);
const filterBar = await screen.findByTestId('cases-table-filters');
let allFilters = within(filterBar).getAllByRole('button');
@ -918,7 +911,7 @@ describe('CasesTableFilters ', () => {
},
}));
appMockRender.render(<CasesTableFilters {...props} />);
renderWithTestingProviders(<CasesTableFilters {...props} />);
const filterBar = await screen.findByTestId('cases-table-filters');
let allFilters: HTMLElement[];
@ -955,7 +948,7 @@ describe('CasesTableFilters ', () => {
JSON.stringify(previousState)
);
appMockRender.render(<CasesTableFilters {...props} />);
renderWithTestingProviders(<CasesTableFilters {...props} />);
await userEvent.click(screen.getByRole('button', { name: 'More' }));
// we need any user action to trigger the filter config update
@ -1023,8 +1016,9 @@ describe('CasesTableFilters ', () => {
},
};
appMockRender = createAppMockRenderer({ license });
appMockRender.render(<CasesTableFilters {...overrideProps} />);
renderWithTestingProviders(<CasesTableFilters {...overrideProps} />, {
wrapperProps: { license },
});
const filters = [
{ testId: 'options-filter-popover-button-status', active: 2 },
@ -1070,8 +1064,9 @@ describe('CasesTableFilters ', () => {
},
};
appMockRender = createAppMockRenderer({ license });
appMockRender.render(<CasesTableFilters {...overrideProps} />);
renderWithTestingProviders(<CasesTableFilters {...overrideProps} />, {
wrapperProps: { license },
});
const filters = [
{ testId: 'options-filter-popover-button-status', active: 2 },

View file

@ -6,7 +6,7 @@
*/
import userEvent, { type UserEvent } from '@testing-library/user-event';
import { waitFor, renderHook } from '@testing-library/react';
import { waitFor, renderHook, screen } from '@testing-library/react';
import {
waitForEuiPopoverOpen,
waitForEuiContextMenuPanelTransition,
@ -15,22 +15,23 @@ import {
import { useActions } from './use_actions';
import { basicCase } from '../../containers/mock';
import * as api from '../../containers/api';
import type { AppMockRenderer } from '../../common/mock';
import { CaseStatuses } from '../../../common/types/domain';
import {
createAppMockRenderer,
noDeleteCasesPermissions,
onlyDeleteCasesPermission,
allCasesPermissions,
readCasesPermissions,
TestProviders,
renderWithTestingProviders,
} from '../../common/mock';
import React from 'react';
jest.mock('../../containers/api');
jest.mock('../../containers/user_profiles/api');
describe('useActions', () => {
let user: UserEvent;
let appMockRender: AppMockRenderer;
beforeAll(() => {
jest.useFakeTimers();
@ -43,17 +44,13 @@ describe('useActions', () => {
beforeEach(() => {
// Workaround for timeout via https://github.com/testing-library/user-event/issues/833#issuecomment-1171452841
user = userEvent.setup({ advanceTimers: jest.advanceTimersByTime });
appMockRender = createAppMockRenderer();
jest.clearAllMocks();
});
afterEach(async () => {
await appMockRender.clearQueryCache();
jest.clearAllMocks();
});
it('renders column actions', async () => {
const { result } = renderHook(() => useActions({ disableActions: false }), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
expect(result.current).toMatchInlineSnapshot(`
@ -70,53 +67,53 @@ describe('useActions', () => {
it('renders the popover', async () => {
const { result } = renderHook(() => useActions({ disableActions: false }), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
const comp = result.current.actions!.render(basicCase) as React.ReactElement;
const res = appMockRender.render(comp);
renderWithTestingProviders(comp);
expect(res.getByTestId(`case-action-popover-${basicCase.id}`)).toBeInTheDocument();
expect(screen.getByTestId(`case-action-popover-${basicCase.id}`)).toBeInTheDocument();
});
it('open the action popover', async () => {
const { result } = renderHook(() => useActions({ disableActions: false }), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
const comp = result.current.actions!.render(basicCase) as React.ReactElement;
const res = appMockRender.render(comp);
renderWithTestingProviders(comp);
await user.click(res.getByTestId(`case-action-popover-button-${basicCase.id}`));
await user.click(screen.getByTestId(`case-action-popover-button-${basicCase.id}`));
await waitForEuiPopoverOpen();
expect(res.getByText('Actions')).toBeInTheDocument();
expect(res.getByTestId(`case-action-status-panel-${basicCase.id}`)).toBeInTheDocument();
expect(res.getByTestId('cases-bulk-action-delete')).toBeInTheDocument();
expect(res.getByTestId('cases-action-copy-id')).toBeInTheDocument();
expect(screen.getByText('Actions')).toBeInTheDocument();
expect(screen.getByTestId(`case-action-status-panel-${basicCase.id}`)).toBeInTheDocument();
expect(screen.getByTestId('cases-bulk-action-delete')).toBeInTheDocument();
expect(screen.getByTestId('cases-action-copy-id')).toBeInTheDocument();
});
it('change the status of the case', async () => {
const updateCasesSpy = jest.spyOn(api, 'updateCases');
const { result } = renderHook(() => useActions({ disableActions: false }), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
const comp = result.current.actions!.render(basicCase) as React.ReactElement;
const res = appMockRender.render(comp);
renderWithTestingProviders(comp);
await user.click(res.getByTestId(`case-action-popover-button-${basicCase.id}`));
await user.click(screen.getByTestId(`case-action-popover-button-${basicCase.id}`));
await waitForEuiPopoverOpen();
await user.click(res.getByTestId(`case-action-status-panel-${basicCase.id}`));
await user.click(screen.getByTestId(`case-action-status-panel-${basicCase.id}`));
await waitForEuiContextMenuPanelTransition();
expect(res.getByTestId('cases-bulk-action-status-open')).toBeInTheDocument();
expect(res.getByTestId('cases-bulk-action-status-in-progress')).toBeInTheDocument();
expect(res.getByTestId('cases-bulk-action-status-closed')).toBeInTheDocument();
expect(screen.getByTestId('cases-bulk-action-status-open')).toBeInTheDocument();
expect(screen.getByTestId('cases-bulk-action-status-in-progress')).toBeInTheDocument();
expect(screen.getByTestId('cases-bulk-action-status-closed')).toBeInTheDocument();
await user.click(res.getByTestId('cases-bulk-action-status-in-progress'));
await user.click(screen.getByTestId('cases-bulk-action-status-in-progress'));
await waitFor(() => {
expect(updateCasesSpy).toHaveBeenCalled();
@ -127,24 +124,24 @@ describe('useActions', () => {
const updateCasesSpy = jest.spyOn(api, 'updateCases');
const { result } = renderHook(() => useActions({ disableActions: false }), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
const comp = result.current.actions!.render(basicCase) as React.ReactElement;
const res = appMockRender.render(comp);
renderWithTestingProviders(comp);
await user.click(res.getByTestId(`case-action-popover-button-${basicCase.id}`));
await user.click(screen.getByTestId(`case-action-popover-button-${basicCase.id}`));
await waitForEuiPopoverOpen();
await user.click(res.getByTestId(`case-action-severity-panel-${basicCase.id}`));
await user.click(screen.getByTestId(`case-action-severity-panel-${basicCase.id}`));
await waitForEuiContextMenuPanelTransition();
expect(res.getByTestId('cases-bulk-action-severity-low')).toBeInTheDocument();
expect(res.getByTestId('cases-bulk-action-severity-medium')).toBeInTheDocument();
expect(res.getByTestId('cases-bulk-action-severity-high')).toBeInTheDocument();
expect(res.getByTestId('cases-bulk-action-severity-critical')).toBeInTheDocument();
expect(screen.getByTestId('cases-bulk-action-severity-low')).toBeInTheDocument();
expect(screen.getByTestId('cases-bulk-action-severity-medium')).toBeInTheDocument();
expect(screen.getByTestId('cases-bulk-action-severity-high')).toBeInTheDocument();
expect(screen.getByTestId('cases-bulk-action-severity-critical')).toBeInTheDocument();
await user.click(res.getByTestId('cases-bulk-action-severity-medium'));
await user.click(screen.getByTestId('cases-bulk-action-severity-medium'));
await waitFor(() => {
expect(updateCasesSpy).toHaveBeenCalled();
@ -162,16 +159,16 @@ describe('useActions', () => {
});
const { result } = renderHook(() => useActions({ disableActions: false }), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
const comp = result.current.actions!.render(basicCase) as React.ReactElement;
const res = appMockRender.render(comp);
renderWithTestingProviders(comp);
await user.click(res.getByTestId(`case-action-popover-button-${basicCase.id}`));
await user.click(screen.getByTestId(`case-action-popover-button-${basicCase.id}`));
await waitForEuiPopoverOpen();
await user.click(res.getByTestId('cases-action-copy-id'));
await user.click(screen.getByTestId('cases-action-copy-id'));
expect(navigator.clipboard.writeText).toHaveBeenCalledWith(basicCase.id);
@ -185,22 +182,22 @@ describe('useActions', () => {
const deleteSpy = jest.spyOn(api, 'deleteCases');
const { result } = renderHook(() => useActions({ disableActions: false }), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
const comp = result.current.actions!.render(basicCase) as React.ReactElement;
const res = appMockRender.render(comp);
renderWithTestingProviders(comp);
await user.click(res.getByTestId(`case-action-popover-button-${basicCase.id}`));
await user.click(screen.getByTestId(`case-action-popover-button-${basicCase.id}`));
await waitForEuiPopoverOpen();
await user.click(res.getByTestId('cases-bulk-action-delete'));
await user.click(screen.getByTestId('cases-bulk-action-delete'));
await waitFor(() => {
expect(res.getByTestId('confirm-delete-case-modal')).toBeInTheDocument();
expect(screen.getByTestId('confirm-delete-case-modal')).toBeInTheDocument();
});
await user.click(res.getByTestId('confirmModalConfirmButton'));
await user.click(screen.getByTestId('confirmModalConfirmButton'));
await waitFor(() => {
expect(deleteSpy).toHaveBeenCalled();
@ -209,24 +206,24 @@ describe('useActions', () => {
it('closes the modal', async () => {
const { result } = renderHook(() => useActions({ disableActions: false }), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
const comp = result.current.actions!.render(basicCase) as React.ReactElement;
const res = appMockRender.render(comp);
renderWithTestingProviders(comp);
await user.click(res.getByTestId(`case-action-popover-button-${basicCase.id}`));
await user.click(screen.getByTestId(`case-action-popover-button-${basicCase.id}`));
await waitForEuiPopoverOpen();
await user.click(res.getByTestId('cases-bulk-action-delete'));
await user.click(screen.getByTestId('cases-bulk-action-delete'));
await waitFor(() => {
expect(res.getByTestId('confirm-delete-case-modal')).toBeInTheDocument();
expect(screen.getByTestId('confirm-delete-case-modal')).toBeInTheDocument();
});
await user.click(res.getByTestId('confirmModalCancelButton'));
await user.click(screen.getByTestId('confirmModalCancelButton'));
expect(res.queryByTestId('confirm-delete-case-modal')).toBeFalsy();
expect(screen.queryByTestId('confirm-delete-case-modal')).not.toBeInTheDocument();
});
});
@ -235,34 +232,34 @@ describe('useActions', () => {
const updateCasesSpy = jest.spyOn(api, 'updateCases');
const { result } = renderHook(() => useActions({ disableActions: false }), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
const comp = result.current.actions!.render(basicCase) as React.ReactElement;
const res = appMockRender.render(comp);
renderWithTestingProviders(comp);
await user.click(res.getByTestId(`case-action-popover-button-${basicCase.id}`));
await user.click(screen.getByTestId(`case-action-popover-button-${basicCase.id}`));
await waitForEuiPopoverOpen();
await user.click(res.getByTestId('cases-bulk-action-tags'));
await user.click(screen.getByTestId('cases-bulk-action-tags'));
await waitFor(() => {
expect(res.getByTestId('cases-edit-tags-flyout')).toBeInTheDocument();
expect(screen.getByTestId('cases-edit-tags-flyout')).toBeInTheDocument();
});
await waitFor(() => {
expect(res.getByText('coke')).toBeInTheDocument();
expect(screen.getByText('coke')).toBeInTheDocument();
});
await user.click(res.getByText('coke'));
await user.click(res.getByTestId('cases-edit-tags-flyout-submit'));
await user.click(screen.getByText('coke'));
await user.click(screen.getByTestId('cases-edit-tags-flyout-submit'));
await waitFor(() => {
expect(updateCasesSpy).toHaveBeenCalled();
});
await waitFor(() => {
expect(res.queryByTestId('cases-edit-tags-flyout')).toBeFalsy();
expect(screen.queryByTestId('cases-edit-tags-flyout')).not.toBeInTheDocument();
});
});
@ -270,210 +267,217 @@ describe('useActions', () => {
const updateCasesSpy = jest.spyOn(api, 'updateCases');
const { result } = renderHook(() => useActions({ disableActions: false }), {
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
});
const comp = result.current.actions!.render(basicCase) as React.ReactElement;
const res = appMockRender.render(comp);
renderWithTestingProviders(comp);
await user.click(res.getByTestId(`case-action-popover-button-${basicCase.id}`));
await user.click(screen.getByTestId(`case-action-popover-button-${basicCase.id}`));
await waitForEuiPopoverOpen();
await user.click(res.getByTestId('cases-bulk-action-assignees'));
await user.click(screen.getByTestId('cases-bulk-action-assignees'));
await waitFor(() => {
expect(res.getByTestId('cases-edit-assignees-flyout')).toBeInTheDocument();
expect(screen.getByTestId('cases-edit-assignees-flyout')).toBeInTheDocument();
});
await waitFor(() => {
expect(res.getByText('Damaged Raccoon')).toBeInTheDocument();
expect(screen.getByText('Damaged Raccoon')).toBeInTheDocument();
});
await user.click(res.getByText('Damaged Raccoon'));
await user.click(res.getByTestId('cases-edit-assignees-flyout-submit'));
await user.click(screen.getByText('Damaged Raccoon'));
await user.click(screen.getByTestId('cases-edit-assignees-flyout-submit'));
await waitFor(() => {
expect(updateCasesSpy).toHaveBeenCalled();
});
await waitFor(() => {
expect(res.queryByTestId('cases-edit-assignees-flyout')).toBeFalsy();
expect(screen.queryByTestId('cases-edit-assignees-flyout')).not.toBeInTheDocument();
});
});
});
describe('Permissions', () => {
it('shows the correct actions with all permissions', async () => {
appMockRender = createAppMockRenderer({ permissions: allCasesPermissions() });
const { result } = renderHook(() => useActions({ disableActions: false }), {
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} permissions={allCasesPermissions()} />,
});
const comp = result.current.actions!.render(basicCase) as React.ReactElement;
const res = appMockRender.render(comp);
renderWithTestingProviders(comp);
await user.click(res.getByTestId(`case-action-popover-button-${basicCase.id}`));
await user.click(screen.getByTestId(`case-action-popover-button-${basicCase.id}`));
await waitForEuiPopoverOpen();
expect(res.getByTestId(`case-action-status-panel-${basicCase.id}`)).toBeInTheDocument();
expect(res.getByTestId(`case-action-severity-panel-${basicCase.id}`)).toBeInTheDocument();
expect(res.getByTestId('cases-bulk-action-delete')).toBeInTheDocument();
expect(res.getByTestId(`actions-separator-${basicCase.id}`)).toBeInTheDocument();
expect(res.getByTestId('cases-action-copy-id')).toBeInTheDocument();
expect(screen.getByTestId(`case-action-status-panel-${basicCase.id}`)).toBeInTheDocument();
expect(screen.getByTestId(`case-action-severity-panel-${basicCase.id}`)).toBeInTheDocument();
expect(screen.getByTestId('cases-bulk-action-delete')).toBeInTheDocument();
expect(screen.getByTestId(`actions-separator-${basicCase.id}`)).toBeInTheDocument();
expect(screen.getByTestId('cases-action-copy-id')).toBeInTheDocument();
});
it('shows the correct actions with no delete permissions', async () => {
appMockRender = createAppMockRenderer({ permissions: noDeleteCasesPermissions() });
const { result } = renderHook(() => useActions({ disableActions: false }), {
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} permissions={noDeleteCasesPermissions()} />,
});
const comp = result.current.actions!.render(basicCase) as React.ReactElement;
const res = appMockRender.render(comp);
renderWithTestingProviders(comp, {
wrapperProps: { permissions: noDeleteCasesPermissions() },
});
await user.click(res.getByTestId(`case-action-popover-button-${basicCase.id}`));
await user.click(screen.getByTestId(`case-action-popover-button-${basicCase.id}`));
await waitForEuiPopoverOpen();
expect(res.getByTestId(`case-action-status-panel-${basicCase.id}`)).toBeInTheDocument();
expect(res.getByTestId(`case-action-severity-panel-${basicCase.id}`)).toBeInTheDocument();
expect(res.getByTestId('cases-action-copy-id')).toBeInTheDocument();
expect(res.queryByTestId('cases-bulk-action-delete')).toBeFalsy();
expect(res.queryByTestId(`actions-separator-${basicCase.id}`)).toBeFalsy();
expect(screen.getByTestId(`case-action-status-panel-${basicCase.id}`)).toBeInTheDocument();
expect(screen.getByTestId(`case-action-severity-panel-${basicCase.id}`)).toBeInTheDocument();
expect(screen.getByTestId('cases-action-copy-id')).toBeInTheDocument();
expect(screen.queryByTestId('cases-bulk-action-delete')).not.toBeInTheDocument();
expect(screen.queryByTestId(`actions-separator-${basicCase.id}`)).not.toBeInTheDocument();
});
it('shows the correct actions with only delete permissions', async () => {
appMockRender = createAppMockRenderer({ permissions: onlyDeleteCasesPermission() });
const { result } = renderHook(() => useActions({ disableActions: false }), {
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} permissions={onlyDeleteCasesPermission()} />,
});
const comp = result.current.actions!.render(basicCase) as React.ReactElement;
const res = appMockRender.render(comp);
renderWithTestingProviders(comp, {
wrapperProps: { permissions: onlyDeleteCasesPermission() },
});
await user.click(res.getByTestId(`case-action-popover-button-${basicCase.id}`));
await user.click(screen.getByTestId(`case-action-popover-button-${basicCase.id}`));
await waitForEuiPopoverOpen();
expect(res.queryByTestId(`case-action-status-panel-${basicCase.id}`)).toBeFalsy();
expect(res.queryByTestId(`case-action-severity-panel-${basicCase.id}`)).toBeFalsy();
expect(res.getByTestId('cases-action-copy-id')).toBeInTheDocument();
expect(res.getByTestId('cases-bulk-action-delete')).toBeInTheDocument();
expect(res.queryByTestId(`actions-separator-${basicCase.id}`)).toBeFalsy();
expect(
screen.queryByTestId(`case-action-status-panel-${basicCase.id}`)
).not.toBeInTheDocument();
expect(
screen.queryByTestId(`case-action-severity-panel-${basicCase.id}`)
).not.toBeInTheDocument();
expect(screen.getByTestId('cases-action-copy-id')).toBeInTheDocument();
expect(screen.getByTestId('cases-bulk-action-delete')).toBeInTheDocument();
expect(screen.queryByTestId(`actions-separator-${basicCase.id}`)).not.toBeInTheDocument();
});
it('returns null if the user does not have update or delete permissions', async () => {
appMockRender = createAppMockRenderer({ permissions: readCasesPermissions() });
const { result } = renderHook(() => useActions({ disableActions: false }), {
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} permissions={readCasesPermissions()} />,
});
expect(result.current.actions).toBe(null);
});
it('disables the action correctly', async () => {
appMockRender = createAppMockRenderer({ permissions: onlyDeleteCasesPermission() });
const { result } = renderHook(() => useActions({ disableActions: true }), {
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} permissions={onlyDeleteCasesPermission()} />,
});
const comp = result.current.actions!.render(basicCase) as React.ReactElement;
const res = appMockRender.render(comp);
renderWithTestingProviders(comp, {
wrapperProps: { permissions: onlyDeleteCasesPermission() },
});
await waitFor(() => {
expect(res.getByTestId(`case-action-popover-button-${basicCase.id}`)).toBeDisabled();
expect(screen.getByTestId(`case-action-popover-button-${basicCase.id}`)).toBeDisabled();
});
});
it('shows actions when user only has reopenCase permission and only when case is closed', async () => {
appMockRender = createAppMockRenderer({
permissions: {
all: false,
read: true,
create: false,
update: false,
delete: false,
reopenCase: true,
push: false,
connectors: true,
settings: false,
createComment: false,
assign: false,
},
});
const permissions = {
all: false,
read: true,
create: false,
update: false,
delete: false,
reopenCase: true,
push: false,
connectors: true,
settings: false,
createComment: false,
assign: false,
};
const { result } = renderHook(() => useActions({ disableActions: false }), {
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} permissions={permissions} />,
});
expect(result.current.actions).not.toBe(null);
const caseWithClosedStatus = { ...basicCase, status: CaseStatuses.closed };
const comp = result.current.actions!.render(caseWithClosedStatus) as React.ReactElement;
const res = appMockRender.render(comp);
renderWithTestingProviders(comp, {
wrapperProps: { permissions },
});
await user.click(res.getByTestId(`case-action-popover-button-${basicCase.id}`));
await user.click(screen.getByTestId(`case-action-popover-button-${basicCase.id}`));
await waitForEuiPopoverOpen();
expect(res.queryByTestId(`case-action-status-panel-${basicCase.id}`)).toBeInTheDocument();
expect(res.queryByTestId(`case-action-severity-panel-${basicCase.id}`)).toBeFalsy();
expect(res.queryByTestId('cases-bulk-action-delete')).toBeFalsy();
expect(res.getByTestId('cases-action-copy-id')).toBeInTheDocument();
expect(res.queryByTestId(`actions-separator-${basicCase.id}`)).toBeFalsy();
expect(screen.getByTestId(`case-action-status-panel-${basicCase.id}`)).toBeInTheDocument();
expect(
screen.queryByTestId(`case-action-severity-panel-${basicCase.id}`)
).not.toBeInTheDocument();
expect(screen.queryByTestId('cases-bulk-action-delete')).not.toBeInTheDocument();
expect(screen.getByTestId('cases-action-copy-id')).toBeInTheDocument();
expect(screen.queryByTestId(`actions-separator-${basicCase.id}`)).not.toBeInTheDocument();
});
it('shows actions with combination of reopenCase and other permissions', async () => {
appMockRender = createAppMockRenderer({
permissions: {
all: false,
read: true,
create: false,
update: false,
delete: true,
reopenCase: true,
push: false,
connectors: true,
settings: false,
createComment: false,
assign: false,
},
});
const permissions = {
all: false,
read: true,
create: false,
update: false,
delete: true,
reopenCase: true,
push: false,
connectors: true,
settings: false,
createComment: false,
assign: false,
};
const { result } = renderHook(() => useActions({ disableActions: false }), {
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} permissions={permissions} />,
});
expect(result.current.actions).not.toBe(null);
const caseWithClosedStatus = { ...basicCase, status: CaseStatuses.closed };
const comp = result.current.actions!.render(caseWithClosedStatus) as React.ReactElement;
const res = appMockRender.render(comp);
renderWithTestingProviders(comp, {
wrapperProps: { permissions },
});
await user.click(res.getByTestId(`case-action-popover-button-${basicCase.id}`));
await user.click(screen.getByTestId(`case-action-popover-button-${basicCase.id}`));
await waitForEuiPopoverOpen();
expect(res.queryByTestId(`case-action-status-panel-${basicCase.id}`)).toBeInTheDocument();
expect(res.queryByTestId(`case-action-severity-panel-${basicCase.id}`)).toBeFalsy();
expect(res.getByTestId('cases-bulk-action-delete')).toBeInTheDocument();
expect(res.getByTestId('cases-action-copy-id')).toBeInTheDocument();
expect(screen.getByTestId(`case-action-status-panel-${basicCase.id}`)).toBeInTheDocument();
expect(
screen.queryByTestId(`case-action-severity-panel-${basicCase.id}`)
).not.toBeInTheDocument();
expect(screen.getByTestId('cases-bulk-action-delete')).toBeInTheDocument();
expect(screen.getByTestId('cases-action-copy-id')).toBeInTheDocument();
});
it('shows no actions with everything false but read', async () => {
appMockRender = createAppMockRenderer({
permissions: {
all: false,
read: true,
create: false,
update: false,
delete: false,
reopenCase: false,
push: false,
connectors: true,
settings: false,
createComment: false,
assign: false,
},
});
const permissions = {
all: false,
read: true,
create: false,
update: false,
delete: false,
reopenCase: false,
push: false,
connectors: true,
settings: false,
createComment: false,
assign: false,
};
const { result } = renderHook(() => useActions({ disableActions: false }), {
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} permissions={permissions} />,
});
expect(result.current.actions).toBe(null);

View file

@ -225,9 +225,10 @@ describe('useAllCasesQueryParams', () => {
await waitFor(() => {
expect(result.current.queryParams).toStrictEqual(defaultStateWithValues.queryParams);
expect(result.current.filterOptions).toStrictEqual(defaultStateWithValues.filterOptions);
});
expect(result.current.filterOptions).toStrictEqual(defaultStateWithValues.filterOptions);
act(() => {
result.current.setFilterOptions(DEFAULT_CASES_TABLE_STATE.filterOptions);
});
@ -238,8 +239,9 @@ describe('useAllCasesQueryParams', () => {
await waitFor(() => {
expect(result.current.queryParams).toStrictEqual(DEFAULT_CASES_TABLE_STATE.queryParams);
expect(result.current.filterOptions).toStrictEqual(DEFAULT_CASES_TABLE_STATE.filterOptions);
});
expect(result.current.filterOptions).toStrictEqual(DEFAULT_CASES_TABLE_STATE.filterOptions);
});
it('urlParams take precedence over localStorage query params values', () => {

View file

@ -8,16 +8,16 @@
import React from 'react';
import { EuiContextMenu } from '@elastic/eui';
import userEvent from '@testing-library/user-event';
import { waitFor, renderHook } from '@testing-library/react';
import { waitFor, renderHook, screen } from '@testing-library/react';
import type { AppMockRenderer } from '../../common/mock';
import {
allCasesPermissions,
createAppMockRenderer,
noDeleteCasesPermissions,
onlyDeleteCasesPermission,
noReopenCasesPermissions,
onlyReopenCasesPermission,
TestProviders,
renderWithTestingProviders,
} from '../../common/mock';
import { useBulkActions } from './use_bulk_actions';
import * as api from '../../containers/api';
@ -27,12 +27,10 @@ jest.mock('../../containers/api');
jest.mock('../../containers/user_profiles/api');
describe('useBulkActions', () => {
let appMockRender: AppMockRenderer;
const onAction = jest.fn();
const onActionSuccess = jest.fn();
beforeEach(() => {
appMockRender = createAppMockRenderer();
jest.clearAllMocks();
});
@ -41,7 +39,7 @@ describe('useBulkActions', () => {
const { result } = renderHook(
() => useBulkActions({ onAction, onActionSuccess, selectedCases: [basicCase] }),
{
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
}
);
@ -192,29 +190,28 @@ describe('useBulkActions', () => {
const { result } = renderHook(
() => useBulkActions({ onAction, onActionSuccess, selectedCases: [basicCase] }),
{
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
}
);
const modals = result.current.modals;
const panels = result.current.panels;
const res = appMockRender.render(
renderWithTestingProviders(
<>
<EuiContextMenu initialPanelId={0} panels={panels} />
{modals}
</>
);
await userEvent.click(res.getByTestId('case-bulk-action-status'));
await userEvent.click(screen.getByTestId('case-bulk-action-status'));
await waitFor(() => {
expect(res.getByTestId('cases-bulk-action-status-open')).toBeInTheDocument();
expect(res.getByTestId('cases-bulk-action-status-in-progress')).toBeInTheDocument();
expect(res.getByTestId('cases-bulk-action-status-closed')).toBeInTheDocument();
});
expect(await screen.findByTestId('cases-bulk-action-status-open')).toBeInTheDocument();
await userEvent.click(res.getByTestId('cases-bulk-action-status-in-progress'), {
expect(screen.getByTestId('cases-bulk-action-status-in-progress')).toBeInTheDocument();
expect(screen.getByTestId('cases-bulk-action-status-closed')).toBeInTheDocument();
await userEvent.click(screen.getByTestId('cases-bulk-action-status-in-progress'), {
pointerEventsCheck: 0,
});
@ -229,30 +226,29 @@ describe('useBulkActions', () => {
const { result } = renderHook(
() => useBulkActions({ onAction, onActionSuccess, selectedCases: [basicCase] }),
{
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
}
);
const modals = result.current.modals;
const panels = result.current.panels;
const res = appMockRender.render(
renderWithTestingProviders(
<>
<EuiContextMenu initialPanelId={0} panels={panels} />
{modals}
</>
);
await userEvent.click(res.getByTestId('case-bulk-action-severity'));
await userEvent.click(screen.getByTestId('case-bulk-action-severity'));
await waitFor(() => {
expect(res.getByTestId('cases-bulk-action-severity-low')).toBeInTheDocument();
expect(res.getByTestId('cases-bulk-action-severity-medium')).toBeInTheDocument();
expect(res.getByTestId('cases-bulk-action-severity-high')).toBeInTheDocument();
expect(res.getByTestId('cases-bulk-action-severity-critical')).toBeInTheDocument();
});
expect(await screen.findByTestId('cases-bulk-action-severity-low')).toBeInTheDocument();
await userEvent.click(res.getByTestId('cases-bulk-action-severity-medium'), {
expect(screen.getByTestId('cases-bulk-action-severity-medium')).toBeInTheDocument();
expect(screen.getByTestId('cases-bulk-action-severity-high')).toBeInTheDocument();
expect(screen.getByTestId('cases-bulk-action-severity-critical')).toBeInTheDocument();
await userEvent.click(screen.getByTestId('cases-bulk-action-severity-medium'), {
pointerEventsCheck: 0,
});
@ -268,24 +264,24 @@ describe('useBulkActions', () => {
const { result } = renderHook(
() => useBulkActions({ onAction, onActionSuccess, selectedCases: [basicCase] }),
{
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
}
);
let modals = result.current.modals;
const panels = result.current.panels;
const res = appMockRender.render(
const { rerender } = renderWithTestingProviders(
<>
<EuiContextMenu initialPanelId={0} panels={panels} />
{modals}
</>
);
await userEvent.click(res.getByTestId('cases-bulk-action-delete'));
await userEvent.click(screen.getByTestId('cases-bulk-action-delete'));
modals = result.current.modals;
res.rerender(
rerender(
<>
<EuiContextMenu initialPanelId={0} panels={panels} />
{modals}
@ -293,10 +289,10 @@ describe('useBulkActions', () => {
);
await waitFor(() => {
expect(res.getByTestId('confirm-delete-case-modal')).toBeInTheDocument();
expect(screen.getByTestId('confirm-delete-case-modal')).toBeInTheDocument();
});
await userEvent.click(res.getByTestId('confirmModalConfirmButton'));
await userEvent.click(screen.getByTestId('confirmModalConfirmButton'));
await waitFor(() => {
expect(deleteSpy).toHaveBeenCalled();
@ -307,24 +303,24 @@ describe('useBulkActions', () => {
const { result } = renderHook(
() => useBulkActions({ onAction, onActionSuccess, selectedCases: [basicCase] }),
{
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
}
);
let modals = result.current.modals;
const panels = result.current.panels;
const res = appMockRender.render(
const { rerender } = renderWithTestingProviders(
<>
<EuiContextMenu initialPanelId={0} panels={panels} />
{modals}
</>
);
await userEvent.click(res.getByTestId('cases-bulk-action-delete'));
await userEvent.click(screen.getByTestId('cases-bulk-action-delete'));
modals = result.current.modals;
res.rerender(
rerender(
<>
<EuiContextMenu initialPanelId={0} panels={panels} />
{modals}
@ -332,20 +328,20 @@ describe('useBulkActions', () => {
);
await waitFor(() => {
expect(res.getByTestId('confirm-delete-case-modal')).toBeInTheDocument();
expect(screen.getByTestId('confirm-delete-case-modal')).toBeInTheDocument();
});
await userEvent.click(res.getByTestId('confirmModalCancelButton'));
await userEvent.click(screen.getByTestId('confirmModalCancelButton'));
modals = result.current.modals;
res.rerender(
rerender(
<>
<EuiContextMenu initialPanelId={0} panels={panels} />
{modals}
</>
);
expect(res.queryByTestId('confirm-delete-case-modal')).toBeFalsy();
expect(screen.queryByTestId('confirm-delete-case-modal')).not.toBeInTheDocument();
});
});
});
@ -357,25 +353,25 @@ describe('useBulkActions', () => {
const { result } = renderHook(
() => useBulkActions({ onAction, onActionSuccess, selectedCases: [basicCase] }),
{
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
}
);
let flyouts = result.current.flyouts;
const panels = result.current.panels;
const res = appMockRender.render(
const { rerender } = renderWithTestingProviders(
<>
<EuiContextMenu initialPanelId={0} panels={panels} />
{flyouts}
</>
);
await userEvent.click(res.getByTestId('cases-bulk-action-tags'));
await userEvent.click(screen.getByTestId('cases-bulk-action-tags'));
flyouts = result.current.flyouts;
res.rerender(
rerender(
<>
<EuiContextMenu initialPanelId={0} panels={panels} />
{flyouts}
@ -383,15 +379,15 @@ describe('useBulkActions', () => {
);
await waitFor(() => {
expect(res.getByTestId('cases-edit-tags-flyout')).toBeInTheDocument();
expect(screen.getByTestId('cases-edit-tags-flyout')).toBeInTheDocument();
});
await waitFor(() => {
expect(res.getByText('coke')).toBeInTheDocument();
expect(screen.getByText('coke')).toBeInTheDocument();
});
await userEvent.click(res.getByText('coke'));
await userEvent.click(res.getByTestId('cases-edit-tags-flyout-submit'));
await userEvent.click(screen.getByText('coke'));
await userEvent.click(screen.getByTestId('cases-edit-tags-flyout-submit'));
await waitFor(() => {
expect(updateCasesSpy).toHaveBeenCalled();
@ -404,25 +400,25 @@ describe('useBulkActions', () => {
const { result } = renderHook(
() => useBulkActions({ onAction, onActionSuccess, selectedCases: [basicCase] }),
{
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
}
);
let flyouts = result.current.flyouts;
const panels = result.current.panels;
const res = appMockRender.render(
const { rerender } = renderWithTestingProviders(
<>
<EuiContextMenu initialPanelId={0} panels={panels} />
{flyouts}
</>
);
await userEvent.click(res.getByTestId('cases-bulk-action-assignees'));
await userEvent.click(screen.getByTestId('cases-bulk-action-assignees'));
flyouts = result.current.flyouts;
res.rerender(
rerender(
<>
<EuiContextMenu initialPanelId={0} panels={panels} />
{flyouts}
@ -430,15 +426,15 @@ describe('useBulkActions', () => {
);
await waitFor(() => {
expect(res.getByTestId('cases-edit-assignees-flyout')).toBeInTheDocument();
expect(screen.getByTestId('cases-edit-assignees-flyout')).toBeInTheDocument();
});
await waitFor(() => {
expect(res.getByText('Damaged Raccoon')).toBeInTheDocument();
expect(screen.getByText('Damaged Raccoon')).toBeInTheDocument();
});
await userEvent.click(res.getByText('Damaged Raccoon'));
await userEvent.click(res.getByTestId('cases-edit-assignees-flyout-submit'));
await userEvent.click(screen.getByText('Damaged Raccoon'));
await userEvent.click(screen.getByTestId('cases-edit-assignees-flyout-submit'));
await waitFor(() => {
expect(updateCasesSpy).toHaveBeenCalled();
@ -448,148 +444,137 @@ describe('useBulkActions', () => {
describe('Permissions', () => {
it('shows the correct actions with all permissions', async () => {
appMockRender = createAppMockRenderer({ permissions: allCasesPermissions() });
const { result } = renderHook(
() => useBulkActions({ onAction, onActionSuccess, selectedCases: [basicCase] }),
{
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
}
);
const modals = result.current.modals;
const panels = result.current.panels;
const res = appMockRender.render(
renderWithTestingProviders(
<>
<EuiContextMenu initialPanelId={0} panels={panels} />
{modals}
</>
</>,
{ wrapperProps: { permissions: allCasesPermissions() } }
);
await waitFor(() => {
expect(res.getByTestId('case-bulk-action-status')).toBeInTheDocument();
expect(res.getByTestId('cases-bulk-action-delete')).toBeInTheDocument();
expect(res.getByTestId('bulk-actions-separator')).toBeInTheDocument();
});
expect(await screen.findByTestId('case-bulk-action-status')).toBeInTheDocument();
expect(screen.getByTestId('cases-bulk-action-delete')).toBeInTheDocument();
expect(screen.getByTestId('bulk-actions-separator')).toBeInTheDocument();
});
it('shows the correct actions with no delete permissions', async () => {
appMockRender = createAppMockRenderer({ permissions: noDeleteCasesPermissions() });
const { result } = renderHook(
() => useBulkActions({ onAction, onActionSuccess, selectedCases: [basicCase] }),
{
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} permissions={noDeleteCasesPermissions()} />,
}
);
const modals = result.current.modals;
const panels = result.current.panels;
const res = appMockRender.render(
renderWithTestingProviders(
<>
<EuiContextMenu initialPanelId={0} panels={panels} />
{modals}
</>
</>,
{ wrapperProps: { permissions: noDeleteCasesPermissions() } }
);
await waitFor(() => {
expect(res.getByTestId('case-bulk-action-status')).toBeInTheDocument();
expect(res.queryByTestId('cases-bulk-action-delete')).toBeFalsy();
expect(res.queryByTestId('bulk-actions-separator')).toBeFalsy();
});
expect(await screen.findByTestId('case-bulk-action-status')).toBeInTheDocument();
expect(screen.queryByTestId('cases-bulk-action-delete')).not.toBeInTheDocument();
expect(screen.queryByTestId('bulk-actions-separator')).not.toBeInTheDocument();
});
it('shows the correct actions with only delete permissions', async () => {
appMockRender = createAppMockRenderer({ permissions: onlyDeleteCasesPermission() });
const { result } = renderHook(
() => useBulkActions({ onAction, onActionSuccess, selectedCases: [basicCase] }),
{
wrapper: appMockRender.AppWrapper,
wrapper: (props) => (
<TestProviders {...props} permissions={onlyDeleteCasesPermission()} />
),
}
);
const modals = result.current.modals;
const panels = result.current.panels;
const res = appMockRender.render(
renderWithTestingProviders(
<>
<EuiContextMenu initialPanelId={0} panels={panels} />
{modals}
</>
</>,
{ wrapperProps: { permissions: onlyDeleteCasesPermission() } }
);
await waitFor(() => {
expect(res.queryByTestId('case-bulk-action-status')).toBeFalsy();
expect(res.getByTestId('cases-bulk-action-delete')).toBeInTheDocument();
expect(res.queryByTestId('bulk-actions-separator')).toBeFalsy();
});
expect(screen.queryByTestId('case-bulk-action-status')).not.toBeInTheDocument();
expect(screen.getByTestId('cases-bulk-action-delete')).toBeInTheDocument();
expect(screen.queryByTestId('bulk-actions-separator')).not.toBeInTheDocument();
});
it('shows the correct actions with no reopen permissions', async () => {
appMockRender = createAppMockRenderer({ permissions: noReopenCasesPermissions() });
const { result } = renderHook(
() => useBulkActions({ onAction, onActionSuccess, selectedCases: [basicCaseClosed] }),
{
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} permissions={noReopenCasesPermissions()} />,
}
);
const modals = result.current.modals;
const panels = result.current.panels;
const res = appMockRender.render(
renderWithTestingProviders(
<>
<EuiContextMenu initialPanelId={0} panels={panels} />
{modals}
</>
</>,
{ wrapperProps: { permissions: noReopenCasesPermissions() } }
);
await waitFor(() => {
expect(res.queryByTestId('case-bulk-action-status')).toBeInTheDocument();
res.queryByTestId('case-bulk-action-status')?.click();
});
expect(await screen.findByTestId('case-bulk-action-status')).toBeInTheDocument();
await userEvent.click(screen.getByTestId('case-bulk-action-status'));
await waitFor(() => {
expect(res.queryByTestId('cases-bulk-action-status-open')).toBeDisabled();
expect(res.queryByTestId('cases-bulk-action-status-in-progress')).toBeDisabled();
expect(res.queryByTestId('cases-bulk-action-status-closed')).toBeDisabled();
});
expect(await screen.findByTestId('cases-bulk-action-status-open')).toBeDisabled();
expect(screen.queryByTestId('cases-bulk-action-status-in-progress')).toBeDisabled();
expect(screen.queryByTestId('cases-bulk-action-status-closed')).toBeDisabled();
});
it('shows the correct actions with reopen permissions', async () => {
appMockRender = createAppMockRenderer({ permissions: onlyReopenCasesPermission() });
const { result } = renderHook(
() => useBulkActions({ onAction, onActionSuccess, selectedCases: [basicCaseClosed] }),
{
wrapper: appMockRender.AppWrapper,
wrapper: (props) => (
<TestProviders {...props} permissions={onlyReopenCasesPermission()} />
),
}
);
const { modals, flyouts, panels } = result.current;
const renderResult = appMockRender.render(
renderWithTestingProviders(
<>
<EuiContextMenu initialPanelId={0} panels={panels} />
{modals}
{flyouts}
</>
</>,
{ wrapperProps: { permissions: onlyReopenCasesPermission() } }
);
await waitFor(() => {
expect(renderResult.queryByTestId('case-bulk-action-status')).toBeInTheDocument();
expect(renderResult.queryByTestId('case-bulk-action-severity')).toBeInTheDocument();
expect(renderResult.queryByTestId('bulk-actions-separator')).not.toBeInTheDocument();
expect(renderResult.queryByTestId('case-bulk-action-delete')).not.toBeInTheDocument();
});
expect(await screen.findByTestId('case-bulk-action-status')).toBeInTheDocument();
expect(screen.getByTestId('case-bulk-action-severity')).toBeInTheDocument();
expect(screen.queryByTestId('bulk-actions-separator')).not.toBeInTheDocument();
expect(screen.queryByTestId('case-bulk-action-delete')).not.toBeInTheDocument();
userEvent.click(renderResult.getByTestId('case-bulk-action-status'));
await userEvent.click(screen.getByTestId('case-bulk-action-status'));
await waitFor(() => {
expect(renderResult.queryByTestId('cases-bulk-action-status-open')).not.toBeDisabled();
expect(
renderResult.queryByTestId('cases-bulk-action-status-in-progress')
).not.toBeDisabled();
expect(renderResult.queryByTestId('cases-bulk-action-status-closed')).not.toBeDisabled();
});
expect(await screen.findByTestId('cases-bulk-action-status-open')).not.toBeDisabled();
expect(screen.queryByTestId('cases-bulk-action-status-in-progress')).not.toBeDisabled();
expect(screen.queryByTestId('cases-bulk-action-status-closed')).not.toBeDisabled();
});
});
});

View file

@ -13,12 +13,13 @@ import type { GetCasesColumn } from './use_cases_columns';
import { ExternalServiceColumn, useCasesColumns } from './use_cases_columns';
import { useGetCasesMockState } from '../../containers/mock';
import { connectors, useCaseConfigureResponse } from '../configure_cases/__mock__';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer, readCasesPermissions, TestProviders } from '../../common/mock';
import { renderHook } from '@testing-library/react';
import { readCasesPermissions, renderWithTestingProviders, TestProviders } from '../../common/mock';
import { renderHook, screen } from '@testing-library/react';
import { CaseStatuses, CustomFieldTypes } from '../../../common/types/domain';
import { userProfilesMap } from '../../containers/user_profiles/api.mock';
import { useGetCaseConfiguration } from '../../containers/configure/use_get_case_configuration';
import { coreMock } from '@kbn/core/public/mocks';
jest.mock('../../containers/configure/use_get_case_configuration');
@ -40,7 +41,6 @@ const DEFAULT_SELECTED_COLUMNS = [
];
describe('useCasesColumns ', () => {
let appMockRender: AppMockRenderer;
const useCasesColumnsProps: GetCasesColumn = {
filterStatus: [CaseStatuses.open],
userProfiles: userProfilesMap,
@ -50,7 +50,7 @@ describe('useCasesColumns ', () => {
beforeEach(() => {
jest.clearAllMocks();
appMockRender = createAppMockRenderer();
useGetCaseConfigurationMock.mockImplementation(() => useCaseConfigureResponse);
});
@ -59,8 +59,6 @@ describe('useCasesColumns ', () => {
license: { type: 'platinum' },
});
appMockRender = createAppMockRenderer({ license });
const { result } = renderHook(
() =>
useCasesColumns({
@ -71,7 +69,7 @@ describe('useCasesColumns ', () => {
})),
}),
{
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} license={license} />,
}
);
@ -176,10 +174,8 @@ describe('useCasesColumns ', () => {
license: { type: 'platinum' },
});
appMockRender = createAppMockRenderer({ license });
const { result } = renderHook(() => useCasesColumns(useCasesColumnsProps), {
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} license={license} />,
});
expect(result.current).toMatchInlineSnapshot(`
@ -276,12 +272,10 @@ describe('useCasesColumns ', () => {
license: { type: 'platinum' },
});
appMockRender = createAppMockRenderer({ license });
const { result } = renderHook(
() => useCasesColumns({ ...useCasesColumnsProps, isSelectorView: true }),
{
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} license={license} />,
}
);
@ -332,7 +326,7 @@ describe('useCasesColumns ', () => {
const { result } = renderHook(
() => useCasesColumns({ ...useCasesColumnsProps, isSelectorView: true }),
{
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
}
);
@ -383,7 +377,7 @@ describe('useCasesColumns ', () => {
const { result } = renderHook(
() => useCasesColumns({ ...useCasesColumnsProps, isSelectorView: true }),
{
wrapper: appMockRender.AppWrapper,
wrapper: TestProviders,
}
);
@ -431,10 +425,8 @@ describe('useCasesColumns ', () => {
});
it('does not shows the actions if the user does not have the right permissions', async () => {
appMockRender = createAppMockRenderer({ permissions: readCasesPermissions() });
const { result } = renderHook(() => useCasesColumns(useCasesColumnsProps), {
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} permissions={readCasesPermissions()} />,
});
expect(result.current).toMatchInlineSnapshot(`
@ -521,7 +513,6 @@ describe('useCasesColumns ', () => {
const textLabel = 'Text Label';
const toggleLabel = 'Toggle Label';
appMockRender = createAppMockRenderer({ permissions: readCasesPermissions() });
useGetCaseConfigurationMock.mockImplementation(() => ({
data: {
...useCaseConfigureResponse.data,
@ -544,7 +535,7 @@ describe('useCasesColumns ', () => {
],
}),
{
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} permissions={readCasesPermissions()} />,
}
);
@ -708,30 +699,32 @@ describe('useCasesColumns ', () => {
});
it('shows the connectors icon if the user has read access to actions', async () => {
const result = appMockRender.render(
renderWithTestingProviders(
<ExternalServiceColumn
theCase={useGetCasesMockState.data.cases[1]}
connectors={connectors}
/>
);
expect(result.getByTestId('cases-table-connector-icon')).toBeInTheDocument();
expect(screen.getByTestId('cases-table-connector-icon')).toBeInTheDocument();
});
it('hides the connectors icon if the user does not have read access to actions', async () => {
appMockRender.coreStart.application.capabilities = {
...appMockRender.coreStart.application.capabilities,
const coreStart = coreMock.createStart();
coreStart.application.capabilities = {
...coreStart.application.capabilities,
actions: { save: false, show: false },
};
const result = appMockRender.render(
renderWithTestingProviders(
<ExternalServiceColumn
theCase={useGetCasesMockState.data.cases[1]}
connectors={connectors}
/>
/>,
{ wrapperProps: { coreStart } }
);
expect(result.queryByTestId('cases-table-connector-icon')).toBe(null);
expect(screen.queryByTestId('cases-table-connector-icon')).toBe(null);
});
});
});

View file

@ -8,14 +8,14 @@
import { licensingMock } from '@kbn/licensing-plugin/public/mocks';
import { renderHook } from '@testing-library/react';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
import { TestProviders } from '../../common/mock';
import { useCasesFeatures } from '../../common/use_cases_features';
import { useCasesColumnsConfiguration } from './use_cases_columns_configuration';
import { useGetCaseConfiguration } from '../../containers/configure/use_get_case_configuration';
import { useCaseConfigureResponse } from '../configure_cases/__mock__';
import { CustomFieldTypes } from '../../../common/types/domain';
import React from 'react';
jest.mock('../../common/use_cases_features');
jest.mock('../../containers/configure/use_get_case_configuration');
@ -24,14 +24,12 @@ const useGetCaseConfigurationMock = useGetCaseConfiguration as jest.Mock;
const useCasesFeaturesMock = useCasesFeatures as jest.Mock;
describe('useCasesColumnsConfiguration ', () => {
let appMockRender: AppMockRenderer;
const license = licensingMock.createLicense({
license: { type: 'platinum' },
});
beforeEach(() => {
jest.clearAllMocks();
appMockRender = createAppMockRenderer({ license });
useCasesFeaturesMock.mockReturnValue({
caseAssignmentAuthorized: true,
isAlertsEnabled: true,
@ -41,7 +39,7 @@ describe('useCasesColumnsConfiguration ', () => {
it('returns all columns correctly', async () => {
const { result } = renderHook(() => useCasesColumnsConfiguration(), {
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} license={license} />,
});
expect(result.current).toMatchInlineSnapshot(`
@ -129,7 +127,7 @@ describe('useCasesColumnsConfiguration ', () => {
});
const { result } = renderHook(() => useCasesColumnsConfiguration(), {
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} license={license} />,
});
expect(result.current.assignees).toMatchInlineSnapshot(`
@ -149,7 +147,7 @@ describe('useCasesColumnsConfiguration ', () => {
});
const { result } = renderHook(() => useCasesColumnsConfiguration(), {
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} license={license} />,
});
expect(result.current.totalAlerts).toMatchInlineSnapshot(`
@ -180,7 +178,7 @@ describe('useCasesColumnsConfiguration ', () => {
}));
const { result } = renderHook(() => useCasesColumnsConfiguration(), {
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} license={license} />,
});
expect(result.current[textKey]).toEqual({

View file

@ -8,11 +8,10 @@
import { licensingMock } from '@kbn/licensing-plugin/public/mocks';
import { renderHook } from '@testing-library/react';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
import { TestProviders } from '../../common/mock';
import { useCasesColumnsSelection } from './use_cases_columns_selection';
import { useCasesColumnsConfiguration } from './use_cases_columns_configuration';
import React from 'react';
jest.mock('./use_cases_columns_configuration');
@ -38,14 +37,11 @@ const casesColumnsConfig = {
};
describe('useCasesColumnsSelection ', () => {
let appMockRender: AppMockRenderer;
const license = licensingMock.createLicense({
license: { type: 'platinum' },
});
beforeEach(() => {
appMockRender = createAppMockRenderer({ license });
useCasesColumnsConfigurationMock.mockReturnValue(casesColumnsConfig);
localStorage.clear();
@ -57,7 +53,7 @@ describe('useCasesColumnsSelection ', () => {
it('returns the expected selectedColumns when the localstorage is empty', async () => {
const { result } = renderHook(() => useCasesColumnsSelection(), {
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} license={license} />,
});
expect(result.current).toMatchInlineSnapshot(`
@ -96,7 +92,7 @@ describe('useCasesColumnsSelection ', () => {
localStorage.setItem(localStorageKey, JSON.stringify(selectedColumns));
const { result } = renderHook(() => useCasesColumnsSelection(), {
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} license={license} />,
});
expect(result.current).toMatchInlineSnapshot(`

View file

@ -6,24 +6,23 @@
*/
import { renderHook, act } from '@testing-library/react';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
import { casesQueriesKeys } from '../../containers/constants';
import { useRefreshCases } from './use_on_refresh_cases';
import { TestProviders, createTestQueryClient } from '../../common/mock';
import React from 'react';
describe('useRefreshCases', () => {
let appMockRender: AppMockRenderer;
beforeEach(() => {
appMockRender = createAppMockRenderer();
jest.clearAllMocks();
});
it('should refresh data on refresh', async () => {
const queryClientSpy = jest.spyOn(appMockRender.queryClient, 'invalidateQueries');
const queryClient = createTestQueryClient();
const queryClientSpy = jest.spyOn(queryClient, 'invalidateQueries');
const { result } = renderHook(() => useRefreshCases(), {
wrapper: appMockRender.AppWrapper,
wrapper: (props) => <TestProviders {...props} queryClient={queryClient} />,
});
act(() => {

View file

@ -5,24 +5,26 @@
* 2.0.
*/
import { act, waitFor, screen, waitForElementToBeRemoved } from '@testing-library/react';
import userEvent, { type UserEvent } from '@testing-library/user-event';
import { waitFor, screen, waitForElementToBeRemoved } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import React from 'react';
import type { AppMockRenderer } from '../../common/mock';
import { MAX_DOCS_PER_PAGE } from '../../../common/constants';
import {
createTestQueryClient,
noCasesPermissions,
onlyDeleteCasesPermission,
createAppMockRenderer,
renderWithTestingProviders,
writeCasesPermissions,
} from '../../common/mock';
import { casesQueriesKeys } from '../../containers/constants';
import { basicCase } from '../../containers/mock';
import { CasesTableUtilityBar } from './utility_bar';
import { useCasesLocalStorage } from '../../common/use_cases_local_storage';
jest.mock('../../common/use_cases_local_storage');
describe('Severity form field', () => {
let user: UserEvent;
let appMockRender: AppMockRenderer;
const deselectCases = jest.fn();
const localStorageKey = 'securitySolution.cases.utilityBar.hideMaxLimitWarning';
@ -42,25 +44,19 @@ describe('Severity form field', () => {
};
beforeAll(() => {
jest.useFakeTimers();
jest.mocked(useCasesLocalStorage).mockReturnValue([false, jest.fn()]);
});
afterAll(() => {
jest.useRealTimers();
sessionStorage.removeItem(localStorageKey);
});
beforeEach(() => {
jest.useFakeTimers();
// Workaround for timeout via https://github.com/testing-library/user-event/issues/833#issuecomment-1171452841
user = userEvent.setup({
advanceTimers: jest.advanceTimersByTime,
});
appMockRender = createAppMockRenderer();
jest.clearAllMocks();
});
it('renders', async () => {
appMockRender.render(<CasesTableUtilityBar {...props} />);
renderWithTestingProviders(<CasesTableUtilityBar {...props} />);
expect(await screen.findByText('Showing 5 of 5 cases')).toBeInTheDocument();
expect(await screen.findByText('Selected 1 case')).toBeInTheDocument();
@ -81,7 +77,7 @@ describe('Severity form field', () => {
},
};
appMockRender.render(<CasesTableUtilityBar {...updatedProps} />);
renderWithTestingProviders(<CasesTableUtilityBar {...updatedProps} />);
expect(await screen.findByText('Showing 10 of 20 cases')).toBeInTheDocument();
expect(await screen.findByText('Selected 1 case')).toBeInTheDocument();
@ -98,7 +94,7 @@ describe('Severity form field', () => {
},
};
appMockRender.render(<CasesTableUtilityBar {...updatedProps} />);
renderWithTestingProviders(<CasesTableUtilityBar {...updatedProps} />);
expect(await screen.findByText('Showing 10 of 20 cases')).toBeInTheDocument();
expect(await screen.findByText('Selected 1 case')).toBeInTheDocument();
@ -117,92 +113,100 @@ describe('Severity form field', () => {
},
};
appMockRender.render(<CasesTableUtilityBar {...updatedProps} />);
renderWithTestingProviders(<CasesTableUtilityBar {...updatedProps} />);
expect(await screen.findByText('Showing 0 of 0 cases')).toBeInTheDocument();
});
it('renders columns popover button when isSelectorView=False', async () => {
appMockRender.render(<CasesTableUtilityBar {...props} />);
renderWithTestingProviders(<CasesTableUtilityBar {...props} />);
expect(await screen.findByTestId('column-selection-popover-button')).toBeInTheDocument();
});
it('does not render columns popover button when isSelectorView=True', async () => {
appMockRender.render(<CasesTableUtilityBar {...props} isSelectorView={true} />);
renderWithTestingProviders(<CasesTableUtilityBar {...props} isSelectorView={true} />);
expect(screen.queryByTestId('column-selection-popover-button')).not.toBeInTheDocument();
});
it('opens the bulk actions correctly', async () => {
appMockRender.render(<CasesTableUtilityBar {...props} />);
renderWithTestingProviders(<CasesTableUtilityBar {...props} />);
await user.click(await screen.findByTestId('case-table-bulk-actions-link-icon'));
await userEvent.click(await screen.findByTestId('case-table-bulk-actions-link-icon'));
expect(await screen.findByTestId('case-table-bulk-actions-context-menu'));
});
it('closes the bulk actions correctly', async () => {
appMockRender.render(<CasesTableUtilityBar {...props} />);
renderWithTestingProviders(<CasesTableUtilityBar {...props} />);
await user.click(await screen.findByTestId('case-table-bulk-actions-link-icon'));
await userEvent.click(await screen.findByTestId('case-table-bulk-actions-link-icon'));
expect(await screen.findByTestId('case-table-bulk-actions-context-menu'));
await user.click(await screen.findByTestId('case-table-bulk-actions-link-icon'));
await userEvent.click(await screen.findByTestId('case-table-bulk-actions-link-icon'));
await waitForElementToBeRemoved(screen.queryByTestId('case-table-bulk-actions-context-menu'));
});
it('refresh correctly', async () => {
appMockRender.render(<CasesTableUtilityBar {...props} />);
const queryClientSpy = jest.spyOn(appMockRender.queryClient, 'invalidateQueries');
const queryClient = createTestQueryClient();
renderWithTestingProviders(<CasesTableUtilityBar {...props} />, {
wrapperProps: { queryClient },
});
await user.click(await screen.findByTestId('all-cases-refresh-link-icon'));
const queryClientSpy = jest.spyOn(queryClient, 'invalidateQueries');
await userEvent.click(await screen.findByTestId('all-cases-refresh-link-icon'));
await waitFor(() => {
expect(deselectCases).toHaveBeenCalled();
expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.casesList());
expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.tags());
expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.userProfiles());
});
expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.casesList());
expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.tags());
expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.userProfiles());
});
it('does not show the bulk actions without update & delete permissions', async () => {
appMockRender = createAppMockRenderer({ permissions: noCasesPermissions() });
appMockRender.render(<CasesTableUtilityBar {...props} />);
renderWithTestingProviders(<CasesTableUtilityBar {...props} />, {
wrapperProps: { permissions: noCasesPermissions() },
});
expect(screen.queryByTestId('case-table-bulk-actions-link-icon')).not.toBeInTheDocument();
});
it('does show the bulk actions with only delete permissions', async () => {
appMockRender = createAppMockRenderer({ permissions: onlyDeleteCasesPermission() });
appMockRender.render(<CasesTableUtilityBar {...props} />);
renderWithTestingProviders(<CasesTableUtilityBar {...props} />, {
wrapperProps: { permissions: onlyDeleteCasesPermission() },
});
expect(await screen.findByTestId('case-table-bulk-actions-link-icon')).toBeInTheDocument();
});
it('does show the bulk actions with update permissions', async () => {
appMockRender = createAppMockRenderer({ permissions: writeCasesPermissions() });
appMockRender.render(<CasesTableUtilityBar {...props} />);
renderWithTestingProviders(<CasesTableUtilityBar {...props} />, {
wrapperProps: { permissions: writeCasesPermissions() },
});
expect(await screen.findByTestId('case-table-bulk-actions-link-icon')).toBeInTheDocument();
});
it('does not show the bulk actions if there are not selected cases', async () => {
appMockRender.render(<CasesTableUtilityBar {...props} selectedCases={[]} />);
renderWithTestingProviders(<CasesTableUtilityBar {...props} selectedCases={[]} />);
expect(screen.queryByTestId('case-table-bulk-actions-link-icon')).not.toBeInTheDocument();
expect(screen.queryByText('Showing 0 cases')).not.toBeInTheDocument();
});
it('shows the clear filter button', async () => {
appMockRender.render(<CasesTableUtilityBar {...props} showClearFiltersButton={true} />);
renderWithTestingProviders(<CasesTableUtilityBar {...props} showClearFiltersButton={true} />);
expect(await screen.findByTestId('all-cases-clear-filters-link-icon')).toBeInTheDocument();
});
it('clears the filters correctly', async () => {
appMockRender.render(<CasesTableUtilityBar {...props} showClearFiltersButton={true} />);
renderWithTestingProviders(<CasesTableUtilityBar {...props} showClearFiltersButton={true} />);
await user.click(await screen.findByTestId('all-cases-clear-filters-link-icon'));
await userEvent.click(await screen.findByTestId('all-cases-clear-filters-link-icon'));
await waitFor(() => {
expect(props.onClearFilters).toHaveBeenCalled();
@ -210,39 +214,42 @@ describe('Severity form field', () => {
});
it('does show the bulk actions with only assign permissions', async () => {
appMockRender = createAppMockRenderer({
permissions: {
...noCasesPermissions(),
assign: true,
renderWithTestingProviders(<CasesTableUtilityBar {...props} />, {
wrapperProps: {
permissions: {
...noCasesPermissions(),
assign: true,
},
},
});
appMockRender.render(<CasesTableUtilityBar {...props} />);
expect(await screen.findByTestId('case-table-bulk-actions-link-icon')).toBeInTheDocument();
});
it('shows bulk actions when only assignCase and update permissions are present', async () => {
appMockRender = createAppMockRenderer({
permissions: {
...noCasesPermissions(),
assign: true,
update: true,
renderWithTestingProviders(<CasesTableUtilityBar {...props} />, {
wrapperProps: {
permissions: {
...noCasesPermissions(),
assign: true,
update: true,
},
},
});
appMockRender.render(<CasesTableUtilityBar {...props} />);
expect(await screen.findByTestId('case-table-bulk-actions-link-icon')).toBeInTheDocument();
});
it('shows bulk actions when only assignCase and delete permissions are present', async () => {
appMockRender = createAppMockRenderer({
permissions: {
...noCasesPermissions(),
assign: true,
delete: true,
renderWithTestingProviders(<CasesTableUtilityBar {...props} />, {
wrapperProps: {
permissions: {
...noCasesPermissions(),
assign: true,
delete: true,
},
},
});
appMockRender.render(<CasesTableUtilityBar {...props} />);
expect(await screen.findByTestId('case-table-bulk-actions-link-icon')).toBeInTheDocument();
});
@ -265,7 +272,7 @@ describe('Severity form field', () => {
async (size) => {
const newPageIndex = MAX_DOCS_PER_PAGE / size - 2;
appMockRender.render(
renderWithTestingProviders(
<CasesTableUtilityBar
{...{
...newProps,
@ -287,7 +294,7 @@ describe('Severity form field', () => {
async (size) => {
const newPageIndex = MAX_DOCS_PER_PAGE / size - 1;
appMockRender.render(
renderWithTestingProviders(
<CasesTableUtilityBar
{...{
...newProps,
@ -309,7 +316,7 @@ describe('Severity form field', () => {
async (size) => {
const newPageIndex = MAX_DOCS_PER_PAGE / size;
appMockRender.render(
renderWithTestingProviders(
<CasesTableUtilityBar
{...{
...newProps,
@ -327,7 +334,7 @@ describe('Severity form field', () => {
);
it('should show dismiss and do not show again buttons correctly', async () => {
appMockRender.render(
renderWithTestingProviders(
<CasesTableUtilityBar
{...{
...newProps,
@ -342,7 +349,7 @@ describe('Severity form field', () => {
});
it('should dismiss warning correctly', async () => {
appMockRender.render(
renderWithTestingProviders(
<CasesTableUtilityBar
{...{
...newProps,
@ -354,31 +361,16 @@ describe('Severity form field', () => {
expect(await screen.findByTestId('all-cases-maximum-limit-warning')).toBeInTheDocument();
expect(await screen.findByTestId('dismiss-warning')).toBeInTheDocument();
await user.click(await screen.findByTestId('dismiss-warning'));
await userEvent.click(await screen.findByTestId('dismiss-warning'));
expect(screen.queryByTestId('all-cases-maximum-limit-warning')).not.toBeInTheDocument();
});
describe('do not show button', () => {
beforeAll(() => {
jest.useFakeTimers();
});
it('should show the limit warning', async () => {
jest.mocked(useCasesLocalStorage).mockReturnValue([false, jest.fn()]);
afterEach(() => {
jest.clearAllTimers();
});
afterAll(() => {
jest.useRealTimers();
sessionStorage.removeItem(localStorageKey);
});
beforeEach(() => {
jest.clearAllMocks();
});
it('should set storage key correctly', async () => {
appMockRender.render(
renderWithTestingProviders(
<CasesTableUtilityBar
{...{
...newProps,
@ -389,12 +381,28 @@ describe('Severity form field', () => {
expect(await screen.findByTestId('all-cases-maximum-limit-warning')).toBeInTheDocument();
expect(await screen.findByTestId('do-not-show-warning')).toBeInTheDocument();
});
expect(localStorage.getItem(localStorageKey)).toBe('false');
it('should NOT show the limit warning if it has been dismissed', async () => {
jest.mocked(useCasesLocalStorage).mockReturnValue([true, jest.fn()]);
renderWithTestingProviders(
<CasesTableUtilityBar
{...{
...newProps,
pagination: { ...newProps.pagination, pageSize: 100, pageIndex: 100 },
}}
/>
);
expect(screen.queryByTestId('all-cases-maximum-limit-warning')).not.toBeInTheDocument();
});
it('should hide warning correctly when do not show button clicked', async () => {
appMockRender.render(
const setDoNotShowAgain = jest.fn();
jest.mocked(useCasesLocalStorage).mockReturnValue([false, setDoNotShowAgain]);
renderWithTestingProviders(
<CasesTableUtilityBar
{...{
...newProps,
@ -403,17 +411,11 @@ describe('Severity form field', () => {
/>
);
expect(await screen.findByTestId('all-cases-maximum-limit-warning')).toBeInTheDocument();
expect(await screen.findByTestId('do-not-show-warning')).toBeInTheDocument();
await userEvent.click(await screen.findByTestId('do-not-show-warning'));
await user.click(await screen.findByTestId('do-not-show-warning'));
act(() => {
jest.advanceTimersByTime(1000);
await waitFor(() => {
expect(setDoNotShowAgain).toHaveBeenCalledWith(true);
});
expect(screen.queryByTestId('all-cases-maximum-limit-warning')).not.toBeInTheDocument();
expect(localStorage.getItem(localStorageKey)).toBe('true');
});
});
});

View file

@ -6,27 +6,25 @@
*/
import React from 'react';
import { screen } from '@testing-library/react';
import { licensingMock } from '@kbn/licensing-plugin/public/mocks';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
import { renderWithTestingProviders } from '../../common/mock';
import { CaseCallouts } from './case_callouts';
describe('CaseCallouts ', () => {
let appMockRender: AppMockRenderer;
beforeEach(() => {
jest.clearAllMocks();
appMockRender = createAppMockRenderer();
});
it('renders', () => {
const result = appMockRender.render(<CaseCallouts />);
expect(result.getByTestId('case-callouts')).toBeInTheDocument();
renderWithTestingProviders(<CaseCallouts />);
expect(screen.getByTestId('case-callouts')).toBeInTheDocument();
});
it('shows the platinum license callout if the user has less than platinum license', () => {
const result = appMockRender.render(<CaseCallouts />);
expect(result.getByTestId('case-callout-license-info')).toBeInTheDocument();
renderWithTestingProviders(<CaseCallouts />);
expect(screen.getByTestId('case-callout-license-info')).toBeInTheDocument();
});
it('does not show the platinum license callout if the user has platinum license', () => {
@ -34,9 +32,8 @@ describe('CaseCallouts ', () => {
license: { type: 'platinum' },
});
appMockRender = createAppMockRenderer({ license });
const result = appMockRender.render(<CaseCallouts />);
renderWithTestingProviders(<CaseCallouts />, { wrapperProps: { license } });
expect(result.queryByTestId('case-callout-license-info')).toBeNull();
expect(screen.queryByTestId('case-callout-license-info')).toBeNull();
});
});

View file

@ -6,22 +6,20 @@
*/
import React from 'react';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
import { screen } from '@testing-library/react';
import { PlatinumLicenseCallout } from './platinum_callout';
import { renderWithTestingProviders } from '../../common/mock';
describe('PlatinumLicenseCallout ', () => {
let appMockRender: AppMockRenderer;
beforeEach(() => {
jest.clearAllMocks();
appMockRender = createAppMockRenderer();
});
it('renders', () => {
const result = appMockRender.render(<PlatinumLicenseCallout />);
renderWithTestingProviders(<PlatinumLicenseCallout />);
expect(result.getByTestId('case-callout-license-info')).toBeInTheDocument();
expect(result.getByText('Upgrade to an appropriate license')).toBeInTheDocument();
expect(screen.getByTestId('case-callout-license-info')).toBeInTheDocument();
expect(screen.getByText('Upgrade to an appropriate license')).toBeInTheDocument();
});
});

View file

@ -11,11 +11,16 @@ import { EuiTitle } from '@elastic/eui';
interface ActionBarStatusItemProps {
title: string | ReactNode;
children?: ReactNode;
dataTestSubj?: string;
}
const ActionBarStatusItemComponent: React.FC<ActionBarStatusItemProps> = ({ title, children }) => (
const ActionBarStatusItemComponent: React.FC<ActionBarStatusItemProps> = ({
title,
children,
dataTestSubj,
}) => (
<>
<EuiTitle size="xxs">
<EuiTitle size="xxs" data-test-subj={dataTestSubj}>
<strong>{title}</strong>
</EuiTitle>
{children}

View file

@ -6,8 +6,7 @@
*/
import React from 'react';
import { mount } from 'enzyme';
import { render, screen, waitFor } from '@testing-library/react';
import { screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { basicCase, basicCaseClosed } from '../../containers/mock';
@ -17,7 +16,7 @@ import {
allCasesPermissions,
noDeleteCasesPermissions,
noUpdateCasesPermissions,
TestProviders,
renderWithTestingProviders,
} from '../../common/mock';
import { useGetCaseConnectors } from '../../containers/use_get_case_connectors';
import { useRefreshCaseViewPage } from '../case_view/use_on_refresh_case_view_page';
@ -48,94 +47,48 @@ describe('CaseActionBar', () => {
});
it('renders', () => {
const wrapper = mount(
<TestProviders>
<CaseActionBar {...defaultProps} />
</TestProviders>
);
renderWithTestingProviders(<CaseActionBar {...defaultProps} />);
expect(wrapper.find(`[data-test-subj="case-view-status"]`).exists()).toBeTruthy();
expect(wrapper.find(`[data-test-subj="case-action-bar-status-date"]`).exists()).toBeTruthy();
expect(wrapper.find(`[data-test-subj="case-view-status-dropdown"]`).exists()).toBeTruthy();
expect(wrapper.find(`[data-test-subj="sync-alerts-switch"]`).exists()).toBeTruthy();
expect(wrapper.find(`[data-test-subj="case-refresh"]`).exists()).toBeTruthy();
expect(wrapper.find(`[data-test-subj="case-view-actions"]`).exists()).toBeTruthy();
expect(screen.getByTestId('case-view-status')).toBeInTheDocument();
expect(screen.getByTestId('case-action-bar-status-date')).toBeInTheDocument();
expect(screen.getByTestId('sync-alerts-switch')).toBeInTheDocument();
expect(screen.getByTestId('case-refresh')).toBeInTheDocument();
expect(screen.getByTestId('case-view-actions')).toBeInTheDocument();
});
it('should show correct status', () => {
const wrapper = mount(
<TestProviders>
<CaseActionBar {...defaultProps} />
</TestProviders>
);
renderWithTestingProviders(<CaseActionBar {...defaultProps} />);
expect(wrapper.find(`[data-test-subj="case-view-status-dropdown"]`).first().text()).toBe(
'Open'
);
expect(screen.getByText('Open')).toBeInTheDocument();
});
it('should show the status as closed when the case is closed', () => {
const wrapper = mount(
<TestProviders>
<CaseActionBar {...defaultProps} caseData={basicCaseClosed} />
</TestProviders>
);
renderWithTestingProviders(<CaseActionBar {...defaultProps} caseData={basicCaseClosed} />);
expect(wrapper.find(`[data-test-subj="case-view-status-dropdown"]`).first().text()).toBe(
'Closed'
);
expect(screen.getByText('Closed')).toBeInTheDocument();
});
it('should show the correct date', () => {
const wrapper = mount(
<TestProviders>
<CaseActionBar {...defaultProps} />
</TestProviders>
);
it('invalidates the queryClient cache onRefresh', async () => {
renderWithTestingProviders(<CaseActionBar {...defaultProps} />);
expect(
wrapper
.find(`[data-test-subj="case-action-bar-status-date"]`)
.find('FormattedRelativePreferenceDate')
.prop('value')
).toBe(basicCase.createdAt);
});
it('invalidates the queryClient cache onRefresh', () => {
const wrapper = mount(
<TestProviders>
<CaseActionBar {...defaultProps} />
</TestProviders>
);
wrapper.find(`[data-test-subj="case-refresh"]`).first().simulate('click');
await userEvent.click(screen.getByTestId('case-refresh'));
expect(useRefreshCaseViewPage()).toHaveBeenCalled();
});
it('should call onUpdateField when changing status', () => {
const wrapper = mount(
<TestProviders>
<CaseActionBar {...defaultProps} />
</TestProviders>
);
it('should call onUpdateField when changing status', async () => {
renderWithTestingProviders(<CaseActionBar {...defaultProps} />);
wrapper.find(`[data-test-subj="case-view-status-dropdown"] button`).simulate('click');
wrapper
.find(`[data-test-subj="case-view-status-dropdown-in-progress"] button`)
.simulate('click');
await userEvent.click(screen.getByRole('button', { name: 'Change status' }));
await userEvent.click(await screen.findByTestId('case-view-status-dropdown-in-progress'));
expect(onUpdateField).toHaveBeenCalledWith({ key: 'status', value: 'in-progress' });
});
it('should call onUpdateField when changing syncAlerts setting', () => {
const wrapper = mount(
<TestProviders>
<CaseActionBar {...defaultProps} />
</TestProviders>
);
it('should call onUpdateField when changing syncAlerts setting', async () => {
renderWithTestingProviders(<CaseActionBar {...defaultProps} />);
wrapper.find('button[data-test-subj="sync-alerts-switch"]').first().simulate('click');
await userEvent.click(screen.getByTestId('sync-alerts-switch'));
expect(onUpdateField).toHaveBeenCalledWith({
key: 'settings',
@ -146,98 +99,73 @@ describe('CaseActionBar', () => {
});
it('should not show the sync alerts toggle when alerting is disabled', () => {
const { queryByText } = render(
<TestProviders features={{ alerts: { sync: false, enabled: true }, metrics: [] }}>
<CaseActionBar {...defaultProps} />
</TestProviders>
);
renderWithTestingProviders(<CaseActionBar {...defaultProps} />, {
wrapperProps: { features: { alerts: { sync: false, enabled: true }, metrics: [] } },
});
expect(queryByText('Sync alerts')).not.toBeInTheDocument();
expect(screen.queryByText('Sync alerts')).not.toBeInTheDocument();
});
it('should show the sync alerts toggle when alerting is enabled', () => {
const { queryByText } = render(
<TestProviders>
<CaseActionBar {...defaultProps} />
</TestProviders>
);
renderWithTestingProviders(<CaseActionBar {...defaultProps} />);
expect(queryByText('Sync alerts')).toBeInTheDocument();
expect(screen.getByText('Sync alerts')).toBeInTheDocument();
});
it('should not show the Case open text when the lifespan feature is enabled', () => {
const props: CaseActionBarProps = { ...defaultProps };
const { queryByText } = render(
<TestProviders features={{ metrics: [CaseMetricsFeature.LIFESPAN] }}>
<CaseActionBar {...props} />
</TestProviders>
);
renderWithTestingProviders(<CaseActionBar {...defaultProps} />, {
wrapperProps: { features: { metrics: [CaseMetricsFeature.LIFESPAN] } },
});
expect(queryByText('Case opened')).not.toBeInTheDocument();
expect(screen.queryByText('Case opened')).not.toBeInTheDocument();
});
it('should show the Case open text when the lifespan feature is disabled', () => {
const { getByText } = render(
<TestProviders>
<CaseActionBar {...defaultProps} />
</TestProviders>
);
renderWithTestingProviders(<CaseActionBar {...defaultProps} />);
expect(getByText('Case opened')).toBeInTheDocument();
expect(screen.getByText('Case opened')).toBeInTheDocument();
});
it('should show the change status text when the user has update privileges', () => {
render(
<TestProviders>
<CaseActionBar {...defaultProps} />
</TestProviders>
);
renderWithTestingProviders(<CaseActionBar {...defaultProps} />);
expect(screen.getByTitle('Change status')).toBeInTheDocument();
});
it('should not show the change status text when the user does not have update privileges', () => {
render(
<TestProviders permissions={noUpdateCasesPermissions()}>
<CaseActionBar {...defaultProps} />
</TestProviders>
);
renderWithTestingProviders(<CaseActionBar {...defaultProps} />, {
wrapperProps: { permissions: noUpdateCasesPermissions() },
});
expect(screen.queryByTitle('Change status')).not.toBeInTheDocument();
});
it('should not show the sync alerts toggle when the user does not have update privileges', () => {
const { queryByText } = render(
<TestProviders permissions={noUpdateCasesPermissions()}>
<CaseActionBar {...defaultProps} />
</TestProviders>
);
renderWithTestingProviders(<CaseActionBar {...defaultProps} />, {
wrapperProps: { permissions: noUpdateCasesPermissions() },
});
expect(queryByText('Sync alerts')).not.toBeInTheDocument();
expect(screen.queryByText('Sync alerts')).not.toBeInTheDocument();
});
it('should not show the delete item in the menu when the user does not have delete privileges', async () => {
const { queryByText, queryByTestId } = render(
<TestProviders permissions={noDeleteCasesPermissions()}>
<CaseActionBar {...defaultProps} />
</TestProviders>
);
renderWithTestingProviders(<CaseActionBar {...defaultProps} />, {
wrapperProps: { permissions: noDeleteCasesPermissions() },
});
await userEvent.click(screen.getByTestId('property-actions-case-ellipses'));
expect(queryByText('Delete case')).not.toBeInTheDocument();
expect(queryByTestId('property-actions-case-trash')).not.toBeInTheDocument();
expect(queryByTestId('property-actions-case-copyClipboard')).toBeInTheDocument();
expect(screen.queryByText('Delete case')).not.toBeInTheDocument();
expect(screen.queryByTestId('property-actions-case-trash')).not.toBeInTheDocument();
expect(screen.getByTestId('property-actions-case-copyClipboard')).toBeInTheDocument();
});
it('should show the the delete item in the menu when the user does have delete privileges', async () => {
const { queryByText } = render(
<TestProviders permissions={allCasesPermissions()}>
<CaseActionBar {...defaultProps} />
</TestProviders>
);
renderWithTestingProviders(<CaseActionBar {...defaultProps} />, {
wrapperProps: { permissions: allCasesPermissions() },
});
await userEvent.click(screen.getByTestId('property-actions-case-ellipses'));
expect(queryByText('Delete case')).toBeInTheDocument();
expect(screen.getByText('Delete case')).toBeInTheDocument();
});
it('shows the external incident action', async () => {
@ -249,11 +177,7 @@ describe('CaseActionBar', () => {
caseData: { ...defaultProps.caseData, connector: connectorWithoutPush },
};
render(
<TestProviders>
<CaseActionBar {...props} />
</TestProviders>
);
renderWithTestingProviders(<CaseActionBar {...props} />);
await userEvent.click(screen.getByTestId('property-actions-case-ellipses'));
@ -263,11 +187,7 @@ describe('CaseActionBar', () => {
});
it('does not show the external incident action', async () => {
render(
<TestProviders>
<CaseActionBar {...defaultProps} />
</TestProviders>
);
renderWithTestingProviders(<CaseActionBar {...defaultProps} />);
await userEvent.click(screen.getByTestId('property-actions-case-ellipses'));

View file

@ -86,7 +86,7 @@ const CaseActionBarComponent: React.FC<CaseActionBarProps> = ({
}
`}
>
<ActionBarStatusItem title={i18n.STATUS} data-test-subj="case-view-status">
<ActionBarStatusItem title={i18n.STATUS} dataTestSubj="case-view-status">
<StatusContextMenu
currentStatus={caseData.status}
disabled={isStatusMenuDisabled}
@ -98,7 +98,7 @@ const CaseActionBarComponent: React.FC<CaseActionBarProps> = ({
<EuiFlexGroup justifyContent="spaceBetween" alignItems="center" responsive={false}>
{!metricsFeatures.includes(CaseMetricsFeature.LIFESPAN) ? (
<EuiFlexItem grow={false}>
<ActionBarStatusItem title={title} data-test-subj="case-action-bar-status-date">
<ActionBarStatusItem title={title} dataTestSubj="case-action-bar-status-date">
<FormattedRelativePreferenceDate value={date} />
</ActionBarStatusItem>
</EuiFlexItem>

View file

@ -8,8 +8,6 @@
import type { FC, PropsWithChildren } from 'react';
import React from 'react';
import userEvent from '@testing-library/user-event';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
import type { FormHook } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib';
import { useForm, Form } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib';
@ -18,15 +16,15 @@ import { Assignees } from './assignees';
import { act, waitFor, screen } from '@testing-library/react';
import * as api from '../../containers/user_profiles/api';
import type { UserProfile } from '@kbn/user-profile-components';
import { renderWithTestingProviders } from '../../common/mock';
jest.mock('../../containers/user_profiles/api');
const currentUserProfile = userProfiles[0];
// Failing: See https://github.com/elastic/kibana/issues/189719
describe.skip('Assignees', () => {
describe('Assignees', () => {
let globalForm: FormHook;
let appMockRender: AppMockRenderer;
const MockHookWrapperComponent: FC<PropsWithChildren<unknown>> = ({ children }) => {
const { form } = useForm();
@ -37,11 +35,10 @@ describe.skip('Assignees', () => {
beforeEach(() => {
jest.clearAllMocks();
appMockRender = createAppMockRenderer();
});
it('renders', async () => {
appMockRender.render(
renderWithTestingProviders(
<MockHookWrapperComponent>
<Assignees isLoading={false} />
</MockHookWrapperComponent>
@ -58,7 +55,7 @@ describe.skip('Assignees', () => {
const spyOnGetCurrentUserProfile = jest.spyOn(api, 'getCurrentUserProfile');
spyOnGetCurrentUserProfile.mockResolvedValue(undefined as unknown as UserProfile);
appMockRender.render(
renderWithTestingProviders(
<MockHookWrapperComponent>
<Assignees isLoading={false} />
</MockHookWrapperComponent>
@ -76,7 +73,7 @@ describe.skip('Assignees', () => {
const spyOnGetCurrentUserProfile = jest.spyOn(api, 'getCurrentUserProfile');
spyOnGetCurrentUserProfile.mockResolvedValue(currentUserProfile);
appMockRender.render(
renderWithTestingProviders(
<MockHookWrapperComponent>
<Assignees isLoading={false} />
</MockHookWrapperComponent>
@ -95,7 +92,7 @@ describe.skip('Assignees', () => {
const spyOnGetCurrentUserProfile = jest.spyOn(api, 'getCurrentUserProfile');
spyOnGetCurrentUserProfile.mockResolvedValue(currentUserProfile);
appMockRender.render(
renderWithTestingProviders(
<MockHookWrapperComponent>
<Assignees isLoading={false} />
</MockHookWrapperComponent>
@ -115,7 +112,7 @@ describe.skip('Assignees', () => {
});
it('assignees users correctly', async () => {
appMockRender.render(
renderWithTestingProviders(
<MockHookWrapperComponent>
<Assignees isLoading={false} />
</MockHookWrapperComponent>
@ -165,7 +162,7 @@ describe.skip('Assignees', () => {
const spyOnSuggestUserProfiles = jest.spyOn(api, 'suggestUserProfiles');
spyOnSuggestUserProfiles.mockResolvedValue(similarProfiles);
appMockRender.render(
renderWithTestingProviders(
<MockHookWrapperComponent>
<Assignees isLoading={false} />
</MockHookWrapperComponent>
@ -202,7 +199,7 @@ describe.skip('Assignees', () => {
const spyOnBulkGetUserProfiles = jest.spyOn(api, 'bulkGetUserProfiles');
spyOnBulkGetUserProfiles.mockResolvedValue([userProfile]);
appMockRender.render(
renderWithTestingProviders(
<MockHookWrapperComponent>
<Assignees isLoading={false} />
</MockHookWrapperComponent>
@ -222,10 +219,11 @@ describe.skip('Assignees', () => {
await waitFor(() => {
expect(spyOnBulkGetUserProfiles).toBeCalledTimes(1);
expect(spyOnBulkGetUserProfiles).toHaveBeenCalledWith({
security: expect.anything(),
uids: [userProfile.uid],
});
});
expect(spyOnBulkGetUserProfiles).toHaveBeenCalledWith({
security: expect.anything(),
uids: [userProfile.uid],
});
expect(await screen.findByText(userProfile.user.full_name)).toBeInTheDocument();

View file

@ -11,19 +11,18 @@ import { screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { useForm, Form } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
import { Category } from './category';
import { useGetCategories } from '../../containers/use_get_categories';
import { categories } from '../../containers/mock';
import { EuiButton } from '@elastic/eui';
import { renderWithTestingProviders } from '../../common/mock';
jest.mock('../../containers/use_get_categories');
const useGetCategoriesMock = useGetCategories as jest.Mock;
describe('Category', () => {
let appMockRender: AppMockRenderer;
const onSubmit = jest.fn();
const FormComponent: FC<PropsWithChildren<unknown>> = ({ children }) => {
@ -40,11 +39,10 @@ describe('Category', () => {
beforeEach(() => {
jest.clearAllMocks();
useGetCategoriesMock.mockReturnValue({ isLoading: false, data: categories });
appMockRender = createAppMockRenderer();
});
it('renders the category field correctly', () => {
appMockRender.render(
renderWithTestingProviders(
<FormComponent>
<Category isLoading={false} />
</FormComponent>
@ -54,7 +52,7 @@ describe('Category', () => {
});
it('shows the optional label correctly', () => {
appMockRender.render(
renderWithTestingProviders(
<FormComponent>
<Category isLoading={false} />
</FormComponent>
@ -64,7 +62,7 @@ describe('Category', () => {
});
it('disables the combobox when it is loading', () => {
appMockRender.render(
renderWithTestingProviders(
<FormComponent>
<Category isLoading={true} />
</FormComponent>
@ -76,7 +74,7 @@ describe('Category', () => {
it('disables the combobox when is loading categories', async () => {
useGetCategoriesMock.mockReturnValue({ isLoading: true, data: categories });
appMockRender.render(
renderWithTestingProviders(
<FormComponent>
<Category isLoading={false} />
</FormComponent>
@ -92,7 +90,7 @@ describe('Category', () => {
useGetCategoriesMock.mockReturnValue(() => ({ isLoading: true, data: [category] }));
appMockRender.render(
renderWithTestingProviders(
<FormComponent>
<Category isLoading={false} />
</FormComponent>

View file

@ -8,17 +8,18 @@
import React from 'react';
import { screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import type { AppMockRenderer } from '../../common/mock';
import { connectorsMock } from '../../containers/mock';
import { Connector } from './connector';
import { useGetIncidentTypes } from '../connectors/resilient/use_get_incident_types';
import { useGetSeverity } from '../connectors/resilient/use_get_severity';
import { useGetChoices } from '../connectors/servicenow/use_get_choices';
import { incidentTypes, severity, choices } from '../connectors/mock';
import { noConnectorsCasePermission, createAppMockRenderer } from '../../common/mock';
import { noConnectorsCasePermission, renderWithTestingProviders } from '../../common/mock';
import { FormTestComponent } from '../../common/test_utils';
import { waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl';
import { coreMock } from '@kbn/core/public/mocks';
jest.mock('../connectors/resilient/use_get_incident_types');
jest.mock('../connectors/resilient/use_get_severity');
@ -49,20 +50,17 @@ const defaultProps = {
isLoadingConnectors: false,
};
// FLAKY: https://github.com/elastic/kibana/issues/208443
describe.skip('Connector', () => {
let appMockRender: AppMockRenderer;
describe('Connector', () => {
beforeEach(() => {
jest.clearAllMocks();
appMockRender = createAppMockRenderer();
useGetIncidentTypesMock.mockReturnValue(useGetIncidentTypesResponse);
useGetSeverityMock.mockReturnValue(useGetSeverityResponse);
useGetChoicesMock.mockReturnValue(useGetChoicesResponse);
});
it('renders correctly', async () => {
appMockRender.render(
renderWithTestingProviders(
<FormTestComponent formDefaultValue={{ connectorId: 'none' }}>
<Connector {...defaultProps} />
</FormTestComponent>
@ -73,7 +71,7 @@ describe.skip('Connector', () => {
});
it('renders loading state correctly', async () => {
appMockRender.render(
renderWithTestingProviders(
<FormTestComponent formDefaultValue={{ connectorId: 'none' }}>
<Connector {...{ ...defaultProps, isLoading: true }} />
</FormTestComponent>
@ -85,7 +83,7 @@ describe.skip('Connector', () => {
});
it('renders default connector correctly', async () => {
appMockRender.render(
renderWithTestingProviders(
<FormTestComponent formDefaultValue={{ connectorId: connectorsMock[2].id }}>
<Connector {...defaultProps} />
</FormTestComponent>
@ -98,7 +96,7 @@ describe.skip('Connector', () => {
});
it('shows all connectors in dropdown', async () => {
appMockRender.render(
renderWithTestingProviders(
<FormTestComponent formDefaultValue={{ connectorId: 'none' }}>
<Connector {...defaultProps} />
</FormTestComponent>
@ -118,7 +116,7 @@ describe.skip('Connector', () => {
});
it('changes connector correctly', async () => {
appMockRender.render(
renderWithTestingProviders(
<FormTestComponent formDefaultValue={{ connectorId: 'none' }}>
<Connector {...defaultProps} />
</FormTestComponent>
@ -135,16 +133,19 @@ describe.skip('Connector', () => {
});
it('shows the actions permission message if the user does not have read access to actions', async () => {
appMockRender.coreStart.application.capabilities = {
...appMockRender.coreStart.application.capabilities,
const coreStart = coreMock.createStart();
coreStart.application.capabilities = {
...coreStart.application.capabilities,
actions: { save: false, show: false },
};
appMockRender.render(
renderWithTestingProviders(
<FormTestComponent formDefaultValue={{ connectorId: 'none' }}>
<Connector {...defaultProps} />
</FormTestComponent>
</FormTestComponent>,
{ wrapperProps: { coreStart } }
);
expect(
await screen.findByTestId('create-case-connector-permissions-error-msg')
).toBeInTheDocument();
@ -152,12 +153,11 @@ describe.skip('Connector', () => {
});
it('shows the actions permission message if the user does not have access to case connector', async () => {
appMockRender = createAppMockRenderer({ permissions: noConnectorsCasePermission() });
appMockRender.render(
renderWithTestingProviders(
<FormTestComponent formDefaultValue={{ connectorId: 'none' }}>
<Connector {...defaultProps} />
</FormTestComponent>
</FormTestComponent>,
{ wrapperProps: { permissions: noConnectorsCasePermission() } }
);
expect(screen.getByTestId('create-case-connector-permissions-error-msg')).toBeInTheDocument();
expect(screen.queryByTestId('caseConnectors')).not.toBeInTheDocument();

View file

@ -9,15 +9,13 @@ import React from 'react';
import { screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
import { FormTestComponent } from '../../common/test_utils';
import { customFieldsConfigurationMock } from '../../containers/mock';
import { CustomFields } from './custom_fields';
import { renderWithTestingProviders } from '../../common/mock';
// Failing: See https://github.com/elastic/kibana/issues/188133
describe.skip('CustomFields', () => {
let appMockRender: AppMockRenderer;
describe('CustomFields', () => {
const onSubmit = jest.fn();
const defaultProps = {
@ -29,11 +27,10 @@ describe.skip('CustomFields', () => {
beforeEach(() => {
jest.clearAllMocks();
appMockRender = createAppMockRenderer();
});
it('renders correctly', async () => {
appMockRender.render(
renderWithTestingProviders(
<FormTestComponent onSubmit={onSubmit}>
<CustomFields {...defaultProps} />
</FormTestComponent>
@ -53,7 +50,7 @@ describe.skip('CustomFields', () => {
});
it('should not show the custom fields if the configuration is empty', async () => {
appMockRender.render(
renderWithTestingProviders(
<FormTestComponent onSubmit={onSubmit}>
<CustomFields
isLoading={false}
@ -62,13 +59,12 @@ describe.skip('CustomFields', () => {
/>
</FormTestComponent>
);
expect(screen.queryByTestId('caseCustomFields')).not.toBeInTheDocument();
expect(screen.queryAllByTestId('create-custom-field', { exact: false }).length).toEqual(0);
});
it('should render as optional fields for text custom fields', async () => {
appMockRender.render(
renderWithTestingProviders(
<FormTestComponent onSubmit={onSubmit}>
<CustomFields
isLoading={false}
@ -77,12 +73,11 @@ describe.skip('CustomFields', () => {
/>
</FormTestComponent>
);
expect(await screen.findAllByTestId('form-optional-field-label')).toHaveLength(4);
});
it('should not set default value when in edit mode', async () => {
appMockRender.render(
renderWithTestingProviders(
<FormTestComponent onSubmit={onSubmit}>
<CustomFields
isLoading={false}
@ -101,7 +96,7 @@ describe.skip('CustomFields', () => {
it('should sort the custom fields correctly', async () => {
const reversedCustomFieldsConfiguration = [...customFieldsConfigurationMock].reverse();
appMockRender.render(
renderWithTestingProviders(
<FormTestComponent onSubmit={onSubmit}>
<CustomFields
isLoading={false}
@ -111,12 +106,11 @@ describe.skip('CustomFields', () => {
</FormTestComponent>
);
const customFieldsWrapper = await screen.findByTestId('caseCustomFields');
const customFields = customFieldsWrapper.querySelectorAll('.euiFormRow');
const customFields = screen.getAllByText(/My test label [1-6]/);
expect(customFields).toHaveLength(6);
expect(customFields[0]).toHaveTextContent('My test label 1');
expect(customFields[0]).toHaveTextContent('My test label 1');
expect(customFields[1]).toHaveTextContent('My test label 2');
expect(customFields[2]).toHaveTextContent('My test label 3');
@ -126,7 +120,7 @@ describe.skip('CustomFields', () => {
});
it('should update the custom fields', async () => {
appMockRender.render(
renderWithTestingProviders(
<FormTestComponent onSubmit={onSubmit}>
<CustomFields {...defaultProps} />
</FormTestComponent>

View file

@ -11,15 +11,13 @@ import userEvent from '@testing-library/user-event';
import { Description } from './description';
import { schema } from '../create/schema';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
import { MAX_DESCRIPTION_LENGTH } from '../../../common/constants';
import { FormTestComponent } from '../../common/test_utils';
import type { FormSchema } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib';
import { renderWithTestingProviders } from '../../common/mock';
// FLAKY: https://github.com/elastic/kibana/issues/187526
describe.skip('Description', () => {
let appMockRender: AppMockRenderer;
describe('Description', () => {
const onSubmit = jest.fn();
const draftStorageKey = `cases.caseView.createCase.description.markdownEditor`;
const defaultProps = {
@ -29,7 +27,7 @@ describe.skip('Description', () => {
beforeEach(() => {
jest.clearAllMocks();
appMockRender = createAppMockRenderer();
window.sessionStorage.clear();
});
@ -38,7 +36,7 @@ describe.skip('Description', () => {
});
it('it renders', async () => {
appMockRender.render(
renderWithTestingProviders(
<FormTestComponent onSubmit={onSubmit}>
<Description {...defaultProps} />
</FormTestComponent>
@ -48,7 +46,7 @@ describe.skip('Description', () => {
});
it('it changes the description', async () => {
appMockRender.render(
renderWithTestingProviders(
<FormTestComponent
onSubmit={onSubmit}
formDefaultValue={{
@ -73,7 +71,7 @@ describe.skip('Description', () => {
});
it('shows an error when description is empty', async () => {
appMockRender.render(
renderWithTestingProviders(
<FormTestComponent
onSubmit={onSubmit}
formDefaultValue={{
@ -103,7 +101,7 @@ describe.skip('Description', () => {
it('shows an error when description is too long', async () => {
const longDescription = 'a'.repeat(MAX_DESCRIPTION_LENGTH + 1);
appMockRender.render(
renderWithTestingProviders(
<FormTestComponent
onSubmit={onSubmit}
formDefaultValue={{

View file

@ -9,8 +9,7 @@ import React from 'react';
import { screen, waitFor, within } from '@testing-library/react';
import { licensingMock } from '@kbn/licensing-plugin/public/mocks';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
import { renderWithTestingProviders } from '../../common/mock';
import { FormTestComponent } from '../../common/test_utils';
import { customFieldsConfigurationMock } from '../../containers/mock';
import { userProfiles } from '../../containers/user_profiles/api.mock';
@ -23,7 +22,7 @@ jest.mock('../../containers/user_profiles/api');
describe('CaseFormFields', () => {
let user: UserEvent;
let appMock: AppMockRenderer;
const onSubmit = jest.fn();
const formDefaultValue = { tags: [] };
const defaultProps = {
@ -42,7 +41,6 @@ describe('CaseFormFields', () => {
beforeEach(() => {
// Workaround for timeout via https://github.com/testing-library/user-event/issues/833#issuecomment-1171452841
user = userEvent.setup({ advanceTimers: jest.advanceTimersByTime });
appMock = createAppMockRenderer();
});
afterEach(() => {
@ -50,7 +48,7 @@ describe('CaseFormFields', () => {
});
it('renders correctly', async () => {
appMock.render(
renderWithTestingProviders(
<FormTestComponent formDefaultValue={formDefaultValue} onSubmit={onSubmit}>
<CaseFormFields {...defaultProps} />
</FormTestComponent>
@ -60,7 +58,7 @@ describe('CaseFormFields', () => {
});
it('renders case fields correctly', async () => {
appMock.render(
renderWithTestingProviders(
<FormTestComponent formDefaultValue={formDefaultValue} onSubmit={onSubmit}>
<CaseFormFields {...defaultProps} />
</FormTestComponent>
@ -74,7 +72,7 @@ describe('CaseFormFields', () => {
});
it('does not render customFields when empty', () => {
appMock.render(
renderWithTestingProviders(
<FormTestComponent formDefaultValue={formDefaultValue} onSubmit={onSubmit}>
<CaseFormFields {...defaultProps} />
</FormTestComponent>
@ -84,7 +82,7 @@ describe('CaseFormFields', () => {
});
it('renders customFields when not empty', async () => {
appMock.render(
renderWithTestingProviders(
<FormTestComponent formDefaultValue={formDefaultValue} onSubmit={onSubmit}>
<CaseFormFields
isLoading={false}
@ -97,7 +95,7 @@ describe('CaseFormFields', () => {
});
it('does not render assignees when no platinum license', () => {
appMock.render(
renderWithTestingProviders(
<FormTestComponent formDefaultValue={formDefaultValue} onSubmit={onSubmit}>
<CaseFormFields {...defaultProps} />
</FormTestComponent>
@ -111,19 +109,18 @@ describe('CaseFormFields', () => {
license: { type: 'platinum' },
});
appMock = createAppMockRenderer({ license });
appMock.render(
renderWithTestingProviders(
<FormTestComponent formDefaultValue={formDefaultValue} onSubmit={onSubmit}>
<CaseFormFields {...defaultProps} />
</FormTestComponent>
</FormTestComponent>,
{ wrapperProps: { license } }
);
expect(await screen.findByTestId('createCaseAssigneesComboBox')).toBeInTheDocument();
});
it('calls onSubmit with case fields', async () => {
appMock.render(
renderWithTestingProviders(
<FormTestComponent formDefaultValue={formDefaultValue} onSubmit={onSubmit}>
<CaseFormFields {...defaultProps} />
</FormTestComponent>
@ -161,7 +158,7 @@ describe('CaseFormFields', () => {
});
it('calls onSubmit with existing case fields', async () => {
appMock.render(
renderWithTestingProviders(
<FormTestComponent
formDefaultValue={{
title: 'Case with Template 1',
@ -196,7 +193,7 @@ describe('CaseFormFields', () => {
configurationCustomFields: customFieldsConfigurationMock,
};
appMock.render(
renderWithTestingProviders(
<FormTestComponent formDefaultValue={formDefaultValue} onSubmit={onSubmit}>
<CaseFormFields {...newProps} />
</FormTestComponent>
@ -252,7 +249,7 @@ describe('CaseFormFields', () => {
configurationCustomFields: customFieldsConfigurationMock,
};
appMock.render(
renderWithTestingProviders(
<FormTestComponent
formDefaultValue={{
customFields: { [customFieldsConfigurationMock[0].key]: 'Test custom filed value' },
@ -290,12 +287,11 @@ describe('CaseFormFields', () => {
license: { type: 'platinum' },
});
appMock = createAppMockRenderer({ license });
appMock.render(
renderWithTestingProviders(
<FormTestComponent formDefaultValue={formDefaultValue} onSubmit={onSubmit}>
<CaseFormFields {...defaultProps} />
</FormTestComponent>
</FormTestComponent>,
{ wrapperProps: { license } }
);
const assigneesComboBox = await screen.findByTestId('createCaseAssigneesComboBox');
@ -325,9 +321,7 @@ describe('CaseFormFields', () => {
license: { type: 'platinum' },
});
appMock = createAppMockRenderer({ license });
appMock.render(
renderWithTestingProviders(
<FormTestComponent
formDefaultValue={{
assignees: [{ uid: userProfiles[1].uid }],
@ -336,7 +330,8 @@ describe('CaseFormFields', () => {
onSubmit={onSubmit}
>
<CaseFormFields {...defaultProps} />
</FormTestComponent>
</FormTestComponent>,
{ wrapperProps: { license } }
);
await user.click(await screen.findByText('Submit'));

View file

@ -14,8 +14,8 @@ import type { FormHook } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_l
import { useForm, Form } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib';
import { Tags } from './tags';
import { schema } from '../create/schema';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer, TestProviders } from '../../common/mock';
import { TestProviders, renderWithTestingProviders } from '../../common/mock';
import { useGetTags } from '../../containers/use_get_tags';
import { MAX_LENGTH_PER_TAG } from '../../../common/constants';
import type { CaseFormFieldsSchemaProps } from './schema';
@ -27,7 +27,6 @@ const useGetTagsMock = useGetTags as jest.Mock;
describe('Tags', () => {
let globalForm: FormHook;
let appMockRender: AppMockRenderer;
const MockHookWrapperComponent: FC<PropsWithChildren<unknown>> = ({ children }) => {
const { form } = useForm<CaseFormFieldsSchemaProps>({
@ -48,7 +47,6 @@ describe('Tags', () => {
beforeEach(() => {
useGetTagsMock.mockReturnValue({ data: ['test'] });
appMockRender = createAppMockRenderer();
});
afterEach(() => {
@ -56,7 +54,7 @@ describe('Tags', () => {
});
it('it renders', async () => {
appMockRender.render(
renderWithTestingProviders(
<MockHookWrapperComponent>
<Tags isLoading={false} />
</MockHookWrapperComponent>
@ -68,7 +66,7 @@ describe('Tags', () => {
});
it('it changes the tags', async () => {
appMockRender.render(
renderWithTestingProviders(
<MockHookWrapperComponent>
<Tags isLoading={false} />
</MockHookWrapperComponent>
@ -81,7 +79,7 @@ describe('Tags', () => {
});
it('it shows error when tag is empty', async () => {
appMockRender.render(
renderWithTestingProviders(
<MockHookWrapperComponent>
<Tags isLoading={false} />
</MockHookWrapperComponent>
@ -97,7 +95,7 @@ describe('Tags', () => {
it('it shows error when tag is too long', async () => {
const longTag = 'z'.repeat(MAX_LENGTH_PER_TAG + 1);
appMockRender.render(
renderWithTestingProviders(
<MockHookWrapperComponent>
<Tags isLoading={false} />
</MockHookWrapperComponent>

View file

@ -7,8 +7,8 @@
import React from 'react';
import { waitFor, screen } from '@testing-library/react';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
import { renderWithTestingProviders } from '../../common/mock';
import { useUrlParams } from '../../common/navigation/hooks';
import { CaseViewPage } from './case_view_page';
import { caseData, caseViewProps } from './mocks';
@ -77,28 +77,25 @@ const caseProps: CaseViewPageProps = {
};
describe('CaseViewPage', () => {
let appMockRenderer: AppMockRenderer;
beforeEach(() => {
jest.clearAllMocks();
useUrlParamsMock.mockReturnValue({});
appMockRenderer = createAppMockRenderer();
});
it('shows the header section', async () => {
appMockRenderer.render(<CaseViewPage {...caseProps} />);
renderWithTestingProviders(<CaseViewPage {...caseProps} />);
expect(await screen.findByTestId('test-case-view-header')).toBeInTheDocument();
});
it('shows the metrics section', async () => {
appMockRenderer.render(<CaseViewPage {...caseProps} />);
renderWithTestingProviders(<CaseViewPage {...caseProps} />);
expect(await screen.findByTestId('test-case-view-metrics')).toBeInTheDocument();
});
it('shows the activity section', async () => {
appMockRenderer.render(<CaseViewPage {...caseProps} />);
renderWithTestingProviders(<CaseViewPage {...caseProps} />);
expect(await screen.findByTestId('test-case-view-activity')).toBeInTheDocument();
});
@ -106,7 +103,7 @@ describe('CaseViewPage', () => {
it('should set the breadcrumbs correctly', async () => {
const onComponentInitialized = jest.fn();
appMockRenderer.render(
renderWithTestingProviders(
<CaseViewPage {...caseProps} onComponentInitialized={onComponentInitialized} />
);

View file

@ -10,12 +10,11 @@ import { screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { licensingMock } from '@kbn/licensing-plugin/public/mocks';
import type { AppMockRenderer } from '../../common/mock';
import type { UseGetCase } from '../../containers/use_get_case';
import type { CaseViewTabsProps } from './case_view_tabs';
import { CASE_VIEW_PAGE_TABS } from '../../../common/types';
import { createAppMockRenderer } from '../../common/mock';
import { renderWithTestingProviders } from '../../common/mock';
import { useCaseViewNavigation } from '../../common/navigation/hooks';
import { useGetCase } from '../../containers/use_get_case';
import { CaseViewTabs } from './case_view_tabs';
@ -58,19 +57,15 @@ export const casePropsWithAlerts: CaseViewTabsProps = {
};
describe('CaseViewTabs', () => {
let appMockRenderer: AppMockRenderer;
const data = { total: 3 };
const basicLicense = licensingMock.createLicense({
license: { type: 'basic' },
});
beforeEach(() => {
useGetCaseObservablesMock.mockReturnValue({ isLoading: false, observables: [] });
useGetCaseFileStatsMock.mockReturnValue({ data });
mockGetCase();
const license = licensingMock.createLicense({
license: { type: 'basic' },
});
appMockRenderer = createAppMockRenderer({ license });
});
afterEach(() => {
@ -79,7 +74,9 @@ describe('CaseViewTabs', () => {
it('should render CaseViewTabs', async () => {
const props = { activeTab: CASE_VIEW_PAGE_TABS.ACTIVITY, caseData };
appMockRenderer.render(<CaseViewTabs {...props} />);
renderWithTestingProviders(<CaseViewTabs {...props} />, {
wrapperProps: { license: basicLicense },
});
expect(await screen.findByTestId('case-view-tab-title-activity')).toBeInTheDocument();
expect(await screen.findByTestId('case-view-tab-title-alerts')).toBeInTheDocument();
@ -87,7 +84,9 @@ describe('CaseViewTabs', () => {
});
it('renders the activity tab by default', async () => {
appMockRenderer.render(<CaseViewTabs {...caseProps} />);
renderWithTestingProviders(<CaseViewTabs {...caseProps} />, {
wrapperProps: { license: basicLicense },
});
expect(await screen.findByTestId('case-view-tab-title-activity')).toHaveAttribute(
'aria-selected',
@ -96,7 +95,12 @@ describe('CaseViewTabs', () => {
});
it('shows the alerts tab as active', async () => {
appMockRenderer.render(<CaseViewTabs {...caseProps} activeTab={CASE_VIEW_PAGE_TABS.ALERTS} />);
renderWithTestingProviders(
<CaseViewTabs {...caseProps} activeTab={CASE_VIEW_PAGE_TABS.ALERTS} />,
{
wrapperProps: { license: basicLicense },
}
);
expect(await screen.findByTestId('case-view-tab-title-alerts')).toHaveAttribute(
'aria-selected',
@ -105,7 +109,12 @@ describe('CaseViewTabs', () => {
});
it('shows the files tab as active', async () => {
appMockRenderer.render(<CaseViewTabs {...caseProps} activeTab={CASE_VIEW_PAGE_TABS.FILES} />);
renderWithTestingProviders(
<CaseViewTabs {...caseProps} activeTab={CASE_VIEW_PAGE_TABS.FILES} />,
{
wrapperProps: { license: basicLicense },
}
);
expect(await screen.findByTestId('case-view-tab-title-files')).toHaveAttribute(
'aria-selected',
@ -114,7 +123,12 @@ describe('CaseViewTabs', () => {
});
it('shows the files tab with the correct count', async () => {
appMockRenderer.render(<CaseViewTabs {...caseProps} activeTab={CASE_VIEW_PAGE_TABS.FILES} />);
renderWithTestingProviders(
<CaseViewTabs {...caseProps} activeTab={CASE_VIEW_PAGE_TABS.FILES} />,
{
wrapperProps: { license: basicLicense },
}
);
const badge = await screen.findByTestId('case-view-files-stats-badge');
@ -124,14 +138,22 @@ describe('CaseViewTabs', () => {
it('do not show count on the files tab if the call isLoading', async () => {
useGetCaseFileStatsMock.mockReturnValue({ isLoading: true, data });
appMockRenderer.render(<CaseViewTabs {...caseProps} activeTab={CASE_VIEW_PAGE_TABS.FILES} />);
renderWithTestingProviders(
<CaseViewTabs {...caseProps} activeTab={CASE_VIEW_PAGE_TABS.FILES} />,
{
wrapperProps: { license: basicLicense },
}
);
expect(screen.queryByTestId('case-view-files-stats-badge')).not.toBeInTheDocument();
});
it('shows the alerts tab with the correct count', async () => {
appMockRenderer.render(
<CaseViewTabs {...casePropsWithAlerts} activeTab={CASE_VIEW_PAGE_TABS.ALERTS} />
renderWithTestingProviders(
<CaseViewTabs {...casePropsWithAlerts} activeTab={CASE_VIEW_PAGE_TABS.ALERTS} />,
{
wrapperProps: { license: basicLicense },
}
);
const badge = await screen.findByTestId('case-view-alerts-stats-badge');
@ -140,8 +162,11 @@ describe('CaseViewTabs', () => {
});
it('the alerts tab count has a different color if the tab is not active', async () => {
appMockRenderer.render(
<CaseViewTabs {...casePropsWithAlerts} activeTab={CASE_VIEW_PAGE_TABS.FILES} />
renderWithTestingProviders(
<CaseViewTabs {...casePropsWithAlerts} activeTab={CASE_VIEW_PAGE_TABS.FILES} />,
{
wrapperProps: { license: basicLicense },
}
);
expect(
@ -151,7 +176,9 @@ describe('CaseViewTabs', () => {
it('navigates to the activity tab when the activity tab is clicked', async () => {
const navigateToCaseViewMock = useCaseViewNavigationMock().navigateToCaseView;
appMockRenderer.render(<CaseViewTabs {...caseProps} />);
renderWithTestingProviders(<CaseViewTabs {...caseProps} />, {
wrapperProps: { license: basicLicense },
});
await userEvent.click(await screen.findByTestId('case-view-tab-title-activity'));
@ -165,7 +192,9 @@ describe('CaseViewTabs', () => {
it('navigates to the alerts tab when the alerts tab is clicked', async () => {
const navigateToCaseViewMock = useCaseViewNavigationMock().navigateToCaseView;
appMockRenderer.render(<CaseViewTabs {...caseProps} />);
renderWithTestingProviders(<CaseViewTabs {...caseProps} />, {
wrapperProps: { license: basicLicense },
});
await userEvent.click(await screen.findByTestId('case-view-tab-title-alerts'));
@ -179,7 +208,9 @@ describe('CaseViewTabs', () => {
it('navigates to the files tab when the files tab is clicked', async () => {
const navigateToCaseViewMock = useCaseViewNavigationMock().navigateToCaseView;
appMockRenderer.render(<CaseViewTabs {...caseProps} />);
renderWithTestingProviders(<CaseViewTabs {...caseProps} />, {
wrapperProps: { license: basicLicense },
});
await userEvent.click(await screen.findByTestId('case-view-tab-title-files'));
@ -192,20 +223,22 @@ describe('CaseViewTabs', () => {
});
it('should display the alerts tab when the feature is enabled', async () => {
appMockRenderer = createAppMockRenderer({ features: { alerts: { enabled: true } } });
appMockRenderer.render(
<CaseViewTabs {...casePropsWithAlerts} activeTab={CASE_VIEW_PAGE_TABS.ALERTS} />
renderWithTestingProviders(
<CaseViewTabs {...casePropsWithAlerts} activeTab={CASE_VIEW_PAGE_TABS.ALERTS} />,
{
wrapperProps: { license: basicLicense, features: { alerts: { enabled: true } } },
}
);
expect(await screen.findByTestId('case-view-tab-title-alerts')).toBeInTheDocument();
});
it('should not display the alerts tab when the feature is disabled', async () => {
appMockRenderer = createAppMockRenderer({ features: { alerts: { enabled: false } } });
appMockRenderer.render(
<CaseViewTabs {...casePropsWithAlerts} activeTab={CASE_VIEW_PAGE_TABS.ALERTS} />
renderWithTestingProviders(
<CaseViewTabs {...casePropsWithAlerts} activeTab={CASE_VIEW_PAGE_TABS.ALERTS} />,
{
wrapperProps: { license: basicLicense, features: { alerts: { enabled: false } } },
}
);
expect(await screen.findByTestId('case-view-tabs')).toBeInTheDocument();
@ -213,12 +246,11 @@ describe('CaseViewTabs', () => {
});
it('should not show the experimental badge on the alerts table', async () => {
appMockRenderer = createAppMockRenderer({
features: { alerts: { isExperimental: false } },
});
appMockRenderer.render(
<CaseViewTabs {...casePropsWithAlerts} activeTab={CASE_VIEW_PAGE_TABS.ALERTS} />
renderWithTestingProviders(
<CaseViewTabs {...casePropsWithAlerts} activeTab={CASE_VIEW_PAGE_TABS.ALERTS} />,
{
wrapperProps: { license: basicLicense, features: { alerts: { isExperimental: false } } },
}
);
expect(await screen.findByTestId('case-view-tabs')).toBeInTheDocument();
@ -228,12 +260,11 @@ describe('CaseViewTabs', () => {
});
it('should show the experimental badge on the alerts table', async () => {
appMockRenderer = createAppMockRenderer({
features: { alerts: { isExperimental: true } },
});
appMockRenderer.render(
<CaseViewTabs {...casePropsWithAlerts} activeTab={CASE_VIEW_PAGE_TABS.ALERTS} />
renderWithTestingProviders(
<CaseViewTabs {...casePropsWithAlerts} activeTab={CASE_VIEW_PAGE_TABS.ALERTS} />,
{
wrapperProps: { license: basicLicense, features: { alerts: { isExperimental: true } } },
}
);
expect(
@ -244,10 +275,11 @@ describe('CaseViewTabs', () => {
it('should not show observable tabs in non-platinum tiers', async () => {
const spyOnUseGetSimilarCases = jest.spyOn(similarCasesHook, 'useGetSimilarCases');
appMockRenderer = createAppMockRenderer();
appMockRenderer.render(
<CaseViewTabs {...casePropsWithAlerts} activeTab={CASE_VIEW_PAGE_TABS.OBSERVABLES} />
renderWithTestingProviders(
<CaseViewTabs {...casePropsWithAlerts} activeTab={CASE_VIEW_PAGE_TABS.OBSERVABLES} />,
{
wrapperProps: { license: basicLicense },
}
);
expect(screen.queryByTestId('case-view-tab-title-observables')).not.toBeInTheDocument();
@ -260,18 +292,18 @@ describe('CaseViewTabs', () => {
});
describe('show observable tabs in platinum tier or higher', () => {
beforeEach(() => {
const license = licensingMock.createLicense({
license: { type: 'platinum' },
});
appMockRenderer = createAppMockRenderer({ license });
const platinumLicense = licensingMock.createLicense({
license: { type: 'platinum' },
});
it('should show observable tabs in platinum+ tiers', async () => {
const spyOnUseGetSimilarCases = jest.spyOn(similarCasesHook, 'useGetSimilarCases');
appMockRenderer.render(
<CaseViewTabs {...casePropsWithAlerts} activeTab={CASE_VIEW_PAGE_TABS.OBSERVABLES} />
renderWithTestingProviders(
<CaseViewTabs {...casePropsWithAlerts} activeTab={CASE_VIEW_PAGE_TABS.OBSERVABLES} />,
{
wrapperProps: { license: platinumLicense },
}
);
// NOTE: ensure we are calling the hook but the fetching is enabled (based on the license)
@ -281,16 +313,22 @@ describe('CaseViewTabs', () => {
});
it('should show the observables tab', async () => {
appMockRenderer.render(
<CaseViewTabs {...casePropsWithAlerts} activeTab={CASE_VIEW_PAGE_TABS.OBSERVABLES} />
renderWithTestingProviders(
<CaseViewTabs {...casePropsWithAlerts} activeTab={CASE_VIEW_PAGE_TABS.OBSERVABLES} />,
{
wrapperProps: { license: platinumLicense },
}
);
expect(await screen.findByTestId('case-view-tab-title-observables')).toBeInTheDocument();
});
it('should show the similar cases tab', async () => {
appMockRenderer.render(
<CaseViewTabs {...casePropsWithAlerts} activeTab={CASE_VIEW_PAGE_TABS.SIMILAR_CASES} />
renderWithTestingProviders(
<CaseViewTabs {...casePropsWithAlerts} activeTab={CASE_VIEW_PAGE_TABS.SIMILAR_CASES} />,
{
wrapperProps: { license: platinumLicense },
}
);
expect(await screen.findByTestId('case-view-tab-title-similar_cases')).toBeInTheDocument();
@ -298,7 +336,9 @@ describe('CaseViewTabs', () => {
it('navigates to the similar cases tab when the similar cases tab is clicked', async () => {
const navigateToCaseViewMock = useCaseViewNavigationMock().navigateToCaseView;
appMockRenderer.render(<CaseViewTabs {...caseProps} />);
renderWithTestingProviders(<CaseViewTabs {...caseProps} />, {
wrapperProps: { license: platinumLicense },
});
await userEvent.click(await screen.findByTestId('case-view-tab-title-similar_cases'));
@ -311,8 +351,11 @@ describe('CaseViewTabs', () => {
});
it('shows the observables tab with the correct count', async () => {
appMockRenderer.render(
<CaseViewTabs {...caseProps} activeTab={CASE_VIEW_PAGE_TABS.OBSERVABLES} />
renderWithTestingProviders(
<CaseViewTabs {...caseProps} activeTab={CASE_VIEW_PAGE_TABS.OBSERVABLES} />,
{
wrapperProps: { license: platinumLicense },
}
);
const badge = await screen.findByTestId('case-view-observables-stats-badge');
@ -323,8 +366,11 @@ describe('CaseViewTabs', () => {
it('do not show count on the observables tab if the call isLoading', async () => {
useGetCaseObservablesMock.mockReturnValue({ isLoading: true, observables: [] });
appMockRenderer.render(
<CaseViewTabs {...caseProps} activeTab={CASE_VIEW_PAGE_TABS.OBSERVABLES} />
renderWithTestingProviders(
<CaseViewTabs {...caseProps} activeTab={CASE_VIEW_PAGE_TABS.OBSERVABLES} />,
{
wrapperProps: { license: platinumLicense },
}
);
expect(screen.queryByTestId('case-view-observables-stats-badge')).not.toBeInTheDocument();

View file

@ -10,8 +10,7 @@ import { useGetCurrentUserProfile } from '../../../containers/user_profiles/use_
import { userProfiles, userProfilesMap } from '../../../containers/user_profiles/api.mock';
import { fireEvent, screen, waitFor } from '@testing-library/react';
import React from 'react';
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer, noAssignCasesPermissions } from '../../../common/mock';
import { noAssignCasesPermissions, renderWithTestingProviders } from '../../../common/mock';
import type { AssignUsersProps } from './assign_users';
import { AssignUsers } from './assign_users';
import { waitForEuiPopoverClose, waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl';
@ -25,7 +24,6 @@ const useGetCurrentUserProfileMock = useGetCurrentUserProfile as jest.Mock;
const currentUserProfile = userProfiles[0];
describe('AssignUsers', () => {
let appMockRender: AppMockRenderer;
let defaultProps: AssignUsersProps;
beforeEach(() => {
@ -39,47 +37,49 @@ describe('AssignUsers', () => {
useSuggestUserProfilesMock.mockReturnValue({ data: userProfiles, isLoading: false });
useGetCurrentUserProfileMock.mockReturnValue({ data: currentUserProfile, isLoading: false });
appMockRender = createAppMockRenderer();
});
it('does not show any assignees when there are none assigned', () => {
appMockRender.render(<AssignUsers {...defaultProps} />);
renderWithTestingProviders(<AssignUsers {...defaultProps} />);
expect(screen.getByText('No users are assigned')).toBeInTheDocument();
});
it('does not show the suggest users edit button when the user does not have assign permissions', () => {
appMockRender = createAppMockRenderer({ permissions: noAssignCasesPermissions() });
appMockRender.render(<AssignUsers {...defaultProps} />);
renderWithTestingProviders(<AssignUsers {...defaultProps} />, {
wrapperProps: { permissions: noAssignCasesPermissions() },
});
expect(screen.queryByText('case-view-assignees-edit')).not.toBeInTheDocument();
});
it('does not show the assign users link when the user does not have assign permissions', () => {
appMockRender = createAppMockRenderer({ permissions: noAssignCasesPermissions() });
appMockRender.render(<AssignUsers {...defaultProps} />);
renderWithTestingProviders(<AssignUsers {...defaultProps} />, {
wrapperProps: { permissions: noAssignCasesPermissions() },
});
expect(screen.queryByTestId('assign yourself')).not.toBeInTheDocument();
expect(screen.queryByTestId('Assign a user')).not.toBeInTheDocument();
});
it('does not show the suggest users edit button when the component is still loading', () => {
appMockRender.render(<AssignUsers {...{ ...defaultProps, isLoading: true }} />);
renderWithTestingProviders(<AssignUsers {...{ ...defaultProps, isLoading: true }} />);
expect(screen.queryByTestId('case-view-assignees-edit')).not.toBeInTheDocument();
expect(screen.getByTestId('case-view-assignees-button-loading')).toBeInTheDocument();
});
it('does not show the assign yourself link when the current profile is undefined', () => {
appMockRender.render(<AssignUsers {...{ ...defaultProps, currentUserProfile: undefined }} />);
renderWithTestingProviders(
<AssignUsers {...{ ...defaultProps, currentUserProfile: undefined }} />
);
expect(screen.queryByText('assign yourself')).not.toBeInTheDocument();
expect(screen.getByText('Assign a user')).toBeInTheDocument();
});
it('shows the suggest users edit button when the user has update permissions', () => {
appMockRender.render(<AssignUsers {...defaultProps} />);
renderWithTestingProviders(<AssignUsers {...defaultProps} />);
expect(screen.getByTestId('case-view-assignees-edit')).toBeInTheDocument();
});
@ -90,7 +90,7 @@ describe('AssignUsers', () => {
caseAssignees: userProfiles.slice(0, 2),
userProfiles: userProfilesMap,
};
appMockRender.render(<AssignUsers {...props} />);
renderWithTestingProviders(<AssignUsers {...props} />);
expect(screen.getByText('Damaged Raccoon')).toBeInTheDocument();
expect(screen.getByText('Physical Dinosaur')).toBeInTheDocument();
@ -100,7 +100,7 @@ describe('AssignUsers', () => {
});
it('shows the rerendered assignees', () => {
const { rerender } = appMockRender.render(<AssignUsers {...defaultProps} />);
const { rerender } = renderWithTestingProviders(<AssignUsers {...defaultProps} />);
const props = {
...defaultProps,
@ -121,7 +121,7 @@ describe('AssignUsers', () => {
...defaultProps,
userProfiles: userProfilesMap,
};
appMockRender.render(<AssignUsers {...props} />);
renderWithTestingProviders(<AssignUsers {...props} />);
fireEvent.click(screen.getByTestId('case-view-assignees-edit-button'));
await waitForEuiPopoverOpen();
@ -137,7 +137,7 @@ describe('AssignUsers', () => {
...defaultProps,
userProfiles: userProfilesMap,
};
appMockRender.render(<AssignUsers {...props} />);
renderWithTestingProviders(<AssignUsers {...props} />);
fireEvent.click(screen.getByText('Assign a user'));
await waitForEuiPopoverOpen();
@ -155,7 +155,7 @@ describe('AssignUsers', () => {
onAssigneesChanged,
userProfiles: userProfilesMap,
};
appMockRender.render(<AssignUsers {...props} />);
renderWithTestingProviders(<AssignUsers {...props} />);
fireEvent.click(screen.getByText('assign yourself'));
@ -185,7 +185,7 @@ describe('AssignUsers', () => {
onAssigneesChanged,
userProfiles: userProfilesMap,
};
appMockRender.render(<AssignUsers {...props} />);
renderWithTestingProviders(<AssignUsers {...props} />);
fireEvent.mouseEnter(
screen.getByTestId(`user-profile-assigned-user-${userProfiles[0].user.username}-remove-group`)
@ -208,7 +208,7 @@ describe('AssignUsers', () => {
onAssigneesChanged,
userProfiles: userProfilesMap,
};
appMockRender.render(<AssignUsers {...props} />);
renderWithTestingProviders(<AssignUsers {...props} />);
fireEvent.click(screen.getByTestId('case-view-assignees-edit-button'));
await waitForEuiPopoverOpen();
@ -248,7 +248,7 @@ describe('AssignUsers', () => {
onAssigneesChanged,
userProfiles: userProfilesMap,
};
appMockRender.render(<AssignUsers {...props} />);
renderWithTestingProviders(<AssignUsers {...props} />);
fireEvent.click(screen.getByTestId('case-view-assignees-edit-button'));
await waitForEuiPopoverOpen();
@ -268,7 +268,7 @@ describe('AssignUsers', () => {
onAssigneesChanged,
userProfiles: userProfilesMap,
};
appMockRender.render(<AssignUsers {...props} />);
renderWithTestingProviders(<AssignUsers {...props} />);
fireEvent.mouseEnter(screen.getByTestId(`user-profile-assigned-user-unknownId1-remove-group`));
fireEvent.click(screen.getByTestId(`user-profile-assigned-user-unknownId1-remove-button`));
@ -290,7 +290,7 @@ describe('AssignUsers', () => {
caseAssignees: [{ uid: 'unknownId1' }, { uid: 'unknownId2' }, { uid: userProfiles[0].uid }],
userProfiles: userProfilesMap,
};
appMockRender.render(<AssignUsers {...props} />);
renderWithTestingProviders(<AssignUsers {...props} />);
expect(screen.getByText('Damaged Raccoon')).toBeInTheDocument();
expect(
@ -309,7 +309,7 @@ describe('AssignUsers', () => {
onAssigneesChanged,
userProfiles: userProfilesMap,
};
appMockRender.render(<AssignUsers {...props} />);
renderWithTestingProviders(<AssignUsers {...props} />);
fireEvent.click(screen.getByTestId('case-view-assignees-edit-button'));
await waitForEuiPopoverOpen();
@ -355,7 +355,7 @@ describe('AssignUsers', () => {
onAssigneesChanged,
userProfiles: userProfilesMap,
};
appMockRender.render(<AssignUsers {...props} />);
renderWithTestingProviders(<AssignUsers {...props} />);
fireEvent.click(screen.getByTestId('case-view-assignees-edit-button'));
await waitForEuiPopoverOpen();

View file

@ -18,8 +18,7 @@ import {
getCaseUsersMockResponse,
getUserAction,
} from '../../../containers/mock';
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer, noUpdateCasesPermissions } from '../../../common/mock';
import { noUpdateCasesPermissions, renderWithTestingProviders } from '../../../common/mock';
import { CaseViewActivity } from './case_view_activity';
import type { CaseUI } from '../../../../common';
import { CASE_VIEW_PAGE_TABS } from '../../../../common/types';
@ -150,7 +149,6 @@ const useReplaceCustomFieldMock = useReplaceCustomField as jest.Mock;
const localStorageKey = `${basicCase.owner}.cases.userActivity.sortOrder`;
describe('Case View Page activity tab', () => {
let appMockRender: AppMockRenderer;
const caseConnectors = getCaseConnectorsMockResponse();
const platinumLicense = licensingMock.createLicense({
license: { type: 'platinum' },
@ -217,7 +215,6 @@ describe('Case View Page activity tab', () => {
beforeEach(() => {
jest.clearAllMocks();
appMockRender = createAppMockRenderer();
localStorage.clear();
@ -226,8 +223,9 @@ describe('Case View Page activity tab', () => {
});
it('should render the activity content and main components', async () => {
appMockRender = createAppMockRenderer({ license: platinumLicense });
appMockRender.render(<CaseViewActivity {...caseProps} />);
renderWithTestingProviders(<CaseViewActivity {...caseProps} />, {
wrapperProps: { license: platinumLicense },
});
const caseViewActivity = await screen.findByTestId('case-view-activity');
expect(await within(caseViewActivity).findAllByTestId('user-actions-list')).toHaveLength(2);
@ -246,8 +244,9 @@ describe('Case View Page activity tab', () => {
});
it('should call use get user actions as per top and bottom actions list', async () => {
appMockRender = createAppMockRenderer({ license: platinumLicense });
appMockRender.render(<CaseViewActivity {...caseProps} />);
renderWithTestingProviders(<CaseViewActivity {...caseProps} />, {
wrapperProps: { license: platinumLicense },
});
const lastPageForAll = Math.ceil(userActionsStats.total / userActivityQueryParams.perPage);
@ -257,35 +256,30 @@ describe('Case View Page activity tab', () => {
userActivityQueryParams,
true
);
expect(useFindCaseUserActionsMock).toHaveBeenCalledWith(
caseData.id,
{ ...userActivityQueryParams, page: lastPageForAll },
true
);
});
expect(useFindCaseUserActionsMock).toHaveBeenCalledWith(
caseData.id,
{ ...userActivityQueryParams, page: lastPageForAll },
true
);
});
it('should not render the case view status button when the user does not have update permissions', async () => {
appMockRender = createAppMockRenderer({
permissions: noUpdateCasesPermissions(),
license: platinumLicense,
renderWithTestingProviders(<CaseViewActivity {...caseProps} />, {
wrapperProps: { license: platinumLicense, permissions: noUpdateCasesPermissions() },
});
appMockRender.render(<CaseViewActivity {...caseProps} />);
expect(screen.queryByTestId('case-view-status-action-button')).not.toBeInTheDocument();
await waitForComponentToUpdate();
});
it('should disable the severity selector when the user does not have update permissions', async () => {
appMockRender = createAppMockRenderer({
permissions: noUpdateCasesPermissions(),
license: platinumLicense,
renderWithTestingProviders(<CaseViewActivity {...caseProps} />, {
wrapperProps: { license: platinumLicense, permissions: noUpdateCasesPermissions() },
});
appMockRender.render(<CaseViewActivity {...caseProps} />);
expect(await screen.findByTestId('case-severity-selection')).toBeDisabled();
await waitForComponentToUpdate();
@ -293,7 +287,9 @@ describe('Case View Page activity tab', () => {
it('should show a loading when loading user actions stats', async () => {
useGetCaseUserActionsStatsMock.mockReturnValue({ isLoading: true });
appMockRender.render(<CaseViewActivity {...caseProps} />);
renderWithTestingProviders(<CaseViewActivity {...caseProps} />);
expect(await screen.findByTestId('case-view-loading-content')).toBeInTheDocument();
expect(screen.queryByTestId('case-view-activity')).not.toBeInTheDocument();
expect(screen.queryByTestId('user-actions-list')).not.toBeInTheDocument();
@ -302,7 +298,7 @@ describe('Case View Page activity tab', () => {
it('should show a loading when updating severity ', async () => {
useOnUpdateFieldMock.mockReturnValue({ isLoading: true, loadingKey: 'severity' });
appMockRender.render(<CaseViewActivity {...caseProps} />);
renderWithTestingProviders(<CaseViewActivity {...caseProps} />);
expect(
(await screen.findByTestId('case-severity-selection')).classList.contains(
@ -314,7 +310,7 @@ describe('Case View Page activity tab', () => {
it('should not show a loading for severity when updating tags', async () => {
useOnUpdateFieldMock.mockReturnValue({ isLoading: true, loadingKey: 'tags' });
appMockRender.render(<CaseViewActivity {...caseProps} />);
renderWithTestingProviders(<CaseViewActivity {...caseProps} />);
expect(
(await screen.findByTestId('case-severity-selection')).classList.contains(
@ -329,16 +325,18 @@ describe('Case View Page activity tab', () => {
caseAssignmentAuthorized: false,
});
appMockRender = createAppMockRenderer({ license: basicLicense });
renderWithTestingProviders(<CaseViewActivity {...caseProps} />, {
wrapperProps: { license: basicLicense },
});
appMockRender.render(<CaseViewActivity {...caseProps} />);
expect(screen.queryByTestId('case-view-assignees')).not.toBeInTheDocument();
});
it('should render the assignees on platinum license', async () => {
appMockRender = createAppMockRenderer({ license: platinumLicense });
renderWithTestingProviders(<CaseViewActivity {...caseProps} />, {
wrapperProps: { license: platinumLicense },
});
appMockRender.render(<CaseViewActivity {...caseProps} />);
expect(await screen.findByTestId('case-view-assignees')).toBeInTheDocument();
await waitForComponentToUpdate();
@ -350,16 +348,17 @@ describe('Case View Page activity tab', () => {
pushToServiceAuthorized: false,
});
appMockRender = createAppMockRenderer({ license: basicLicense });
renderWithTestingProviders(<CaseViewActivity {...caseProps} />, {
wrapperProps: { license: basicLicense },
});
appMockRender.render(<CaseViewActivity {...caseProps} />);
expect(screen.queryByTestId('case-view-edit-connector')).not.toBeInTheDocument();
});
it('should render the connector on platinum license', async () => {
appMockRender = createAppMockRenderer({ license: platinumLicense });
appMockRender.render(<CaseViewActivity {...caseProps} />);
renderWithTestingProviders(<CaseViewActivity {...caseProps} />, {
wrapperProps: { license: platinumLicense },
});
expect(await screen.findByTestId('case-view-edit-connector')).toBeInTheDocument();
});
@ -371,7 +370,8 @@ describe('Case View Page activity tab', () => {
observableTypes: [],
},
});
appMockRender.render(
renderWithTestingProviders(
<CaseViewActivity
{...caseProps}
caseData={{
@ -403,7 +403,7 @@ describe('Case View Page activity tab', () => {
},
});
appMockRender.render(
renderWithTestingProviders(
<CaseViewActivity
{...caseProps}
caseData={{
@ -430,7 +430,7 @@ describe('Case View Page activity tab', () => {
});
it('should call user action hooks correctly when filtering for all', async () => {
appMockRender.render(<CaseViewActivity {...caseProps} />);
renderWithTestingProviders(<CaseViewActivity {...caseProps} />);
const lastPageForAll = Math.ceil(userActionsStats.total / userActivityQueryParams.perPage);
@ -452,7 +452,7 @@ describe('Case View Page activity tab', () => {
});
it('should call user action hooks correctly when filtering for comments', async () => {
appMockRender.render(<CaseViewActivity {...caseProps} />);
renderWithTestingProviders(<CaseViewActivity {...caseProps} />);
const lastPageForComment = Math.ceil(
userActionsStats.totalComments / userActivityQueryParams.perPage
@ -476,7 +476,7 @@ describe('Case View Page activity tab', () => {
});
it('should call user action hooks correctly when filtering for history', async () => {
appMockRender.render(<CaseViewActivity {...caseProps} />);
renderWithTestingProviders(<CaseViewActivity {...caseProps} />);
const lastPageForHistory = Math.ceil(
userActionsStats.totalOtherActions / userActivityQueryParams.perPage
@ -503,8 +503,7 @@ describe('Case View Page activity tab', () => {
describe('Case users', () => {
describe('Assignees', () => {
it('should render assignees in the participants section', async () => {
appMockRender = createAppMockRenderer({ license: platinumLicense });
appMockRender.render(
renderWithTestingProviders(
<CaseViewActivity
{...caseProps}
caseData={{
@ -513,7 +512,10 @@ describe('Case View Page activity tab', () => {
uid: assignee.uid ?? 'not-valid',
})),
}}
/>
/>,
{
wrapperProps: { license: platinumLicense },
}
);
const assigneesSection = within(await screen.findByTestId('case-view-assignees'));
@ -534,8 +536,7 @@ describe('Case View Page activity tab', () => {
},
});
appMockRender = createAppMockRenderer();
appMockRender.render(<CaseViewActivity {...caseProps} />);
renderWithTestingProviders(<CaseViewActivity {...caseProps} />);
const userActions = within((await screen.findAllByTestId('user-actions-list'))[1]);
@ -560,8 +561,7 @@ describe('Case View Page activity tab', () => {
},
});
appMockRender = createAppMockRenderer();
appMockRender.render(<CaseViewActivity {...caseProps} />);
renderWithTestingProviders(<CaseViewActivity {...caseProps} />);
const userActions = within((await screen.findAllByTestId('user-actions-list'))[1]);
@ -635,8 +635,7 @@ describe('Case View Page activity tab', () => {
},
});
appMockRender = createAppMockRenderer();
appMockRender.render(<CaseViewActivity {...caseProps} />);
renderWithTestingProviders(<CaseViewActivity {...caseProps} />);
const userActions = within((await screen.findAllByTestId('user-actions-list'))[1]);
@ -650,7 +649,7 @@ describe('Case View Page activity tab', () => {
describe('Category', () => {
it('should show the category correctly', async () => {
appMockRender.render(
renderWithTestingProviders(
<CaseViewActivity
{...caseProps}
caseData={{

View file

@ -9,13 +9,12 @@ import React from 'react';
import { waitFor, screen } from '@testing-library/react';
import { OBSERVABILITY_OWNER } from '../../../../common/constants';
import { alertCommentWithIndices, basicCase } from '../../../containers/mock';
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
import type { CaseUI } from '../../../../common';
import { CaseViewAlerts } from './case_view_alerts';
import * as api from '../../../containers/api';
import type { FeatureIdsResponse } from '../../../containers/types';
import { SECURITY_SOLUTION_RULE_TYPE_IDS } from '@kbn/securitysolution-rules';
import { renderWithTestingProviders } from '../../../common/mock';
jest.mock('../../../containers/api');
@ -24,33 +23,49 @@ const caseData: CaseUI = {
comments: [...basicCase.comments, alertCommentWithIndices],
};
const getAlertsStateTableMock = jest.fn().mockReturnValue(<div data-test-subj="alerts-table" />);
const getAlertConfigIdPerRuleTypesMock = jest
.fn()
.mockReturnValue('case-details-alerts-observability');
describe('CaseUI View Page activity tab', () => {
const getAlertsStateTableMock = jest.fn();
let appMockRender: AppMockRenderer;
beforeEach(() => {
appMockRender = createAppMockRenderer();
appMockRender.coreStart.triggersActionsUi.getAlertsStateTable =
getAlertsStateTableMock.mockReturnValue(<div data-test-subj="alerts-table" />);
appMockRender.coreStart.triggersActionsUi.alertsTableConfigurationRegistry.register({
id: 'case-details-alerts-observability',
columns: [],
ruleTypeIds: ['log-threshold'],
});
});
afterEach(() => {
jest.clearAllMocks();
});
it('should render the alerts table', async () => {
appMockRender.render(<CaseViewAlerts caseData={caseData} />);
renderWithTestingProviders(<CaseViewAlerts caseData={caseData} />, {
wrapperProps: {
services: {
triggersActionsUi: {
getAlertsStateTable: getAlertsStateTableMock,
// @ts-expect-error: not all services are required
alertsTableConfigurationRegistry: {
getAlertConfigIdPerRuleTypes: getAlertConfigIdPerRuleTypesMock,
},
},
},
},
});
expect(await screen.findByTestId('alerts-table')).toBeInTheDocument();
});
it('should call the alerts table with correct props for security solution', async () => {
appMockRender.render(<CaseViewAlerts caseData={caseData} />);
renderWithTestingProviders(<CaseViewAlerts caseData={caseData} />, {
wrapperProps: {
services: {
triggersActionsUi: {
getAlertsStateTable: getAlertsStateTableMock,
// @ts-expect-error: not all services are required
alertsTableConfigurationRegistry: {
getAlertConfigIdPerRuleTypes: getAlertConfigIdPerRuleTypesMock,
},
},
},
},
});
await waitFor(async () => {
expect(getAlertsStateTableMock).toHaveBeenCalledWith({
alertsTableConfigurationRegistry: expect.anything(),
@ -76,13 +91,27 @@ describe('CaseUI View Page activity tab', () => {
ruleTypeIds: { buckets: [{ doc_count: 1, key: 'log-threshold' }] },
},
} as unknown as FeatureIdsResponse);
appMockRender.render(
renderWithTestingProviders(
<CaseViewAlerts
caseData={{
...caseData,
owner: OBSERVABILITY_OWNER,
}}
/>
/>,
{
wrapperProps: {
services: {
triggersActionsUi: {
getAlertsStateTable: getAlertsStateTableMock,
// @ts-expect-error: not all services are required
alertsTableConfigurationRegistry: {
getAlertConfigIdPerRuleTypes: getAlertConfigIdPerRuleTypesMock,
},
},
},
},
}
);
await waitFor(async () => {
@ -104,14 +133,28 @@ describe('CaseUI View Page activity tab', () => {
it('should call the getFeatureIds with the correct alert ID', async () => {
const getFeatureIdsMock = jest.spyOn(api, 'getFeatureIds');
appMockRender.render(
renderWithTestingProviders(
<CaseViewAlerts
caseData={{
...caseData,
owner: OBSERVABILITY_OWNER,
}}
/>
/>,
{
wrapperProps: {
services: {
triggersActionsUi: {
getAlertsStateTable: getAlertsStateTableMock,
// @ts-expect-error: not all services are required
alertsTableConfigurationRegistry: {
getAlertConfigIdPerRuleTypes: getAlertConfigIdPerRuleTypesMock,
},
},
},
},
}
);
await waitFor(async () => {
expect(getFeatureIdsMock).toHaveBeenCalledWith({
query: {
@ -125,13 +168,26 @@ describe('CaseUI View Page activity tab', () => {
});
it('should show an empty prompt when the cases has no alerts', async () => {
appMockRender.render(
renderWithTestingProviders(
<CaseViewAlerts
caseData={{
...caseData,
comments: [],
}}
/>
/>,
{
wrapperProps: {
services: {
triggersActionsUi: {
getAlertsStateTable: getAlertsStateTableMock,
// @ts-expect-error: not all services are required
alertsTableConfigurationRegistry: {
getAlertConfigIdPerRuleTypes: getAlertConfigIdPerRuleTypesMock,
},
},
},
},
}
);
expect(await screen.findByTestId('caseViewAlertsEmpty')).toBeInTheDocument();

View file

@ -10,12 +10,11 @@ import { screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import type { CaseUI } from '../../../../common';
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
import { alertCommentWithIndices, basicCase } from '../../../containers/mock';
import { useGetCaseFiles } from '../../../containers/use_get_case_files';
import { CaseViewFiles, DEFAULT_CASE_FILES_FILTERING_OPTIONS } from './case_view_files';
import { renderWithTestingProviders } from '../../../common/mock';
jest.mock('../../../containers/use_get_case_files');
@ -27,37 +26,30 @@ const caseData: CaseUI = {
};
describe('Case View Page files tab', () => {
let appMockRender: AppMockRenderer;
useGetCaseFilesMock.mockReturnValue({
data: { files: [], total: 11 },
isLoading: false,
});
beforeEach(() => {
appMockRender = createAppMockRenderer();
jest.clearAllMocks();
});
afterEach(async () => {
await appMockRender.clearQueryCache();
});
it('should render the utility bar for the files table', async () => {
appMockRender.render(<CaseViewFiles caseData={caseData} />);
renderWithTestingProviders(<CaseViewFiles caseData={caseData} />);
expect((await screen.findAllByTestId('cases-files-add')).length).toBe(2);
expect(await screen.findByTestId('cases-files-search')).toBeInTheDocument();
});
it('should render the files table', async () => {
appMockRender.render(<CaseViewFiles caseData={caseData} />);
renderWithTestingProviders(<CaseViewFiles caseData={caseData} />);
expect(await screen.findByTestId('cases-files-table')).toBeInTheDocument();
});
it('clicking table pagination triggers calls to useGetCaseFiles', async () => {
appMockRender.render(<CaseViewFiles caseData={caseData} />);
renderWithTestingProviders(<CaseViewFiles caseData={caseData} />);
expect(await screen.findByTestId('cases-files-table')).toBeInTheDocument();
@ -75,7 +67,7 @@ describe('Case View Page files tab', () => {
it('changing perPage value triggers calls to useGetCaseFiles', async () => {
const targetPagination = 50;
appMockRender.render(<CaseViewFiles caseData={caseData} />);
renderWithTestingProviders(<CaseViewFiles caseData={caseData} />);
expect(await screen.findByTestId('cases-files-table')).toBeInTheDocument();
@ -97,7 +89,7 @@ describe('Case View Page files tab', () => {
});
it('search by word triggers calls to useGetCaseFiles', async () => {
appMockRender.render(<CaseViewFiles caseData={caseData} />);
renderWithTestingProviders(<CaseViewFiles caseData={caseData} />);
expect(await screen.findByTestId('cases-files-table')).toBeInTheDocument();

View file

@ -8,28 +8,23 @@
import React from 'react';
import { screen } from '@testing-library/react';
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
import { basicCase } from '../../../containers/mock';
import { CaseViewObservables } from './case_view_observables';
import { renderWithTestingProviders } from '../../../common/mock';
describe('Case View Page observables tab', () => {
let appMockRender: AppMockRenderer;
beforeEach(() => {
appMockRender = createAppMockRenderer();
jest.clearAllMocks();
});
it('should render the utility bar for the observables table', async () => {
appMockRender.render(<CaseViewObservables isLoading={false} caseData={basicCase} />);
renderWithTestingProviders(<CaseViewObservables isLoading={false} caseData={basicCase} />);
expect((await screen.findAllByTestId('cases-observables-add')).length).toBe(2);
});
it('should render the observable table', async () => {
appMockRender.render(<CaseViewObservables isLoading={false} caseData={basicCase} />);
renderWithTestingProviders(<CaseViewObservables isLoading={false} caseData={basicCase} />);
expect(await screen.findByTestId('cases-observables-table')).toBeInTheDocument();
});

View file

@ -9,11 +9,10 @@ import React from 'react';
import { screen } from '@testing-library/react';
import type { CaseUI } from '../../../../common';
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
import { alertCommentWithIndices, basicCase } from '../../../containers/mock';
import { CaseViewSimilarCases } from './case_view_similar_cases';
import { renderWithTestingProviders } from '../../../common/mock';
const caseData: CaseUI = {
...basicCase,
@ -21,16 +20,13 @@ const caseData: CaseUI = {
};
// Failing: See https://github.com/elastic/kibana/issues/207056
describe.skip('Case View Page similar cases tab', () => {
let appMockRender: AppMockRenderer;
describe('Case View Page similar cases tab', () => {
beforeEach(() => {
appMockRender = createAppMockRenderer();
jest.clearAllMocks();
});
it('should render the similar cases table', async () => {
appMockRender.render(<CaseViewSimilarCases caseData={caseData} />);
renderWithTestingProviders(<CaseViewSimilarCases caseData={caseData} />);
expect(await screen.findByTestId('similar-cases-table')).toBeInTheDocument();
});

View file

@ -8,8 +8,7 @@
import React from 'react';
import { screen, waitFor, within } from '@testing-library/react';
import type { AppMockRenderer } from '../../../common/mock';
import { readCasesPermissions, createAppMockRenderer } from '../../../common/mock';
import { readCasesPermissions, renderWithTestingProviders } from '../../../common/mock';
import { CustomFields } from './custom_fields';
import { customFieldsMock, customFieldsConfigurationMock } from '../../../containers/mock';
@ -17,21 +16,15 @@ import userEvent from '@testing-library/user-event';
import { CustomFieldTypes } from '../../../../common/types/domain';
// Failing: See https://github.com/elastic/kibana/issues/185046
describe.skip('Case View Page files tab', () => {
describe('Case View Page files tab', () => {
const onSubmit = jest.fn();
let appMockRender: AppMockRenderer;
beforeEach(() => {
appMockRender = createAppMockRenderer();
jest.clearAllMocks();
});
afterEach(async () => {
await appMockRender.clearQueryCache();
});
it('should render the custom fields correctly', async () => {
appMockRender.render(
renderWithTestingProviders(
<CustomFields
isLoading={false}
customFields={customFieldsMock}
@ -47,7 +40,7 @@ describe.skip('Case View Page files tab', () => {
});
it('should render the custom fields types when the custom fields are empty', async () => {
appMockRender.render(
renderWithTestingProviders(
<CustomFields
isLoading={false}
customFields={[]}
@ -61,7 +54,7 @@ describe.skip('Case View Page files tab', () => {
});
it('should not show the custom fields if the configuration is empty', () => {
appMockRender.render(
renderWithTestingProviders(
<CustomFields
isLoading={false}
customFields={customFieldsMock}
@ -77,7 +70,7 @@ describe.skip('Case View Page files tab', () => {
it('should sort the custom fields correctly', async () => {
const reversedConfiguration = [...customFieldsConfigurationMock].reverse();
appMockRender.render(
renderWithTestingProviders(
<CustomFields
isLoading={false}
customFields={[]}
@ -113,15 +106,14 @@ describe.skip('Case View Page files tab', () => {
});
it('pass the permissions to custom fields correctly', async () => {
appMockRender = createAppMockRenderer({ permissions: readCasesPermissions() });
appMockRender.render(
renderWithTestingProviders(
<CustomFields
isLoading={false}
customFields={customFieldsMock}
customFieldsConfiguration={customFieldsConfigurationMock}
onSubmit={onSubmit}
/>
/>,
{ wrapperProps: { permissions: readCasesPermissions() } }
);
expect(
@ -130,7 +122,7 @@ describe.skip('Case View Page files tab', () => {
});
it('removes extra custom fields', async () => {
appMockRender.render(
renderWithTestingProviders(
<CustomFields
isLoading={false}
customFields={customFieldsMock}
@ -151,7 +143,7 @@ describe.skip('Case View Page files tab', () => {
});
it('updates an existing toggle field correctly', async () => {
appMockRender.render(
renderWithTestingProviders(
<CustomFields
isLoading={false}
customFields={customFieldsMock}
@ -172,7 +164,7 @@ describe.skip('Case View Page files tab', () => {
});
it('updates new toggle field correctly', async () => {
appMockRender.render(
renderWithTestingProviders(
<CustomFields
isLoading={false}
customFields={[]}
@ -193,7 +185,7 @@ describe.skip('Case View Page files tab', () => {
});
it('updates existing text field correctly', async () => {
appMockRender.render(
renderWithTestingProviders(
<CustomFields
isLoading={false}
customFields={customFieldsMock}
@ -224,7 +216,7 @@ describe.skip('Case View Page files tab', () => {
});
it('updates new text field correctly', async () => {
appMockRender.render(
renderWithTestingProviders(
<CustomFields
isLoading={false}
customFields={[]}

View file

@ -10,8 +10,7 @@ import React from 'react';
import type { EditCategoryProps } from './edit_category';
import { EditCategory } from './edit_category';
import userEvent, { type UserEvent } from '@testing-library/user-event';
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer, readCasesPermissions } from '../../../common/mock';
import { readCasesPermissions, renderWithTestingProviders } from '../../../common/mock';
import { waitFor, screen } from '@testing-library/react';
import { useGetCategories } from '../../../containers/use_get_categories';
@ -31,7 +30,6 @@ const useGetCategoriesMock = useGetCategories as jest.Mock;
describe('EditCategory ', () => {
let user: UserEvent;
let appMockRender: AppMockRenderer;
beforeAll(() => {
jest.useFakeTimers();
@ -44,7 +42,6 @@ describe('EditCategory ', () => {
beforeEach(() => {
// Workaround for timeout via https://github.com/testing-library/user-event/issues/833#issuecomment-1171452841
user = userEvent.setup({ advanceTimers: jest.advanceTimersByTime });
appMockRender = createAppMockRenderer();
useGetCategoriesMock.mockReturnValue({
data: categories,
@ -57,27 +54,27 @@ describe('EditCategory ', () => {
});
it('Shows the category header', () => {
appMockRender.render(<EditCategory {...defaultProps} />);
renderWithTestingProviders(<EditCategory {...defaultProps} />);
expect(screen.getByText('Category')).toBeInTheDocument();
});
it('renders no categories', () => {
appMockRender.render(<EditCategory {...defaultProps} />);
renderWithTestingProviders(<EditCategory {...defaultProps} />);
expect(screen.getByTestId('cases-categories')).toBeInTheDocument();
expect(screen.getByTestId('no-categories')).toBeInTheDocument();
});
it('renders category value', () => {
appMockRender.render(<EditCategory {...defaultProps} category="sample" />);
renderWithTestingProviders(<EditCategory {...defaultProps} category="sample" />);
expect(screen.getByText('sample')).toBeInTheDocument();
expect(screen.queryByTestId('no-categories')).not.toBeInTheDocument();
});
it('renders loading state', () => {
appMockRender.render(<EditCategory {...defaultProps} isLoading={true} />);
renderWithTestingProviders(<EditCategory {...defaultProps} isLoading={true} />);
expect(screen.getByTestId('category-loading')).toBeInTheDocument();
expect(screen.queryByTestId('category-edit-button')).not.toBeInTheDocument();
@ -89,7 +86,7 @@ describe('EditCategory ', () => {
isLoading: true,
});
appMockRender.render(<EditCategory {...defaultProps} />);
renderWithTestingProviders(<EditCategory {...defaultProps} />);
expect(screen.getByTestId('category-loading')).toBeInTheDocument();
@ -99,7 +96,7 @@ describe('EditCategory ', () => {
});
it('shows combo box on edit', async () => {
appMockRender.render(<EditCategory {...defaultProps} />);
renderWithTestingProviders(<EditCategory {...defaultProps} />);
await user.click(screen.getByTestId('category-edit-button'));
@ -109,7 +106,7 @@ describe('EditCategory ', () => {
});
it('should select category from list', async () => {
appMockRender.render(<EditCategory {...defaultProps} />);
renderWithTestingProviders(<EditCategory {...defaultProps} />);
await user.click(screen.getByTestId('category-edit-button'));
@ -129,7 +126,7 @@ describe('EditCategory ', () => {
});
it('should add new category', async () => {
appMockRender.render(<EditCategory {...defaultProps} />);
renderWithTestingProviders(<EditCategory {...defaultProps} />);
await user.click(screen.getByTestId('category-edit-button'));
@ -149,7 +146,7 @@ describe('EditCategory ', () => {
});
it('should trim category', async () => {
appMockRender.render(<EditCategory {...defaultProps} />);
renderWithTestingProviders(<EditCategory {...defaultProps} />);
await user.click(screen.getByTestId('category-edit-button'));
@ -169,7 +166,7 @@ describe('EditCategory ', () => {
});
it('should not save category on cancel click', async () => {
appMockRender.render(<EditCategory {...defaultProps} />);
renderWithTestingProviders(<EditCategory {...defaultProps} />);
await user.click(screen.getByTestId('category-edit-button'));
@ -187,12 +184,13 @@ describe('EditCategory ', () => {
await waitFor(() => {
expect(onSubmit).not.toBeCalled();
expect(screen.getByTestId('no-categories')).toBeInTheDocument();
});
expect(screen.getByTestId('no-categories')).toBeInTheDocument();
});
it('should be able to remove category', async () => {
appMockRender.render(<EditCategory {...defaultProps} category={'My category'} />);
renderWithTestingProviders(<EditCategory {...defaultProps} category={'My category'} />);
expect(screen.getByText('My category')).toBeInTheDocument();
@ -216,7 +214,7 @@ describe('EditCategory ', () => {
it('should disabled the save button on error', async () => {
const bigCategory = 'a'.repeat(51);
appMockRender.render(<EditCategory {...defaultProps} />);
renderWithTestingProviders(<EditCategory {...defaultProps} />);
await user.click(screen.getByTestId('category-edit-button'));
@ -238,7 +236,7 @@ describe('EditCategory ', () => {
});
it('should disabled the save button on empty state', async () => {
appMockRender.render(<EditCategory {...defaultProps} />);
renderWithTestingProviders(<EditCategory {...defaultProps} />);
await user.click(screen.getByTestId('category-edit-button'));
@ -250,28 +248,29 @@ describe('EditCategory ', () => {
});
it('should disabled the save button when not changing category', async () => {
appMockRender.render(<EditCategory {...defaultProps} category={'My category'} />);
renderWithTestingProviders(<EditCategory {...defaultProps} category={'My category'} />);
await user.click(screen.getByTestId('category-edit-button'));
await waitFor(() => {
expect(screen.getByTestId('categories-list')).toBeInTheDocument();
expect(screen.getByTestId('comboBoxSearchInput')).toHaveValue('My category');
});
expect(screen.getByTestId('comboBoxSearchInput')).toHaveValue('My category');
expect(screen.getByTestId('edit-category-submit')).toBeDisabled();
});
it('does not show edit button when the user does not have update permissions', () => {
const newAppMockRenderer = createAppMockRenderer({ permissions: readCasesPermissions() });
newAppMockRenderer.render(<EditCategory {...defaultProps} />);
renderWithTestingProviders(<EditCategory {...defaultProps} />, {
wrapperProps: { permissions: readCasesPermissions() },
});
expect(screen.queryByTestId('category-edit-button')).not.toBeInTheDocument();
});
it('should set the category correctly if it is updated', async () => {
const { rerender } = appMockRender.render(
const { rerender } = renderWithTestingProviders(
<EditCategory {...defaultProps} category={'My category'} />
);
@ -279,9 +278,10 @@ describe('EditCategory ', () => {
await waitFor(() => {
expect(screen.getByTestId('categories-list')).toBeInTheDocument();
expect(screen.getByTestId('comboBoxSearchInput')).toHaveValue('My category');
});
expect(screen.getByTestId('comboBoxSearchInput')).toHaveValue('My category');
await user.click(screen.getByTestId('edit-category-cancel'));
rerender(<EditCategory {...defaultProps} category="category from the API" />);
@ -290,12 +290,13 @@ describe('EditCategory ', () => {
await waitFor(() => {
expect(screen.getByTestId('categories-list')).toBeInTheDocument();
expect(screen.getByTestId('comboBoxSearchInput')).toHaveValue('category from the API');
});
expect(screen.getByTestId('comboBoxSearchInput')).toHaveValue('category from the API');
});
it('removes the category correctly using the cross button', async () => {
appMockRender.render(<EditCategory {...defaultProps} category="My category" />);
renderWithTestingProviders(<EditCategory {...defaultProps} category="My category" />);
await waitFor(() => {
expect(screen.getByText('My category')).toBeInTheDocument();

View file

@ -11,8 +11,7 @@ import userEvent, { type UserEvent } from '@testing-library/user-event';
import type { EditTagsProps } from './edit_tags';
import { EditTags } from './edit_tags';
import { readCasesPermissions, createAppMockRenderer } from '../../../common/mock';
import type { AppMockRenderer } from '../../../common/mock';
import { readCasesPermissions, renderWithTestingProviders } from '../../../common/mock';
import { useGetTags } from '../../../containers/use_get_tags';
import { MAX_LENGTH_PER_TAG } from '../../../../common/constants';
@ -27,7 +26,6 @@ const defaultProps: EditTagsProps = {
describe('EditTags ', () => {
let user: UserEvent;
let appMockRender: AppMockRenderer;
const sampleTags = ['coke', 'pepsi'];
const fetchTags = jest.fn();
@ -52,19 +50,17 @@ describe('EditTags ', () => {
data: sampleTags,
refetch: fetchTags,
}));
appMockRender = createAppMockRenderer();
});
it('renders no tags message', async () => {
appMockRender.render(<EditTags {...defaultProps} />);
renderWithTestingProviders(<EditTags {...defaultProps} />);
expect(await screen.findByTestId('no-tags')).toBeInTheDocument();
expect(await screen.findByTestId('tag-list-edit-button')).toBeInTheDocument();
});
it('edit tag from options on submit', async () => {
appMockRender.render(<EditTags {...defaultProps} />);
renderWithTestingProviders(<EditTags {...defaultProps} />);
await user.click(await screen.findByTestId('tag-list-edit-button'));
@ -78,7 +74,7 @@ describe('EditTags ', () => {
});
it('add new tags on submit', async () => {
appMockRender.render(<EditTags {...defaultProps} />);
renderWithTestingProviders(<EditTags {...defaultProps} />);
await user.click(await screen.findByTestId('tag-list-edit-button'));
@ -94,7 +90,7 @@ describe('EditTags ', () => {
});
it('trims the tags on submit', async () => {
appMockRender.render(<EditTags {...defaultProps} />);
renderWithTestingProviders(<EditTags {...defaultProps} />);
await user.click(await screen.findByTestId('tag-list-edit-button'));
@ -110,7 +106,7 @@ describe('EditTags ', () => {
});
it('cancels on cancel', async () => {
appMockRender.render(<EditTags {...defaultProps} />);
renderWithTestingProviders(<EditTags {...defaultProps} />);
await user.click(await screen.findByTestId('tag-list-edit-button'));
@ -130,7 +126,7 @@ describe('EditTags ', () => {
});
it('shows error when tag is empty', async () => {
appMockRender.render(<EditTags {...defaultProps} />);
renderWithTestingProviders(<EditTags {...defaultProps} />);
await user.click(await screen.findByTestId('tag-list-edit-button'));
@ -146,7 +142,7 @@ describe('EditTags ', () => {
it('shows error when tag is too long', async () => {
const longTag = 'z'.repeat(MAX_LENGTH_PER_TAG + 1);
appMockRender.render(<EditTags {...defaultProps} />);
renderWithTestingProviders(<EditTags {...defaultProps} />);
await user.click(await screen.findByTestId('tag-list-edit-button'));
@ -164,8 +160,9 @@ describe('EditTags ', () => {
});
it('does not render when the user does not have update permissions', () => {
appMockRender = createAppMockRenderer({ permissions: readCasesPermissions() });
appMockRender.render(<EditTags {...defaultProps} />);
renderWithTestingProviders(<EditTags {...defaultProps} />, {
wrapperProps: { permissions: readCasesPermissions() },
});
expect(screen.queryByTestId('tag-list-edit')).not.toBeInTheDocument();
});

View file

@ -6,8 +6,6 @@
*/
import React from 'react';
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
import { screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
@ -17,6 +15,7 @@ import { userProfiles } from '../../../containers/user_profiles/api.mock';
import { waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl';
import type { UserProfileWithAvatar } from '@kbn/user-profile-components';
import type { AssigneeWithProfile } from '../../user_profiles/types';
import { renderWithTestingProviders } from '../../../common/mock';
jest.mock('../../../containers/user_profiles/api');
@ -25,9 +24,7 @@ const asAssignee = (profile: UserProfileWithAvatar): AssigneeWithProfile => ({
profile,
});
// Failing: See https://github.com/elastic/kibana/issues/171600
describe.skip('SuggestUsersPopover', () => {
let appMockRender: AppMockRenderer;
describe('SuggestUsersPopover', () => {
const defaultProps: SuggestUsersPopoverProps = {
isLoading: false,
assignedUsersWithProfiles: [],
@ -38,14 +35,10 @@ describe.skip('SuggestUsersPopover', () => {
currentUserProfile: undefined,
};
beforeEach(() => {
appMockRender = createAppMockRenderer();
});
it('calls onUsersChange when 1 user is selected', async () => {
const onUsersChange = jest.fn();
const props = { ...defaultProps, onUsersChange };
appMockRender.render(<SuggestUsersPopover {...props} />);
renderWithTestingProviders(<SuggestUsersPopover {...props} />);
await waitForEuiPopoverOpen();
@ -72,7 +65,7 @@ describe.skip('SuggestUsersPopover', () => {
it('calls onUsersChange when multiple users are selected', async () => {
const onUsersChange = jest.fn();
const props = { ...defaultProps, onUsersChange };
appMockRender.render(<SuggestUsersPopover {...props} />);
renderWithTestingProviders(<SuggestUsersPopover {...props} />);
await waitForEuiPopoverOpen();
@ -115,7 +108,7 @@ describe.skip('SuggestUsersPopover', () => {
currentUserProfile: userProfiles[1],
onUsersChange,
};
appMockRender.render(<SuggestUsersPopover {...props} />);
renderWithTestingProviders(<SuggestUsersPopover {...props} />);
await waitForEuiPopoverOpen();
@ -160,7 +153,7 @@ describe.skip('SuggestUsersPopover', () => {
});
it('does not show the assigned users total if there are no assigned users', async () => {
appMockRender.render(<SuggestUsersPopover {...defaultProps} />);
renderWithTestingProviders(<SuggestUsersPopover {...defaultProps} />);
await waitForEuiPopoverOpen();
@ -174,7 +167,7 @@ describe.skip('SuggestUsersPopover', () => {
});
it('shows the 1 assigned total after clicking on a user', async () => {
appMockRender.render(<SuggestUsersPopover {...defaultProps} />);
renderWithTestingProviders(<SuggestUsersPopover {...defaultProps} />);
await waitForEuiPopoverOpen();
@ -192,7 +185,7 @@ describe.skip('SuggestUsersPopover', () => {
...defaultProps,
assignedUsersWithProfiles: [{ uid: userProfiles[0].uid, profile: userProfiles[0] }],
};
appMockRender.render(<SuggestUsersPopover {...props} />);
renderWithTestingProviders(<SuggestUsersPopover {...props} />);
await waitForEuiPopoverOpen();
@ -206,7 +199,7 @@ describe.skip('SuggestUsersPopover', () => {
...defaultProps,
togglePopover,
};
appMockRender.render(<SuggestUsersPopover {...props} />);
renderWithTestingProviders(<SuggestUsersPopover {...props} />);
await waitForEuiPopoverOpen();
@ -218,7 +211,7 @@ describe.skip('SuggestUsersPopover', () => {
});
it('shows results initially', async () => {
appMockRender.render(<SuggestUsersPopover {...defaultProps} />);
renderWithTestingProviders(<SuggestUsersPopover {...defaultProps} />);
await waitForEuiPopoverOpen();

View file

@ -11,17 +11,15 @@ import { UserList } from './user_list';
import * as i18n from '../translations';
import { basicCase } from '../../../containers/mock';
import { useCaseViewNavigation } from '../../../common/navigation/hooks';
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
import userEvent from '@testing-library/user-event';
import { userProfilesMap } from '../../../containers/user_profiles/api.mock';
import { renderWithTestingProviders } from '../../../common/mock';
jest.mock('../../../common/navigation/hooks');
const useCaseViewNavigationMock = useCaseViewNavigation as jest.Mock;
// FLAKY: https://github.com/elastic/kibana/issues/192640
describe.skip('UserList ', () => {
describe('UserList ', () => {
const title = basicCase.title;
const caseLink = 'https://example.com/cases/test';
const user = {
@ -32,17 +30,16 @@ describe.skip('UserList ', () => {
const open = jest.fn();
const getCaseViewUrl = jest.fn().mockReturnValue(caseLink);
let appMockRender: AppMockRenderer;
beforeEach(() => {
jest.clearAllMocks();
appMockRender = createAppMockRenderer();
useCaseViewNavigationMock.mockReturnValue({ getCaseViewUrl });
window.open = open;
});
it('triggers mailto when email icon clicked', async () => {
appMockRender.render(
renderWithTestingProviders(
<UserList
theCase={basicCase}
headline={i18n.REPORTER}
@ -63,7 +60,7 @@ describe.skip('UserList ', () => {
});
it('sort the users correctly', () => {
appMockRender.render(
renderWithTestingProviders(
<UserList
theCase={basicCase}
headline={i18n.REPORTER}
@ -89,15 +86,20 @@ describe.skip('UserList ', () => {
});
it('return null if no users', () => {
const result = appMockRender.render(
<UserList theCase={basicCase} headline={i18n.REPORTER} users={[]} />
renderWithTestingProviders(
<UserList
theCase={basicCase}
headline={i18n.REPORTER}
users={[]}
dataTestSubj={'user-list-wrapper'}
/>
);
expect(result.container).toBeEmptyDOMElement();
expect(screen.queryByTestId('user-list-wrapper')).not.toBeInTheDocument();
});
it('shows the loading spinner if loading', () => {
appMockRender.render(
renderWithTestingProviders(
<UserList
theCase={basicCase}
headline={i18n.REPORTER}
@ -114,7 +116,7 @@ describe.skip('UserList ', () => {
});
it('should render users with user profiles correctly', () => {
appMockRender.render(
renderWithTestingProviders(
<UserList
theCase={basicCase}
headline={i18n.REPORTER}
@ -137,7 +139,7 @@ describe.skip('UserList ', () => {
});
it('should not render invalid users', () => {
appMockRender.render(
renderWithTestingProviders(
<UserList
theCase={basicCase}
headline={i18n.REPORTER}
@ -171,7 +173,7 @@ describe.skip('UserList ', () => {
});
it('should render Unknown users correctly', () => {
appMockRender.render(
renderWithTestingProviders(
<UserList
theCase={basicCase}
headline={i18n.REPORTER}

View file

@ -26,10 +26,10 @@ import { usePostPushToService } from '../../containers/use_post_push_to_service'
import { useKibana } from '../../common/lib/kibana';
import { useFindCaseUserActions } from '../../containers/use_find_case_user_actions';
import { useGetSupportedActionConnectors } from '../../containers/configure/use_get_supported_action_connectors';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
import { createTestQueryClient, renderWithTestingProviders } from '../../common/mock';
import CaseView from '.';
import { waitFor } from '@testing-library/react';
import { waitFor, screen } from '@testing-library/react';
import { useGetTags } from '../../containers/use_get_tags';
import { casesQueriesKeys } from '../../containers/constants';
import {
@ -86,8 +86,6 @@ describe('CaseView', () => {
});
};
let appMockRenderer: AppMockRenderer;
beforeAll(() => {
mockGetCase();
useGetCaseMetricsMock.mockReturnValue(defaultGetCaseMetrics);
@ -104,27 +102,26 @@ describe('CaseView', () => {
beforeEach(() => {
jest.clearAllMocks();
appMockRenderer = createAppMockRenderer();
});
it('should show an error if a case return error', async () => {
mockGetCase({ isError: true });
const result = appMockRenderer.render(<CaseView {...caseViewProps} />);
renderWithTestingProviders(<CaseView {...caseViewProps} />);
expect(result.queryByTestId('case-view-does-not-exist')).toBeInTheDocument();
expect(screen.getByTestId('case-view-does-not-exist')).toBeInTheDocument();
});
it('should return spinner if loading', async () => {
mockGetCase({ isLoading: true });
const result = appMockRenderer.render(<CaseView {...caseViewProps} />);
expect(result.queryByTestId('case-view-loading')).toBeInTheDocument();
renderWithTestingProviders(<CaseView {...caseViewProps} />);
expect(screen.getByTestId('case-view-loading')).toBeInTheDocument();
});
it('should return case view when data is there', async () => {
mockGetCase({ data: { ...defaultGetCase.data, outcome: 'exactMatch' } });
const result = appMockRenderer.render(<CaseView {...caseViewProps} />);
renderWithTestingProviders(<CaseView {...caseViewProps} />);
expect(result.queryByTestId('case-view-title')).toBeInTheDocument();
expect(screen.getByTestId('case-view-title')).toBeInTheDocument();
expect(spacesUiApiMock.components.getLegacyUrlConflict).not.toHaveBeenCalled();
expect(spacesUiApiMock.redirectLegacyUrl).not.toHaveBeenCalled();
});
@ -140,8 +137,8 @@ describe('CaseView', () => {
aliasPurpose: resolveAliasPurpose,
},
});
const result = appMockRenderer.render(<CaseView {...caseViewProps} />);
expect(result.queryByTestId('case-view-title')).toBeInTheDocument();
renderWithTestingProviders(<CaseView {...caseViewProps} />);
expect(screen.getByTestId('case-view-title')).toBeInTheDocument();
expect(spacesUiApiMock.components.getLegacyUrlConflict).not.toHaveBeenCalled();
expect(spacesUiApiMock.redirectLegacyUrl).toHaveBeenCalledWith({
path: `/cases/${resolveAliasId}`,
@ -156,10 +153,10 @@ describe('CaseView', () => {
data: { ...defaultGetCase.data, outcome: 'conflict', aliasTargetId: resolveAliasId },
});
const result = appMockRenderer.render(<CaseView {...caseViewProps} />);
renderWithTestingProviders(<CaseView {...caseViewProps} />);
expect(result.queryByTestId('case-view-title')).toBeInTheDocument();
expect(result.queryByTestId('conflict-component')).toBeInTheDocument();
expect(screen.getByTestId('case-view-title')).toBeInTheDocument();
expect(screen.getByTestId('conflict-component')).toBeInTheDocument();
expect(spacesUiApiMock.redirectLegacyUrl).not.toHaveBeenCalled();
expect(spacesUiApiMock.components.getLegacyUrlConflict).toHaveBeenCalledWith({
@ -171,21 +168,26 @@ describe('CaseView', () => {
});
it('should refresh data on refresh', async () => {
const queryClientSpy = jest.spyOn(appMockRenderer.queryClient, 'invalidateQueries');
const result = appMockRenderer.render(<CaseView {...caseViewProps} />);
await userEvent.click(result.getByTestId('case-refresh'));
const queryClient = createTestQueryClient();
const queryClientSpy = jest.spyOn(queryClient, 'invalidateQueries');
renderWithTestingProviders(<CaseView {...caseViewProps} />, { wrapperProps: { queryClient } });
await userEvent.click(screen.getByTestId('case-refresh'));
expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.caseView());
expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.tags());
});
describe('when a `refreshRef` prop is provided', () => {
let refreshRef: CaseViewProps['refreshRef'];
let queryClientSpy: jest.SpyInstance;
beforeEach(async () => {
queryClientSpy = jest.spyOn(appMockRenderer.queryClient, 'invalidateQueries');
refreshRef = React.createRef();
appMockRenderer.render(
});
it('should set it with expected refresh interface', async () => {
renderWithTestingProviders(
<CaseView
{...{
refreshRef,
@ -196,20 +198,36 @@ describe('CaseView', () => {
}}
/>
);
});
it('should set it with expected refresh interface', async () => {
expect(refreshRef!.current).toEqual({
refreshCase: expect.any(Function),
});
});
it('should refresh actions and comments', async () => {
const queryClient = createTestQueryClient();
const queryClientSpy = jest.spyOn(queryClient, 'invalidateQueries');
renderWithTestingProviders(
<CaseView
{...{
refreshRef,
caseId: '1234',
onComponentInitialized: jest.fn(),
showAlertDetails: jest.fn(),
useFetchAlertData: jest.fn().mockReturnValue([false, alertsHit[0]]),
}}
/>,
{ wrapperProps: { queryClient } }
);
refreshRef!.current!.refreshCase();
await waitFor(() => {
expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.caseView());
expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.tags());
});
expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.tags());
});
});
});

View file

@ -6,7 +6,7 @@
*/
import React from 'react';
import { render, waitFor } from '@testing-library/react';
import { waitFor, screen } from '@testing-library/react';
import {
basicCaseMetrics,
basicCaseNumericValueFeatures,
@ -14,7 +14,7 @@ import {
} from '../../../containers/mock';
import { CaseViewMetrics } from '.';
import type { SingleCaseMetrics, SingleCaseMetricsFeature } from '../../../../common/ui';
import { TestProviders } from '../../../common/mock';
import { renderWithTestingProviders } from '../../../common/mock';
import { useGetCaseMetrics } from '../../../containers/use_get_case_metrics';
import { useCasesFeatures } from '../../../common/use_cases_features';
import { CaseMetricsFeature } from '../../../../common/types/api';
@ -40,11 +40,7 @@ const renderCaseMetrics = ({
}));
useCasesFeaturesMock.mockReturnValue({ metricsFeatures: features });
return render(
<TestProviders>
<CaseViewMetrics caseId={'1234'} />
</TestProviders>
);
return renderWithTestingProviders(<CaseViewMetrics caseId={'1234'} />);
};
interface FeatureTest {
@ -107,40 +103,40 @@ const metricsFeaturesTests: FeatureTest[] = [
];
describe('CaseViewMetrics', () => {
beforeEach(() => {});
it('should render', () => {
const { getByTestId } = renderCaseMetrics();
expect(getByTestId('case-view-metrics-panel')).toBeInTheDocument();
renderCaseMetrics();
expect(screen.getByTestId('case-view-metrics-panel')).toBeInTheDocument();
});
it('should render loading spinner', () => {
const { getByTestId } = renderCaseMetrics({ isLoading: true });
expect(getByTestId('case-view-metrics-spinner')).toBeInTheDocument();
renderCaseMetrics({ isLoading: true });
expect(screen.getByTestId('case-view-metrics-spinner')).toBeInTheDocument();
});
it('should render metrics with default value 0', async () => {
const { getAllByText } = renderCaseMetrics({
renderCaseMetrics({
metrics: {},
features: basicCaseNumericValueFeatures,
});
await waitFor(() => {
expect(getAllByText('0')).toHaveLength(basicCaseNumericValueFeatures.length);
expect(screen.getAllByText('0')).toHaveLength(basicCaseNumericValueFeatures.length);
});
});
it('should render status metrics with default value of a dash', () => {
const { getAllByText } = renderCaseMetrics({ metrics: {} });
renderCaseMetrics({ metrics: {} });
// \u2014 is the unicode for a long dash
expect(getAllByText('\u2014')).toHaveLength(3);
expect(screen.getAllByText('\u2014')).toHaveLength(3);
});
it('should not render if no features are returned', () => {
const result = renderCaseMetrics({ features: [] });
expect(result.container.innerHTML).toEqual('');
renderCaseMetrics({ features: [] });
expect(screen.queryByTestId('case-view-metrics-panel')).not.toBeInTheDocument();
});
it('should render open to close duration with the icon when it is reopened', () => {
const { getByText, getByTestId } = renderCaseMetrics({
renderCaseMetrics({
metrics: {
lifespan: {
creationDate: new Date(0).toISOString(),
@ -154,12 +150,12 @@ describe('CaseViewMetrics', () => {
},
});
expect(getByText('2 milliseconds (reopened)')).toBeInTheDocument();
expect(getByTestId('case-metrics-lifespan-reopen-icon')).toBeInTheDocument();
expect(screen.getByText('2 milliseconds (reopened)')).toBeInTheDocument();
expect(screen.getByTestId('case-metrics-lifespan-reopen-icon')).toBeInTheDocument();
});
it('should not render open to close duration with the icon when it is not reopened', () => {
const { getByText, queryByTestId } = renderCaseMetrics({
renderCaseMetrics({
metrics: {
lifespan: {
creationDate: new Date(0).toISOString(),
@ -173,8 +169,8 @@ describe('CaseViewMetrics', () => {
},
});
expect(getByText('2 milliseconds')).toBeInTheDocument();
expect(queryByTestId('case-metrics-lifespan-reopen-icon')).not.toBeInTheDocument();
expect(screen.getByText('2 milliseconds')).toBeInTheDocument();
expect(screen.queryByTestId('case-metrics-lifespan-reopen-icon')).not.toBeInTheDocument();
});
it('should prevent negative value for isolateHost actions', () => {
@ -186,21 +182,22 @@ describe('CaseViewMetrics', () => {
},
},
};
const { getByText } = renderCaseMetrics({
renderCaseMetrics({
metrics: incosistentMetrics,
features: [CaseMetricsFeature.ACTIONS_ISOLATE_HOST],
});
expect(getByText('Isolated hosts')).toBeInTheDocument();
expect(getByText('0')).toBeInTheDocument();
expect(screen.getByText('Isolated hosts')).toBeInTheDocument();
expect(screen.getByText('0')).toBeInTheDocument();
});
describe.each(metricsFeaturesTests)('Metrics feature tests', ({ feature, items }) => {
it(`should not render other metrics when rendering feature: ${feature}`, () => {
const { queryByText } = renderCaseMetrics({ features: [feature] });
renderCaseMetrics({ features: [feature] });
metricsFeaturesTests.forEach(({ feature: otherFeature, items: otherItems }) => {
if (feature !== otherFeature) {
otherItems.forEach(({ title }) => {
expect(queryByText(title)).toBeNull();
expect(screen.queryByText(title)).toBeNull();
});
}
});
@ -208,9 +205,9 @@ describe('CaseViewMetrics', () => {
describe.each(items)(`Metric feature: ${feature} item: %s`, ({ title, value }) => {
it('should render metric', () => {
const { getByText } = renderCaseMetrics({ features: [feature] });
expect(getByText(title)).toBeInTheDocument();
expect(getByText(value)).toBeInTheDocument();
renderCaseMetrics({ features: [feature] });
expect(screen.getByText(title)).toBeInTheDocument();
expect(screen.getByText(value)).toBeInTheDocument();
});
});
});

View file

@ -8,8 +8,8 @@
import React from 'react';
import { getAllCasesSelectorModalNoProviderLazy } from '../../client/ui/get_all_cases_selector_modal';
import { getCreateCaseFlyoutLazyNoProvider } from '../../client/ui/get_create_case_flyout';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
import { renderWithTestingProviders } from '../../common/mock';
import { getInitialCasesContextState } from './state/cases_context_reducer';
import { CasesGlobalComponents } from './cases_global_components';
@ -21,10 +21,7 @@ const getAllCasesSelectorModalNoProviderLazyMock =
getAllCasesSelectorModalNoProviderLazy as jest.Mock;
describe('Cases context UI', () => {
let appMock: AppMockRenderer;
beforeEach(() => {
appMock = createAppMockRenderer();
getCreateCaseFlyoutLazyNoProviderMock.mockClear();
});
@ -39,7 +36,7 @@ describe('Cases context UI', () => {
},
},
};
appMock.render(<CasesGlobalComponents state={state} />);
renderWithTestingProviders(<CasesGlobalComponents state={state} />);
expect(getCreateCaseFlyoutLazyNoProviderMock).toHaveBeenCalledWith({ attachments: [] });
});
@ -50,7 +47,7 @@ describe('Cases context UI', () => {
isFlyoutOpen: false,
},
};
appMock.render(<CasesGlobalComponents state={state} />);
renderWithTestingProviders(<CasesGlobalComponents state={state} />);
expect(getCreateCaseFlyoutLazyNoProviderMock).not.toHaveBeenCalled();
});
});
@ -68,7 +65,7 @@ describe('Cases context UI', () => {
},
},
};
appMock.render(<CasesGlobalComponents state={state} />);
renderWithTestingProviders(<CasesGlobalComponents state={state} />);
expect(getAllCasesSelectorModalNoProviderLazyMock).toHaveBeenCalledWith({
attachments: [],
onRowClick,
@ -82,7 +79,7 @@ describe('Cases context UI', () => {
isModalOpen: false,
},
};
appMock.render(<CasesGlobalComponents state={state} />);
renderWithTestingProviders(<CasesGlobalComponents state={state} />);
expect(getAllCasesSelectorModalNoProviderLazyMock).toHaveBeenCalled();
});
});

View file

@ -7,10 +7,10 @@
import { renderHook, act } from '@testing-library/react';
import { useCasesAddToExistingCaseModal } from '../../all_cases/selector_modal/use_cases_add_to_existing_case_modal';
import { createAppMockRenderer } from '../../../common/mock';
import { useIsAddToCaseOpen } from './use_is_add_to_case_open';
import { useCasesToast } from '../../../common/use_cases_toast';
import { useCasesAddToNewCaseFlyout } from '../../create/flyout/use_cases_add_to_new_case_flyout';
import { TestProviders } from '../../../common/mock';
jest.mock('../../../common/use_cases_toast');
const useCasesToastMock = useCasesToast as jest.Mock;
@ -18,8 +18,6 @@ useCasesToastMock.mockReturnValue({
showInfoToast: jest.fn(),
});
const { AppWrapper } = createAppMockRenderer();
describe('use is add to existing case modal open hook', () => {
beforeEach(() => {
jest.clearAllMocks();
@ -32,7 +30,7 @@ describe('use is add to existing case modal open hook', () => {
});
it('should return false when the add to case modal and flyout are not open', async () => {
const { result } = renderHook(useIsAddToCaseOpen, { wrapper: AppWrapper });
const { result } = renderHook(useIsAddToCaseOpen, { wrapper: TestProviders });
expect(result.current).toEqual(false);
});
@ -44,7 +42,7 @@ describe('use is add to existing case modal open hook', () => {
isOpen: useIsAddToCaseOpen(),
};
},
{ wrapper: AppWrapper }
{ wrapper: TestProviders }
);
expect(result.current.isOpen).toEqual(false);
@ -63,7 +61,7 @@ describe('use is add to existing case modal open hook', () => {
isOpen: useIsAddToCaseOpen(),
};
},
{ wrapper: AppWrapper }
{ wrapper: TestProviders }
);
expect(result.current.isOpen).toEqual(false);

View file

@ -15,7 +15,7 @@ import { MAX_CATEGORY_LENGTH } from '../../../common/constants';
import { FormTestComponent } from '../../common/test_utils';
// Failing: See https://github.com/elastic/kibana/issues/177791
describe.skip('Category', () => {
describe('Category', () => {
const onSubmit = jest.fn();
it('renders the category field correctly', async () => {

View file

@ -6,19 +6,11 @@
*/
import React from 'react';
import type { ComponentType, ReactWrapper } from 'enzyme';
import { mount } from 'enzyme';
import { render, screen } from '@testing-library/react';
import { screen } from '@testing-library/react';
import type { Props } from './connectors';
import { Connectors } from './connectors';
import {
type AppMockRenderer,
noConnectorsCasePermission,
createAppMockRenderer,
TestProviders,
} from '../../common/mock';
import { ConnectorsDropdown } from './connectors_dropdown';
import { noConnectorsCasePermission, renderWithTestingProviders } from '../../common/mock';
import { connectors, actionTypes } from './__mock__';
import { ConnectorTypes } from '../../../common/types/domain';
import userEvent from '@testing-library/user-event';
@ -30,8 +22,6 @@ const useApplicationCapabilitiesMock = useApplicationCapabilities as jest.Mocked
jest.mock('../../common/lib/kibana');
describe('Connectors', () => {
let wrapper: ReactWrapper;
let appMockRender: AppMockRenderer;
const onChangeConnector = jest.fn();
const handleShowEditFlyout = jest.fn();
const onAddNewConnector = jest.fn();
@ -49,110 +39,85 @@ describe('Connectors', () => {
onAddNewConnector,
};
beforeAll(() => {
wrapper = mount(<Connectors {...props} />, {
wrappingComponent: TestProviders as ComponentType<React.PropsWithChildren<{}>>,
});
});
beforeEach(() => {
jest.clearAllMocks();
appMockRender = createAppMockRenderer();
});
it('shows the connectors from group', () => {
expect(wrapper.find('[data-test-subj="case-connectors-form-group"]').first().exists()).toBe(
true
);
renderWithTestingProviders(<Connectors {...props} />);
expect(screen.getByTestId('case-connectors-form-group')).toBeInTheDocument();
});
it('shows the connectors form row', () => {
expect(wrapper.find('[data-test-subj="case-connectors-form-row"]').first().exists()).toBe(true);
renderWithTestingProviders(<Connectors {...props} />);
expect(screen.getByTestId('case-connectors-form-row')).toBeInTheDocument();
});
it('shows the connectors dropdown', () => {
expect(wrapper.find('[data-test-subj="case-connectors-dropdown"]').first().exists()).toBe(true);
renderWithTestingProviders(<Connectors {...props} />);
expect(screen.getByTestId('dropdown-connectors')).toBeInTheDocument();
});
it('pass the correct props to child', () => {
const connectorsDropdownProps = wrapper.find(ConnectorsDropdown).props();
expect(connectorsDropdownProps).toMatchObject({
disabled: false,
isLoading: false,
connectors,
selectedConnector: 'none',
onChange: props.onChangeConnector,
});
});
it('the connector is changed successfully', async () => {
renderWithTestingProviders(<Connectors {...props} />);
it('the connector is changed successfully', () => {
wrapper.find('button[data-test-subj="dropdown-connectors"]').simulate('click');
wrapper.find('button[data-test-subj="dropdown-connector-resilient-2"]').simulate('click');
await userEvent.click(screen.getByTestId('dropdown-connectors'));
await userEvent.click(screen.getByTestId('dropdown-connector-resilient-2'));
expect(onChangeConnector).toHaveBeenCalled();
expect(onChangeConnector).toHaveBeenCalledWith('resilient-2');
});
it('the connector is changed successfully to none', () => {
it('the connector is changed successfully to none', async () => {
onChangeConnector.mockClear();
const newWrapper = mount(
renderWithTestingProviders(
<Connectors
{...props}
selectedConnector={{ id: 'servicenow-1', type: ConnectorTypes.serviceNowITSM }}
/>,
{
wrappingComponent: TestProviders as ComponentType<React.PropsWithChildren<{}>>,
}
/>
);
newWrapper.find('button[data-test-subj="dropdown-connectors"]').simulate('click');
newWrapper.find('button[data-test-subj="dropdown-connector-no-connector"]').simulate('click');
await userEvent.click(screen.getByTestId('dropdown-connectors'));
await userEvent.click(screen.getByTestId('dropdown-connector-no-connector'));
expect(onChangeConnector).toHaveBeenCalled();
expect(onChangeConnector).toHaveBeenCalledWith('none');
});
it('shows the add connector button', () => {
appMockRender.render(<Connectors {...props} />);
renderWithTestingProviders(<Connectors {...props} />);
expect(screen.getByTestId('add-new-connector')).toBeInTheDocument();
});
it('shows the add connector flyout when the button is clicked', async () => {
appMockRender.render(<Connectors {...props} />);
renderWithTestingProviders(<Connectors {...props} />);
await userEvent.click(await screen.findByTestId('add-new-connector'));
expect(onAddNewConnector).toHaveBeenCalled();
});
it('the text of the update button is shown correctly', () => {
const newWrapper = mount(
renderWithTestingProviders(
<Connectors
{...props}
selectedConnector={{ id: 'servicenow-1', type: ConnectorTypes.serviceNowITSM }}
/>,
{
wrappingComponent: TestProviders as ComponentType<React.PropsWithChildren<{}>>,
}
/>
);
expect(
newWrapper
.find('button[data-test-subj="case-configure-update-selected-connector-button"]')
.text()
).toBe('Update My SN connector');
expect(screen.getByText('Update My SN connector')).toBeInTheDocument();
});
it('shows the deprecated callout when the connector is deprecated', async () => {
render(
renderWithTestingProviders(
<Connectors
{...props}
selectedConnector={{ id: 'servicenow-uses-table-api', type: ConnectorTypes.serviceNowITSM }}
/>,
{
// wrapper: TestProviders produces a TS error
wrapper: ({ children }) => <TestProviders>{children}</TestProviders>,
}
/>
);
expect(screen.getByText('This connector type is deprecated')).toBeInTheDocument();
@ -160,10 +125,7 @@ describe('Connectors', () => {
});
it('does not shows the deprecated callout when the connector is none', async () => {
render(<Connectors {...props} />, {
// wrapper: TestProviders produces a TS error
wrapper: ({ children }) => <TestProviders>{children}</TestProviders>,
});
renderWithTestingProviders(<Connectors {...props} />);
expect(screen.queryByText('Deprecated connector type')).not.toBeInTheDocument();
});
@ -171,28 +133,29 @@ describe('Connectors', () => {
it('shows the actions permission message if the user does not have read access to actions', async () => {
useApplicationCapabilitiesMock().actions = { crud: false, read: false };
appMockRender.render(<Connectors {...props} />);
renderWithTestingProviders(<Connectors {...props} />);
expect(
await screen.findByTestId('configure-case-connector-permissions-error-msg')
).toBeInTheDocument();
expect(screen.queryByTestId('case-connectors-dropdown')).not.toBeInTheDocument();
expect(screen.queryByTestId('dropdown-connectors')).not.toBeInTheDocument();
});
it('shows the actions permission message if the user does not have access to case connector', async () => {
appMockRender = createAppMockRenderer({ permissions: noConnectorsCasePermission() });
renderWithTestingProviders(<Connectors {...props} />, {
wrapperProps: { permissions: noConnectorsCasePermission() },
});
const result = appMockRender.render(<Connectors {...props} />);
expect(
result.getByTestId('configure-case-connector-permissions-error-msg')
screen.getByTestId('configure-case-connector-permissions-error-msg')
).toBeInTheDocument();
expect(result.queryByTestId('case-connectors-dropdown')).toBe(null);
expect(screen.queryByTestId('dropdown-connectors')).toBe(null);
});
it('it should hide the "Add Connector" button when the user lacks the capability to add a new connector', () => {
useApplicationCapabilitiesMock().actions = { crud: false, read: true };
appMockRender.render(<Connectors {...props} />);
renderWithTestingProviders(<Connectors {...props} />);
expect(screen.queryByTestId('add-new-connector')).not.toBeInTheDocument();
});

View file

@ -120,7 +120,6 @@ const ConnectorsComponent: React.FC<Props> = ({
selectedConnector={selectedConnector.id}
isLoading={isLoading}
onChange={onChangeConnector}
data-test-subj="case-connectors-dropdown"
/>
) : (
<EuiText data-test-subj="configure-case-connector-permissions-error-msg" size="s">

View file

@ -70,7 +70,7 @@ describe('ConnectorsDropdown', () => {
</EuiFlexItem>
<EuiFlexItem>
<span
data-test-subj="dropdown-connector-no-connector"
data-test-subj="dropdown-connector-no-connector-label"
>
No connector selected
</span>

View file

@ -56,7 +56,7 @@ const noConnectorOption = {
/>
</EuiFlexItem>
<EuiFlexItem>
<span data-test-subj={`dropdown-connector-no-connector`}>{i18n.NO_CONNECTOR}</span>
<span data-test-subj={`dropdown-connector-no-connector-label`}>{i18n.NO_CONNECTOR}</span>
</EuiFlexItem>
</EuiFlexGroup>
),

View file

@ -5,14 +5,14 @@
* 2.0.
*/
import userEvent from '@testing-library/user-event';
import React from 'react';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
import userEvent from '@testing-library/user-event';
import { screen } from '@testing-library/react';
import { renderWithTestingProviders } from '../../common/mock';
import { DeleteConfirmationModal } from './delete_confirmation_modal';
describe('DeleteConfirmationModal', () => {
let appMock: AppMockRenderer;
const props = {
title: 'My custom field',
message: 'This is a sample message',
@ -21,32 +21,31 @@ describe('DeleteConfirmationModal', () => {
};
beforeEach(() => {
appMock = createAppMockRenderer();
jest.clearAllMocks();
});
it('renders correctly', async () => {
const result = appMock.render(<DeleteConfirmationModal {...props} />);
renderWithTestingProviders(<DeleteConfirmationModal {...props} />);
expect(result.getByTestId('confirm-delete-modal')).toBeInTheDocument();
expect(result.getByText('Delete')).toBeInTheDocument();
expect(result.getByText('Cancel')).toBeInTheDocument();
expect(screen.getByTestId('confirm-delete-modal')).toBeInTheDocument();
expect(screen.getByText('Delete')).toBeInTheDocument();
expect(screen.getByText('Cancel')).toBeInTheDocument();
});
it('calls onConfirm', async () => {
const result = appMock.render(<DeleteConfirmationModal {...props} />);
renderWithTestingProviders(<DeleteConfirmationModal {...props} />);
expect(result.getByText('Delete')).toBeInTheDocument();
await userEvent.click(result.getByText('Delete'));
expect(screen.getByText('Delete')).toBeInTheDocument();
await userEvent.click(screen.getByText('Delete'));
expect(props.onConfirm).toHaveBeenCalled();
});
it('calls onCancel', async () => {
const result = appMock.render(<DeleteConfirmationModal {...props} />);
renderWithTestingProviders(<DeleteConfirmationModal {...props} />);
expect(result.getByText('Cancel')).toBeInTheDocument();
await userEvent.click(result.getByText('Cancel'));
expect(screen.getByText('Cancel')).toBeInTheDocument();
await userEvent.click(screen.getByText('Cancel'));
expect(props.onCancel).toHaveBeenCalled();
});

View file

@ -9,8 +9,7 @@ import React from 'react';
import { fireEvent, screen, waitFor, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer, mockedTestProvidersOwner } from '../../common/mock';
import { mockedTestProvidersOwner, renderWithTestingProviders } from '../../common/mock';
import {
connectorsMock,
customFieldsConfigurationMock,
@ -41,8 +40,6 @@ jest.mock('../../containers/user_profiles/api');
const useGetChoicesMock = useGetChoices as jest.Mock;
describe('CommonFlyout ', () => {
let appMockRender: AppMockRenderer;
const props = {
onCloseFlyout: jest.fn(),
onSaveField: jest.fn(),
@ -57,11 +54,10 @@ describe('CommonFlyout ', () => {
beforeEach(() => {
jest.clearAllMocks();
appMockRender = createAppMockRenderer();
});
it('renders flyout correctly', async () => {
appMockRender.render(<CommonFlyout {...props}>{children}</CommonFlyout>);
renderWithTestingProviders(<CommonFlyout {...props}>{children}</CommonFlyout>);
expect(await screen.findByTestId('common-flyout')).toBeInTheDocument();
expect(await screen.findByTestId('common-flyout-header')).toBeInTheDocument();
@ -70,13 +66,13 @@ describe('CommonFlyout ', () => {
});
it('renders flyout header correctly', async () => {
appMockRender.render(<CommonFlyout {...props}>{children}</CommonFlyout>);
renderWithTestingProviders(<CommonFlyout {...props}>{children}</CommonFlyout>);
expect(await screen.findByText('Flyout header'));
});
it('renders loading state correctly', async () => {
appMockRender.render(
renderWithTestingProviders(
<CommonFlyout {...{ ...props, isLoading: true }}>{children}</CommonFlyout>
);
@ -84,14 +80,16 @@ describe('CommonFlyout ', () => {
});
it('renders disable state correctly', async () => {
appMockRender.render(<CommonFlyout {...{ ...props, disabled: true }}>{children}</CommonFlyout>);
renderWithTestingProviders(
<CommonFlyout {...{ ...props, disabled: true }}>{children}</CommonFlyout>
);
expect(await screen.findByTestId('common-flyout-cancel')).toBeDisabled();
expect(await screen.findByTestId('common-flyout-save')).toBeDisabled();
});
it('calls onCloseFlyout on cancel', async () => {
appMockRender.render(<CommonFlyout {...props}>{children}</CommonFlyout>);
renderWithTestingProviders(<CommonFlyout {...props}>{children}</CommonFlyout>);
await userEvent.click(await screen.findByTestId('common-flyout-cancel'));
@ -101,7 +99,7 @@ describe('CommonFlyout ', () => {
});
it('calls onCloseFlyout on close', async () => {
appMockRender.render(<CommonFlyout {...props}>{children}</CommonFlyout>);
renderWithTestingProviders(<CommonFlyout {...props}>{children}</CommonFlyout>);
await userEvent.click(await screen.findByTestId('euiFlyoutCloseButton'));
@ -111,7 +109,7 @@ describe('CommonFlyout ', () => {
});
it('does not call onSaveField when not valid data', async () => {
appMockRender.render(<CommonFlyout {...props}>{children}</CommonFlyout>);
renderWithTestingProviders(<CommonFlyout {...props}>{children}</CommonFlyout>);
await userEvent.click(await screen.findByTestId('common-flyout-save'));
@ -124,7 +122,7 @@ describe('CommonFlyout ', () => {
);
it('should render custom field form in flyout', async () => {
appMockRender.render(<CommonFlyout {...props}>{renderBody}</CommonFlyout>);
renderWithTestingProviders(<CommonFlyout {...props}>{renderBody}</CommonFlyout>);
expect(await screen.findByTestId('custom-field-label-input')).toBeInTheDocument();
expect(await screen.findByTestId('custom-field-type-selector')).toBeInTheDocument();
@ -133,7 +131,7 @@ describe('CommonFlyout ', () => {
});
it('calls onSaveField form correctly', async () => {
appMockRender.render(<CommonFlyout {...props}>{renderBody}</CommonFlyout>);
renderWithTestingProviders(<CommonFlyout {...props}>{renderBody}</CommonFlyout>);
await userEvent.click(await screen.findByTestId('custom-field-label-input'));
await userEvent.paste('Summary');
@ -150,7 +148,7 @@ describe('CommonFlyout ', () => {
});
it('shows error if field label is too long', async () => {
appMockRender.render(<CommonFlyout {...props}>{renderBody}</CommonFlyout>);
renderWithTestingProviders(<CommonFlyout {...props}>{renderBody}</CommonFlyout>);
const message = 'z'.repeat(MAX_CUSTOM_FIELD_LABEL_LENGTH + 1);
@ -165,7 +163,7 @@ describe('CommonFlyout ', () => {
describe('Text custom field', () => {
it('calls onSaveField with correct params when a custom field is NOT required', async () => {
appMockRender.render(<CommonFlyout {...props}>{renderBody}</CommonFlyout>);
renderWithTestingProviders(<CommonFlyout {...props}>{renderBody}</CommonFlyout>);
await userEvent.click(await screen.findByTestId('custom-field-label-input'));
await userEvent.paste('Summary');
@ -182,7 +180,7 @@ describe('CommonFlyout ', () => {
});
it('calls onSaveField with correct params when a custom field is NOT required and has a default value', async () => {
appMockRender.render(<CommonFlyout {...props}>{renderBody}</CommonFlyout>);
renderWithTestingProviders(<CommonFlyout {...props}>{renderBody}</CommonFlyout>);
await userEvent.click(await screen.findByTestId('custom-field-label-input'));
await userEvent.paste('Summary');
@ -202,7 +200,7 @@ describe('CommonFlyout ', () => {
});
it('calls onSaveField with the correct params when a custom field is required', async () => {
appMockRender.render(<CommonFlyout {...props}>{renderBody}</CommonFlyout>);
renderWithTestingProviders(<CommonFlyout {...props}>{renderBody}</CommonFlyout>);
await userEvent.click(await screen.findByTestId('custom-field-label-input'));
await userEvent.paste('Summary');
@ -223,7 +221,7 @@ describe('CommonFlyout ', () => {
});
it('calls onSaveField with the correct params when a custom field is required and the defaultValue is missing', async () => {
appMockRender.render(<CommonFlyout {...props}>{renderBody}</CommonFlyout>);
renderWithTestingProviders(<CommonFlyout {...props}>{renderBody}</CommonFlyout>);
await userEvent.click(await screen.findByTestId('custom-field-label-input'));
await userEvent.paste('Summary');
@ -250,7 +248,7 @@ describe('CommonFlyout ', () => {
data: customFieldsConfigurationMock[0],
};
appMockRender.render(<CommonFlyout {...modifiedProps}>{newRenderBody}</CommonFlyout>);
renderWithTestingProviders(<CommonFlyout {...modifiedProps}>{newRenderBody}</CommonFlyout>);
expect(await screen.findByTestId('custom-field-label-input')).toHaveAttribute(
'value',
@ -265,7 +263,7 @@ describe('CommonFlyout ', () => {
});
it('shows an error if default value is too long', async () => {
appMockRender.render(<CommonFlyout {...props}>{renderBody}</CommonFlyout>);
renderWithTestingProviders(<CommonFlyout {...props}>{renderBody}</CommonFlyout>);
await userEvent.click(await screen.findByTestId('custom-field-label-input'));
await userEvent.paste('Summary');
@ -283,7 +281,7 @@ describe('CommonFlyout ', () => {
describe('Toggle custom field', () => {
it('calls onSaveField with correct params when a custom field is NOT required', async () => {
appMockRender.render(<CommonFlyout {...props}>{renderBody}</CommonFlyout>);
renderWithTestingProviders(<CommonFlyout {...props}>{renderBody}</CommonFlyout>);
fireEvent.change(await screen.findByTestId('custom-field-type-selector'), {
target: { value: CustomFieldTypes.TOGGLE },
@ -305,7 +303,7 @@ describe('CommonFlyout ', () => {
});
it('calls onSaveField with the correct default value when a custom field is required', async () => {
appMockRender.render(<CommonFlyout {...props}>{renderBody}</CommonFlyout>);
renderWithTestingProviders(<CommonFlyout {...props}>{renderBody}</CommonFlyout>);
fireEvent.change(await screen.findByTestId('custom-field-type-selector'), {
target: { value: CustomFieldTypes.TOGGLE },
@ -332,7 +330,7 @@ describe('CommonFlyout ', () => {
<CustomFieldsForm onChange={onChange} initialValue={customFieldsConfigurationMock[1]} />
);
appMockRender.render(<CommonFlyout {...props}>{newRenderBody}</CommonFlyout>);
renderWithTestingProviders(<CommonFlyout {...props}>{newRenderBody}</CommonFlyout>);
expect(await screen.findByTestId('custom-field-label-input')).toHaveAttribute(
'value',
@ -378,7 +376,7 @@ describe('CommonFlyout ', () => {
);
it('should render template form in flyout', async () => {
appMockRender.render(<CommonFlyout {...props}>{renderBody}</CommonFlyout>);
renderWithTestingProviders(<CommonFlyout {...props}>{renderBody}</CommonFlyout>);
expect(await screen.findByTestId('common-flyout')).toBeInTheDocument();
expect(await screen.findByTestId('template-creation-form-steps')).toBeInTheDocument();
@ -401,9 +399,7 @@ describe('CommonFlyout ', () => {
],
};
appMockRender = createAppMockRenderer({ license });
appMockRender.render(
renderWithTestingProviders(
<CommonFlyout {...props}>
{({ onChange }: FlyOutBodyProps<TemplateFormProps>) => (
<TemplateForm
@ -413,7 +409,8 @@ describe('CommonFlyout ', () => {
onChange={onChange}
/>
)}
</CommonFlyout>
</CommonFlyout>,
{ wrapperProps: { license } }
);
// template fields
@ -454,11 +451,13 @@ describe('CommonFlyout ', () => {
).toHaveValue('this is a text field value');
// connector
expect(await screen.findByTestId('dropdown-connector-no-connector')).toBeInTheDocument();
expect(
await screen.findByTestId('dropdown-connector-no-connector-label')
).toBeInTheDocument();
});
it('calls onSaveField form correctly', async () => {
appMockRender.render(<CommonFlyout {...props}>{renderBody}</CommonFlyout>);
renderWithTestingProviders(<CommonFlyout {...props}>{renderBody}</CommonFlyout>);
await userEvent.click(await screen.findByTestId('template-name-input'));
await userEvent.paste('Template name');
@ -508,7 +507,7 @@ describe('CommonFlyout ', () => {
/>
);
appMockRender.render(<CommonFlyout {...props}>{newRenderBody}</CommonFlyout>);
renderWithTestingProviders(<CommonFlyout {...props}>{newRenderBody}</CommonFlyout>);
const caseTitle = await screen.findByTestId('caseTitle');
await userEvent.click(within(caseTitle).getByTestId('input'));
@ -564,7 +563,7 @@ describe('CommonFlyout ', () => {
/>
);
appMockRender.render(<CommonFlyout {...props}>{newRenderBody}</CommonFlyout>);
renderWithTestingProviders(<CommonFlyout {...props}>{newRenderBody}</CommonFlyout>);
const textCustomField = await screen.findByTestId(
`${customFieldsConfigurationMock[0].key}-text-create-custom-field`
@ -658,7 +657,7 @@ describe('CommonFlyout ', () => {
/>
);
appMockRender.render(<CommonFlyout {...props}>{newRenderBody}</CommonFlyout>);
renderWithTestingProviders(<CommonFlyout {...props}>{newRenderBody}</CommonFlyout>);
expect(await screen.findByTestId('connector-fields-sn-itsm')).toBeInTheDocument();
@ -722,7 +721,7 @@ describe('CommonFlyout ', () => {
/>
);
appMockRender.render(<CommonFlyout {...props}>{newRenderBody}</CommonFlyout>);
renderWithTestingProviders(<CommonFlyout {...props}>{newRenderBody}</CommonFlyout>);
await userEvent.clear(await screen.findByTestId('template-name-input'));
await userEvent.click(await screen.findByTestId('template-name-input'));
@ -775,7 +774,7 @@ describe('CommonFlyout ', () => {
});
it('shows error when template name is empty', async () => {
appMockRender.render(<CommonFlyout {...props}>{renderBody}</CommonFlyout>);
renderWithTestingProviders(<CommonFlyout {...props}>{renderBody}</CommonFlyout>);
await userEvent.click(await screen.findByTestId('template-description-input'));
await userEvent.paste('Template description');
@ -790,7 +789,7 @@ describe('CommonFlyout ', () => {
});
it('shows error if template name is too long', async () => {
appMockRender.render(<CommonFlyout {...props}>{renderBody}</CommonFlyout>);
renderWithTestingProviders(<CommonFlyout {...props}>{renderBody}</CommonFlyout>);
const message = 'z'.repeat(MAX_TEMPLATE_NAME_LENGTH + 1);
@ -803,7 +802,7 @@ describe('CommonFlyout ', () => {
});
it('shows error if template description is too long', async () => {
appMockRender.render(<CommonFlyout {...props}>{renderBody}</CommonFlyout>);
renderWithTestingProviders(<CommonFlyout {...props}>{renderBody}</CommonFlyout>);
const message = 'z'.repeat(MAX_TEMPLATE_DESCRIPTION_LENGTH + 1);

View file

@ -17,8 +17,12 @@ import {
customFieldsConfigurationMock,
templatesConfigurationMock,
} from '../../containers/mock';
import { TestProviders, createAppMockRenderer, noCasesSettingsPermission } from '../../common/mock';
import type { AppMockRenderer } from '../../common/mock';
import {
TestProviders,
noCasesSettingsPermission,
renderWithTestingProviders,
} from '../../common/mock';
import { Connectors } from './connectors';
import { ClosureOptions } from './closure_options';
@ -574,12 +578,13 @@ describe('ConfigureCases', () => {
await waitFor(() => {
wrapper.update();
expect(wrapper.find('[data-test-subj="add-connector-flyout"]').exists()).toBe(true);
expect(getAddConnectorFlyoutMock).toHaveBeenCalledWith(
expect.objectContaining({
featureId: 'cases',
})
);
});
expect(getAddConnectorFlyoutMock).toHaveBeenCalledWith(
expect.objectContaining({
featureId: 'cases',
})
);
});
test('it show the edit flyout when pressing the update connector button', async () => {
@ -609,11 +614,12 @@ describe('ConfigureCases', () => {
await waitFor(() => {
wrapper.update();
expect(wrapper.find('[data-test-subj="edit-connector-flyout"]').exists()).toBe(true);
expect(getEditConnectorFlyoutMock).toHaveBeenCalledWith(
expect.objectContaining({ connector: connectors[1] })
);
});
expect(getEditConnectorFlyoutMock).toHaveBeenCalledWith(
expect.objectContaining({ connector: connectors[1] })
);
expect(
wrapper.find('[data-test-subj="case-configure-action-bottom-bar"]').exists()
).toBeFalsy();
@ -621,12 +627,11 @@ describe('ConfigureCases', () => {
});
describe('custom fields', () => {
let appMockRender: AppMockRenderer;
let persistCaseConfigure: jest.Mock;
beforeEach(() => {
jest.clearAllMocks();
appMockRender = createAppMockRenderer();
persistCaseConfigure = jest.fn();
usePersistConfigurationMock.mockImplementation(() => ({
...usePersistConfigurationMockResponse,
@ -635,7 +640,7 @@ describe('ConfigureCases', () => {
});
it('renders custom field group when no custom fields available', () => {
appMockRender.render(<ConfigureCases />);
renderWithTestingProviders(<ConfigureCases />);
expect(screen.getByTestId('custom-fields-form-group')).toBeInTheDocument();
});
@ -658,7 +663,7 @@ describe('ConfigureCases', () => {
},
}));
appMockRender.render(<ConfigureCases />);
renderWithTestingProviders(<ConfigureCases />);
expect(
screen.getByTestId(`custom-field-${customFieldsMock[0].key}-${customFieldsMock[0].type}`)
@ -674,7 +679,7 @@ describe('ConfigureCases', () => {
},
}));
appMockRender.render(<ConfigureCases />);
renderWithTestingProviders(<ConfigureCases />);
const list = screen.getByTestId('custom-fields-list');
@ -694,7 +699,7 @@ describe('ConfigureCases', () => {
},
}));
appMockRender.render(<ConfigureCases />);
renderWithTestingProviders(<ConfigureCases />);
const list = screen.getByTestId('custom-fields-list');
@ -755,7 +760,7 @@ describe('ConfigureCases', () => {
},
}));
appMockRender.render(<ConfigureCases />);
renderWithTestingProviders(<ConfigureCases />);
const list = await screen.findByTestId('custom-fields-list');
@ -816,7 +821,7 @@ describe('ConfigureCases', () => {
},
}));
appMockRender.render(<ConfigureCases />);
renderWithTestingProviders(<ConfigureCases />);
await userEvent.click(await screen.findByTestId(`add-custom-field`));
@ -909,7 +914,7 @@ describe('ConfigureCases', () => {
},
}));
appMockRender.render(<ConfigureCases />);
renderWithTestingProviders(<ConfigureCases />);
const list = screen.getByTestId('custom-fields-list');
@ -959,7 +964,7 @@ describe('ConfigureCases', () => {
});
it('opens fly out for when click on add field', async () => {
appMockRender.render(<ConfigureCases />);
renderWithTestingProviders(<ConfigureCases />);
await userEvent.click(screen.getByTestId('add-custom-field'));
@ -971,7 +976,7 @@ describe('ConfigureCases', () => {
});
it('closes fly out for when click on cancel', async () => {
appMockRender.render(<ConfigureCases />);
renderWithTestingProviders(<ConfigureCases />);
await userEvent.click(screen.getByTestId('add-custom-field'));
@ -984,7 +989,7 @@ describe('ConfigureCases', () => {
});
it('closes fly out for when click on save field', async () => {
appMockRender.render(<ConfigureCases />);
renderWithTestingProviders(<ConfigureCases />);
await userEvent.click(screen.getByTestId('add-custom-field'));
@ -1025,12 +1030,11 @@ describe('ConfigureCases', () => {
});
describe('templates', () => {
let appMockRender: AppMockRenderer;
const persistCaseConfigure = jest.fn();
beforeEach(() => {
jest.clearAllMocks();
appMockRender = createAppMockRenderer();
usePersistConfigurationMock.mockImplementation(() => ({
...usePersistConfigurationMockResponse,
mutate: persistCaseConfigure,
@ -1039,14 +1043,14 @@ describe('ConfigureCases', () => {
});
it('should render template section', async () => {
appMockRender.render(<ConfigureCases />);
renderWithTestingProviders(<ConfigureCases />);
expect(await screen.findByTestId('templates-form-group')).toBeInTheDocument();
expect(await screen.findByTestId('add-template')).toBeInTheDocument();
});
it('should render template form in flyout', async () => {
appMockRender.render(<ConfigureCases />);
renderWithTestingProviders(<ConfigureCases />);
expect(await screen.findByTestId('templates-form-group')).toBeInTheDocument();
@ -1060,7 +1064,7 @@ describe('ConfigureCases', () => {
});
it('should add template', async () => {
appMockRender.render(<ConfigureCases />);
renderWithTestingProviders(<ConfigureCases />);
expect(await screen.findByTestId('templates-form-group')).toBeInTheDocument();
@ -1161,7 +1165,7 @@ describe('ConfigureCases', () => {
},
}));
appMockRender.render(<ConfigureCases />);
renderWithTestingProviders(<ConfigureCases />);
const list = screen.getByTestId('templates-list');
@ -1204,7 +1208,7 @@ describe('ConfigureCases', () => {
},
}));
appMockRender.render(<ConfigureCases />);
renderWithTestingProviders(<ConfigureCases />);
const list = screen.getByTestId('templates-list');
@ -1262,12 +1266,11 @@ describe('ConfigureCases', () => {
});
describe('observable types', () => {
let appMockRender: AppMockRenderer;
const persistCaseConfigure = jest.fn();
beforeEach(() => {
jest.clearAllMocks();
appMockRender = createAppMockRenderer();
usePersistConfigurationMock.mockImplementation(() => ({
...usePersistConfigurationMockResponse,
mutate: persistCaseConfigure,
@ -1276,14 +1279,14 @@ describe('ConfigureCases', () => {
});
it('should render observable types section', async () => {
appMockRender.render(<ConfigureCases />);
renderWithTestingProviders(<ConfigureCases />);
expect(await screen.findByTestId('observable-types-form-group')).toBeInTheDocument();
expect(await screen.findByTestId('add-observable-type')).toBeInTheDocument();
});
it('opens fly out for when click on add observable type', async () => {
appMockRender.render(<ConfigureCases />);
renderWithTestingProviders(<ConfigureCases />);
await userEvent.click(screen.getByTestId('add-observable-type'));
@ -1291,7 +1294,7 @@ describe('ConfigureCases', () => {
});
it('closes fly out for when click on cancel', async () => {
appMockRender.render(<ConfigureCases />);
renderWithTestingProviders(<ConfigureCases />);
await userEvent.click(screen.getByTestId('add-observable-type'));
@ -1304,7 +1307,7 @@ describe('ConfigureCases', () => {
});
it('closes fly out and updates the data when click on save', async () => {
appMockRender.render(<ConfigureCases />);
renderWithTestingProviders(<ConfigureCases />);
await userEvent.click(screen.getByTestId('add-observable-type'));
@ -1336,7 +1339,7 @@ describe('ConfigureCases', () => {
},
}));
appMockRender.render(<ConfigureCases />);
renderWithTestingProviders(<ConfigureCases />);
const list = screen.getByTestId('observable-types-list');
@ -1384,7 +1387,7 @@ describe('ConfigureCases', () => {
},
}));
appMockRender.render(<ConfigureCases />);
renderWithTestingProviders(<ConfigureCases />);
const list = screen.getByTestId('observable-types-list');
@ -1416,13 +1419,12 @@ describe('ConfigureCases', () => {
});
describe('rendering with license limitations', () => {
let appMockRender: AppMockRenderer;
let persistCaseConfigure: jest.Mock;
beforeEach(() => {
// Default setup
jest.clearAllMocks();
useGetConnectorsMock.mockImplementation(() => ({ useConnectorsResponse }));
appMockRender = createAppMockRenderer();
persistCaseConfigure = jest.fn();
usePersistConfigurationMock.mockImplementation(() => ({
...usePersistConfigurationMockResponse,
@ -1438,18 +1440,18 @@ describe('ConfigureCases', () => {
});
it('should not render connectors and closure options', () => {
appMockRender.render(<ConfigureCases />);
renderWithTestingProviders(<ConfigureCases />);
expect(screen.queryByTestId('dropdown-connectors')).not.toBeInTheDocument();
expect(screen.queryByTestId('closure-options-radio-group')).not.toBeInTheDocument();
});
it('should render custom field section', () => {
appMockRender.render(<ConfigureCases />);
renderWithTestingProviders(<ConfigureCases />);
expect(screen.getByTestId('custom-fields-form-group')).toBeInTheDocument();
});
it('should not render observable types section', async () => {
appMockRender.render(<ConfigureCases />);
renderWithTestingProviders(<ConfigureCases />);
expect(screen.queryByTestId('observable-types-form-group')).not.toBeInTheDocument();
expect(screen.queryByTestId('add-observable-type')).not.toBeInTheDocument();

View file

@ -9,8 +9,8 @@ import React from 'react';
import { screen } from '@testing-library/react';
import { ConnectorSelector } from './form';
import { useKibana } from '../../common/lib/kibana';
import type { AppMockRenderer } from '../../common/mock';
import { createAppMockRenderer } from '../../common/mock';
import { renderWithTestingProviders } from '../../common/mock';
import { UseField } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib';
import { FormTestComponent } from '../../common/test_utils';
import { connectorsMock } from '../../containers/mock';
@ -30,10 +30,7 @@ describe('ConnectorSelector', () => {
isLoading: false,
};
let appMock: AppMockRenderer;
beforeEach(() => {
appMock = createAppMockRenderer();
jest.clearAllMocks();
});
@ -44,12 +41,8 @@ describe('ConnectorSelector', () => {
});
});
afterEach(async () => {
await appMock.clearQueryCache();
});
it('should render', async () => {
appMock.render(
renderWithTestingProviders(
<FormTestComponent>
<UseField
path="connectorId"
@ -65,7 +58,7 @@ describe('ConnectorSelector', () => {
});
it('should set the selected connector to none if the connector is not available', async () => {
appMock.render(
renderWithTestingProviders(
<FormTestComponent formDefaultValue={{ connectorId: 'foo' }}>
<UseField
path="connectorId"
@ -81,7 +74,7 @@ describe('ConnectorSelector', () => {
});
it('should set the selected connector correctly', async () => {
appMock.render(
renderWithTestingProviders(
<FormTestComponent formDefaultValue={{ connectorId: connectorsMock[0].id }}>
<UseField
path="connectorId"

View file

@ -68,10 +68,10 @@ describe('ConnectorCard ', () => {
/>
);
const getByText = createQueryWithMarkup(screen.getByText);
const getByTextWithMarkup = createQueryWithMarkup(screen.getByText);
for (const item of listItems) {
expect(getByText(`${item.title}: ${item.description}`)).toBeInTheDocument();
expect(getByTextWithMarkup(`${item.title}: ${item.description}`)).toBeInTheDocument();
}
});

View file

@ -10,24 +10,21 @@ import { screen } from '@testing-library/react';
import { connector } from '../mock';
import FieldsPreview from './case_fields_preview';
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
import { renderWithTestingProviders } from '../../../common/mock';
describe('Webhook fields: Preview', () => {
let appMockRenderer: AppMockRenderer;
beforeEach(() => {
appMockRenderer = createAppMockRenderer();
jest.clearAllMocks();
});
it('does not render any fields', () => {
appMockRenderer.render(<FieldsPreview connector={connector} fields={null} />);
renderWithTestingProviders(<FieldsPreview connector={connector} fields={null} />);
expect(screen.queryByTestId('card-list-item')).not.toBeInTheDocument();
});
it('shows the warning comment callout', () => {
appMockRenderer.render(<FieldsPreview connector={connector} fields={null} />);
renderWithTestingProviders(<FieldsPreview connector={connector} fields={null} />);
expect(screen.getByTestId('create-comment-warning')).toBeInTheDocument();
});
@ -37,7 +34,7 @@ describe('Webhook fields: Preview', () => {
config: { createCommentUrl: 'https://example.com', createCommentJson: {} },
};
appMockRenderer.render(<FieldsPreview connector={configuredConnector} fields={null} />);
renderWithTestingProviders(<FieldsPreview connector={configuredConnector} fields={null} />);
expect(screen.queryByTestId('create-comment-warning')).not.toBeInTheDocument();
});
});

View file

@ -7,7 +7,7 @@
import React from 'react';
import { omit } from 'lodash/fp';
import { waitFor, screen, fireEvent, within } from '@testing-library/react';
import { screen, fireEvent, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { connector, issues } from '../mock';
@ -16,8 +16,8 @@ import { useGetFieldsByIssueType } from './use_get_fields_by_issue_type';
import { useGetIssue } from './use_get_issue';
import Fields from './case_fields';
import { useGetIssues } from './use_get_issues';
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
import { renderWithTestingProviders } from '../../../common/mock';
import { MockFormWrapperComponent } from '../test_utils';
jest.mock('./use_get_issue_types');
@ -93,10 +93,7 @@ describe('Jira Fields', () => {
data: { data: issues[0] },
};
let appMockRenderer: AppMockRenderer;
beforeEach(() => {
appMockRenderer = createAppMockRenderer();
useGetIssueTypesMock.mockReturnValue(useGetIssueTypesResponse);
useGetFieldsByIssueTypeMock.mockReturnValue(useGetFieldsByIssueTypeResponse);
useGetIssuesMock.mockReturnValue(useGetIssuesResponse);
@ -105,7 +102,7 @@ describe('Jira Fields', () => {
});
it('all params fields are rendered', async () => {
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent>
<Fields connector={connector} />
</MockFormWrapperComponent>
@ -114,13 +111,11 @@ describe('Jira Fields', () => {
expect(await screen.findByTestId('prioritySelect')).toBeInTheDocument();
expect(await screen.findByTestId('issueTypeSelect')).toBeInTheDocument();
await waitFor(() => {
expect(screen.queryByTestId('search-parent-issues')).toBeInTheDocument();
});
expect(await screen.findByTestId('search-parent-issues')).toBeInTheDocument();
});
it('renders the fields correctly when selecting an issue type', async () => {
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent>
<Fields connector={connector} />
</MockFormWrapperComponent>
@ -138,7 +133,7 @@ describe('Jira Fields', () => {
});
it('sets parent correctly', async () => {
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent>
<Fields connector={connector} />
</MockFormWrapperComponent>
@ -151,7 +146,7 @@ describe('Jira Fields', () => {
});
it('searches parent correctly', async () => {
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent>
<Fields connector={connector} />
</MockFormWrapperComponent>
@ -171,7 +166,7 @@ describe('Jira Fields', () => {
it('disabled the fields when loading issue types', async () => {
useGetIssueTypesMock.mockReturnValue({ ...useGetIssueTypesResponse, isLoading: true });
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent>
<Fields connector={connector} />
</MockFormWrapperComponent>
@ -187,7 +182,7 @@ describe('Jira Fields', () => {
isLoading: true,
});
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent>
<Fields connector={connector} />
</MockFormWrapperComponent>
@ -201,7 +196,7 @@ describe('Jira Fields', () => {
useGetFieldsByIssueTypeMock.mockReturnValue(response);
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent>
<Fields connector={connector} />
</MockFormWrapperComponent>
@ -215,7 +210,7 @@ describe('Jira Fields', () => {
useGetFieldsByIssueTypeMock.mockReturnValue(response);
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent>
<Fields connector={connector} />
</MockFormWrapperComponent>
@ -225,7 +220,7 @@ describe('Jira Fields', () => {
});
it('sets issue type correctly', async () => {
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent fields={fields}>
<Fields connector={connector} />
</MockFormWrapperComponent>
@ -236,7 +231,7 @@ describe('Jira Fields', () => {
});
it('sets priority correctly', async () => {
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent fields={fields}>
<Fields connector={connector} />
</MockFormWrapperComponent>
@ -250,7 +245,7 @@ describe('Jira Fields', () => {
it('sets existing parent correctly', async () => {
const newFields = { ...fields, parent: 'personKey' };
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent fields={newFields}>
<Fields connector={connector} />
</MockFormWrapperComponent>
@ -262,7 +257,7 @@ describe('Jira Fields', () => {
it('resets existing parent correctly', async () => {
const newFields = { ...fields, parent: 'personKey' };
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent fields={newFields}>
<Fields connector={connector} />
</MockFormWrapperComponent>
@ -280,7 +275,7 @@ describe('Jira Fields', () => {
});
it('should submit Jira connector', async () => {
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent fields={fields}>
<Fields connector={connector} />
</MockFormWrapperComponent>
@ -309,7 +304,7 @@ describe('Jira Fields', () => {
});
it('should validate the issue type correctly', async () => {
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent>
<Fields connector={connector} />
</MockFormWrapperComponent>
@ -318,9 +313,7 @@ describe('Jira Fields', () => {
expect(await screen.findByTestId('prioritySelect')).toBeInTheDocument();
expect(await screen.findByTestId('issueTypeSelect')).toBeInTheDocument();
await waitFor(() => {
expect(screen.queryByTestId('search-parent-issues')).toBeInTheDocument();
});
expect(await screen.findByTestId('search-parent-issues')).toBeInTheDocument();
await userEvent.click(await screen.findByTestId('submit-form'));
@ -330,7 +323,7 @@ describe('Jira Fields', () => {
it('should not show the loading skeleton when loading issue types', async () => {
useGetIssueTypesMock.mockReturnValue({ ...useGetIssueTypesResponse, isLoading: true });
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent fields={fields}>
<Fields connector={connector} />
</MockFormWrapperComponent>
@ -342,7 +335,7 @@ describe('Jira Fields', () => {
it('should not show the loading skeleton when issueType is null', async () => {
useGetIssueTypesMock.mockReturnValue({ ...useGetIssueTypesResponse, isLoading: true });
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent fields={{ ...fields, issueType: null }}>
<Fields connector={connector} />
</MockFormWrapperComponent>
@ -352,7 +345,7 @@ describe('Jira Fields', () => {
});
it('should not show the loading skeleton when does not load fields', async () => {
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent fields={fields}>
<Fields connector={connector} />
</MockFormWrapperComponent>
@ -367,7 +360,7 @@ describe('Jira Fields', () => {
isLoading: true,
});
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent fields={fields}>
<Fields connector={connector} />
</MockFormWrapperComponent>

View file

@ -11,8 +11,8 @@ import { screen } from '@testing-library/react';
import { connector } from '../mock';
import { useGetIssueTypes } from './use_get_issue_types';
import FieldsPreview from './case_fields_preview';
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
import { renderWithTestingProviders } from '../../../common/mock';
import { createQueryWithMarkup } from '../../../common/test_utils';
jest.mock('./use_get_issue_types');
@ -43,21 +43,18 @@ describe('Jira Fields: Preview', () => {
parent: 'Parent Task',
};
let appMockRenderer: AppMockRenderer;
beforeEach(() => {
appMockRenderer = createAppMockRenderer();
useGetIssueTypesMock.mockReturnValue(useGetIssueTypesResponse);
jest.clearAllMocks();
});
it('renders all fields correctly', () => {
appMockRenderer.render(<FieldsPreview connector={connector} fields={fields} />);
renderWithTestingProviders(<FieldsPreview connector={connector} fields={fields} />);
const getByText = createQueryWithMarkup(screen.getByText);
const getByTextWithMarkup = createQueryWithMarkup(screen.getByText);
expect(getByText('Issue type: Task')).toBeInTheDocument();
expect(getByText('Parent issue: Parent Task')).toBeInTheDocument();
expect(getByText('Priority: High')).toBeInTheDocument();
expect(getByTextWithMarkup('Issue type: Task')).toBeInTheDocument();
expect(getByTextWithMarkup('Parent issue: Parent Task')).toBeInTheDocument();
expect(getByTextWithMarkup('Priority: High')).toBeInTheDocument();
});
});

View file

@ -11,8 +11,7 @@ import { useKibana, useToasts } from '../../../common/lib/kibana';
import { connector } from '../mock';
import { useGetFieldsByIssueType } from './use_get_fields_by_issue_type';
import * as api from './api';
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
import { TestProviders } from '../../../common/mock';
jest.mock('../../../common/lib/kibana');
jest.mock('./api');
@ -21,10 +20,8 @@ const useKibanaMock = useKibana as jest.Mocked<typeof useKibana>;
describe('useGetFieldsByIssueType', () => {
const { http } = useKibanaMock().services;
let appMockRender: AppMockRenderer;
beforeEach(() => {
appMockRender = createAppMockRenderer();
jest.clearAllMocks();
});
@ -37,7 +34,7 @@ describe('useGetFieldsByIssueType', () => {
connector,
issueType: '1',
}),
{ wrapper: appMockRender.AppWrapper }
{ wrapper: TestProviders }
);
await waitFor(() => result.current.isSuccess);
@ -58,7 +55,7 @@ describe('useGetFieldsByIssueType', () => {
http,
issueType: '1',
}),
{ wrapper: appMockRender.AppWrapper }
{ wrapper: TestProviders }
);
expect(spy).not.toHaveBeenCalledWith();
@ -73,7 +70,7 @@ describe('useGetFieldsByIssueType', () => {
connector,
issueType: null,
}),
{ wrapper: appMockRender.AppWrapper }
{ wrapper: TestProviders }
);
expect(spy).not.toHaveBeenCalledWith();
@ -95,7 +92,7 @@ describe('useGetFieldsByIssueType', () => {
connector,
issueType: '1',
}),
{ wrapper: appMockRender.AppWrapper }
{ wrapper: TestProviders }
);
await waitFor(() => {
@ -121,7 +118,7 @@ describe('useGetFieldsByIssueType', () => {
connector,
issueType: '1',
}),
{ wrapper: appMockRender.AppWrapper }
{ wrapper: TestProviders }
);
await waitFor(() => {

View file

@ -11,8 +11,7 @@ import { useKibana, useToasts } from '../../../common/lib/kibana';
import { connector as actionConnector } from '../mock';
import { useGetIssue } from './use_get_issue';
import * as api from './api';
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
import { TestProviders } from '../../../common/mock';
jest.mock('../../../common/lib/kibana');
jest.mock('./api');
@ -21,10 +20,8 @@ const useKibanaMock = useKibana as jest.Mocked<typeof useKibana>;
describe('useGetIssue', () => {
const { http } = useKibanaMock().services;
let appMockRender: AppMockRenderer;
beforeEach(() => {
appMockRender = createAppMockRenderer();
jest.clearAllMocks();
});
@ -37,7 +34,7 @@ describe('useGetIssue', () => {
actionConnector,
id: 'RJ-107',
}),
{ wrapper: appMockRender.AppWrapper }
{ wrapper: TestProviders }
);
await waitFor(() => expect(result.current.isSuccess).toBe(true));
@ -58,7 +55,7 @@ describe('useGetIssue', () => {
http,
id: 'RJ-107',
}),
{ wrapper: appMockRender.AppWrapper }
{ wrapper: TestProviders }
);
expect(spy).not.toHaveBeenCalledWith();
@ -73,7 +70,7 @@ describe('useGetIssue', () => {
actionConnector,
id: '',
}),
{ wrapper: appMockRender.AppWrapper }
{ wrapper: TestProviders }
);
expect(spy).not.toHaveBeenCalledWith();
@ -95,13 +92,14 @@ describe('useGetIssue', () => {
actionConnector,
id: 'RJ-107',
}),
{ wrapper: appMockRender.AppWrapper }
{ wrapper: TestProviders }
);
await waitFor(() => {
expect(result.current.isError).toBe(true);
expect(addError).toHaveBeenCalled();
});
expect(addError).toHaveBeenCalled();
});
it('calls addError when the getIssue api returns successfully but contains an error', async () => {
@ -122,12 +120,13 @@ describe('useGetIssue', () => {
actionConnector,
id: 'RJ-107',
}),
{ wrapper: appMockRender.AppWrapper }
{ wrapper: TestProviders }
);
await waitFor(() => {
expect(result.current.isSuccess).toBe(true);
expect(addError).toHaveBeenCalled();
});
expect(addError).toHaveBeenCalled();
});
});

View file

@ -11,8 +11,7 @@ import { useKibana, useToasts } from '../../../common/lib/kibana';
import { connector } from '../mock';
import { useGetIssueTypes } from './use_get_issue_types';
import * as api from './api';
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
import { TestProviders } from '../../../common/mock';
jest.mock('../../../common/lib/kibana');
jest.mock('./api');
@ -21,10 +20,8 @@ const useKibanaMock = useKibana as jest.Mocked<typeof useKibana>;
describe('useGetIssueTypes', () => {
const { http } = useKibanaMock().services;
let appMockRender: AppMockRenderer;
beforeEach(() => {
appMockRender = createAppMockRenderer();
jest.clearAllMocks();
});
@ -36,7 +33,7 @@ describe('useGetIssueTypes', () => {
http,
connector,
}),
{ wrapper: appMockRender.AppWrapper }
{ wrapper: TestProviders }
);
await waitFor(() => result.current.isSuccess);
@ -55,7 +52,7 @@ describe('useGetIssueTypes', () => {
useGetIssueTypes({
http,
}),
{ wrapper: appMockRender.AppWrapper }
{ wrapper: TestProviders }
);
expect(spy).not.toHaveBeenCalledWith();
@ -76,7 +73,7 @@ describe('useGetIssueTypes', () => {
http,
connector,
}),
{ wrapper: appMockRender.AppWrapper }
{ wrapper: TestProviders }
);
await waitFor(() => {
@ -101,7 +98,7 @@ describe('useGetIssueTypes', () => {
http,
connector,
}),
{ wrapper: appMockRender.AppWrapper }
{ wrapper: TestProviders }
);
await waitFor(() => {

View file

@ -11,8 +11,7 @@ import { useKibana, useToasts } from '../../../common/lib/kibana';
import { connector as actionConnector } from '../mock';
import { useGetIssues } from './use_get_issues';
import * as api from './api';
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
import { TestProviders } from '../../../common/mock';
jest.mock('../../../common/lib/kibana');
jest.mock('./api');
@ -21,10 +20,8 @@ const useKibanaMock = useKibana as jest.Mocked<typeof useKibana>;
describe('useGetIssues', () => {
const { http } = useKibanaMock().services;
let appMockRender: AppMockRenderer;
beforeEach(() => {
appMockRender = createAppMockRenderer();
jest.clearAllMocks();
});
@ -37,17 +34,18 @@ describe('useGetIssues', () => {
actionConnector,
query: 'Task',
}),
{ wrapper: appMockRender.AppWrapper }
{ wrapper: TestProviders }
);
await waitFor(() => {
expect(result.current.isSuccess).toBe(true);
expect(spy).toHaveBeenCalledWith({
http,
signal: expect.anything(),
connectorId: actionConnector.id,
title: 'Task',
});
});
expect(spy).toHaveBeenCalledWith({
http,
signal: expect.anything(),
connectorId: actionConnector.id,
title: 'Task',
});
});
@ -60,7 +58,7 @@ describe('useGetIssues', () => {
actionConnector,
query: 'Task',
}),
{ wrapper: appMockRender.AppWrapper }
{ wrapper: TestProviders }
);
expect(spy).not.toHaveBeenCalledWith();
@ -82,13 +80,14 @@ describe('useGetIssues', () => {
actionConnector,
query: 'Task',
}),
{ wrapper: appMockRender.AppWrapper }
{ wrapper: TestProviders }
);
await waitFor(() => {
expect(result.current.isError).toBe(true);
expect(addError).toHaveBeenCalled();
});
expect(addError).toHaveBeenCalled();
});
it('calls addError when the getIssues api returns successfully but contains an error', async () => {
@ -109,12 +108,13 @@ describe('useGetIssues', () => {
actionConnector,
query: 'Task',
}),
{ wrapper: appMockRender.AppWrapper }
{ wrapper: TestProviders }
);
await waitFor(() => {
expect(result.current.isSuccess).toBe(true);
expect(addError).toHaveBeenCalled();
});
expect(addError).toHaveBeenCalled();
});
});

View file

@ -13,8 +13,8 @@ import { connector, resilientIncidentTypes, resilientSeverity } from '../mock';
import { useGetIncidentTypes } from './use_get_incident_types';
import { useGetSeverity } from './use_get_severity';
import Fields from './case_fields';
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
import { renderWithTestingProviders } from '../../../common/mock';
import { MockFormWrapperComponent } from '../test_utils';
jest.mock('../../../common/lib/kibana');
@ -47,7 +47,6 @@ describe('ResilientParamsFields renders', () => {
};
let user: UserEvent;
let appMockRenderer: AppMockRenderer;
beforeAll(() => {
jest.useFakeTimers();
@ -60,14 +59,14 @@ describe('ResilientParamsFields renders', () => {
beforeEach(() => {
// Workaround for timeout via https://github.com/testing-library/user-event/issues/833#issuecomment-1171452841
user = userEvent.setup({ advanceTimers: jest.advanceTimersByTime });
appMockRenderer = createAppMockRenderer();
useGetIncidentTypesMock.mockReturnValue(useGetIncidentTypesResponse);
useGetSeverityMock.mockReturnValue(useGetSeverityResponse);
jest.clearAllMocks();
});
it('all params fields are rendered', () => {
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent fields={fields}>
<Fields connector={connector} />
</MockFormWrapperComponent>
@ -80,7 +79,7 @@ describe('ResilientParamsFields renders', () => {
it('disabled the fields when loading incident types', async () => {
useGetIncidentTypesMock.mockReturnValue({ ...useGetIncidentTypesResponse, isLoading: true });
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent fields={fields}>
<Fields connector={connector} />
</MockFormWrapperComponent>
@ -95,7 +94,7 @@ describe('ResilientParamsFields renders', () => {
isLoading: true,
});
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent fields={fields}>
<Fields connector={connector} />
</MockFormWrapperComponent>
@ -105,7 +104,7 @@ describe('ResilientParamsFields renders', () => {
});
it('sets issue type correctly', async () => {
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent fields={fields}>
<Fields connector={connector} />
</MockFormWrapperComponent>
@ -121,7 +120,7 @@ describe('ResilientParamsFields renders', () => {
});
it('sets severity correctly', async () => {
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent fields={fields}>
<Fields connector={connector} />
</MockFormWrapperComponent>
@ -132,7 +131,7 @@ describe('ResilientParamsFields renders', () => {
});
it('should submit a resilient connector', async () => {
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent fields={fields}>
<Fields connector={connector} />
</MockFormWrapperComponent>
@ -140,9 +139,10 @@ describe('ResilientParamsFields renders', () => {
await waitFor(() => {
expect(screen.getByTestId('incidentTypeComboBox')).toBeInTheDocument();
expect(screen.getByRole('option', { name: 'Low' }));
});
expect(screen.getByRole('option', { name: 'Low' }));
const checkbox = within(screen.getByTestId('incidentTypeComboBox')).getByTestId(
'comboBoxSearchInput'
);

View file

@ -12,8 +12,8 @@ import { connector } from '../mock';
import { useGetIncidentTypes } from './use_get_incident_types';
import { useGetSeverity } from './use_get_severity';
import FieldsPreview from './case_fields_preview';
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
import { renderWithTestingProviders } from '../../../common/mock';
import { createQueryWithMarkup } from '../../../common/test_utils';
jest.mock('../../../common/lib/kibana');
@ -67,21 +67,18 @@ describe('Jira Fields: Preview', () => {
severityCode: '5',
};
let appMockRenderer: AppMockRenderer;
beforeEach(() => {
appMockRenderer = createAppMockRenderer();
useGetIncidentTypesMock.mockReturnValue(useGetIncidentTypesResponse);
useGetSeverityMock.mockReturnValue(useGetSeverityResponse);
jest.clearAllMocks();
});
it('renders all fields correctly', () => {
appMockRenderer.render(<FieldsPreview connector={connector} fields={fields} />);
renderWithTestingProviders(<FieldsPreview connector={connector} fields={fields} />);
const getByText = createQueryWithMarkup(screen.getByText);
const getByTextWithMarkup = createQueryWithMarkup(screen.getByText);
expect(getByText('Incident types: Malware, Denial of Service')).toBeInTheDocument();
expect(getByText('Severity: Medium')).toBeInTheDocument();
expect(getByTextWithMarkup('Incident types: Malware, Denial of Service')).toBeInTheDocument();
expect(getByTextWithMarkup('Severity: Medium')).toBeInTheDocument();
});
});

View file

@ -11,8 +11,7 @@ import { useKibana, useToasts } from '../../../common/lib/kibana';
import { connector } from '../mock';
import { useGetIncidentTypes } from './use_get_incident_types';
import * as api from './api';
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
import { TestProviders } from '../../../common/mock';
jest.mock('../../../common/lib/kibana');
jest.mock('./api');
@ -21,11 +20,9 @@ const useKibanaMock = useKibana as jest.Mocked<typeof useKibana>;
describe('useGetIncidentTypes', () => {
const { http } = useKibanaMock().services;
let appMockRender: AppMockRenderer;
beforeEach(() => {
jest.clearAllMocks();
appMockRender = createAppMockRenderer();
});
it('calls the api when invoked with the correct parameters', async () => {
@ -36,7 +33,7 @@ describe('useGetIncidentTypes', () => {
http,
connector,
}),
{ wrapper: appMockRender.AppWrapper }
{ wrapper: TestProviders }
);
await waitFor(() => result.current.isSuccess);
@ -55,7 +52,7 @@ describe('useGetIncidentTypes', () => {
useGetIncidentTypes({
http,
}),
{ wrapper: appMockRender.AppWrapper }
{ wrapper: TestProviders }
);
expect(spy).not.toHaveBeenCalledWith();
@ -76,7 +73,7 @@ describe('useGetIncidentTypes', () => {
http,
connector,
}),
{ wrapper: appMockRender.AppWrapper }
{ wrapper: TestProviders }
);
await waitFor(() => {
@ -101,7 +98,7 @@ describe('useGetIncidentTypes', () => {
http,
connector,
}),
{ wrapper: appMockRender.AppWrapper }
{ wrapper: TestProviders }
);
await waitFor(() => {

View file

@ -10,9 +10,8 @@ import { waitFor, renderHook } from '@testing-library/react';
import { useKibana, useToasts } from '../../../common/lib/kibana';
import { connector } from '../mock';
import { useGetSeverity } from './use_get_severity';
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
import * as api from './api';
import { TestProviders } from '../../../common/mock';
jest.mock('../../../common/lib/kibana');
jest.mock('./api');
@ -21,10 +20,8 @@ const useKibanaMock = useKibana as jest.Mocked<typeof useKibana>;
describe('useGetSeverity', () => {
const { http } = useKibanaMock().services;
let appMockRender: AppMockRenderer;
beforeEach(() => {
appMockRender = createAppMockRenderer();
jest.clearAllMocks();
});
@ -36,7 +33,7 @@ describe('useGetSeverity', () => {
http,
connector,
}),
{ wrapper: appMockRender.AppWrapper }
{ wrapper: TestProviders }
);
await waitFor(() => result.current.isSuccess);
@ -55,7 +52,7 @@ describe('useGetSeverity', () => {
useGetSeverity({
http,
}),
{ wrapper: appMockRender.AppWrapper }
{ wrapper: TestProviders }
);
expect(spy).not.toHaveBeenCalledWith();
@ -76,7 +73,7 @@ describe('useGetSeverity', () => {
http,
connector,
}),
{ wrapper: appMockRender.AppWrapper }
{ wrapper: TestProviders }
);
await waitFor(() => {
@ -101,7 +98,7 @@ describe('useGetSeverity', () => {
http,
connector,
}),
{ wrapper: appMockRender.AppWrapper }
{ wrapper: TestProviders }
);
await waitFor(() => {

View file

@ -40,8 +40,7 @@ jest.mock('@kbn/es-ui-shared-plugin/public', () => {
};
});
// FLAKY: https://github.com/elastic/kibana/issues/207077
describe.skip('JsonEditorField', () => {
describe('JsonEditorField', () => {
const setValue = jest.fn();
const props = {
field: {

View file

@ -12,9 +12,9 @@ import userEvent, { type UserEvent } from '@testing-library/user-event';
import { connector, choices } from '../mock';
import { useGetChoices } from './use_get_choices';
import Fields from './servicenow_itsm_case_fields';
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
import { MockFormWrapperComponent } from '../test_utils';
import { renderWithTestingProviders } from '../../../common/mock';
jest.mock('../../../common/lib/kibana');
jest.mock('./use_get_choices');
@ -28,7 +28,6 @@ useGetChoicesMock.mockReturnValue({
describe('ServiceNowITSM Fields', () => {
let user: UserEvent;
const appMockRenderer: AppMockRenderer = createAppMockRenderer();
beforeAll(() => {
jest.useFakeTimers();
@ -59,7 +58,7 @@ describe('ServiceNowITSM Fields', () => {
});
it('all params fields are rendered', async () => {
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent fields={fields}>
<Fields connector={connector} />
</MockFormWrapperComponent>
@ -74,7 +73,7 @@ describe('ServiceNowITSM Fields', () => {
});
it('transforms the categories to options correctly', async () => {
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent fields={fields}>
<Fields connector={connector} />
</MockFormWrapperComponent>
@ -90,7 +89,7 @@ describe('ServiceNowITSM Fields', () => {
});
it('transforms the subcategories to options correctly', async () => {
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent fields={fields}>
<Fields connector={connector} />
</MockFormWrapperComponent>
@ -100,7 +99,7 @@ describe('ServiceNowITSM Fields', () => {
});
it('transforms the options correctly', async () => {
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent fields={fields}>
<Fields connector={connector} />
</MockFormWrapperComponent>
@ -122,7 +121,7 @@ describe('ServiceNowITSM Fields', () => {
it('shows the deprecated callout if the connector is deprecated', async () => {
const tableApiConnector = { ...connector, isDeprecated: true };
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent fields={fields}>
<Fields connector={tableApiConnector} />
</MockFormWrapperComponent>
@ -132,7 +131,7 @@ describe('ServiceNowITSM Fields', () => {
});
it('does not show the deprecated callout when the connector is not deprecated', async () => {
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent fields={fields}>
<Fields connector={connector} />
</MockFormWrapperComponent>
@ -141,7 +140,7 @@ describe('ServiceNowITSM Fields', () => {
});
it('does not show the deprecated callout when the connector is preconfigured and not deprecated', async () => {
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent fields={fields}>
<Fields connector={{ ...connector, isPreconfigured: true }} />
</MockFormWrapperComponent>
@ -151,7 +150,7 @@ describe('ServiceNowITSM Fields', () => {
});
it('shows the deprecated callout when the connector is preconfigured and deprecated', async () => {
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent fields={fields}>
<Fields connector={{ ...connector, isPreconfigured: true, isDeprecated: true }} />
</MockFormWrapperComponent>
@ -168,7 +167,7 @@ describe('ServiceNowITSM Fields', () => {
subcategory: '',
};
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent fields={customFields}>
<Fields connector={connector} />
</MockFormWrapperComponent>
@ -182,7 +181,7 @@ describe('ServiceNowITSM Fields', () => {
const testers = ['severity', 'urgency', 'impact'];
testers.forEach((subj) =>
it(`${subj.toUpperCase()}`, async () => {
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent fields={fields}>
<Fields connector={connector} />
</MockFormWrapperComponent>
@ -197,7 +196,7 @@ describe('ServiceNowITSM Fields', () => {
});
it('should submit a service now itsm connector', async () => {
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent fields={fields}>
<Fields connector={connector} />
</MockFormWrapperComponent>
@ -236,7 +235,7 @@ describe('ServiceNowITSM Fields', () => {
});
it('resets subcategory when changing category', async () => {
appMockRenderer.render(
renderWithTestingProviders(
<MockFormWrapperComponent fields={fields}>
<Fields connector={connector} />
</MockFormWrapperComponent>

Some files were not shown because too many files have changed in this diff Show more