diff --git a/web/__test__/components/Registration.test.ts b/web/__test__/components/Registration.test.ts
index 5196d0c872..dce6329d51 100644
--- a/web/__test__/components/Registration.test.ts
+++ b/web/__test__/components/Registration.test.ts
@@ -88,7 +88,11 @@ vi.mock('@unraid/ui', async (importOriginal) => {
return {
...actual,
- BrandButton: { template: '', props: ['text', 'title', 'icon', 'disabled'] },
+ BrandButton: {
+ template:
+ '',
+ props: ['text', 'title', 'icon', 'disabled'],
+ },
CardWrapper: { template: '
' },
PageContainer: { template: '
' },
SettingsGrid: { template: '
' },
@@ -321,6 +325,8 @@ describe('Registration.standalone.vue', () => {
const moveButton = wrapper.find('[data-testid="move-license-to-tpm"]');
expect(moveButton.exists()).toBe(true);
+ expect(moveButton.attributes('disabled')).toBeUndefined();
+ expect(findItemByLabel(t('TPM GUID'))?.props('text')).toBe('03-V35H8S0L1QHK1SBG1XHXJNH7');
});
it('shows Move License to TPM when flashGuid is missing but the active GUID is still a flash GUID', async () => {
@@ -349,7 +355,7 @@ describe('Registration.standalone.vue', () => {
expect(accountStore.replaceTpm).toHaveBeenCalled();
});
- it('does not show Move License to TPM for trial states', async () => {
+ it('shows a disabled Move License to TPM button for trial states', async () => {
serverStore.state = 'TRIAL';
serverStore.guid = '058F-6387-0000-0000F1F1E1C6';
serverStore.flashGuid = '058F-6387-0000-0000F1F1E1C6';
@@ -358,7 +364,43 @@ describe('Registration.standalone.vue', () => {
await wrapper.vm.$nextTick();
- expect(wrapper.find('[data-testid="move-license-to-tpm"]').exists()).toBe(false);
+ const moveButton = wrapper.find('[data-testid="move-license-to-tpm"]');
+
+ expect(moveButton.exists()).toBe(true);
+ expect(moveButton.attributes('disabled')).toBeDefined();
+ expect(findItemByLabel(t('TPM GUID'))?.props('text')).toBe('03-V35H8S0L1QHK1SBG1XHXJNH7');
+ expect(wrapper.text()).toContain(
+ 'Trials are locked to the registered GUID. You can move to TPM by purchasing a license.'
+ );
+ });
+
+ it('shows a disabled Move License to TPM button for expired trial states', async () => {
+ serverStore.state = 'EEXPIRED';
+ serverStore.guid = '058F-6387-0000-0000F1F1E1C6';
+ serverStore.flashGuid = '058F-6387-0000-0000F1F1E1C6';
+ serverStore.tpmGuid = '03-V35H8S0L1QHK1SBG1XHXJNH7';
+ serverStore.keyfile = 'keyfile-present';
+
+ await wrapper.vm.$nextTick();
+
+ const moveButton = wrapper.find('[data-testid="move-license-to-tpm"]');
+
+ expect(moveButton.exists()).toBe(true);
+ expect(moveButton.attributes('disabled')).toBeDefined();
+ });
+
+ it('does not trigger the TPM replacement action when the trial TPM button is clicked', async () => {
+ serverStore.state = 'TRIAL';
+ serverStore.guid = '058F-6387-0000-0000F1F1E1C6';
+ serverStore.flashGuid = '058F-6387-0000-0000F1F1E1C6';
+ serverStore.tpmGuid = '03-V35H8S0L1QHK1SBG1XHXJNH7';
+ serverStore.keyfile = 'keyfile-present';
+
+ await wrapper.vm.$nextTick();
+
+ await wrapper.find('[data-testid="move-license-to-tpm"]').trigger('click');
+
+ expect(accountStore.replaceTpm).not.toHaveBeenCalled();
});
it('does not show Move License to TPM after switching to TPM boot', async () => {
diff --git a/web/src/components/Registration.standalone.vue b/web/src/components/Registration.standalone.vue
index b5de772cc6..2796fc95e6 100644
--- a/web/src/components/Registration.standalone.vue
+++ b/web/src/components/Registration.standalone.vue
@@ -134,10 +134,9 @@ const showPartnerActivationCode = computed(() => {
(currentState === 'ENOKEYFILE' || currentState === 'TRIAL' || currentState === 'EEXPIRED')
);
});
-const showTpmTransferInfo = computed((): boolean =>
+const showTpmTransferButton = computed((): boolean =>
Boolean(
- keyInstalled.value &&
- !showTrialExpiration.value &&
+ (keyInstalled.value || showTrialExpiration.value) &&
bootDeviceType.value === 'flash' &&
// The active GUID tells us whether we're still booted from flash, even if
// flashGuid is missing or has already fallen back to the TPM value.
@@ -146,6 +145,7 @@ const showTpmTransferInfo = computed((): boolean =>
guid.value !== tpmGuid.value
)
);
+const disableTpmTransferButton = computed((): boolean => showTrialExpiration.value);
// Organize items into three sections
const bootDeviceItems = computed((): RegistrationItemProps[] => {
@@ -158,6 +158,14 @@ const bootDeviceItems = computed((): RegistrationItemProps[] => {
},
]
: []),
+ ...(showTpmTransferButton.value && tpmGuid.value
+ ? [
+ {
+ label: t('registration.tpmGuid'),
+ text: tpmGuid.value,
+ },
+ ]
+ : []),
...(bootDeviceType.value
? [
{
@@ -390,12 +398,19 @@ const actionItems = computed((): RegistrationItemProps[] => {
>
{{ t('registration.actions') }}
+
+ {{ t('registration.moveLicenseToTpmTrialDisabled') }}
+