Vue-test-utils: remove hasStyle

Created on 5 Jan 2018  Â·  21Comments  Â·  Source: vuejs/vue-test-utils

I think we should remove the hasStyle method.

The only reason it's useful is to check styles applied by stylesheets.

Personally, I don't think we should encourage this.

Note, you can test the element style property:

wrapper.element.style.color // red

This method gives a value based assertion rather than a Boolean assertion

What are peoples thoughts?

discussion

Most helpful comment

Note, you can test the element style property:

wrapper.element.style.color // red

All 21 comments

I have used it once, which was a in a demo app that allowed users to create a shape where they set the color using a input box, which they could type a hex/rgb number. This used hasStyle to test -- but I haven't used hasStyle in any production apps.

If you were making a sitebuilder or something, where users can define styles and stuff themselves, it might be useful?

I don't have a strong opinion and wouldn't be sad to see it go, though. Just throwing some thoughts for discussion.

Edit: how to test v-show without hasStyle?

I think it can still be useful to perform assertions in some use cases.

Maybe a styles() method could be added too, returning key/value object (it would then be consistent with classes()).

We are applying some styles dynamically, we have list of files and we set background-image style for every image file. Logic for different type of files is different. In tests we are using hasStyle method to check if image is set properly.

One thing which we don't like about this kind of methods is that result reported from failed assertion is (expected true to equals false) instead of (expected url('some-image.png') to equals url('some-not-valid-image.png')), but it's out of scope of this issue.

That would require to add custom matchers for the underlying assertion library.

What about adding an inlineStyles (and remove hasStyle) method that returns an object with the camel-case rules and its values, that way we can still address the v-show case:

expect(wrapper.inlineStyles().display).toBe('none');
expect(wrapper.inlineStyles().backgroundImage).toBe(imageUrl);

This will solve this as well, right?

One thing which we don't like about this kind of methods is that result reported from failed assertion is (expected true to equals false) instead of (expected url('some-image.png') to equals url('some-not-valid-image.png')), but it's out of scope of this issue.

I'll be willing to make a PR if you guys agree.

Note, you can test the element style property:

wrapper.element.style.color // red

Yes @eddyerburgh you're right, is built in 😂

expect(wrapper.element.style.display).toBe('none');

Works great, thanks. I vote to remove hasStyle, again.

Thanks @eddyerburgh for great input. In this case I agree that remove hasStyle is ok

I've added a deprecation notice and it'll be removed before v1.0.0

You need to access the Wrapper element:

expect(wrapper.element.style['background-color']).to.equal('green');

On Fri, Jan 19, 2018 at 9:01 AM, Serj L notifications@github.com wrote:

@eddyerburgh https://github.com/eddyerburgh is there a way to test
style on wrapper directly? We have something like that:

And we used to test our component like that:

it('sets background-color to emailStatusColorCode prop value', () => {
const wrapper = mount(EmailsItemStatus, { propsData: { emailStatusColorCode: 'green' } });
expect(wrapper.hasStyle('background-color', 'green'))
});

But since there is a deprecation I tried to use new syntax. But it seems
like it doesn't work on a wrapper:

it('sets background-color to emailStatusColorCode prop value', () => {
const wrapper = mount(EmailsItemStatus, { propsData: { emailStatusColorCode: 'green' } });
expect(wrapper.style['background-color']).to.equal('green');
});

It shows this error:

TypeError: Cannot read property 'background-color' of undefined
at Context. (.tmp/mocha-webpack/1516352347096/bundle.js:46857:25)

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/vuejs/vue-test-utils/issues/330#issuecomment-358905802,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AMlbW4kgCut5BLaTFEg2yeXNMcFqZ72Fks5tMFn7gaJpZM4RUVe5
.

@eddyerburgh Can I suggested that put the line of expect(wrapper.element.style['background-color']).to.equal('green'); as the next line of deprecation notice?

When I first see the deprecation notice, I'm so confused that what to do now and what's the best practise.

Good idea 😀

Would you like to make a PR adding It?

On 31 Jan 2018 08:31, "Song Liu" notifications@github.com wrote:

@eddyerburgh https://github.com/eddyerburgh Can I suggested that put
the line of expect(wrapper.element.style['background-color']).to.equal('
green'); as the next line of deprecation notice?

When I first see the deprecation notice, I'm so confused that what to do
now and what's the suggestion.

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/vuejs/vue-test-utils/issues/330#issuecomment-361859753,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AMlbW-brR8eRDd4tqVG1bgeeR1VHC_ksks5tQCTfgaJpZM4RUVe5
.

What happen to computed style after the removal? The wrapper.element.style seems can only access inline styles. Does the window.getComputedStyle applies anywhere?

window.getComputedStyle is not always available (NodeJS/Jest).

@eddyerburgh Sorry for reply so late.
After reading the code carefully, It seems words after the sentence -- Use wrapper.element.style instead already done the same thing.

If there still some thing need to be done, just let me know:)

image
When I want to access $el.style to resize my element and test it with vue-jest, it failed. For jsDOM is not work expected as browser DOM, which is really annoying.

image

Fairly sure $el.style.height should still be available. Can you post the test and full component is possible?

jsdom doesn't implement layout at all, so if you generate style using methods like getBoundingClientRect, your code will not work as expected.

You can either mock the properties, or run tests in a real browser with Karma,

BlockContainer.vue
<template>
  <div
    class="block-container"
    :class="{'block-container--large': this.size === 'large'}"
    :style="`background-image:url(${bg})`">
    <span class="_title" ref="title">{{title}}</span>
    <div class="_body" ref="body">
      <slot><span>block-container</span></slot>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    title: {
      type: [String, Number],
      required: true
    },
    size: {
      type: String,
      default: 'normal',
    },
  },

  computed: {
    ratio() {
      if (this.size === 'normal') {
        return 1.654
      } else if (this.size === 'large') {
        return 1.290
      } else {
        return 1
      }
    },

    bg() {
      if (this.size === 'large') {
        return require('./bg-large.png')
      } else {
        return require('./bg.png')
      }
    }
  },

  mounted() {
    function resizeHeight() {
      const width = this.$el.clientWidth
      this.$el.style.height = (width / this.ratio).toString() + 'px'

      // title lineHeight
      const titleRatio = 18.2
      const lineHeight = width / titleRatio
      this.$refs.title.style.lineHeight = lineHeight.toString() + 'px'

      // body height
      const height = this.$el.clientHeight
      this.$refs.body.style.height = (height - lineHeight).toString() + 'px'
      this.$refs.body.style.top = lineHeight.toString() + 'px'
    }

    resizeHeight.call(this)
    window.addEventListener('resize', resizeHeight.bind(this))
  }
}
</script>

<style lang="scss" scoped>
.block-container {
  background-image: url(./bg.png);
  background-size: 100% 100%;
  background-position: top center;
  background-repeat: no-repeat;
  height: 300px;
  width: 100%;
  position: relative;
  overflow: hidden;
  margin-bottom: 24px;

  ._title {
    color: #fff;
    top: 0;
    width: 100%;
    text-align: center;
    position: absolute;
    font-size: 12px;
    line-height: 28px;
  }

  ._body {
    position: absolute;
    top: 24px;
    width: 100%;
    height: 100%;
    text-align: center;
    padding: 3px;
    padding-top: 2px;
    box-sizing: border-box;
  }
}
</style>
// BlockContainer.spec.vue
import {shallowMount} from '@vue/test-utils'
import BlockContainer from '@/components/controls/BlockContainer'

describe('BlockContainer.vue', () => {
  it('should setup without error.', () => {
    const wrapper = shallowMount(BlockContainer, {
      propsData: {
        title: 'title'
      },

      mocks: {
        $el: {
          clientWidth: 600,
          clientHeight: 600,
          style: {
            width: '400px',
            height: '400px',
          }
        }
      }
    })
    expect(wrapper).toBeTruthy()
  })
})

Is $el readonly? And it fails again. @lmiller1990

@wisetc sorry, forgot this. are you still looking for a solution? can have a look tonight.

You need to access the Wrapper element: js expect(wrapper.element.style['background-color']).to.equal('green');

This throws an error in TypeScript. In TS unit tests, this is the working syntax:

expect(wrapper.element.style.getPropertyValue('background-color')).toBe('green');
Was this page helpful?
0 / 5 - 0 ratings