Skip to content

Feature/averageifs function - #1732

Open
Tobiadefami wants to merge 7 commits into
developfrom
feature/averageifs-function
Open

Feature/averageifs function#1732
Tobiadefami wants to merge 7 commits into
developfrom
feature/averageifs-function

Conversation

@Tobiadefami

@Tobiadefami Tobiadefami commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator

Context

HyperFormula supports AVERAGEIF and other conditional aggregation functions, but it does not support AVERAGEIFS.

This change adds AVERAGEIFS, allowing values to be averaged when all corresponding criteria are satisfied. It uses the existing conditional aggregation and caching infrastructure and includes function metadata, translations, documentation, and tests.

How did you test your changes?

Added tests covering:

  • Required and repeated arguments.
  • Invalid criteria and mismatched range dimensions.
  • Single and multiple criteria.
  • Scalar, reference, range, and calculated-range arguments.
  • Error propagation.
  • Ignoring non-numeric values in the average range.
  • Division-by-zero errors when no numeric values qualify.
  • Valid averages equal to zero.
  • Conditional aggregation caching.
  • Recalculation after changes to the average or criteria ranges.
  • Public function metadata.
  • The Portuguese translation.

All 28 focused tests passed.

Additionally, I ran:

  • npm run bundle:cjs
  • npm run docs:generate-function-docs

Both commands completed successfully.

Types of changes

  • Breaking change (a fix or a feature because of which an existing functionality doesn't work as
    expected anymore)
  • New feature or improvement (a non-breaking change that adds functionality)
  • Bug fix (a non-breaking change that fixes an issue)
  • Additional language file, or a change to an existing language file (translations)
  • Change to the documentation

Related issues:

Checklist:

  • I have reviewed the guidelines about [Contributing to HyperFormula](https://
    hyperformula.handsontable.com/guide/contributing.html) and I confirm that my code follows the code style of
    this project.
  • I have signed the Contributor License Agreement.
  • My change is compliant with the [OpenDocument](https://docs.oasis-open.org/office/OpenDocument/v1.3/
    os/part4-formula/OpenDocument-v1.3-os-part4-formula.html) standard.
  • My change is compatible with Microsoft Excel.
  • My change is compatible with Google Sheets.
  • I described my changes in the [CHANGELOG.md](https://github.com/handsontable/hyperformula/blob/master/
    CHANGELOG.md) file.
  • My changes require a documentation update.
  • My changes require a migration guide.

Note

Low Risk
New statistical function on established conditional-aggregation infrastructure; limited blast radius beyond formula evaluation behavior for AVERAGEIFS/AVERAGEIF refactors.

Overview
Adds Excel-compatible AVERAGEIFS, which averages numeric cells in average_range only when every paired criteria range/criterion is satisfied.

The implementation lives in ConditionalAggregationPlugin, following the same repeatLastArgs pattern as SUMIFS/COUNTIFS and reusing computeConditionalAggregationFunction with shared helpers (composeAverageResults, mapToAverageResult, finalizeAverageResult) that also simplify AVERAGEIF finalization. Statistical function metadata and localized names are registered across the existing language packs, and the unreleased changelog documents the addition.

Reviewed by Cursor Bugbot for commit c6e1fb5. Bugbot is set up for automated code reviews on this repo. Configure here.

@cla-external-contractor-signup

Copy link
Copy Markdown

@Tobiadefami thanks for the pull request. No CLA step needed here — our records show you signed the Contributor License Agreement on 2026-07-31. That signature came from our previous signing form and has been carried over, so there is nothing for you to re-sign.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 13, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
hyperformula-docs c6e1fb5 Commit Preview URL

Branch Preview URL
Sep 04 2026, 08:05 PM

@Tobiadefami
Tobiadefami requested a review from sequba August 13, 2026 09:08
@github-actions

github-actions Bot commented Aug 13, 2026

Copy link
Copy Markdown

Performance comparison of head (c6e1fb5) vs base (c920375)

                                     testName |    base |   head | change
-------------------------------------------------------------------------
                                      Sheet A |  501.45 | 495.89 | -1.11%
                                      Sheet B |  161.92 | 159.84 | -1.28%
                                      Sheet T |  143.26 | 141.42 | -1.28%
                                Column ranges |  472.46 |  475.2 | +0.58%
                                Sorted lookup | 14909.3 |  14503 | -2.73%
Sheet A:  change value, add/remove row/column |   15.59 |  15.35 | -1.54%
 Sheet B: change value, add/remove row/column |  133.65 | 137.95 | +3.22%
                   Column ranges - add column |  147.55 | 151.39 | +2.60%
                Column ranges - without batch |  453.17 | 472.62 | +4.29%
                        Column ranges - batch |  114.32 | 119.62 | +4.64%

Comment thread src/interpreter/plugin/ConditionalAggregationPlugin.ts Outdated
@marcin-kordas-hoc

Copy link
Copy Markdown
Collaborator

Hey @Tobiadefami — one process thing unrelated to the code itself (which looks solid, see the review above): the paired hyperformula-tests PR seems to have slipped through for this one. The branch feature/averageifs-function is there with real, good tests (function-averageifs.spec.ts + the metadata/i18n/custom-functions updates — I read through them, nice coverage on error propagation, caching, and CRUD recalculation), but there's no PR wrapping it, unlike TAKE (#28) and CHOOSECOLS (#34) which both have theirs open.

Could you open a PR there for this branch? Same thing seems to have happened for #1733's companion branch (fix/averageif-zero-average) — also has commits, also no PR yet. Both should be quick since the work itself is already done and pushed, just need the PR opened so they're visible for review the same way your other two are.

Nothing else blocking here — just flagging it now so it's not a surprise closer to merge.

@Tobiadefami

Copy link
Copy Markdown
Collaborator Author

@marcin-kordas-hoc Done — AVERAGEIFS is in test repo PR 36, and the zero-average fix is in test repo PR 35.

@marcin-kordas-hoc marcin-kordas-hoc left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving. The engine code here got a clean verdict on 16 Aug and the head has not moved since, so this is about closing the loop on the two things that were still open.

Paired tests now verified against this head. CI on this PR last ran on 13 Aug, while the feature/averageifs-function test branch received commits through 22 Aug — so the green badge above never executed the current test suite. I checked it directly instead: engine 8f54b3ab0 against tests d0f8a4f, function-averageifs.spec.ts29/29 passing. The 22 Aug delta (percents, currencies, dates) is structurally the same as the MAXIFS siblings and passes here.

One caveat on the record: I could not re-trigger the workflow — this token has no actions: write, and test.yml has no workflow_dispatch, so the only paths are the re-run button or a new push. Worth one click before merge so the PR's own badge reflects a run that included those tests. My local run is evidence the tests pass, not a substitute for the official record.

Also unable to resolve my own thread on ConditionalAggregationPlugin.ts from here (same token limitation) — your reply on it is correct and it needs no further action, so please mark it resolved.

Merging still waits for the freeze to lift.

sequba commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

AVERAGEIFS drops booleans in average_range; Excel counts them as 1 and 0

Flagging this before merge, since the PR ticks "My change is compatible with Microsoft Excel" and there is a test that currently locks the divergence in.

Repro (verified against this branch at f4ebe7e):

A B
1 =TRUE() y
2 =FALSE() y
3 10 y

=AVERAGEIFS(A1:A3, B1:B3, "y")10. Excel returns 3.667, i.e. (1 + 0 + 10) / 3.

Why Excel returns that. The AVERAGEIFS page linked from HF-140 states:

Cells in average_range that contain TRUE evaluate as 1; cells in average_range that contain FALSE evaluate as 0 (zero).

This is one of the spots where Excel deliberately makes AVERAGEIFS differ from AVERAGEIF — the AVERAGEIF page says the opposite:

Cells in range that contain TRUE or FALSE are ignored.

So boolean handling is not something averageifs can inherit from averageif: the two genuinely need different mapping functions. The implementation here reuses AVERAGEIF's shape, so booleans fall through to AverageResult.empty at src/interpreter/plugin/ConditionalAggregationPlugin.ts:253-255.

Suggested fix. In the map function at lines 248-256, handle booleans explicitly before the AverageResult.empty fallback: trueAverageResult.single(1), falseAverageResult.single(0). Text and blank cells should keep being ignored — that matches Excel too.

Test that needs updating alongside it. In the paired tests PR, unit/interpreter/function-averageifs.spec.ts:187 (ignores non-numeric values in the average range) puts =TRUE() in the averaged range and asserts 20. Under Excel semantics that fixture — 10, text, TRUE, empty, 30, all matching the criterion — averages to 41 / 3 ≈ 13.67: text and the empty cell stay ignored, the TRUE counts as 1.

Our preference is to match Excel here, rather than record the current behaviour in docs/guide/list-of-differences.md. AVERAGEIFS is brand-new public surface with no backward-compatibility constraint, the spec is unambiguous, and the alternative means shipping a documented deviation on a function whose whole purpose is Excel parity.


Generated by Claude Code

sequba commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

averageifs duplicates averageif's body — the shared scaffolding should be extracted

averageifs (src/interpreter/plugin/ConditionalAggregationPlugin.ts:228) is structurally a copy of averageif (line 192). Once you set aside how the condition arguments are assembled and the CellError handling, the two are the same code — the reduction tail in particular is character-for-character identical:

// averageif, lines 209-213   ==   averageifs, lines 259-263
if (averageResult instanceof CellError) {
  return averageResult
} else {
  return averageResult.averageValue() ?? new CellError(ErrorType.DIV_BY_ZERO)
}

This isn't a hypothetical maintenance argument — the duplication has already cost a PR. Those two blocks used to disagree: averageif had || where it needed ??, so a legitimate average of 0 came back as #DIV/0!, while the newer averageifs copy was written with ?? from the start. Fixing that needed its own PR (#1733). The divergence is no longer visible here — f4ebe7e merged develop, so both copies now read ?? and I've verified both return 0 for a zero average — but the reason it could happen at all is that the same four lines exist twice.

To be clear about the scope of what I'm suggesting: not one function serving both. The mapping lambda should stay per-function — as I noted in the boolean-handling comment above, Excel deliberately treats TRUE/FALSE differently in AVERAGEIF and AVERAGEIFS, so those two lambdas have to diverge. What's worth extracting is the scaffolding around them:

private computeAverage(
  values: SimpleRangeValue,
  conditionArgs: RawInterpreterValue[],
  functionName: string,
  mapFn: (arg: InternalScalarValue) => AverageResult | CellError,
): InterpreterValue

Both public methods then reduce to assembling their own arguments and passing their own mapFn. One definition of what happens when nothing qualifies, one definition of the CellError short-circuit — so the next fix to either lands in both.

DEV_DOCS asks for exactly this:

Avoid duplication. Extract shared logic instead of copying it, and reuse the existing helpers and abstractions of the codebase.

And this file already demonstrates the pattern: mapToRawScalarValue (line 65) is shared by four call sites across SUMIF/SUMIFS/MINIFS/MAXIFS, and zeroForInfinite (line 57) by two, rather than being inlined into each function.


Generated by Claude Code

@sequba sequba left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One inline note on the Portuguese translation, with a broader ask: the localized names added here should each be confirmed against the sources DEV_DOCS lists, rather than inferred from the neighbouring entries in the same pack — ptPT.ts turns out not to be internally consistent, so its neighbours aren't a safe reference.


Generated by Claude Code

AVERAGE: 'MÉDIA',
AVERAGEA: 'MÉDIAA',
AVERAGEIF: 'MÉDIASE',
AVERAGEIFS: 'MÉDIA.SE.S',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MÉDIA.SE.S doesn't match the naming shape of the rest of this pack — the whole family needs checking against the DEV_DOCS sources

Commit 46ac574 changed this entry from MÉDIASES to MÉDIA.SE.S. The result is that AVERAGEIF and AVERAGEIFS — the same two words, "média" + "se" — are now spelled to two different conventions one line apart:

AVERAGEIF:  'MÉDIASE',      // line 40
AVERAGEIFS: 'MÉDIA.SE.S',   // line 41

The rest of the conditional family in this file:

Function ptPT.ts Function ptPT.ts
SUMIF SOMASE MAXIFS MÁXIMOSES
SUMIFS SOMASES MINIFS MÍNIMOSES
COUNTIF CONT.SE IFS SE.S
COUNTIFS CONT.SES

My read — and this is the part that needs confirming, not taking from me — is that MÉDIASE, SOMASE, SOMASES, MÁXIMOSES and MÍNIMOSES are the pt-BR names, while MÉDIA.SE.S (and SE.S) are the pt-PT ones, so a pack labelled ptPT is mostly populated with Brazilian names. If that's right, this new entry is the correct one and the surrounding pack is what's wrong — which would make this a follow-up ticket on the pack rather than a change to this PR. I'd rather not guess at it either way.

What I'd ask for here: verify every name added in this PR against the sources DEV_DOCS names, rather than deriving them from the neighbouring entries — since, as the table shows, the neighbours are not a reliable guide in this file. DEV_DOCS is specific about where to look:

Only add a localized function name after confirming that Microsoft Excel ships that exact name. If an authoritative source does not provide a localized name, keep the English name instead of translating or inferring one.

with the Functions Translator and dolf.trieschnigg.nl as the primary sources, the localized alphabetical list as the fallback, and this instruction for the fallback path:

Find the link whose URL contains functions/<english-name>-function, then follow it and confirm that the individual function page uses the same localized name in its title and formula syntax. Check each locale independently because Excel keeps some function names in English.

Two other entries in this PR would benefit from the same check, both because they keep the English name:

  • csCZ.tsAVERAGEIFS: 'AVERAGEIFS'. Plausibly correct, since every *IFS in that pack is English.
  • idID.tsAVERAGEIFS: 'AVERAGEIFS', while AVERAGEIF is RATA-RATA.JIKA, MAXIFS is MAKS.JIKAS, MINIFS is MIN.JIKAS and SUMIFS is JUMLAH.JIKAH. Indonesian isn't an Excel locale, so DEV_DOCS routes it to Google Sheets (https://support.google.com/docs/table/25273?hl=id) and permits the English fallback only "for functions that Google Sheets does not list either." Given the MAKS.JIKAS / MIN.JIKAS pattern already in that file, it seems likely Sheets does list a name — but I couldn't reach that page from my environment to confirm, so it needs a human to open it.

The other fourteen look consistent with their packs to me; the ask is just that they've each been checked against a source rather than inferred.


Generated by Claude Code

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for flagging. I verified all 17 names against the DEV_DOCS.md sources. The entries in this PR are correct, including MÉDIA.SE.S for ptPT and AVERAGEIFS for csCZ and idID.

The surrounding ptPT entries have pre-existing inconsistencies. I’ll address those in a separate follow-up PR to keep this PR scoped to AVERAGEIFS.

@sequba sequba left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Three code-quality notes on the new averageifs method, grouped into one review since they all sit within lines 220-256 and none of them blocks the PR:

  1. Line 220 — the JSDoc names the arguments AverageRange/CriterionRange1/Criterion1, while this same PR publishes average_range/criteria_range1/criteria1 through getFunctionDetails and the generated docs page.
  2. Line 241composeFunction is hoisted out of computeFn but the map lambda isn't, so the latter is rebuilt per output cell under vectorization. Neither captures anything; both belong at module level.
  3. Line 248 — the lambda re-implements the CellError/ExtendedNumber dispatch that mapToRawScalarValue (line 65) already provides for the four *IF(S) siblings. Note the sequencing caveat there: if the boolean-handling fix lands, extending the helper is probably better than reusing it as-is.

These are separate from, and smaller than, the two points I raised as top-level comments (Excel boolean semantics, and the averageif/averageifs duplication).


Generated by Claude Code

}

/**
* Corresponds to AVERAGEIFS(AverageRange, CriterionRange1, Criterion1, ...)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The JSDoc names the arguments differently from everything else this PR ships

Here: AverageRange, CriterionRange1, Criterion1 (and again on lines 222-223).

But statistical.ts:44 in this same PR publishes average_range, criteria_range1, criteria1, and those are what reach users — the generated guide page now renders:

AVERAGEIFS(average_range, criteria_range1, criteria1, [criteria_range2, criteria2], ...)

and getFunctionDetails('AVERAGEIFS') returns the same three names. So there are two vocabularies for the same three arguments, and the one in the JSDoc doesn't exist anywhere a user can see it.

Worth aligning the JSDoc to the published names. It's the neighbouring convention too — the AVERAGEIF JSDoc above uses Range/Criterion/AverageRange, which at least match that function's own signature.


Generated by Claude Code

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for flagging. Fixed in commit c6e1fb5. The JSDoc now uses the published argument names average_range, criteria_range1, and criteria1.

}
}

const computeFn = (values: SimpleRangeValue, ...args: unknown[]) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

composeFunction is hoisted out of computeFn but the map lambda isn't — and neither needs to be here at all

composeFunction (line 231) is built once per averageifs() call. The map lambda (lines 248-256) is built inside computeFn, so it's rebuilt on every invocation of computeFn. Under array vectorization that's once per output cell — runFunction in FunctionPlugin.ts:427-431 loops the result array and calls calculateSingleCellOfResultArray (and hence computeFn) per cell.

Two pure functions sitting fifteen lines apart in the same method, one hoisted and one not, with nothing to justify the difference.

Neither captures anything from the enclosing scope — composeFunction closes over only CellError, and the map lambda over CellError, isExtendedNumber, getRawValue and AverageResult, all module-level imports. Neither touches this, functionName, values or args. So both can simply be module-level constants next to the existing zeroForInfinite (line 57) and mapToRawScalarValue (line 65), which is where this file already puts helpers of exactly this kind.

I won't oversell the performance side — the allocation is small next to the range scan it wraps. But DEV_DOCS does ask for attention here:

Consider the computational complexity of every change, especially in code that runs per cell, per formula, or per dependency-graph node.

and moving both out costs nothing and removes the inconsistency.


Generated by Claude Code

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in commit c6e1fb5.

Both helpers are now module-level functions, and computeFn passes their references directly.

functionName,
AverageResult.empty,
composeFunction,
(arg) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This re-implements the three-way split mapToRawScalarValue already does, 180 lines up

mapToRawScalarValue (line 65) is exactly this dispatch — CellError → itself, ExtendedNumber → raw number, anything else → undefined:

function mapToRawScalarValue(arg: InternalScalarValue): Maybe<CellError | RawScalarValue> {
  if (arg instanceof CellError) { return arg }
  if (isExtendedNumber(arg)) { return getRawValue(arg) }
  return undefined
}

It's the shared definition for SUMIF, SUMIFS, MINIFS and MAXIFS (lines 171, 186, 328, 355). This lambda spells the same three branches out again, so "what counts as an error" and "what counts as a number" now have two definitions in one file, and only the four *IF(S) siblings are discoverable to someone grepping for the helper.

It reuses cleanly with a typeof narrowing — no cast needed, unlike the existing call sites:

(arg) => {
  const raw = mapToRawScalarValue(arg)
  if (raw instanceof CellError) { return raw }
  return typeof raw === 'number' ? AverageResult.single(raw) : AverageResult.empty
}

One caveat, and it's why I'd sequence this after the boolean question. If AVERAGEIFS is changed to follow Excel on booleans (my separate comment above — TRUE → 1, FALSE → 0), then this mapper needs a branch mapToRawScalarValue doesn't have, since AVERAGEIF must keep ignoring booleans. At that point the better shape is probably to extend the helper — an optional "coerce booleans to numbers" parameter, defaulting to off — so there's still one definition of the dispatch, rather than a second inline copy that has drifted by one branch. Either way the goal is the same: don't leave two hand-written versions of this in the file.


Generated by Claude Code

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in commit c6e1fb5cc.

mapToAverageResult now delegates scalar classification to mapToRawScalarValue, while preserving AVERAGEIFS error propagation and its verified behavior of ignoring Boolean cells.

@Tobiadefami

Copy link
Copy Markdown
Collaborator Author

AVERAGEIFS drops booleans in average_range; Excel counts them as 1 and 0

Flagging this before merge, since the PR ticks "My change is compatible with Microsoft Excel" and there is a test that currently locks the divergence in.

Repro (verified against this branch at f4ebe7e):

A B
1 =TRUE() y
2 =FALSE() y
3 10 y
=AVERAGEIFS(A1:A3, B1:B3, "y")10. Excel returns 3.667, i.e. (1 + 0 + 10) / 3.

Why Excel returns that. The AVERAGEIFS page linked from HF-140 states:

Cells in average_range that contain TRUE evaluate as 1; cells in average_range that contain FALSE evaluate as 0 (zero).

This is one of the spots where Excel deliberately makes AVERAGEIFS differ from AVERAGEIF — the AVERAGEIF page says the opposite:

Cells in range that contain TRUE or FALSE are ignored.

So boolean handling is not something averageifs can inherit from averageif: the two genuinely need different mapping functions. The implementation here reuses AVERAGEIF's shape, so booleans fall through to AverageResult.empty at src/interpreter/plugin/ConditionalAggregationPlugin.ts:253-255.

Suggested fix. In the map function at lines 248-256, handle booleans explicitly before the AverageResult.empty fallback: trueAverageResult.single(1), falseAverageResult.single(0). Text and blank cells should keep being ignored — that matches Excel too.

Test that needs updating alongside it. In the paired tests PR, unit/interpreter/function-averageifs.spec.ts:187 (ignores non-numeric values in the average range) puts =TRUE() in the averaged range and asserts 20. Under Excel semantics that fixture — 10, text, TRUE, empty, 30, all matching the criterion — averages to 41 / 3 ≈ 13.67: text and the empty cell stay ignored, the TRUE counts as 1.

Our preference is to match Excel here, rather than record the current behaviour in docs/guide/list-of-differences.md. AVERAGEIFS is brand-new public surface with no backward-compatibility constraint, the spec is unambiguous, and the alternative means shipping a documented deviation on a function whose whole purpose is Excel parity.

Generated by Claude Code

Thanks for flagging. I verified this directly in Excel for the web. With TRUE, FALSE, and 10 in average_range, and all three rows matching the criterion, AVERAGEIFS returns 10. This shows that Boolean values in average_range are ignored rather than coerced to 1 and 0. The cited Microsoft documentation refers more generally to cells in “range” and is ambiguous about whether that means average_range.

I have attached the reproduction screenshot for reference.
Screenshot_20260904_203158

@codecov

codecov Bot commented Sep 4, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.32%. Comparing base (c920375) to head (c6e1fb5).

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff            @@
##           develop    #1732   +/-   ##
========================================
  Coverage    97.32%   97.32%           
========================================
  Files          195      195           
  Lines        15739    15762   +23     
  Branches      3390     3467   +77     
========================================
+ Hits         15318    15341   +23     
+ Misses         421      413    -8     
- Partials         0        8    +8     
Files with missing lines Coverage Δ
src/i18n/languages/csCZ.ts 100.00% <ø> (ø)
src/i18n/languages/daDK.ts 100.00% <ø> (ø)
src/i18n/languages/deDE.ts 100.00% <ø> (ø)
src/i18n/languages/enGB.ts 100.00% <ø> (ø)
src/i18n/languages/esES.ts 100.00% <ø> (ø)
src/i18n/languages/fiFI.ts 100.00% <ø> (ø)
src/i18n/languages/frFR.ts 100.00% <ø> (ø)
src/i18n/languages/huHU.ts 100.00% <ø> (ø)
src/i18n/languages/idID.ts 100.00% <ø> (ø)
src/i18n/languages/itIT.ts 100.00% <ø> (ø)
... and 9 more

... and 5 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants