Dijkstra's algorithm without relaxation
I see you have tested the case when there is no path to the destination, but I'm not convinced that returning seemingly valid data in that case is a good idea. You can easily catch such case by adding an else clause to the main while loop. You will land there if the loop ends without break.
Disregarding the no path case you can simplify the second while loop to

path = []
while f in prev:
    path.append(f)
    f = prev[f]

The visited set is redundant because it is the same as the set of keys of prev, and v not in prev has similar performance to v not in visited.