diff --git a/src/index-bar/test/index.spec.js b/src/index-bar/test/index.spec.js index c7c59c2fd..dcda50ed0 100644 --- a/src/index-bar/test/index.spec.js +++ b/src/index-bar/test/index.spec.js @@ -1,5 +1,11 @@ import { nextTick, onMounted, ref } from 'vue'; -import { mount, trigger, triggerDrag, mockScrollIntoView } from '../../../test'; +import { + mount, + trigger, + triggerDrag, + mockScrollTop, + mockScrollIntoView, +} from '../../../test'; import IndexBar from '..'; import IndexAnchor from '../../index-anchor'; @@ -108,8 +114,7 @@ test('should update active anchor after page scroll', async () => { }, }); - window.scrollTop = 0; - await trigger(window, 'scroll'); + await mockScrollTop(0); expect(wrapper.html()).toMatchSnapshot(); wrapper.vm.sticky = true; @@ -146,13 +151,11 @@ test('should emit change event when active index changed', async () => { }, }); - window.scrollTop = 0; - await trigger(window, 'scroll'); + await mockScrollTop(0); expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenLastCalledWith('B'); - window.scrollTop = 100; - await trigger(window, 'scroll'); + await mockScrollTop(100); expect(onChange).toHaveBeenCalledTimes(2); expect(onChange).toHaveBeenLastCalledWith('D'); diff --git a/src/pull-refresh/test/index.spec.js b/src/pull-refresh/test/index.spec.js index e2590c3b1..4d0c494b0 100644 --- a/src/pull-refresh/test/index.spec.js +++ b/src/pull-refresh/test/index.spec.js @@ -1,5 +1,11 @@ import PullRefresh from '..'; -import { mount, later, trigger, triggerDrag } from '../../../test'; +import { + mount, + later, + trigger, + triggerDrag, + mockScrollTop, +} from '../../../test'; test('should render different head content in different pulling status', async () => { const wrapper = mount(PullRefresh); @@ -82,11 +88,11 @@ test('should not trigger pull refresh when not in page top', async () => { const track = wrapper.find('.van-pull-refresh__track'); // ignore touch event when not at page top - window.scrollTop = 1; + await mockScrollTop(1); triggerDrag(track, 0, 100); expect(wrapper.emitted('update:modelValue')).toBeFalsy(); - window.scrollTop = 0; + await mockScrollTop(0); triggerDrag(track, 0, 100); expect(wrapper.emitted('update:modelValue')).toBeTruthy(); }); diff --git a/src/sticky/test/__snapshots__/index.legacy.js.snap b/src/sticky/test/__snapshots__/index.legacy.js.snap deleted file mode 100644 index fbfac5d00..000000000 --- a/src/sticky/test/__snapshots__/index.legacy.js.snap +++ /dev/null @@ -1,69 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`container prop 1`] = ` -
-
-
- Content -
-
-
-`; - -exports[`container prop 2`] = ` -
-
-
- Content -
-
-
-`; - -exports[`offset-top prop 1`] = ` -
-
- Content -
-
-`; - -exports[`offset-top with rem unit 1`] = ` -
-
- Content -
-
-`; - -exports[`offset-top with vw unit 1`] = ` -
-
- Content -
-
-`; - -exports[`sticky to top 1`] = ` -
-
- Content -
-
-`; - -exports[`sticky to top 2`] = ` -
-
- Content -
-
-`; - -exports[`z-index prop 1`] = ` -
-
- Content -
-
-`; diff --git a/src/sticky/test/__snapshots__/index.spec.js.snap b/src/sticky/test/__snapshots__/index.spec.js.snap new file mode 100644 index 000000000..4e14c31cb --- /dev/null +++ b/src/sticky/test/__snapshots__/index.spec.js.snap @@ -0,0 +1,79 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should add offset top when using offset-top prop 1`] = ` +
+
+ Content +
+
+`; + +exports[`should allow to using offset-top prop with rem unit 1`] = ` +
+
+ Content +
+
+`; + +exports[`should allow to using offset-top prop with vw unit 1`] = ` +
+
+ Content +
+
+`; + +exports[`should sticky inside container when using container prop 1`] = ` +
+
+
+ Content +
+
+
+`; + +exports[`should sticky inside container when using container prop 2`] = ` +
+
+
+ Content +
+
+
+`; + +exports[`should sticky to top after scrolling 1`] = ` +
+
+ Content +
+
+`; + +exports[`should sticky to top after scrolling 2`] = ` +
+
+ Content +
+
+`; + +exports[`should update z-index when using z-index prop 1`] = ` +
+
+ Content +
+
+`; diff --git a/src/sticky/test/index.legacy.js b/src/sticky/test/index.legacy.js deleted file mode 100644 index c49a069ed..000000000 --- a/src/sticky/test/index.legacy.js +++ /dev/null @@ -1,171 +0,0 @@ -import { mount, mockScrollTop } from '../../../test'; - -test('sticky to top', () => { - const wrapper = mount({ - template: ` - - Content - - `, - }); - - expect(wrapper.html()).toMatchSnapshot(); - mockScrollTop(100); - expect(wrapper.html()).toMatchSnapshot(); - mockScrollTop(0); -}); - -test('z-index prop', () => { - const wrapper = mount({ - template: ` - - Content - - `, - }); - - mockScrollTop(100); - expect(wrapper.html()).toMatchSnapshot(); - mockScrollTop(0); -}); - -test('offset-top prop', () => { - const wrapper = mount({ - template: ` - - Content - - `, - }); - - mockScrollTop(100); - expect(wrapper.html()).toMatchSnapshot(); - mockScrollTop(0); -}); - -test('offset-top with rem unit', () => { - const originGetComputedStyle = window.getComputedStyle; - - window.getComputedStyle = () => ({ fontSize: '16px' }); - - const wrapper = mount({ - template: ` - - Content - - `, - }); - - mockScrollTop(100); - expect(wrapper.html()).toMatchSnapshot(); - mockScrollTop(0); - - window.getComputedStyle = originGetComputedStyle; -}); - -test('offset-top with vw unit', () => { - window.innerWidth = 300; - - const wrapper = mount({ - template: ` - - Content - - `, - }); - - mockScrollTop(100); - expect(wrapper.html()).toMatchSnapshot(); - mockScrollTop(0); -}); - -test('should not trigger scroll event when hidden', () => { - const scroll = jest.fn(); - mount({ - template: ` - - Content - - `, - methods: { - scroll, - }, - }); - - expect(scroll).toHaveBeenCalledTimes(0); -}); - -test('container prop', () => { - const wrapper = mount({ - template: ` -
- - Content - -
- `, - data() { - return { - container: null, - }; - }, - mounted() { - this.container = this.$refs.container; - }, - }); - - mockScrollTop(15); - expect(wrapper.html()).toMatchSnapshot(); - mockScrollTop(25); - expect(wrapper.html()).toMatchSnapshot(); - mockScrollTop(0); -}); - -test('trigger scroll when visibility changed', () => { - const originIntersectionObserver = window.IntersectionObserver; - - const observe = jest.fn(); - const unobserve = jest.fn(); - const scroll = jest.fn(); - - let observerCallback; - - window.IntersectionObserver = class IntersectionObserver { - constructor(callback) { - observerCallback = callback; - } - - observe() { - observe(); - } - - unobserve() { - unobserve(); - } - }; - - const wrapper = mount({ - template: ` - - Content - - `, - methods: { - scroll, - }, - }); - - expect(observe).toHaveBeenCalledTimes(1); - expect(scroll).toHaveBeenCalledTimes(1); - - observerCallback([{ intersectionRatio: 1 }]); - expect(scroll).toHaveBeenCalledTimes(2); - - observerCallback([{ intersectionRatio: 0 }]); - expect(scroll).toHaveBeenCalledTimes(2); - - wrapper.unmount(); - expect(unobserve).toHaveBeenCalledTimes(1); - - window.IntersectionObserver = originIntersectionObserver; -}); diff --git a/src/sticky/test/index.spec.js b/src/sticky/test/index.spec.js new file mode 100644 index 000000000..06762145d --- /dev/null +++ b/src/sticky/test/index.spec.js @@ -0,0 +1,184 @@ +import { nextTick, ref } from 'vue'; +import { mount, mockScrollTop } from '../../../test'; +import Sticky from '..'; + +test('should sticky to top after scrolling', async () => { + const wrapper = mount({ + render() { + return Content; + }, + }); + + expect(wrapper.html()).toMatchSnapshot(); + + await mockScrollTop(100); + expect(wrapper.html()).toMatchSnapshot(); + await mockScrollTop(0); +}); + +test('should update z-index when using z-index prop', async () => { + const wrapper = mount({ + render() { + return ( + + Content + + ); + }, + }); + + await mockScrollTop(100); + expect(wrapper.html()).toMatchSnapshot(); + await mockScrollTop(0); +}); + +test('should add offset top when using offset-top prop', async () => { + const wrapper = mount({ + render() { + return ( + + Content + + ); + }, + }); + + await mockScrollTop(100); + expect(wrapper.html()).toMatchSnapshot(); + await mockScrollTop(0); +}); + +test('should allow to using offset-top prop with rem unit', async () => { + const originGetComputedStyle = window.getComputedStyle; + + window.getComputedStyle = () => ({ fontSize: '16px' }); + + const wrapper = mount({ + render() { + return ( + + Content + + ); + }, + }); + + await mockScrollTop(100); + expect(wrapper.html()).toMatchSnapshot(); + + await mockScrollTop(0); + window.getComputedStyle = originGetComputedStyle; +}); + +test('should allow to using offset-top prop with vw unit', async () => { + window.innerWidth = 300; + + const wrapper = mount({ + render() { + return ( + + Content + + ); + }, + }); + + await mockScrollTop(100); + expect(wrapper.html()).toMatchSnapshot(); + await mockScrollTop(0); +}); + +test('should not trigger scroll event when hidden', () => { + const onScroll = jest.fn(); + + mount({ + render() { + return ( + + Content + + ); + }, + }); + + expect(onScroll).toHaveBeenCalledTimes(0); +}); + +test('should sticky inside container when using container prop', async () => { + const wrapper = mount({ + setup() { + const container = ref(); + return { + container, + }; + }, + render() { + return ( +
+ + Content + +
+ ); + }, + }); + + await nextTick(); + await mockScrollTop(15); + expect(wrapper.html()).toMatchSnapshot(); + await mockScrollTop(25); + expect(wrapper.html()).toMatchSnapshot(); + await mockScrollTop(0); +}); + +test('should emit scroll event when visibility changed', async () => { + const originIntersectionObserver = window.IntersectionObserver; + + const observe = jest.fn(); + const unobserve = jest.fn(); + const onScroll = jest.fn(); + + let observerCallback; + + window.IntersectionObserver = class IntersectionObserver { + constructor(callback) { + observerCallback = callback; + } + + observe() { + observe(); + } + + unobserve() { + unobserve(); + } + }; + + const wrapper = mount({ + render() { + return ( + + Content + + ); + }, + }); + + await nextTick(); + await mockScrollTop(0); + + expect(observe).toHaveBeenCalledTimes(1); + expect(onScroll).toHaveBeenCalledTimes(1); + + observerCallback([{ intersectionRatio: 1 }]); + expect(onScroll).toHaveBeenCalledTimes(2); + + wrapper.element.style.display = 'none'; + observerCallback([{ intersectionRatio: 0 }]); + expect(onScroll).toHaveBeenCalledTimes(2); + + wrapper.unmount(); + expect(unobserve).toHaveBeenCalledTimes(1); + + window.IntersectionObserver = originIntersectionObserver; +}); diff --git a/test/dom.ts b/test/dom.ts index 71f083cbd..c07be8935 100644 --- a/test/dom.ts +++ b/test/dom.ts @@ -1,3 +1,4 @@ +import { nextTick } from 'vue'; import { trigger } from './event'; function mockHTMLElementOffset() { @@ -36,9 +37,7 @@ export function mockScrollIntoView() { return fn; } -export function mockGetBoundingClientRect( - rect: DOMRect -): () => void { +export function mockGetBoundingClientRect(rect: DOMRect): () => void { const originMethod = Element.prototype.getBoundingClientRect; Element.prototype.getBoundingClientRect = jest.fn(() => rect); @@ -48,9 +47,10 @@ export function mockGetBoundingClientRect( }; } -export function mockScrollTop(value: number) { +export async function mockScrollTop(value: number) { Object.defineProperty(window, 'scrollTop', { value, writable: true }); trigger(window, 'scroll'); + return nextTick(); } mockScrollIntoView();