Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions src/components/KButton/KButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@
</template>

<script setup lang="ts">
import { computed, onMounted, useAttrs, watch } from 'vue'
import { computed, onMounted, useAttrs } from 'vue'
import { ButtonAppearances } from '@/types'
import { useDeprecated } from '@/composables/useDeprecated'
import type { ButtonAppearance, ButtonProps, ButtonSize, ButtonSlots } from '@/types'

const {
Expand All @@ -31,11 +32,10 @@ const {
} = defineProps<ButtonProps>()

// Deprecation warning. Remove this in next major release.
watch(() => icon, (value) => {
if (typeof value === 'string') {
console.warn('KButton: `icon` prop usage has changed. Please refer to the migration guide for more details: https://kongponents.konghq.com/guide/migrating-to-version-9.html#kbutton')
}
}, { immediate: true })
useDeprecated(() => typeof icon === 'string', {
notice: '`icon` prop usage has changed',
fragment: 'kbutton',
})

const slots = defineSlots<ButtonSlots>()
const attrs = useAttrs()
Expand Down Expand Up @@ -119,9 +119,10 @@ const listeners = computed(() => {
})

onMounted(() => {
if (slots.icon) {
console.warn('KButton: `icon` slot is deprecated. Please slot an icon into the `default` slot instead. See the migration guide for more details: https://kongponents.konghq.com/guide/migrating-to-version-9.html#kbutton')
}
useDeprecated(() => !!slots.icon, {
notice: '`icon` slot is deprecated. Please slot an icon into the `default` slot instead',
fragment: 'kbutton',
})
})
</script>

Expand Down
64 changes: 64 additions & 0 deletions src/composables/useDeprecated.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { defineComponent } from 'vue'
import { useDeprecated, composeWarning } from '@/composables/useDeprecated'

describe('useDeprecated', () => {
const CORRECT_CONDITION = 'condition'
const COMPONENT_NAME = 'KTestComponent'
const notice = 'heads up'

let assertion = CORRECT_CONDITION
let docPath: string | undefined = undefined
let fragment: string | undefined = undefined
const TestComponent = defineComponent({
name: COMPONENT_NAME,
setup() {
useDeprecated(() => assertion === CORRECT_CONDITION, {
notice,
docPath,
fragment,
})
},
template: '<div />',
})

beforeEach(() => {
cy.stub(console, 'warn').as('consoleWarn')
assertion = CORRECT_CONDITION
docPath = undefined
fragment = undefined
})

it('should warn the user when the condition was met', () => {
cy.mount(TestComponent)
cy.get('@consoleWarn').should('be.calledWith', composeWarning(COMPONENT_NAME, notice))
})

it('should not warn when the condition returns false', () => {
assertion = 'another condition'

cy.mount(TestComponent)
cy.get('@consoleWarn').should('not.be.called')
})

describe('path and fragment', () => {
const testCases = [
{ docPath: 'path/to/example', fragment: 'anchor' },
{ docPath: 'path/to/example', fragment: undefined },
{ docPath: undefined, fragment: 'anchor' },
{ docPath: undefined, fragment: undefined },
]

testCases.forEach(({ docPath: testDocPath, fragment: testFragment }) => {
it(`should warn correctly with docPath: "${testDocPath}" and fragment: "${testFragment}"`, () => {
assertion = CORRECT_CONDITION
docPath = testDocPath
fragment = testFragment

const expectedWarning = composeWarning(COMPONENT_NAME, notice, testDocPath, testFragment)

cy.mount(TestComponent)
cy.get('@consoleWarn').should('be.calledWith', expectedWarning)
})
})
})
})
30 changes: 30 additions & 0 deletions src/composables/useDeprecated.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { getCurrentInstance, watch } from 'vue'

import type { WatchSource } from 'vue'

export interface UseDeprecatedProps {
notice: string
docPath?: string
fragment?: string
}

export const composeWarning = (componentName: string, notice: string, docPath: string = 'guide/migrating-to-version-9.html', fragment = '') =>
`${componentName}: ${notice}. See the migration guide for more details: https://kongponents.konghq.com/${docPath}${fragment ? `#${fragment}` : ''}`

export const useDeprecated = (condition: WatchSource<boolean>, {
notice,
docPath,
fragment,
}: UseDeprecatedProps) => {
const instance = getCurrentInstance()

if (!instance) {
throw new Error('useDeprecated can only be invoked inside setups')
}

watch(condition, (exists) => {
if (exists) {
console.warn(composeWarning(instance.type.name!, notice, docPath, fragment))
}
}, { immediate: true })
}