frame method
Turns a frame reference — a preview row's shots.base/shots.head, or
a scenario step's FrameRef.path — into a file beside directory.
Null when this report does not carry that frame. An export writes
what the shot cache still held: a frame evicted before it ran keeps its
original reference rather than gaining a PNG, which the page renders as
nothing rendered and this reports as nothing to open. Composing a path
for it anyway would hand back a File that is not there — the one
failure a typed reader exists to prevent, because it is indistinguishable
from a file the caller simply has not written yet.
Throws StateError on a report whose frames are
ComparisonFrames.local, which is a different mistake: not one absent
frame but the wrong directory. There is nothing openable there at all — a
preview's reference is a ShotCache key rather than a path, and a
scenario step's is a headerless raw frame no image library will read.
Both are what an export exists to turn into PNGs.
Implementation
File? frame(String reference) {
if (index.frames == ComparisonFrames.local) {
throw StateError(
'This comparison names frames on the machine that ran it, so '
'"$reference" cannot be opened from here. Re-run with '
'`fw compare --report=<dir>` and read the `web/` it writes, which '
'carries the frames as PNGs.',
);
}
var native = reference.replaceAll('/', Platform.pathSeparator);
// An absolute reference inside an exported page is one the export could
// not rewrite. It points into whichever machine produced it — where it may
// even still exist, and be the raw frame rather than the PNG this claims
// to hand back — so it is not this page's to open either.
if (File(native).isAbsolute) return null;
var file = File('$directory${Platform.pathSeparator}$native');
return file.existsSync() ? file : null;
}