Merge pull request #7239 from Liu8Can/fix/register-promo-code-flicker

fix: prevent promo code field flash on registration
This commit is contained in:
Wesley Liddick
2026-09-17 16:41:35 +08:00
committed by GitHub
2 changed files with 51 additions and 8 deletions
+7 -1
View File
@@ -422,7 +422,13 @@ const confirmPassword = ref('')
// Public settings
const registrationEnabled = ref<boolean>(true)
const emailVerifyEnabled = ref<boolean>(false)
const promoCodeEnabled = ref<boolean>(true)
// Public settings are injected into the app store before Vue mounts. Use that
// value for the first render so a disabled promo-code field never flashes
// while the async settings request is still in flight. If injection is
// unavailable, fail closed until the request explicitly enables the field.
const promoCodeEnabled = ref<boolean>(
appStore.cachedPublicSettings?.promo_code_enabled === true
)
const invitationCodeEnabled = ref<boolean>(false)
const affiliateEnabled = ref<boolean>(false)
const turnstileEnabled = ref<boolean>(false)
@@ -2,12 +2,25 @@ import { flushPromises, mount } from '@vue/test-utils'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import RegisterView from '@/views/auth/RegisterView.vue'
const { getPublicSettingsMock, registerMock, showErrorMock, pushMock, verifyActionMock } = vi.hoisted(() => ({
const {
getPublicSettingsMock,
registerMock,
showErrorMock,
pushMock,
verifyActionMock,
appStoreMock
} = vi.hoisted(() => ({
getPublicSettingsMock: vi.fn(),
registerMock: vi.fn(),
showErrorMock: vi.fn(),
pushMock: vi.fn(),
verifyActionMock: vi.fn()
verifyActionMock: vi.fn(),
appStoreMock: {
cachedPublicSettings: null as { promo_code_enabled?: boolean } | null,
showError: (...args: unknown[]) => showErrorMock(...args),
showSuccess: vi.fn(),
showWarning: vi.fn()
}
}))
const publicSettings = {
@@ -49,11 +62,7 @@ vi.mock('vue-i18n', () => ({
vi.mock('@/stores', () => ({
useAuthStore: () => ({ register: (...args: unknown[]) => registerMock(...args) }),
useAppStore: () => ({
showError: (...args: unknown[]) => showErrorMock(...args),
showSuccess: vi.fn(),
showWarning: vi.fn()
})
useAppStore: () => appStoreMock
}))
vi.mock('@/api/auth', async () => {
@@ -93,12 +102,40 @@ describe('RegisterView', () => {
showErrorMock.mockReset()
pushMock.mockReset()
verifyActionMock.mockReset()
appStoreMock.cachedPublicSettings = null
sessionStorage.removeItem('register_data')
verifyActionMock.mockResolvedValue({ token: 'ticket', randstr: 'randstr' })
getPublicSettingsMock.mockResolvedValue(publicSettings)
registerMock.mockResolvedValue({})
})
it('does not flash the promo-code field before disabled settings finish loading', async () => {
let resolveSettings!: (settings: typeof publicSettings) => void
getPublicSettingsMock.mockReturnValueOnce(
new Promise<typeof publicSettings>((resolve) => {
resolveSettings = resolve
})
)
const wrapper = mountRegister()
expect(wrapper.find('#promo_code').exists()).toBe(false)
resolveSettings(publicSettings)
await flushPromises()
expect(wrapper.find('#promo_code').exists()).toBe(false)
})
it('uses injected public settings to show an enabled promo-code field on first render', () => {
appStoreMock.cachedPublicSettings = { promo_code_enabled: true }
getPublicSettingsMock.mockReturnValueOnce(new Promise(() => {}))
const wrapper = mountRegister()
expect(wrapper.find('#promo_code').exists()).toBe(true)
})
it.each([
['', 'auth.confirmPasswordRequired'],
['different-password', 'auth.passwordsDoNotMatch']