diff --git a/src/components/KButton/KButton.vue b/src/components/KButton/KButton.vue index da593238ec..992dd04019 100644 --- a/src/components/KButton/KButton.vue +++ b/src/components/KButton/KButton.vue @@ -17,8 +17,9 @@ diff --git a/src/composables/useDeprecated.cy.ts b/src/composables/useDeprecated.cy.ts new file mode 100644 index 0000000000..a154b86038 --- /dev/null +++ b/src/composables/useDeprecated.cy.ts @@ -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: '
', + }) + + 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) + }) + }) + }) +}) diff --git a/src/composables/useDeprecated.ts b/src/composables/useDeprecated.ts new file mode 100644 index 0000000000..3070dcf877 --- /dev/null +++ b/src/composables/useDeprecated.ts @@ -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, { + 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 }) +}