Skip to content

Commit

Permalink
fix: clear words in RestoreKey (#1515)
Browse files Browse the repository at this point in the history
Signed-off-by: Hristiyan <hristiyan.valkov@limechain.tech>
Signed-off-by: Yordan Iliev <yordan.iliev@limechain.tech>
Co-authored-by: Yordan Iliev <yordan.iliev@limechain.tech>
  • Loading branch information
icoxxx and yiliev0 authored Feb 11, 2025
1 parent 4802b91 commit a5dcdd6
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 27 deletions.
24 changes: 20 additions & 4 deletions automation/pages/RegistrationPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,26 @@ class RegistrationPage extends BasePage {
return this.inputRecoveryWordBase + index;
}

async clearLastRecoveryPhraseWord() {
const lastWordIndex = 24;
const selector = this.getRecoveryWordSelector(lastWordIndex);
await this.click(selector);
for (let i = 0; i < this.recoveryPhraseWords[lastWordIndex].length; i++) {
await this.window.keyboard.press('Backspace');
}
await this.window.keyboard.press('Backspace');
}

async isFinalNextButtonVisible() {
return await this.isElementVisible(this.finalNextButtonSelector);
}

async fillLastRecoveryPhraseWord() {
const lastWordIndex = 24;
const selector = this.getRecoveryWordSelector(lastWordIndex);
await this.fill(selector, this.recoveryPhraseWords[lastWordIndex]);
}

// Method to capture all the recovery phrase words and their indexes
async captureRecoveryPhraseWords() {
this.recoveryPhraseWords = {}; // Reset the recoveryPhraseWords object
Expand Down Expand Up @@ -418,10 +438,6 @@ class RegistrationPage extends BasePage {
async getPublicKey() {
return await this.getText(this.publicKeySpanSelector);
}

async getPrivateKey() {
return await this.getText(this.privateKeySpanSelector);
}
}

module.exports = RegistrationPage;
30 changes: 30 additions & 0 deletions automation/tests/registrationTests.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,36 @@ test.describe('Registration tests', () => {
expect(isMnemonicCleared).toBe(true);
});

test('Verify words are persisted after deleting a single word', async () => {
globalCredentials.email = generateRandomEmail();
globalCredentials.password = generateRandomPassword();

await registrationPage.register(
globalCredentials.email,
globalCredentials.password,
globalCredentials.password,
);

const isTabVisible = await registrationPage.isCreateNewTabVisible();
expect(isTabVisible).toBe(true);

await registrationPage.clickOnCreateNewTab();

await registrationPage.clickOnUnderstandCheckbox();
await registrationPage.clickOnGenerateButton();
await registrationPage.captureRecoveryPhraseWords();

await registrationPage.clickOnImportTab();

await registrationPage.fillAllMissingRecoveryPhraseWords();

await registrationPage.clearLastRecoveryPhraseWord();
await registrationPage.fillLastRecoveryPhraseWord();
await registrationPage.clickOnNextImportButton();

expect(await registrationPage.isFinalNextButtonVisible()).toBe(true);
});

test('Verify final step of account setup has all correct elements', async () => {
globalCredentials.email = generateRandomEmail();
globalCredentials.password = generateRandomPassword();
Expand Down
24 changes: 15 additions & 9 deletions front-end/src/renderer/components/RecoveryPhrase/Import.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
<script setup lang="ts">
import { onBeforeMount, ref, watch } from 'vue';
import { onBeforeMount, ref, watch, watchEffect } from 'vue';
import useUserStore from '@renderer/stores/storeUser';
import { validateMnemonic } from '@renderer/services/keyPairService';
import AppRecoveryPhraseWord from '@renderer/components/ui/AppRecoveryPhraseWord.vue';
/* Props */
const props = defineProps<{
shouldClear?: boolean;
}>();
/* Emits */
const emit = defineEmits(['reset-cleared']);
/* Constants */
const WORD_COUNT = 24;
const getDefaultWords = () => Array(WORD_COUNT).fill('');
Expand Down Expand Up @@ -92,14 +100,12 @@ watch(words, async newWords => {
}
});
watch(
() => user.recoveryPhrase,
async newRecoveryPhrase => {
if (!newRecoveryPhrase) {
handleClearWords();
}
},
);
watchEffect(() => {
if (props.shouldClear) {
handleClearWords();
emit('reset-cleared', false);
}
});
</script>
<template>
<div>
Expand Down
19 changes: 16 additions & 3 deletions front-end/src/renderer/components/modals/RecoveryPhraseModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import useUserStore from '@renderer/stores/storeUser';
import AppButton from '@renderer/components/ui/AppButton.vue';
import AppModal from '@renderer/components/ui/AppModal.vue';
import Import from '@renderer/components/RecoveryPhrase/Import.vue';
import { ref } from 'vue';
/* Props */
defineProps<{
Expand All @@ -19,6 +20,9 @@ const emit = defineEmits<{
/* Stores */
const user = useUserStore();
/* State */
const shouldClearInputs = ref(false);
/* Handlers */
const handleSubmit = () => {
if (!user.recoveryPhrase) throw new Error('Recovery phrase is required');
Expand All @@ -37,7 +41,8 @@ const handleClose = (show: boolean) => {
};
/* Handlers */
const handleClearWords = () => {
const handleClearWords = (value: boolean) => {
shouldClearInputs.value = value;
user.setRecoveryPhrase(null);
};
</script>
Expand All @@ -63,12 +68,20 @@ const handleClearWords = () => {

<p class="text-center">You may skip this step and all keys will be marked as external</p>

<Import class="mt-4" />
<Import
:should-clear="shouldClearInputs"
@reset-cleared="handleClearWords($event)"
class="mt-4"
/>

<hr class="separator my-5" />

<div class="flex-between-centered gap-4 overflow-hidden">
<AppButton color="borderless" type="button" class="min-w-unset" @click="handleClearWords"
<AppButton
color="borderless"
type="button"
class="min-w-unset"
@click="handleClearWords(true)"
>Clear</AppButton
>
<div class="flex-between-centered gap-4">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,16 @@ const tabItems = ref<TabItem[]>([
]);
const activeTabIndex = ref(1);
const mnemonicHashNickname = ref('');
const shouldClearInputs = ref(false);
/* Getters */
const activeTabTitle = computed(() => tabItems.value[activeTabIndex.value].title);
/* Handlers */
const handleClearWords = () => (user.recoveryPhrase = null);
const handleClearWords = (value: boolean) => {
shouldClearInputs.value = value;
user.setRecoveryPhrase(null);
};
const handleImport = async () => {
if (user.recoveryPhrase === null) return;
Expand Down Expand Up @@ -92,7 +96,7 @@ watch(activeTabTitle, newTitle => {
<Generate :handle-next="handleNext" />
</template>
<template v-else-if="activeTabTitle === importExistingTitle">
<Import />
<Import :should-clear="shouldClearInputs" @reset-cleared="handleClearWords($event)" />

<div class="form-group mt-4">
<label class="form-label">Enter Recovery Phrase Nickname</label>
Expand All @@ -105,7 +109,7 @@ watch(activeTabTitle, newTitle => {
</div>

<div class="flex-between-centered mt-6">
<AppButton data-testid="button-clear" color="borderless" @click="handleClearWords"
<AppButton data-testid="button-clear" color="borderless" @click="handleClearWords(true)"
>Clear</AppButton
>
<AppButton
Expand Down
4 changes: 3 additions & 1 deletion front-end/src/renderer/pages/RestoreKey/RestoreKey.vue
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ const handleMnemonicHashNickname = (nickname: string) => {
const handleNextStep = () => step.value++;
const handleClearWords = () => (user.recoveryPhrase = null);
const handleClearWords = () => {
user.setRecoveryPhrase(null);
};
/* Hooks */
onBeforeUnmount(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,23 @@ const emit = defineEmits<{
/* State */
const mnemonicHashNickname = ref('');
const shouldClearInputs = ref(false);
/* Handlers */
const handleImportRecoveryPhrase = () => {
emit('next', mnemonicHashNickname.value);
};
const handleClearWords = () => {
const handleClearWords = (value: boolean) => {
shouldClearInputs.value = value;
emit('clear');
};
</script>

<template>
<form @submit.prevent="handleImportRecoveryPhrase" class="fill-remaining">
<h1 class="text-display text-bold text-center">Enter your Recovery Phrase</h1>
<div class="mt-8">
<Import />
<Import :should-clear="shouldClearInputs" @reset-cleared="handleClearWords($event)" />
<div class="form-group mt-4">
<label class="form-label">Enter Recovery Phrase Nickname</label>
<RecoveryPhraseNicknameInput
Expand All @@ -44,7 +45,9 @@ const handleClearWords = () => {
</div>
<div class="row justify-content-between mt-6">
<div class="col-4 d-grid">
<AppButton type="button" color="secondary" @click="handleClearWords">Clear</AppButton>
<AppButton type="button" color="secondary" @click="handleClearWords(true)"
>Clear</AppButton
>
</div>
<div class="col-4 d-grid">
<AppButton
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const { getPassword, passwordModalOpened } = usePersonalPassword();
/* State */
const step = ref(0);
const loadingText = ref<string | null>(null);
const shouldClearInputs = ref(false);
/* Handlers */
const handleImportRecoveryPhrase = async () => {
Expand Down Expand Up @@ -59,7 +60,10 @@ const handleImportRecoveryPhrase = async () => {
}
};
const handleClearWords = () => (user.recoveryPhrase = null);
const handleClearWords = (value: boolean) => {
shouldClearInputs.value = value;
user.setRecoveryPhrase(null);
};
const storeKeys = async (
keys: {
Expand Down Expand Up @@ -163,10 +167,10 @@ onMounted(() => {
>
<h1 class="text-display text-bold text-center">Enter your Recovery Phrase</h1>
<div class="mt-8">
<Import />
<Import :should-clear="shouldClearInputs" @reset-cleared="handleClearWords($event)" />
<div class="row justify-content-between mt-6">
<div class="col-4 d-grid">
<AppButton type="button" color="secondary" @click="handleClearWords"
<AppButton type="button" color="secondary" @click="handleClearWords(true)"
>Clear</AppButton
>
</div>
Expand Down

0 comments on commit a5dcdd6

Please sign in to comment.