import React from 'react';
import { waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import enLocale from '../../../../app/_locales/en/messages.json';
import { renderWithLocalization } from '../../../../test/lib/render-helpers';
import SrpInput from '.';
const tooFewWords = new Array(11).fill('test').join(' ');
const tooManyWords = new Array(25).fill('test').join(' ');
const invalidWordCount = new Array(13).fill('test').join(' ');
const invalidChecksum = new Array(12).fill('test').join(' ');
const invalidWordCorrectChecksum = `aardvark ${new Array(10)
.fill('test')
.join(' ')} wolf`;
const correct = `${new Array(11).fill('test').join(' ')} ball`;
const invalidInputs = [
tooFewWords,
invalidWordCount,
invalidChecksum,
invalidWordCorrectChecksum,
];
const poorlyFormattedInputs = [
` ${correct}`,
`\t${correct}`,
`\n${correct}`,
`${correct} `,
`${correct}\t`,
`${correct}\n`,
`${new Array(11).fill('test').join(' ')} ball`,
`${new Array(11).fill('test').join('\t')}\tball`,
];
const whitespaceCharacters = [' ', ' ', '\n', '\t'];
describe('srp-input', () => {
beforeEach(() => {
jest.resetAllMocks();
});
describe('onChange event', () => {
it('should not fire event on render', async () => {
const onChange = jest.fn();
const { getByText } = renderWithLocalization(
,
);
await waitFor(() => getByText(enLocale.secretRecoveryPhrase.message));
expect(onChange).not.toHaveBeenCalled();
});
describe('invalid typed inputs', () => {
it('should fire event with empty string when only first field is filled out', async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
getByTestId('import-srp__srp-word-0').focus();
await userEvent.keyboard('test');
expect(onChange).toHaveBeenLastCalledWith('');
});
it('should fire event with empty string when one field is empty', async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
for (const index of new Array(11).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.keyboard('test');
}
expect(onChange).toHaveBeenLastCalledWith('');
});
it('should fire event with empty string when one field has two words', async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
for (const index of new Array(11).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.keyboard(index === 0 ? 'test test' : 'test');
}
getByTestId(`import-srp__srp-word-11`).focus();
await userEvent.keyboard('ball');
expect(onChange).toHaveBeenLastCalledWith('');
});
it('should fire event with empty string when one field has two words and one is empty', async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
for (const index of new Array(10).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.keyboard(index === 0 ? 'test test' : 'test');
}
getByTestId(`import-srp__srp-word-11`).focus();
await userEvent.keyboard('ball');
expect(onChange).toHaveBeenLastCalledWith('');
});
it('should fire event with empty string if SRP has invalid checksum', async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
const srpParts = invalidChecksum.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.keyboard(srpParts[index]);
}
expect(onChange).toHaveBeenLastCalledWith('');
});
it('should fire event with empty string if SRP has invalid word', async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
const srpParts = invalidWordCorrectChecksum.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.keyboard(srpParts[index]);
}
expect(onChange).toHaveBeenLastCalledWith('');
});
it('should fire event with empty string if SRP was valid, then a word was removed', async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
const srpParts = correct.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.keyboard(srpParts[index]);
}
await userEvent.clear(getByTestId('import-srp__srp-word-0'));
expect(onChange).toHaveBeenLastCalledWith('');
});
it('should fire event with empty string if SRP was valid, then was changed to invalidate the checksum', async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
const srpParts = correct.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.keyboard(srpParts[index]);
}
await userEvent.clear(getByTestId('import-srp__srp-word-0'));
getByTestId(`import-srp__srp-word-0`).focus();
await userEvent.keyboard('ball');
expect(onChange).toHaveBeenLastCalledWith('');
});
it('should fire event with empty string if valid SRP is pasted, then replaced with an SRP with an invalid word', async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
getByTestId('import-srp__srp-word-0').focus();
await userEvent.paste(correct);
const srpParts = invalidWordCorrectChecksum.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.keyboard(srpParts[index]);
}
expect(onChange).toHaveBeenLastCalledWith('');
});
});
describe('invalid individually pasted inputs', () => {
it('should fire event with empty string when only first field is filled out', async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
getByTestId('import-srp__srp-word-0').focus();
await userEvent.paste('test');
expect(onChange).toHaveBeenLastCalledWith('');
});
it('should fire event with empty string when one field is empty', async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
for (const index of new Array(11).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.paste('test');
}
expect(onChange).toHaveBeenLastCalledWith('');
});
it('should fire event with empty string if SRP has invalid checksum', async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
const srpParts = invalidChecksum.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.paste(srpParts[index]);
}
expect(onChange).toHaveBeenLastCalledWith('');
});
it('should fire event with empty string if SRP has invalid word', async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
const srpParts = invalidWordCorrectChecksum.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.paste(srpParts[index]);
}
expect(onChange).toHaveBeenLastCalledWith('');
});
it('should fire event with empty string if SRP was valid, then a word was removed', async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
const srpParts = correct.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.paste(srpParts[index]);
}
await userEvent.clear(getByTestId('import-srp__srp-word-0'));
expect(onChange).toHaveBeenLastCalledWith('');
});
it('should fire event with empty string if SRP was valid, then was changed to invalidate the checksum', async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
const srpParts = correct.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.keyboard(srpParts[index]);
}
await userEvent.clear(getByTestId('import-srp__srp-word-0'));
getByTestId('import-srp__srp-word-0').focus();
await userEvent.paste('ball');
expect(onChange).toHaveBeenLastCalledWith('');
});
it('should fire event with empty string if valid SRP is pasted, then replaced with an SRP with an invalid word', async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
getByTestId('import-srp__srp-word-0').focus();
await userEvent.paste(correct);
const srpParts = invalidWordCorrectChecksum.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.paste(srpParts[index]);
}
expect(onChange).toHaveBeenLastCalledWith('');
});
});
describe('invalid pasted inputs', () => {
it(`should fire event with empty string upon invalid pasted input: 'test'`, async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
getByTestId('import-srp__srp-word-0').focus();
await userEvent.paste('test');
expect(onChange).toHaveBeenLastCalledWith('');
});
it(`should not fire any event when pasted contents includes >24 words`, async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
getByTestId('import-srp__srp-word-0').focus();
await userEvent.paste(tooManyWords);
expect(onChange).not.toHaveBeenCalled();
});
for (const invalidInput of invalidInputs) {
it(`should fire event with empty string upon invalid pasted input: '${invalidInput}'`, async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
getByTestId('import-srp__srp-word-0').focus();
await userEvent.paste(invalidInput);
expect(onChange).toHaveBeenLastCalledWith('');
});
it(`should fire event with empty string upon invalid input pasted into second field: '${invalidInput}'`, async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
getByTestId('import-srp__srp-word-1').focus();
await userEvent.paste(invalidInput);
expect(onChange).toHaveBeenLastCalledWith('');
});
it(`should fire event with empty string after replacing valid SRP with: '${invalidInput}'`, async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
getByTestId('import-srp__srp-word-1').focus();
await userEvent.paste(correct);
await userEvent.paste(invalidInput);
expect(onChange).toHaveBeenLastCalledWith('');
});
}
it('should fire with empty string when full valid SRP is replaced by prefix', async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
getByTestId('import-srp__srp-word-1').focus();
await userEvent.paste(correct);
await userEvent.paste('test test');
expect(onChange).toHaveBeenLastCalledWith('');
});
});
describe('valid typed inputs', () => {
it('should fire event with a valid SRP', async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
const srpParts = correct.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.keyboard(srpParts[index]);
}
expect(onChange).toHaveBeenLastCalledWith(correct);
});
for (const whitespaceCharacter of whitespaceCharacters) {
it(`should fire event with a valid SRP preceded by a '${whitespaceCharacter}'`, async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
const srpParts = correct.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.keyboard(
index === 0
? `${whitespaceCharacter}${srpParts[index]}`
: srpParts[index],
);
}
expect(onChange).toHaveBeenLastCalledWith(correct);
});
it(`should fire event with a valid SRP followed by a '${whitespaceCharacter}'`, async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
const srpParts = correct.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.keyboard(
index === 11
? `${srpParts[index]}${whitespaceCharacter}`
: srpParts[index],
);
}
expect(onChange).toHaveBeenLastCalledWith(correct);
});
it(`should fire event with a valid SRP where each word is followed by a'${whitespaceCharacter}'`, async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
const srpParts = correct.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.keyboard(
`${srpParts[index]}${whitespaceCharacter}`,
);
}
expect(onChange).toHaveBeenLastCalledWith(correct);
});
}
});
describe('valid individually pasted inputs', () => {
it('should fire event with a valid SRP', async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
const srpParts = correct.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.paste(srpParts[index]);
}
expect(onChange).toHaveBeenLastCalledWith(correct);
});
it('should fire event with a valid SRP when each word is pasted in two parts', async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
const srpParts = correct.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.paste(srpParts[index].slice(0, 2));
await userEvent.paste(srpParts[index].slice(2));
}
expect(onChange).toHaveBeenLastCalledWith(correct);
});
for (const whitespaceCharacter of whitespaceCharacters) {
it(`should fire event with a valid SRP preceded by a '${whitespaceCharacter}'`, async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
const srpParts = correct.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.paste(
index === 0
? `${whitespaceCharacter}${srpParts[index]}`
: srpParts[index],
);
}
expect(onChange).toHaveBeenLastCalledWith(correct);
});
it(`should fire event with a valid SRP followed by a '${whitespaceCharacter}'`, async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
const srpParts = correct.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.paste(
index === 11
? `${srpParts[index]}${whitespaceCharacter}`
: srpParts[index],
);
}
expect(onChange).toHaveBeenLastCalledWith(correct);
});
it(`should fire event with a valid SRP where each word is followed by a'${whitespaceCharacter}'`, async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
const srpParts = correct.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.paste(`${srpParts[index]}${whitespaceCharacter}`);
}
expect(onChange).toHaveBeenLastCalledWith(correct);
});
}
});
describe('valid pasted inputs', () => {
it('should fire event with a valid SRP', async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
getByTestId('import-srp__srp-word-0').focus();
await userEvent.paste(correct);
expect(onChange).toHaveBeenLastCalledWith(correct);
});
it('should fire event with a valid SRP when replacing invalid SRP', async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
getByTestId('import-srp__srp-word-0').focus();
await userEvent.paste(invalidChecksum);
await userEvent.paste(correct);
expect(onChange).toHaveBeenLastCalledWith(correct);
});
for (const poorlyFormattedInput of poorlyFormattedInputs) {
it(`should fire with formatted SRP when given poorly formatted valid SRP: '${poorlyFormattedInput}'`, async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
getByTestId('import-srp__srp-word-0').focus();
await userEvent.paste(poorlyFormattedInput);
expect(onChange).toHaveBeenLastCalledWith(correct);
});
it(`should fire with formatted SRP when poorly formatted valid SRP is pasted into second field: '${poorlyFormattedInput}'`, async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
getByTestId('import-srp__srp-word-1').focus();
await userEvent.paste(poorlyFormattedInput);
expect(onChange).toHaveBeenLastCalledWith(correct);
});
}
});
});
describe('SRP validation error', () => {
it('should not show error for empty input', async () => {
const onChange = jest.fn();
const { getByText, queryByText } = renderWithLocalization(
,
);
await waitFor(() => getByText(enLocale.secretRecoveryPhrase.message));
expect(
queryByText(enLocale.seedPhraseReq.message),
).not.toBeInTheDocument();
expect(
queryByText(enLocale.invalidSeedPhrase.message),
).not.toBeInTheDocument();
});
describe('typed', () => {
it('should show word requirement error if SRP has too few words', async () => {
const onChange = jest.fn();
const { getByTestId, queryByText } = renderWithLocalization(
,
);
const srpParts = tooFewWords.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.keyboard(srpParts[index]);
}
expect(queryByText(enLocale.seedPhraseReq.message)).toBeInTheDocument();
expect(
queryByText(enLocale.invalidSeedPhrase.message),
).not.toBeInTheDocument();
});
it('should show word requirement error if SRP has an unsupported word count above 12 but below 24', async () => {
const onChange = jest.fn();
const { getByRole, getByTestId, queryByText } = renderWithLocalization(
,
);
await userEvent.selectOptions(getByRole('combobox'), '15');
const srpParts = invalidWordCount.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.keyboard(srpParts[index]);
}
expect(queryByText(enLocale.seedPhraseReq.message)).toBeInTheDocument();
expect(
queryByText(enLocale.invalidSeedPhrase.message),
).not.toBeInTheDocument();
});
it('should show invalid SRP error if SRP is correct length but has an invalid checksum', async () => {
const onChange = jest.fn();
const { getByTestId, queryByText } = renderWithLocalization(
,
);
const srpParts = invalidChecksum.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.keyboard(srpParts[index]);
}
expect(
queryByText(enLocale.seedPhraseReq.message),
).not.toBeInTheDocument();
expect(
queryByText(enLocale.invalidSeedPhrase.message),
).toBeInTheDocument();
});
it('should show invalid SRP error if SRP is correct length and has correct checksum but has an invalid word', async () => {
const onChange = jest.fn();
const { getByTestId, queryByText } = renderWithLocalization(
,
);
const srpParts = invalidWordCorrectChecksum.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.keyboard(srpParts[index]);
}
expect(
queryByText(enLocale.seedPhraseReq.message),
).not.toBeInTheDocument();
expect(
queryByText(enLocale.invalidSeedPhrase.message),
).toBeInTheDocument();
});
it('should not show error for valid SRP', async () => {
const onChange = jest.fn();
const { getByTestId, queryByText } = renderWithLocalization(
,
);
const srpParts = correct.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.keyboard(srpParts[index]);
}
expect(
queryByText(enLocale.seedPhraseReq.message),
).not.toBeInTheDocument();
expect(
queryByText(enLocale.invalidSeedPhrase.message),
).not.toBeInTheDocument();
});
for (const whitespaceCharacter of whitespaceCharacters) {
it(`should not show error for a valid SRP preceded by a '${whitespaceCharacter}'`, async () => {
const onChange = jest.fn();
const { getByTestId, queryByText } = renderWithLocalization(
,
);
const srpParts = correct.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.keyboard(
index === 0
? `${whitespaceCharacter}${srpParts[index]}`
: srpParts[index],
);
}
expect(
queryByText(enLocale.seedPhraseReq.message),
).not.toBeInTheDocument();
expect(
queryByText(enLocale.invalidSeedPhrase.message),
).not.toBeInTheDocument();
});
it(`should not show error for a valid SRP followed by a '${whitespaceCharacter}'`, async () => {
const onChange = jest.fn();
const { getByTestId, queryByText } = renderWithLocalization(
,
);
const srpParts = correct.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.keyboard(
index === 11
? `${srpParts[index]}${whitespaceCharacter}`
: srpParts[index],
);
}
expect(
queryByText(enLocale.seedPhraseReq.message),
).not.toBeInTheDocument();
expect(
queryByText(enLocale.invalidSeedPhrase.message),
).not.toBeInTheDocument();
});
it(`should not show error for a valid SRP where each word is followed by a'${whitespaceCharacter}'`, async () => {
const onChange = jest.fn();
const { getByTestId, queryByText } = renderWithLocalization(
,
);
const srpParts = correct.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.keyboard(
`${srpParts[index]}${whitespaceCharacter}`,
);
}
expect(
queryByText(enLocale.seedPhraseReq.message),
).not.toBeInTheDocument();
expect(
queryByText(enLocale.invalidSeedPhrase.message),
).not.toBeInTheDocument();
});
}
});
describe('individually pasted', () => {
it('should show word requirement error if SRP has too few words', async () => {
const onChange = jest.fn();
const { getByTestId, queryByText } = renderWithLocalization(
,
);
const srpParts = tooFewWords.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.paste(srpParts[index]);
}
expect(queryByText(enLocale.seedPhraseReq.message)).toBeInTheDocument();
expect(
queryByText(enLocale.invalidSeedPhrase.message),
).not.toBeInTheDocument();
});
it('should show word requirement error if SRP has an unsupported word count above 12 but below 24', async () => {
const onChange = jest.fn();
const { getByTestId, getByRole, queryByText } = renderWithLocalization(
,
);
await userEvent.selectOptions(getByRole('combobox'), '15');
const srpParts = invalidWordCount.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.paste(srpParts[index]);
}
expect(queryByText(enLocale.seedPhraseReq.message)).toBeInTheDocument();
expect(
queryByText(enLocale.invalidSeedPhrase.message),
).not.toBeInTheDocument();
});
it('should show invalid SRP error if SRP is correct length but has an invalid checksum', async () => {
const onChange = jest.fn();
const { getByTestId, queryByText } = renderWithLocalization(
,
);
const srpParts = invalidChecksum.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.paste(srpParts[index]);
}
expect(
queryByText(enLocale.seedPhraseReq.message),
).not.toBeInTheDocument();
expect(
queryByText(enLocale.invalidSeedPhrase.message),
).toBeInTheDocument();
});
it('should show invalid SRP error if SRP is correct length and has correct checksum but has an invalid word', async () => {
const onChange = jest.fn();
const { getByTestId, queryByText } = renderWithLocalization(
,
);
const srpParts = invalidWordCorrectChecksum.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.paste(srpParts[index]);
}
expect(
queryByText(enLocale.seedPhraseReq.message),
).not.toBeInTheDocument();
expect(
queryByText(enLocale.invalidSeedPhrase.message),
).toBeInTheDocument();
});
it('should not show error for valid SRP', async () => {
const onChange = jest.fn();
const { getByTestId, queryByText } = renderWithLocalization(
,
);
const srpParts = correct.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.paste(srpParts[index]);
}
expect(
queryByText(enLocale.seedPhraseReq.message),
).not.toBeInTheDocument();
expect(
queryByText(enLocale.invalidSeedPhrase.message),
).not.toBeInTheDocument();
});
for (const whitespaceCharacter of whitespaceCharacters) {
it(`should not show error for a valid SRP preceded by a '${whitespaceCharacter}'`, async () => {
const onChange = jest.fn();
const { getByTestId, queryByText } = renderWithLocalization(
,
);
const srpParts = correct.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.paste(
index === 0
? `${whitespaceCharacter}${srpParts[index]}`
: srpParts[index],
);
}
expect(
queryByText(enLocale.seedPhraseReq.message),
).not.toBeInTheDocument();
expect(
queryByText(enLocale.invalidSeedPhrase.message),
).not.toBeInTheDocument();
});
it(`should not show error for a valid SRP followed by a '${whitespaceCharacter}'`, async () => {
const onChange = jest.fn();
const { getByTestId, queryByText } = renderWithLocalization(
,
);
const srpParts = correct.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.paste(
index === 11
? `${srpParts[index]}${whitespaceCharacter}`
: srpParts[index],
);
}
expect(
queryByText(enLocale.seedPhraseReq.message),
).not.toBeInTheDocument();
expect(
queryByText(enLocale.invalidSeedPhrase.message),
).not.toBeInTheDocument();
});
it(`should not show error for a valid SRP where each word is followed by a'${whitespaceCharacter}'`, async () => {
const onChange = jest.fn();
const { getByTestId, queryByText } = renderWithLocalization(
,
);
const srpParts = correct.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.paste(`${srpParts[index]}${whitespaceCharacter}`);
}
expect(
queryByText(enLocale.seedPhraseReq.message),
).not.toBeInTheDocument();
expect(
queryByText(enLocale.invalidSeedPhrase.message),
).not.toBeInTheDocument();
});
}
});
describe('pasted', () => {
it('should show word requirement error if SRP has too few words', async () => {
const onChange = jest.fn();
const { getByTestId, queryByText } = renderWithLocalization(
,
);
getByTestId('import-srp__srp-word-0').focus();
await userEvent.paste(tooFewWords);
expect(queryByText(enLocale.seedPhraseReq.message)).toBeInTheDocument();
expect(
queryByText(enLocale.invalidSeedPhrase.message),
).not.toBeInTheDocument();
});
it('should show word requirement error if SRP has an unsupported word count above 12 but below 24', async () => {
const onChange = jest.fn();
const { getByTestId, queryByText } = renderWithLocalization(
,
);
getByTestId('import-srp__srp-word-0').focus();
await userEvent.paste(invalidWordCount);
expect(queryByText(enLocale.seedPhraseReq.message)).toBeInTheDocument();
expect(
queryByText(enLocale.invalidSeedPhrase.message),
).not.toBeInTheDocument();
});
it('should show invalid SRP error if SRP is correct length but has an invalid checksum', async () => {
const onChange = jest.fn();
const { getByTestId, queryByText } = renderWithLocalization(
,
);
getByTestId('import-srp__srp-word-0').focus();
await userEvent.paste(invalidChecksum);
expect(
queryByText(enLocale.seedPhraseReq.message),
).not.toBeInTheDocument();
expect(
queryByText(enLocale.invalidSeedPhrase.message),
).toBeInTheDocument();
});
it('should show invalid SRP error if SRP is correct length and has correct checksum but has an invalid word', async () => {
const onChange = jest.fn();
const { getByTestId, queryByText } = renderWithLocalization(
,
);
getByTestId('import-srp__srp-word-0').focus();
await userEvent.paste(invalidWordCorrectChecksum);
expect(
queryByText(enLocale.seedPhraseReq.message),
).not.toBeInTheDocument();
expect(
queryByText(enLocale.invalidSeedPhrase.message),
).toBeInTheDocument();
});
it('should not show error for valid SRP', async () => {
const onChange = jest.fn();
const { getByTestId, queryByText } = renderWithLocalization(
,
);
getByTestId('import-srp__srp-word-0').focus();
await userEvent.paste(correct);
expect(
queryByText(enLocale.seedPhraseReq.message),
).not.toBeInTheDocument();
expect(
queryByText(enLocale.invalidSeedPhrase.message),
).not.toBeInTheDocument();
});
for (const poorlyFormattedInput of poorlyFormattedInputs) {
it(`should not show error for poorly formatted valid SRP: '${poorlyFormattedInput}'`, async () => {
const onChange = jest.fn();
const { getByTestId, queryByText } = renderWithLocalization(
,
);
getByTestId('import-srp__srp-word-0').focus();
await userEvent.paste(poorlyFormattedInput);
expect(
queryByText(enLocale.seedPhraseReq.message),
).not.toBeInTheDocument();
expect(
queryByText(enLocale.invalidSeedPhrase.message),
).not.toBeInTheDocument();
});
}
});
});
describe('Show/hide SRP', () => {
it('should default to not showing SRP', async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
for (const index of new Array(12).keys()) {
expect(getByTestId(`import-srp__srp-word-${index}`)).toHaveAttribute(
'type',
'password',
);
expect(
getByTestId(`import-srp__srp-word-${index}-checkbox`),
).not.toBeChecked();
}
});
describe('default hidden', () => {
it('should prevent reading typed SRP', async () => {
const onChange = jest.fn();
const { getByTestId, queryAllByRole } = renderWithLocalization(
,
);
const srpParts = correct.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.keyboard(srpParts[index]);
expect(queryAllByRole('textbox')).toHaveLength(0);
}
});
it('should prevent reading individually pasted SRP', async () => {
const onChange = jest.fn();
const { getByTestId, queryAllByRole } = renderWithLocalization(
,
);
const srpParts = correct.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.paste(srpParts[index]);
expect(queryAllByRole('textbox')).toHaveLength(0);
}
});
it('should prevent reading pasted SRP', async () => {
const onChange = jest.fn();
const { getByTestId, queryAllByRole } = renderWithLocalization(
,
);
getByTestId('import-srp__srp-word-0').focus();
await userEvent.paste(correct);
expect(queryAllByRole('textbox')).toHaveLength(0);
});
});
describe('shown then hidden', () => {
it('should prevent reading typed SRP', async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
const srpParts = correct.split(' ');
for (const index of new Array(srpParts.length).keys()) {
await userEvent.click(
getByTestId(`import-srp__srp-word-${index}-checkbox`),
);
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.keyboard(srpParts[index]);
await userEvent.click(
getByTestId(`import-srp__srp-word-${index}-checkbox`),
);
expect(getByTestId(`import-srp__srp-word-${index}`)).toHaveAttribute(
'type',
'password',
);
}
});
it('should prevent reading individually pasted SRP', async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
const srpParts = correct.split(' ');
for (const index of new Array(srpParts.length).keys()) {
await userEvent.click(
getByTestId(`import-srp__srp-word-${index}-checkbox`),
);
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.paste(srpParts[index]);
await userEvent.click(
getByTestId(`import-srp__srp-word-${index}-checkbox`),
);
expect(getByTestId(`import-srp__srp-word-${index}`)).toHaveAttribute(
'type',
'password',
);
}
});
});
describe('shown after input', () => {
it('should show words from typed SRP', async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
const srpParts = correct.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.keyboard(srpParts[index]);
}
for (const index of new Array(srpParts.length).keys()) {
await userEvent.click(
getByTestId(`import-srp__srp-word-${index}-checkbox`),
);
expect(getByTestId(`import-srp__srp-word-${index}`)).toHaveAttribute(
'type',
'text',
);
expect(getByTestId(`import-srp__srp-word-${index}`)).toHaveValue(
srpParts[index],
);
await userEvent.click(
getByTestId(`import-srp__srp-word-${index}-checkbox`),
);
}
});
it('should show words from individually pasted SRP', async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
const srpParts = correct.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.paste(srpParts[index]);
}
for (const index of new Array(srpParts.length).keys()) {
await userEvent.click(
getByTestId(`import-srp__srp-word-${index}-checkbox`),
);
expect(getByTestId(`import-srp__srp-word-${index}`)).toHaveAttribute(
'type',
'text',
);
expect(getByTestId(`import-srp__srp-word-${index}`)).toHaveValue(
srpParts[index],
);
await userEvent.click(
getByTestId(`import-srp__srp-word-${index}-checkbox`),
);
}
});
it('should show words from pasted SRP', async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
getByTestId('import-srp__srp-word-0').focus();
await userEvent.paste(correct);
const srpParts = correct.split(' ');
for (const index of new Array(srpParts.length).keys()) {
await userEvent.click(
getByTestId(`import-srp__srp-word-${index}-checkbox`),
);
expect(getByTestId(`import-srp__srp-word-${index}`)).toHaveAttribute(
'type',
'text',
);
expect(getByTestId(`import-srp__srp-word-${index}`)).toHaveValue(
srpParts[index],
);
await userEvent.click(
getByTestId(`import-srp__srp-word-${index}-checkbox`),
);
}
});
});
describe('shown before input', () => {
it('should show words from typed SRP', async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
const srpParts = correct.split(' ');
for (const index of new Array(srpParts.length).keys()) {
await userEvent.click(
getByTestId(`import-srp__srp-word-${index}-checkbox`),
);
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.keyboard(srpParts[index]);
expect(
getByTestId(`import-srp__srp-word-${index}-checkbox`),
).toBeChecked();
expect(getByTestId(`import-srp__srp-word-${index}`)).toHaveAttribute(
'type',
'text',
);
expect(getByTestId(`import-srp__srp-word-${index}`)).toHaveValue(
srpParts[index],
);
}
});
it('should show words from individually pasted SRP', async () => {
const onChange = jest.fn();
const { getByTestId } = renderWithLocalization(
,
);
const srpParts = correct.split(' ');
for (const index of new Array(srpParts.length).keys()) {
await userEvent.click(
getByTestId(`import-srp__srp-word-${index}-checkbox`),
);
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.paste(srpParts[index]);
expect(
getByTestId(`import-srp__srp-word-${index}-checkbox`),
).toBeChecked();
expect(getByTestId(`import-srp__srp-word-${index}`)).toHaveAttribute(
'type',
'text',
);
expect(getByTestId(`import-srp__srp-word-${index}`)).toHaveValue(
srpParts[index],
);
}
});
});
describe('hidden after paste', () => {
it('should hide all inputs after an incomplete multi-word paste', async () => {
const onChange = jest.fn();
const { getByTestId, queryAllByRole } = renderWithLocalization(
,
);
await userEvent.click(getByTestId('import-srp__srp-word-0-checkbox'));
getByTestId('import-srp__srp-word-0').focus();
await userEvent.keyboard('test');
expect(queryAllByRole('textbox')).toHaveLength(1);
await userEvent.paste(tooFewWords);
expect(queryAllByRole('textbox')).toHaveLength(0);
for (const index of new Array(12).keys()) {
expect(
getByTestId(`import-srp__srp-word-${index}-checkbox`),
).not.toBeChecked();
}
});
it('should hide all inputs after a full SRP paste', async () => {
const onChange = jest.fn();
const { getByTestId, queryAllByRole } = renderWithLocalization(
,
);
await userEvent.click(getByTestId('import-srp__srp-word-0-checkbox'));
getByTestId('import-srp__srp-word-0').focus();
await userEvent.keyboard('test');
expect(queryAllByRole('textbox')).toHaveLength(1);
await userEvent.paste(correct);
expect(queryAllByRole('textbox')).toHaveLength(0);
for (const index of new Array(12).keys()) {
expect(
getByTestId(`import-srp__srp-word-${index}-checkbox`),
).not.toBeChecked();
}
});
it('should not hide inputs after a single word paste', async () => {
const onChange = jest.fn();
const { getByTestId, queryAllByRole } = renderWithLocalization(
,
);
await userEvent.click(getByTestId('import-srp__srp-word-0-checkbox'));
getByTestId('import-srp__srp-word-0').focus();
await userEvent.keyboard('test');
expect(queryAllByRole('textbox')).toHaveLength(1);
await userEvent.paste('test');
expect(queryAllByRole('textbox')).toHaveLength(1);
expect(getByTestId('import-srp__srp-word-0-checkbox')).toBeChecked();
});
});
it('should hide shown field when another field is shown', async () => {
const onChange = jest.fn();
const { getByTestId, queryAllByRole } = renderWithLocalization(
,
);
getByTestId('import-srp__srp-word-0').focus();
await userEvent.paste(correct);
await userEvent.click(getByTestId('import-srp__srp-word-0-checkbox'));
expect(getByTestId('import-srp__srp-word-0-checkbox')).toBeChecked();
await userEvent.click(getByTestId('import-srp__srp-word-1-checkbox'));
expect(queryAllByRole('textbox')).toHaveLength(1);
expect(getByTestId('import-srp__srp-word-0-checkbox')).not.toBeChecked();
expect(getByTestId('import-srp__srp-word-1-checkbox')).toBeChecked();
});
});
describe('clear after paste', () => {
it('should not clear clipboard after typing SRP', async () => {
const onChange = jest.fn();
const writeTextSpy = jest.spyOn(window.navigator.clipboard, 'writeText');
const { getByTestId } = renderWithLocalization(
,
);
const srpParts = correct.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.keyboard(srpParts[index]);
}
expect(writeTextSpy).not.toHaveBeenCalled();
});
it('should not clear the clipboard after individually pasting SRP', async () => {
const onChange = jest.fn();
const writeTextSpy = jest.spyOn(window.navigator.clipboard, 'writeText');
const { getByTestId } = renderWithLocalization(
,
);
const srpParts = correct.split(' ');
for (const index of new Array(srpParts.length).keys()) {
getByTestId(`import-srp__srp-word-${index}`).focus();
await userEvent.paste(srpParts[index]);
}
expect(writeTextSpy).not.toHaveBeenCalled();
});
it('should not clear the clipboard after pasting SRP with too many words', async () => {
const onChange = jest.fn();
const writeTextSpy = jest.spyOn(window.navigator.clipboard, 'writeText');
const { getByTestId } = renderWithLocalization(
,
);
getByTestId('import-srp__srp-word-0').focus();
await userEvent.paste(tooManyWords);
expect(writeTextSpy).not.toHaveBeenCalled();
});
it('should clear the clipboard after pasting incomplete SRP', async () => {
const onChange = jest.fn();
const writeTextSpy = jest.spyOn(window.navigator.clipboard, 'writeText');
const { getByTestId } = renderWithLocalization(
,
);
getByTestId('import-srp__srp-word-0').focus();
await userEvent.paste(tooFewWords);
expect(writeTextSpy).toHaveBeenCalledWith('');
});
it('should clear the clipboard after pasting correct SRP', async () => {
const onChange = jest.fn();
const writeTextSpy = jest.spyOn(window.navigator.clipboard, 'writeText');
const { getByTestId } = renderWithLocalization(
,
);
getByTestId('import-srp__srp-word-0').focus();
await userEvent.paste(correct);
expect(writeTextSpy).toHaveBeenCalledWith('');
});
});
describe('number of words dropdown', () => {
it('should default to 12 words', () => {
const onChange = jest.fn();
const { queryByTestId, queryByRole } = renderWithLocalization(
,
);
expect(
queryByRole('option', {
name: enLocale.srpInputNumberOfWords.message.replace('$1', '12'),
selected: true,
}),
).toBeInTheDocument();
expect(queryByTestId('import-srp__srp-word-11')).toBeInTheDocument();
expect(queryByTestId('import-srp__srp-word-12')).not.toBeInTheDocument();
});
it('should be updated on paste to allow room for a longer SRP', async () => {
const onChange = jest.fn();
const {
getByTestId,
queryByTestId,
queryByRole,
} = renderWithLocalization();
getByTestId('import-srp__srp-word-0').focus();
await userEvent.paste(new Array(15).fill('test').join(' '));
expect(
queryByRole('option', {
name: enLocale.srpInputNumberOfWords.message.replace('$1', '15'),
selected: true,
}),
).toBeInTheDocument();
expect(queryByTestId('import-srp__srp-word-14')).toBeInTheDocument();
expect(queryByTestId('import-srp__srp-word-15')).not.toBeInTheDocument();
});
it('should be updated on paste to match the size of a shorter SRP', async () => {
const onChange = jest.fn();
const {
getByRole,
getByTestId,
queryByTestId,
queryByRole,
} = renderWithLocalization();
await userEvent.selectOptions(getByRole('combobox'), '15');
getByTestId('import-srp__srp-word-0').focus();
await userEvent.paste(correct);
expect(
queryByRole('option', {
name: enLocale.srpInputNumberOfWords.message.replace('$1', '12'),
selected: true,
}),
).toBeInTheDocument();
expect(queryByTestId('import-srp__srp-word-11')).toBeInTheDocument();
expect(queryByTestId('import-srp__srp-word-12')).not.toBeInTheDocument();
});
it('should round up to nearest valid size on paste when SRP has an invalid number of words', async () => {
const onChange = jest.fn();
const {
getByTestId,
queryByTestId,
queryByRole,
} = renderWithLocalization();
getByTestId('import-srp__srp-word-0').focus();
await userEvent.paste(invalidWordCount);
expect(
queryByRole('option', {
name: enLocale.srpInputNumberOfWords.message.replace('$1', '15'),
selected: true,
}),
).toBeInTheDocument();
expect(queryByTestId('import-srp__srp-word-14')).toBeInTheDocument();
expect(queryByTestId('import-srp__srp-word-15')).not.toBeInTheDocument();
});
it('should update the number of fields', async () => {
const onChange = jest.fn();
const { getByRole, queryByTestId, queryByRole } = renderWithLocalization(
,
);
await userEvent.selectOptions(getByRole('combobox'), '24');
expect(
queryByRole('option', {
name: enLocale.srpInputNumberOfWords.message.replace('$1', '24'),
selected: true,
}),
).toBeInTheDocument();
expect(queryByTestId('import-srp__srp-word-23')).toBeInTheDocument();
expect(queryByTestId('import-srp__srp-word-24')).not.toBeInTheDocument();
});
it('should forget any field state that is no longer shown', async () => {
const onChange = jest.fn();
const { getByRole, getByTestId, queryByTestId } = renderWithLocalization(
,
);
getByTestId('import-srp__srp-word-0').focus();
await userEvent.paste(new Array(15).fill('test').join(' '));
await userEvent.selectOptions(getByRole('combobox'), '12');
await userEvent.selectOptions(getByRole('combobox'), '15');
expect(queryByTestId('import-srp__srp-word-14')).toBeInTheDocument();
expect(queryByTestId('import-srp__srp-word-15')).not.toBeInTheDocument();
expect(queryByTestId('import-srp__srp-word-11').value).toBe('test');
expect(queryByTestId('import-srp__srp-word-12').value).toBe('');
expect(queryByTestId('import-srp__srp-word-13').value).toBe('');
expect(queryByTestId('import-srp__srp-word-14').value).toBe('');
});
});
describe('paste error', () => {
it('should show paste error when too many words are pasted', async () => {
const onChange = jest.fn();
const { getByTestId, queryByText } = renderWithLocalization(
,
);
getByTestId('import-srp__srp-word-0').focus();
await userEvent.paste(tooManyWords);
expect(
queryByText(enLocale.srpPasteFailedTooManyWords.message),
).toBeInTheDocument();
});
it('should allow dismissing the paste error', async () => {
const onChange = jest.fn();
const { getByTestId, getByText, queryByText } = renderWithLocalization(
,
);
getByTestId('import-srp__srp-word-0').focus();
await userEvent.paste(tooManyWords);
await userEvent.click(getByText('Dismiss'));
expect(
queryByText(enLocale.srpPasteFailedTooManyWords.message),
).not.toBeInTheDocument();
});
it('should dismiss the paste error after paste with fewer than 24 words', async () => {
const onChange = jest.fn();
const { getByTestId, queryByText } = renderWithLocalization(
,
);
getByTestId('import-srp__srp-word-0').focus();
await userEvent.paste(tooManyWords);
await userEvent.paste(correct);
expect(
queryByText(enLocale.srpPasteFailedTooManyWords.message),
).not.toBeInTheDocument();
});
it('should not dismiss the paste error after a second paste with over 24 words', async () => {
const onChange = jest.fn();
const { getByTestId, queryByText } = renderWithLocalization(
,
);
getByTestId('import-srp__srp-word-0').focus();
await userEvent.paste(tooManyWords);
await userEvent.paste(tooManyWords);
expect(
queryByText(enLocale.srpPasteFailedTooManyWords.message),
).toBeInTheDocument();
});
it('should dismiss the paste error after typing', async () => {
const onChange = jest.fn();
const { getByTestId, queryByText } = renderWithLocalization(
,
);
getByTestId('import-srp__srp-word-0').focus();
await userEvent.paste(tooManyWords);
await userEvent.keyboard('test');
expect(
queryByText(enLocale.srpPasteFailedTooManyWords.message),
).not.toBeInTheDocument();
});
});
});