Skip to content

Commit

Permalink
feat: Bound DTL queries to the base element (#100)
Browse files Browse the repository at this point in the history
Closes #98 

BREAKING CHANGE: baseElement is no longer tied to the document body, and container is no longer the parent node of the element wrapper, but a wrapper div.

These changes shouldn't affect you if you weren't relying on either `baseElement` or `container`.
  • Loading branch information
afontcu authored Oct 9, 2019
1 parent 787a34a commit c4eacd2
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 9 deletions.
6 changes: 6 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
"vue-jest": "^3.0.4",
"vue-router": "^3.1.2",
"vue-template-compiler": "^2.6.10",
"vuetify": "^2.0.19",
"vuex": "^3.1.1"
},
"peerDependencies": {
Expand Down
22 changes: 22 additions & 0 deletions src/__tests__/components/Vuetify.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<template>
<v-app>
<v-btn @click="show = true">open</v-btn>
<v-dialog v-model="show">
<v-card>
<v-card-title class="headline green lighten-3">Lorem</v-card-title>
<v-card-text>Lorem ipsum dolor sit amet.</v-card-text>
</v-card>
</v-dialog>
</v-app>
</template>

<script>
export default {
name: 'VuetifyDemoComponent',
data() {
return {
show: false,
}
},
}
</script>
77 changes: 77 additions & 0 deletions src/__tests__/render.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import {render} from '@testing-library/vue'
import '@testing-library/jest-dom/extend-expect'

test('baseElement defaults to document.body', () => {
const {baseElement} = render({template: '<div />'})
expect(baseElement).toBe(document.body)
})

test('renders custom baseElement', () => {
const Component = {template: '<span />'}

const {baseElement, container} = render(Component, {
baseElement: document.createElement('blink'),
})

expect(baseElement).toMatchInlineSnapshot(`
<blink>
<div>
<span />
</div>
</blink>
`)

expect(container).toMatchInlineSnapshot(`
<div>
<span />
</div>
`)
})

test('renders container', () => {
const {container, getByTestId} = render({
template: '<div data-testid="myDiv">my content</div>',
})

expect(container.firstChild).toHaveTextContent(
getByTestId('myDiv').textContent,
)
})

test('container defaults to div', () => {
const {container} = render({template: '<div />'})

expect(container.tagName).toBe('DIV')
})

test('renders custom container', () => {
const blink = document.createElement('blink')
const Component = {template: '<div />'}

const {container} = render(Component, {
container: document.body.appendChild(blink),
})

expect(container).toBe(blink)
})

test('baseElement matches container if not custom baseElement is provided', () => {
const blink = document.createElement('blink')
const Component = {template: '<div />'}

const {container, baseElement} = render(Component, {
container: document.body.appendChild(blink),
})

expect(container).toMatchInlineSnapshot(`
<blink>
<div />
</blink>
`)

expect(baseElement).toMatchInlineSnapshot(`
<blink>
<div />
</blink>
`)
})
33 changes: 33 additions & 0 deletions src/__tests__/vuetify.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import Vue from 'vue'
import {render, fireEvent} from '@testing-library/vue'
import Vuetify from 'vuetify'
import VuetifyDemoComponent from './components/Vuetify'

// We need to use a global Vue instance, otherwise Vuetify will complain about
// read-only attributes.
// More info: https://github.com/vuetifyjs/vuetify/issues/4068
// https://vuetifyjs.com/en/getting-started/unit-testing
Vue.use(Vuetify)

// Vuetify requires you to wrap you app with a v-app component that provides
// a <div data-app="true"> node. So you can do that, or you can also set the
// attribute to the DOM.
document.body.setAttribute('data-app', true)
// Another solution is to create a custom renderer that provides all the
// environment required by Vuetify.

test('renders a Vuetify-powered component', async () => {
const {getByText} = render(VuetifyDemoComponent, {
vuetify: new Vuetify(),
})

await fireEvent.click(getByText('open'))

expect(getByText('Lorem ipsum dolor sit amet.')).toMatchInlineSnapshot(`
<div
class="v-card__text"
>
Lorem ipsum dolor sit amet.
</div>
`)
})
25 changes: 16 additions & 9 deletions src/vue-testing-library.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,19 @@ const mountedWrappers = new Set()

function render(
TestComponent,
{store = null, routes = null, ...mountOptions} = {},
{
store = null,
routes = null,
container: customContainer,
baseElement: customBaseElement,
...mountOptions
} = {},
configurationCb,
) {
const div = document.createElement('div')
const baseElement = customBaseElement || customContainer || document.body
const container = customContainer || baseElement.appendChild(div)

const localVue = createLocalVue()
let vuexStore = null
let router = null
Expand Down Expand Up @@ -53,15 +63,12 @@ function render(
})

mountedWrappers.add(wrapper)

const div = document.createElement('div')
wrapper.element.parentNode.insertBefore(div, wrapper.element)
div.appendChild(wrapper.element)
container.appendChild(wrapper.element)

return {
container: wrapper.element.parentNode,
baseElement: document.body,
debug: (el = wrapper.element) => logDOM(el),
container,
baseElement,
debug: (el = baseElement) => logDOM(el),
unmount: () => wrapper.destroy(),
isUnmounted: () => wrapper.vm._isDestroyed,
html: () => wrapper.html(),
Expand All @@ -70,7 +77,7 @@ function render(
wrapper.setProps(_)
return wait()
},
...getQueriesForElement(wrapper.element.parentNode),
...getQueriesForElement(baseElement),
}
}

Expand Down

0 comments on commit c4eacd2

Please sign in to comment.