mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-05-03 12:42:01 +00:00
chore: migrate tests from tests-ui/ to colocate with source files (#7811)
## Summary Migrates all unit tests from `tests-ui/` to colocate with their source files in `src/`, improving discoverability and maintainability. ## Changes - **What**: Relocated all unit tests to be adjacent to the code they test, following the `<source>.test.ts` naming convention - **Config**: Updated `vitest.config.ts` to remove `tests-ui` include pattern and `@tests-ui` alias - **Docs**: Moved testing documentation to `docs/testing/` with updated paths and patterns ## Review Focus - Migration patterns documented in `temp/plans/migrate-tests-ui-to-src.md` - Tests use `@/` path aliases instead of relative imports - Shared fixtures placed in `__fixtures__/` directories ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-7811-chore-migrate-tests-from-tests-ui-to-colocate-with-source-files-2da6d73d36508147a4cce85365dee614) by [Unito](https://www.unito.io) --------- Co-authored-by: Amp <amp@ampcode.com> Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
@@ -1,177 +0,0 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { computed, effectScope, ref } from 'vue'
|
||||
import type { EffectScope } from 'vue'
|
||||
|
||||
import type { CloudSubscriptionStatusResponse } from '@/platform/cloud/subscription/composables/useSubscription'
|
||||
import { useSubscriptionCancellationWatcher } from '@/platform/cloud/subscription/composables/useSubscriptionCancellationWatcher'
|
||||
|
||||
describe('useSubscriptionCancellationWatcher', () => {
|
||||
const trackMonthlySubscriptionCancelled = vi.fn()
|
||||
const telemetryMock: Pick<
|
||||
import('@/platform/telemetry/types').TelemetryProvider,
|
||||
'trackMonthlySubscriptionCancelled'
|
||||
> = {
|
||||
trackMonthlySubscriptionCancelled
|
||||
}
|
||||
|
||||
const baseStatus: CloudSubscriptionStatusResponse = {
|
||||
is_active: true,
|
||||
subscription_id: 'sub_123',
|
||||
renewal_date: '2025-11-16'
|
||||
}
|
||||
|
||||
const subscriptionStatus = ref<CloudSubscriptionStatusResponse | null>(
|
||||
baseStatus
|
||||
)
|
||||
const isActive = ref(true)
|
||||
const isActiveSubscription = computed(() => isActive.value)
|
||||
|
||||
let shouldWatch = true
|
||||
const shouldWatchCancellation = () => shouldWatch
|
||||
|
||||
const activeScopes: EffectScope[] = []
|
||||
|
||||
const initWatcher = (
|
||||
options: Parameters<typeof useSubscriptionCancellationWatcher>[0]
|
||||
): ReturnType<typeof useSubscriptionCancellationWatcher> => {
|
||||
const scope = effectScope()
|
||||
let result: ReturnType<typeof useSubscriptionCancellationWatcher> | null =
|
||||
null
|
||||
scope.run(() => {
|
||||
result = useSubscriptionCancellationWatcher(options)
|
||||
})
|
||||
if (!result) {
|
||||
throw new Error('Failed to initialize cancellation watcher')
|
||||
}
|
||||
activeScopes.push(scope)
|
||||
return result
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers()
|
||||
trackMonthlySubscriptionCancelled.mockReset()
|
||||
subscriptionStatus.value = { ...baseStatus }
|
||||
isActive.value = true
|
||||
shouldWatch = true
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
activeScopes.forEach((scope) => scope.stop())
|
||||
activeScopes.length = 0
|
||||
vi.useRealTimers()
|
||||
})
|
||||
|
||||
it('polls with exponential backoff and fires telemetry once cancellation detected', async () => {
|
||||
const fetchStatus = vi.fn(async () => {
|
||||
if (fetchStatus.mock.calls.length === 2) {
|
||||
isActive.value = false
|
||||
subscriptionStatus.value = {
|
||||
is_active: false,
|
||||
subscription_id: 'sub_cancelled',
|
||||
renewal_date: '2025-11-16',
|
||||
end_date: '2025-12-01'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const { startCancellationWatcher } = initWatcher({
|
||||
fetchStatus,
|
||||
isActiveSubscription,
|
||||
subscriptionStatus,
|
||||
telemetry: telemetryMock,
|
||||
shouldWatchCancellation
|
||||
})
|
||||
|
||||
startCancellationWatcher()
|
||||
|
||||
await vi.advanceTimersByTimeAsync(5000)
|
||||
expect(fetchStatus).toHaveBeenCalledTimes(1)
|
||||
|
||||
await vi.advanceTimersByTimeAsync(15000)
|
||||
expect(fetchStatus).toHaveBeenCalledTimes(2)
|
||||
expect(
|
||||
telemetryMock.trackMonthlySubscriptionCancelled
|
||||
).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
it('triggers a check immediately when window regains focus', async () => {
|
||||
const fetchStatus = vi.fn(async () => {
|
||||
isActive.value = false
|
||||
subscriptionStatus.value = {
|
||||
...baseStatus,
|
||||
is_active: false,
|
||||
end_date: '2025-12-01'
|
||||
}
|
||||
})
|
||||
|
||||
const { startCancellationWatcher } = initWatcher({
|
||||
fetchStatus,
|
||||
isActiveSubscription,
|
||||
subscriptionStatus,
|
||||
telemetry: telemetryMock,
|
||||
shouldWatchCancellation
|
||||
})
|
||||
|
||||
startCancellationWatcher()
|
||||
|
||||
window.dispatchEvent(new Event('focus'))
|
||||
await Promise.resolve()
|
||||
|
||||
expect(fetchStatus).toHaveBeenCalledTimes(1)
|
||||
expect(
|
||||
telemetryMock.trackMonthlySubscriptionCancelled
|
||||
).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
it('stops after max attempts when subscription stays active', async () => {
|
||||
const fetchStatus = vi.fn(async () => {})
|
||||
|
||||
const { startCancellationWatcher } = initWatcher({
|
||||
fetchStatus,
|
||||
isActiveSubscription,
|
||||
subscriptionStatus,
|
||||
telemetry: telemetryMock,
|
||||
shouldWatchCancellation
|
||||
})
|
||||
|
||||
startCancellationWatcher()
|
||||
|
||||
const delays = [5000, 15000, 45000, 135000]
|
||||
for (const delay of delays) {
|
||||
await vi.advanceTimersByTimeAsync(delay)
|
||||
}
|
||||
|
||||
expect(fetchStatus).toHaveBeenCalledTimes(4)
|
||||
expect(trackMonthlySubscriptionCancelled).not.toHaveBeenCalled()
|
||||
|
||||
await vi.advanceTimersByTimeAsync(200000)
|
||||
expect(fetchStatus).toHaveBeenCalledTimes(4)
|
||||
})
|
||||
|
||||
it('does not start watcher when guard fails or subscription inactive', async () => {
|
||||
const fetchStatus = vi.fn()
|
||||
|
||||
const { startCancellationWatcher } = initWatcher({
|
||||
fetchStatus,
|
||||
isActiveSubscription,
|
||||
subscriptionStatus,
|
||||
telemetry: telemetryMock,
|
||||
shouldWatchCancellation
|
||||
})
|
||||
|
||||
shouldWatch = false
|
||||
startCancellationWatcher()
|
||||
await vi.advanceTimersByTimeAsync(60000)
|
||||
expect(fetchStatus).not.toHaveBeenCalled()
|
||||
|
||||
shouldWatch = true
|
||||
isActive.value = false
|
||||
subscriptionStatus.value = {
|
||||
...baseStatus,
|
||||
is_active: false
|
||||
}
|
||||
startCancellationWatcher()
|
||||
await vi.advanceTimersByTimeAsync(60000)
|
||||
expect(fetchStatus).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user