diff --git a/.husky/pre-commit b/.husky/pre-commit
index 98475b50..acd310a4 100644
--- a/.husky/pre-commit
+++ b/.husky/pre-commit
@@ -1 +1,2 @@
+pnpm lint
pnpm test
diff --git a/docs/examples/ExampleActiveClasses.vue b/docs/examples/ExampleActiveClasses.vue
index bb126dd4..bdd6cbe3 100644
--- a/docs/examples/ExampleActiveClasses.vue
+++ b/docs/examples/ExampleActiveClasses.vue
@@ -1,5 +1,5 @@
-
+
{{ slide }}
diff --git a/tests/components/SlottedApp.vue b/tests/components/SlottedApp.vue
index 5992e932..29c8bd1a 100644
--- a/tests/components/SlottedApp.vue
+++ b/tests/components/SlottedApp.vue
@@ -1,11 +1,11 @@
-
+
diff --git a/tests/integration/__snapshots__/carousel.spec.ts.snap b/tests/integration/__snapshots__/carousel.spec.ts.snap
index ac471e33..35582477 100644
--- a/tests/integration/__snapshots__/carousel.spec.ts.snap
+++ b/tests/integration/__snapshots__/carousel.spec.ts.snap
@@ -1,6 +1,67 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
-exports[`Wrap around Carousel.ts > It renders wrapAround correctly 1`] = `
+exports[`SSR Carousel > renders server side properly 1`] = `
+"
+
+
+
+ Item 2 of 5
+
+
"
+`;
+
+exports[`SSR Carousel > renders server side properly 2`] = `"Item 2 of 5
"`;
+
+exports[`SSR Carousel > renders slotted server side properly 1`] = `
+"
+
+
+
+ - 4
+ - 5
+ - 1
+ - 2
+ - 3
+ - 4
+ - 5
+ - 1
+ - 2
+
+
+ Item 1 of 5
+
+
"
+`;
+
+exports[`SSR Carousel > renders slotted server side properly 2`] = `""`;
+
+exports[`Wrap around Carousel.ts > renders wrapAround correctly 1`] = `
"
diff --git a/tests/integration/carousel.spec.ts b/tests/integration/carousel.spec.ts
index 98923203..0ece246a 100644
--- a/tests/integration/carousel.spec.ts
+++ b/tests/integration/carousel.spec.ts
@@ -1,15 +1,18 @@
import { mount } from '@vue/test-utils'
-import { expect, it, describe, beforeAll } from 'vitest'
-
+import { expect, it, describe, beforeAll, vi, afterEach } from 'vitest'
+import { Component, createSSRApp, h } from 'vue'
+import { renderToString } from 'vue/server-renderer'
import App from '../components/BasicApp.vue'
import SlottedApp from '../components/SlottedApp.vue'
+import type { ComponentProps } from 'vue-component-type-helpers'
+
describe('Carousel.ts', () => {
- let wrapper: any
+ let wrapper: ReturnType>
beforeAll(async () => {
- wrapper = mount(App, { props: { slideNum: 5 } })
+ wrapper = await mount(App, { props: { slideNum: 5 } })
})
it('It renders *five* slides correctly', () => {
@@ -29,10 +32,10 @@ describe('Carousel.ts', () => {
})
describe('Slotted Carousel.ts', () => {
- let wrapper: any
+ let wrapper: ReturnType>
beforeAll(async () => {
- wrapper = mount(SlottedApp, { props: { slideNum: 3 } })
+ wrapper = await mount(SlottedApp, { props: { slideNum: 3 } })
})
it('It renders *three* slides correctly', () => {
@@ -52,15 +55,104 @@ describe('Slotted Carousel.ts', () => {
})
describe('Wrap around Carousel.ts', () => {
- let wrapper: any
+ let wrapper: ReturnType>
beforeAll(async () => {
- wrapper = mount(App, {
+ wrapper = await mount(App, {
props: { wrapAround: true, itemsToShow: 3, slideNum: 9, modelValue: 8 },
})
})
- it('It renders wrapAround correctly', () => {
+ it('renders wrapAround correctly', () => {
+ expect(wrapper.html()).toMatchSnapshot()
+ })
+})
+
+describe('SSR Carousel', () => {
+ const consoleMock = vi.spyOn(console, 'warn').mockImplementation(() => undefined)
+
+ afterEach(() => {
+ consoleMock.mockReset()
+ })
+
+ const renderSSR = async >(
+ component: T,
+ props: P = {}
+ ) => {
+ const comp = {
+ render() {
+ return h('div', { id: 'app' }, h(component, props))
+ },
+ }
+ // Simulate a SSR env where there is no window or document
+ const windowBackup = window
+ const documentBackup = document
+ Object.defineProperty(global, 'window', {
+ value: undefined,
+ enumerable: true,
+ writable: false,
+ })
+ const app = createSSRApp(comp)
+ const html = await renderToString(app)
+
+ Object.defineProperty(global, 'window', {
+ value: windowBackup,
+ enumerable: true,
+ writable: false,
+ })
+ Object.defineProperty(global, 'document', {
+ value: documentBackup,
+ enumerable: true,
+ writable: false,
+ })
+ Object.defineProperty(global.window, 'innerWidth', { value: 700 })
+ document.body.innerHTML = html
+ const wrapper = await mount(comp, { attachTo: '#app' })
+ return [html, wrapper]
+ }
+
+ it('renders server side properly', async () => {
+ const [html, wrapper] = await renderSSR(App, {
+ wrapAround: true,
+ modelValue: 1,
+ itemsToShow: 2,
+ })
+
+ expect(consoleMock).not.toHaveBeenCalled()
+ expect(wrapper.html()).toMatchSnapshot()
+ expect(html).toMatchSnapshot()
+ })
+
+ it('renders slotted server side properly', async () => {
+ const [html, wrapper] = await renderSSR(SlottedApp, {
+ wrapAround: true,
+ slideNum: 5,
+ })
+
+ expect(consoleMock).not.toHaveBeenCalled()
expect(wrapper.html()).toMatchSnapshot()
+ expect(html).toMatchSnapshot()
+ })
+
+ it("doesn't get hydration mismatch with breakpoints", async () => {
+ const [html, wrapper] = await renderSSR(App, {
+ wrapAround: true,
+ breakpoints: {
+ 600: {
+ itemsToShow: 3,
+ },
+ },
+ modelValue: 1,
+ itemsToShow: 1,
+ })
+ expect(consoleMock).not.toHaveBeenCalled()
+
+ const slides = wrapper.findAll('.carousel__slide--visible')
+ expect(slides.length).toBe(3)
+
+ const el = document.createElement('div')
+ el.innerHTML = html
+ const slidesSSR = el.querySelectorAll('.carousel__slide--visible')
+ expect(slidesSSR.length).toBe(1)
})
})