Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: clear words in RestoreKey #1515

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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
Loading