Денис, у тебя здесь главная ошибка в том, что ты при первом же несовпадении контакта возвращаешь 'No such contact'. То есть по сути у тебя логика будет работать только для первого в массиве контакта и только если свойство есть. Но у тебя же и другие контакты проверяются. А как до них дойдет логика? В данном случае никак. То есть тебе надо перечислить все контакты и только если перебрал все и не нашел ни одного по имени, тогда только возвращать ошибку, то есть вынести это условие за пределы цикла. Если в цикле отработает целевое условие и ты выполнишь return - тогда и не дойдет дело до возврата ошибки. А если в цикле ничто не выполнится, тогда уже вернешь ошибку.

Второй момент: ты сразу первым делом проверяешь двойное условие
if (contacts[i].firstName == name && contacts[i].hasOwnProperty(prop)) {
Не надо так. Первое главное условие у тебя: это найден контакт или нет. Если найден, тогда по нему уже все и проверяй далее. Если нет - то пропусти его. То есть оберни все в условие

if(name === contacts[i].firstName) { // Здесь уже все остальные условия пропиши. }
Третий момент: старайся не использовать нестрогое сравнение ==, старайся всегда строгое ===. Иначе не редко будешь ловить логические ошибки.