Popover doesn't close in test #666
Replies: 5 comments
-
Did u find solution? |
Beta Was this translation helpful? Give feedback.
-
@voskresla No, unfortunately not yet :/ For now, I removed the failing test (which isn't nice of course). But I would very much like to know what's causing the failure. If you come across a solution yourself, please let me know :) |
Beta Was this translation helpful? Give feedback.
-
Did you register the close-popover directive? |
Beta Was this translation helpful? Give feedback.
-
Hi, I further simplified the component for showing, but the "main" component reflects this behavior. In contrast to the component's code, which I posted earlier, I outsourced the content of the popover to a new component <template>
<v-popover>
<div>Trigger</div>
<template slot="popover">
<slot></slot>
</template>
</v-popover>
</template>
<script lang="ts">
import { defineComponent } from '@vue/composition-api';
import Vue from 'vue';
import VTooltipDefault, { VPopover } from 'v-tooltip';
Vue.component('v-popover', VPopover);
Vue.use(VTooltipDefault, { disposeTimeout: 200 }); // needed for transitions, test always fails if it's missing
export default defineComponent({
setup(){},
})
</script> And <template>
<div v-close-popover @click="clickHandler"><slot></slot></div>
</template>
<script lang="ts">
import { defineComponent } from '@vue/composition-api';
import Vue from 'vue';
import { VClosePopover } from 'v-tooltip';
Vue.directive('close-popover', VClosePopover);
/**
* Simple component to be used as option e.g. for MySelect component.
*/
export default defineComponent({
setup(props, { emit }) {
function clickHandler(event: Event): void {
emit('click', event);
}
return { clickHandler };
},
});
</script> Corresponding test: import { render, fireEvent, waitFor, waitForElementToBeRemoved } from '@testing-library/vue';
import '@testing-library/jest-dom';
import MySelect from './mySelect.vue';
import MyOption from './myOption.vue';
import Vue from 'vue';
import VueCompositionApi from '@vue/composition-api';
Vue.use(VueCompositionApi);
// patch for error in v-tooltip package:
// [Vue warn]: Error in directive tooltip bind hook: "TypeError: document.createRange is not a function"
// see https://stackoverflow.com/questions/61691375/jest-test-typeerror-document-createrange-is-not-a-function
document.createRange = () => ({
// eslint-disable-next-line @typescript-eslint/no-empty-function
setStart: () => {},
// eslint-disable-next-line @typescript-eslint/no-empty-function
setEnd: () => {},
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
//@ts-ignore
commonAncestorContainer: {
nodeName: 'BODY',
ownerDocument: document,
},
});
describe('My select component', () => {
// ... some other tests
it('closes the popover once the popover content is clicked', async () => {
const { getByText, queryByText } = render(MySelect, {
stubs: {
'my-option': MyOption,
},
slots: {
default: `
<my-option value="1" v-close-popover>Option 1</my-option>
<my-option value="2" v-close-popover>Option 2</my-option>`,
},
});
await waitFor(() => {
expect(getByText('Trigger')).toBeInTheDocument();
});
const trigger = getByText('Trigger');
await fireEvent.click(trigger);
await waitFor(() => {
expect(getByText('Option 1')).toBeInTheDocument();
});
const content = getByText('Option 1');
await fireEvent.click(content);
await waitForElementToBeRemoved(() => queryByText('Option 1')); // --> This fails
});
}); I ran the test sequentially multiple times and counted: It failed in 4 of 25 cases, always for the same reason ( nteuffel vue-components % npm run test src/components/mySelect
> @my-project/vue-components@2.15.0 test /Users/nteuffel/[…]/vue-components
> vue-cli-service test:unit "src/components/mySelect"
FAIL src/components/mySelect/mySelect.spec.ts
My select component
✕ closes the popover once the popover content is clicked (1131ms)
● My select component › closes the popover once the popover content is clicked
Timed out in waitForElementToBeRemoved.
<html>
<head>
<style
type="text/css"
>
.resize-observer[data-v-b329ee4c]{position:absolute;top:0;left:0;z-index:-1;width:100%;height:100%;border:none;background-color:transparent;pointer-events:none;display:block;overflow:hidden;opacity:0}.resize-observer[data-v-b329ee4c] object{display:block;position:absolute;top:0;left:0;height:100%;width:100%;overflow:hidden;pointer-events:none;z-index:-1}
</style>
</head>
<body>
<div>
<div
class="v-popover open"
>
<div
aria-describedby="popover_5dvdjzarno"
class="trigger"
style="display: inline-block;"
>
<div>
Trigger
</div>
</div>
</div>
</div>
<div
aria-hidden="false"
class="tooltip popover vue-popover-theme open"
id="popover_5dvdjzarno"
style="visibility: visible; position: absolute; will-change: transform; top: 0px; left: 0px; transform: translate3d(NaNpx, NaNpx, 0);"
tabindex="0"
x-placement="bottom"
>
<div
class="wrapper"
>
<div
class="tooltip-inner popover-inner"
style="position: relative;"
>
<div>
<div
value="1"
>
Option 1
</div>
<div
value="2"
>
Option 2
</div>
</div>
<div
class="resize-observer"
data-v-b329ee4c=""
tabindex="-1"
>
<object
aria-hidden="true"
data="about:blank"
tabindex="-1"
type="text/html"
/>
</div>
</div>
<div
class="tooltip-arrow popover-arrow"
/>
</div>
</div>
</body>
</html>
45 | const content = getByText('Option 1');
46 | await fireEvent.click(content);
> 47 | await waitForElementToBeRemoved(() => queryByText('Option 1')); // --> This fails
| ^
48 | });
49 | });
at waitForElementToBeRemoved (../../node_modules/@testing-library/dom/dist/wait-for-element-to-be-removed.js:22:24)
at src/components/mySelect/mySelect.spec.ts:47:9
at step (../../node_modules/tslib/tslib.js:136:27)
at Object.next (../../node_modules/tslib/tslib.js:117:57)
at fulfilled (../../node_modules/tslib/tslib.js:107:62)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: 2.798s
Ran all test suites matching /src\/components\/mySelect/i.
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! @my-project/vue-components@2.15.0 test: `vue-cli-service test:unit "src/components/mySelect"`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the @my-project/vue-components@2.15.0 test script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /Users/nteuffel/.npm/_logs/2021-01-11T10_33_41_515Z-debug.log
nteuffel vue-components % npm run test src/components/mySelect
> @my-project/vue-components@2.15.0 test /Users/nteuffel/[…]/vue-components
> vue-cli-service test:unit "src/components/mySelect"
PASS src/components/mySelect/mySelect.spec.ts
My select component
✓ closes the popover once the popover content is clicked (376ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 2.656s, estimated 3s
Ran all test suites matching /src\/components\/mySelect/i. I have absolutely no clue why some of the tests fail and others don't. 4/25 seems a good rate, still I can't risk integrating this test into my test suite unless it passes always. Thanks in advance. |
Beta Was this translation helpful? Give feedback.
-
Hi,
I set up a minimal component to show this behavior: <template>
<div>
<v-popover ref="myComponentRef">
<div>Trigger</div>
<template slot="popover">
<div @click="handleClose">
Content
</div>
</template>
</v-popover>
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from '@vue/composition-api';
import Vue from 'vue';
import { VPopover } from 'v-tooltip';
Vue.component('v-popover', VPopover);
export default defineComponent({
setup() {
const myComponentRef = ref();
function handleClose() {
myComponentRef.value.hide();
}
return {
handleClose,
myComponentRef,
};
},
});
</script> When I open the component in Storybook, everything works as intended: The popover opens when I click on myComponent.spec.ts: import { render, fireEvent, waitFor } from '@testing-library/vue';
import '@testing-library/jest-dom';
import MyComponent from './myComponent.vue';
import Vue from 'vue';
import VueCompositionApi from '@vue/composition-api';
Vue.use(VueCompositionApi);
// patch for error in v-tooltip package:
// [Vue warn]: Error in directive tooltip bind hook: "TypeError: document.createRange is not a function"
// see https://stackoverflow.com/questions/61691375/jest-test-typeerror-document-createrange-is-not-a-function
document.createRange = () => ({
// eslint-disable-next-line @typescript-eslint/no-empty-function
setStart: () => {},
// eslint-disable-next-line @typescript-eslint/no-empty-function
setEnd: () => {},
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
//@ts-ignore
commonAncestorContainer: {
nodeName: 'BODY',
ownerDocument: document,
},
});
describe('MyComponent', () => {
// Works
it('renders the trigger', () => {
const { getByText } = render(MyComponent);
// renders trigger
expect(getByText('Trigger')).toBeInTheDocument();
});
// Works
it('opens the tooltip', async () => {
const { getByText } = render(MyComponent);
const trigger = getByText('Trigger');
fireEvent.click(trigger);
await waitFor(() => {
expect(getByText('Content')).toBeInTheDocument();
});
});
// Fails
it('closes the tooltip on window click', async () => {
const { getByText } = render(MyComponent);
const trigger = getByText('Trigger');
fireEvent.click(trigger);
await waitFor(() => {
expect(getByText('Content')).toBeInTheDocument();
});
fireEvent.click(window); // throws error
await waitFor(() => {
// this fails
expect(getByText('Content')).not.toBeInTheDocument();
});
});
// Fails
it('closes the tooltip on content click', async () => {
const { getByText } = render(MyComponent);
const trigger = getByText('Trigger');
fireEvent.click(trigger);
await waitFor(() => {
expect(getByText('Content')).toBeInTheDocument();
});
fireEvent.click(getByText('Content'));
await waitFor(() => {
// this fails
expect(getByText('Content')).not.toBeInTheDocument();
});
});
}); When I test for closing the tooltip on window click (third test), an error is thrown: Am I invoking the tests wrongly? If so: What should I do differently? Or do I have to add some special handling for the window click in my tests? By the way: This is a pretty awesome and useful package, apart from these minor issues :) Thanks for your efforts! |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Hi,
first of all: Thanks for creating such a great library! For now, everything works fine for me, except for one small issue:
I created an own
select
component, very similar to the native one: I can select a value from a list of options, displayed in a dropdown. When clicking on an option, that option is displayed as value and the dropdown closes (handled by the v-close-popover directive). When using the component e.g. in Storybook, everything works fine. But when I want to test its functionalities in a spec file, the dropdown doesn't close when selecting an option.I would be very thankful for any hint as to what I'm doing wrong or where I should look for a solution.
Cheers!
Nanda
Here's my component code:
And this is the test file, where all tests work, except for the last one:
Beta Was this translation helpful? Give feedback.
All reactions