featureparity 0.0.13 → 0.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/lib/fp/junit.rb +80 -8
  3. data/lib/fp/version.rb +1 -1
  4. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e3dba0cc6ba18239f6952822d96bd4526d26d207e8b7e5448554de745e6517a8
4
- data.tar.gz: 1521147f4b1574062b3e04f22cef0ce1cb7ef6b822f767c3f75ed66a200b6a5c
3
+ metadata.gz: 7fc65a33008ccbd43f9b8ec10f7e3c013ab3ed502980f97b64c55e14ff1d2eb5
4
+ data.tar.gz: a841a639236c27ea6bf7c30ba1a7f4a5710176bc0fd4bb153daac009d89e90db
5
5
  SHA512:
6
- metadata.gz: a65ac140de45599a9a5a27f4705e179fd816bad77fe563477fd6b92efbc0d592cea80f8c90c2e519d559fc604927d6b321c3a3af99bb10c2b99b9e06b39467f5
7
- data.tar.gz: c9ba4966e9a2d036f266b3646eb0c7569399d606d196175df189047de7693c55badce253c94205045449ca7b20117a6f496eeee486067c03ca2291f2caed026f
6
+ metadata.gz: df0c381690d9fa55e189e3a057eddd35c979bb970fac56b9294ad426d758613374c483c5f4317829cedd5a85d3ff3443a543e8dbcfdff99a146a82c7de831c53
7
+ data.tar.gz: f2d8dd3a182c74e6e7ef5e4395803eaf86a62b510532227c2b7ec4c3bf4a3fe06db62c8866280d016c7cb4d1cb6a786b2b5c2dcb731f5f0ada518de288eb3714
data/lib/fp/junit.rb CHANGED
@@ -46,8 +46,10 @@ module Fp
46
46
  # A testcase paired with the marker that annotates it. `precise` records whether we
47
47
  # know *which* test the marker sits above (matched by line or by test name) or only
48
48
  # that the marker is somewhere in the same file — a title is only worth reporting in
49
- # the first case.
50
- Match = Struct.new(:testcase, :marker, :precise, keyword_init: true)
49
+ # the first case. `repo_file` is the testcase's source path made relative to the git
50
+ # repo root (see repo_relative_file), so evidence links resolve regardless of the
51
+ # base_dir the runner reported paths against.
52
+ Match = Struct.new(:testcase, :marker, :precise, :repo_file, keyword_init: true)
51
53
 
52
54
  # Evidence discovered by binding a testcase to a marker.
53
55
  # `line` is the 1-based line number of the test in its source file: the
@@ -191,7 +193,7 @@ module Fp
191
193
  if surface.nil? || surface.empty?
192
194
  missing_surface << { slug: marker[:slug], file: tc.file }
193
195
  else
194
- record_binding(bindings, marker[:slug], surface, tc, marker, titles_reliable: match.precise)
196
+ record_binding(bindings, marker[:slug], surface, tc, marker, match.repo_file, titles_reliable: match.precise)
195
197
  end
196
198
  end
197
199
  end
@@ -232,7 +234,7 @@ module Fp
232
234
  end
233
235
 
234
236
  key = [marker[:slug], surface]
235
- agg = aggregates[key] ||= { file: tc.file, line: tc.line || marker[:line], ran: 0, failed: 0, skipped: 0 }
237
+ agg = aggregates[key] ||= { file: match.repo_file || tc.file, line: tc.line || marker[:line], ran: 0, failed: 0, skipped: 0 }
236
238
  if tc.stub?
237
239
  agg[:skipped] += 1
238
240
  else
@@ -274,17 +276,23 @@ module Fp
274
276
  # can never disagree about which test a marker annotates.
275
277
  def walk_matches(testcases, base_dir)
276
278
  marker_cache = {}
279
+ prefix_cache = {}
277
280
 
278
281
  # Group testcases by their source file so we can reason about ordering.
279
- testcases.group_by(&:file).each do |_file, cases|
282
+ testcases.group_by(&:file).each do |file, cases|
280
283
  markers = markers_for(cases.first, base_dir, marker_cache)
281
284
  next if markers.empty?
282
285
 
286
+ # The path we'll store as evidence: relative to the git root, not to base_dir,
287
+ # so a GitHub blob link resolves. base_dir's offset below the root is cached, so
288
+ # this is one shell-out per run, not per file.
289
+ repo_file = repo_relative_file(file, base_dir, prefix_cache)
290
+
283
291
  cases.each do |tc|
284
292
  marker, precise = marker_for(tc, cases, markers)
285
293
  next unless marker
286
294
 
287
- yield Match.new(testcase: tc, marker: marker, precise: precise)
295
+ yield Match.new(testcase: tc, marker: marker, precise: precise, repo_file: repo_file)
288
296
  end
289
297
  end
290
298
  end
@@ -363,8 +371,8 @@ module Fp
363
371
  candidate
364
372
  end
365
373
 
366
- def record_binding(bindings, slug, surface, testcase, marker, titles_reliable: true)
367
- rel_file = testcase.file
374
+ def record_binding(bindings, slug, surface, testcase, marker, repo_file, titles_reliable: true)
375
+ rel_file = repo_file || testcase.file
368
376
  key = [slug, surface, rel_file]
369
377
  state = testcase.stub? ? 'stub' : 'present'
370
378
 
@@ -400,6 +408,70 @@ module Fp
400
408
  cache[file] = markers
401
409
  end
402
410
 
411
+ # Rewrite a report-relative test-file path so it is relative to the git repo root.
412
+ #
413
+ # Runners report paths relative to wherever they ran: RSpec/minitest from the repo
414
+ # root, but vitest from its own package (frontend/), which is why the web job passes
415
+ # `--base-dir frontend`. That base_dir is enough to *find* the markers, but the path
416
+ # we then store as `source_file` was the raw report path (`src/pages/Matrix.test.jsx`),
417
+ # not the repo-root path (`frontend/src/pages/Matrix.test.jsx`). The web app builds a
418
+ # GitHub link as `blob/<sha>/<source_file>`, and a blob path is always relative to the
419
+ # git root — so the missing `frontend/` prefix produced a 404 on every web test link.
420
+ #
421
+ # The fix is purely additive: find how far base_dir sits below the git root and
422
+ # prepend that. When base_dir *is* the git root (the Ruby suites, run from the repo
423
+ # root), the prefix is empty and the original path is returned byte-for-byte — so this
424
+ # only ever corrects a subdirectory base_dir and never rewrites a path that was
425
+ # already right. Falls back to the raw path when there's no git checkout (an agent
426
+ # running from a tarball) or base_dir sits outside one.
427
+ def repo_relative_file(file, base_dir, cache = {})
428
+ return file if file.nil? || file.empty?
429
+
430
+ prefix = base_dir_prefix(base_dir, cache)
431
+ return file if prefix.nil? || prefix.empty?
432
+
433
+ File.join(prefix, file)
434
+ end
435
+
436
+ # base_dir's path relative to the git root that contains it: '' when base_dir is the
437
+ # root, 'frontend' when it's a package below it, nil when base_dir isn't in a checkout
438
+ # (or sits above the root). Cached per base_dir so a report shells out once.
439
+ def base_dir_prefix(base_dir, cache)
440
+ absolute = File.expand_path(base_dir)
441
+ return cache[absolute] if cache.key?(absolute)
442
+
443
+ root = git_toplevel_for(absolute)
444
+ prefix =
445
+ if root.nil?
446
+ nil
447
+ else
448
+ rel = relative_path(absolute, root)
449
+ rel == '.' || rel.start_with?('..') ? '' : rel
450
+ end
451
+ cache[absolute] = prefix
452
+ end
453
+
454
+ # The git repo root containing `dir`, or nil if `dir` isn't inside a checkout.
455
+ def git_toplevel_for(dir)
456
+ out = `git -C #{quote(dir)} rev-parse --show-toplevel 2>/dev/null`
457
+ root = out.strip
458
+ ($?&.success? && !root.empty?) ? File.expand_path(root) : nil
459
+ end
460
+
461
+ def relative_path(absolute, root)
462
+ require 'pathname'
463
+ Pathname.new(absolute).relative_path_from(Pathname.new(root)).to_s
464
+ rescue ArgumentError
465
+ # Different roots on Windows, or otherwise not relative — treat as outside.
466
+ '..'
467
+ end
468
+
469
+ # Minimal shell-quote for a path passed to `git -C`. The directory comes from
470
+ # --base-dir, not arbitrary report content, but quoting keeps spaces safe.
471
+ def quote(str)
472
+ "'#{str.gsub("'", "'\\\\''")}'"
473
+ end
474
+
403
475
  # Scan file contents for fp:<slug>[@surface[,surface...]] markers, returning
404
476
  # [{ slug:, surfaces: [..], line:, title:, title_kind: }, ...] (1-based line numbers).
405
477
  # `surfaces` is [] when the marker pins none (use the default surface).
data/lib/fp/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Fp
4
- VERSION = '0.0.13'
4
+ VERSION = '0.0.14'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: featureparity
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.13
4
+ version: 0.0.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stowzilla