Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide an approved method to get a status for a single BCD key #1204

Merged
merged 10 commits into from
Jun 17, 2024
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

55 changes: 45 additions & 10 deletions packages/compute-baseline/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,21 @@

By the [W3C WebDX Community Group](https://www.w3.org/community/webdx/) and contributors.

`compute-baseline` computes preliminary [Baseline statuses](https://github.com/web-platform-dx/web-features/blob/main/docs/baseline.md) from `@mdn/browser-compat-data` feature keys.
`compute-baseline` computes [Baseline statuses](https://github.com/web-platform-dx/web-features/blob/main/docs/baseline.md) from `@mdn/browser-compat-data` feature keys.
You can use `compute-baseline` to help you find interoperable web platform features, propose new [`web-features`](https://github.com/web-platform-dx/web-features/) features, or compare support between features.

`compute-baseline` also provides utility classes for working with `@mdn/browser-compat-data` generally.

## Limitations

If you need authoritative Baseline statuses, check out the [`web-features`](https://github.com/web-platform-dx/web-features/tree/main/packages/web-features) package instead.
If you need authoritative Baseline statuses, check out the [`web-features`](https://github.com/web-platform-dx/web-features/tree/main/packages/web-features) package first.
Most of the time, the status information provided by `web-features` is the best representation of a feature overall.

Don't use `compute-baseline` to generate publishable Baseline statuses for arbitrary web platform features.
The results of `compute-baseline` invocations have _not_ received editorial review.
Strictly speaking, a Baseline status requires editorial review, so statuses generated by `compute-baseline` are tentative.
If you need authoritative Baseline statuses, check out the [`web-features`](https://github.com/web-platform-dx/web-features/tree/main/packages/web-features) package instead.

You can use `compute-baseline` to explore possibilities or do error correction.
For example, you might use `compute-baseline` to hide a Baseline status, when showing a broader feature's status might be misleading.
If you need to know the Baseline status of a specific browser compatibility data entry within a `web-features` feature, then you can use the `getStatus` method.
The `web-features` package and the `getStatus` method are the **only** ways to get a status that have completed the full Baseline editorial review process.
Copy link
Collaborator

Choose a reason for hiding this comment

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

In order for this to be accurate, we need a way to review the individual statuses. Grouping compat keys by their generated status with comments is the approach we've discussed.


All other invocations of `compute-baseline` have _not_ received editorial review.
Don't use `compute-baseline` to generate publishable Baseline statuses for arbitrary web platform features.
If you're not sure whether your application fits with the definition of Baseline, please [file an issue](https://github.com/web-platform-dx/web-features/issues/new).

## Prerequisites
Expand All @@ -40,8 +38,41 @@ Run:

## Usage

### Get a Baseline status for a portion of a feature

ddbeck marked this conversation as resolved.
Show resolved Hide resolved
To get a Baseline status for a specific browser compatibility data entry within a `web-features` feature, call `getStatus` with the web feature's ID and the BCD feature key as parameters, as shown below:

<!-- TODO: replace getStatus("fetch", "api.Response.json") with a call that produces different results than the main feature status, when there is one -->

```javascript
import { getStatus } from "compute-baseline";

getStatus("fetch", "api.Response.json");
ddbeck marked this conversation as resolved.
Show resolved Hide resolved
```

Returns:

```
{
baseline: 'high',
baseline_low_date: '2017-03-27',
baseline_high_date: '2019-09-27',
support: {
chrome: '42',
chrome_android: '42',
edge: '14',
firefox: '39',
firefox_android: '39',
safari: '10.1',
safari_ios: '10.3'
}
}
```

### Check support for a group of compat keys

ddbeck marked this conversation as resolved.
Show resolved Hide resolved
**Note**: This example returns support data that has not received an editorial review. Do not use for presenting a Baseline status. See [Limitations](#limitations).

```javascript
import { computeBaseline } from "compute-baseline";

Expand Down Expand Up @@ -73,6 +104,8 @@ Use the `toJSON()` method to get a `web-features`-like plain JSON representation

### Check support for a single support key

**Note**: This example returns support data that has not received an editorial review. Do not use for presenting a Baseline status. See [Limitations](#limitations).

Sometimes it can be helpful to know if parent features have less support than the specific feature you're checking (for example, the parent is behind a prefix or flag) when computing a status for a deeply-nested feature.
This is typically most interesting when checking a single key.
Use the `withAncestors` option:
Expand All @@ -88,7 +121,9 @@ computeBaseline({

### Bring your own compatibility data

If you don't want to import `@mdn/browser-compat-data` as your data source, you can bring your own schema-compatible compat data.
**Note**: This example returns support data that has not received an editorial review. Do not use for presenting a Baseline status. See [Limitations](#limitations).

If you want to use some other source of data (such as pre-release browser-compat-data), you can bring your own schema-compatible compat data.

```javascript
import data from "some-parsed-json-file";
Expand Down
2 changes: 1 addition & 1 deletion packages/compute-baseline/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "compute-baseline",
"version": "0.1.1",
"version": "0.2.0",
"description": "A library for computing web-features statuses from browser compatibility data",
"exports": {
".": "./dist/baseline/index.js",
Expand Down
18 changes: 17 additions & 1 deletion packages/compute-baseline/src/baseline/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,26 @@ import { Temporal } from "@js-temporal/polyfill";
import * as chai from "chai";
import chaiJestSnapshot from "chai-jest-snapshot";

import { computeBaseline, keystoneDateToStatus } from "./index.js";
import { computeBaseline, getStatus, keystoneDateToStatus } from "./index.js";

chai.use(chaiJestSnapshot);

describe("getStatus", function () {
before(function () {
chaiJestSnapshot.resetSnapshotRegistry();
});

beforeEach(function () {
chaiJestSnapshot.configureUsingMochaContext(this);
});

it("returns a status", function () {
const result = getStatus("fetch", "api.Response.json");
assert.equal(result.baseline, "high");
chai.expect(result).to.matchSnapshot();
});
});

describe("computeBaseline", function () {
before(function () {
chaiJestSnapshot.resetSnapshotRegistry();
Expand Down
17 changes: 17 additions & 0 deletions packages/compute-baseline/src/baseline/index.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,20 @@ Object {
}",
}
`;

exports[`getStatus returns a status 1`] = `
Object {
"baseline": "high",
"baseline_high_date": "2019-09-27",
"baseline_low_date": "2017-03-27",
"support": Object {
"chrome": "42",
"chrome_android": "42",
"edge": "14",
"firefox": "39",
"firefox_android": "39",
"safari": "10.1",
"safari_ios": "10.3",
},
}
`;
43 changes: 39 additions & 4 deletions packages/compute-baseline/src/baseline/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export const BASELINE_LOW_TO_HIGH_DURATION = Temporal.Duration.from({
type BaselineStatus = "low" | "high" | false;
type BaselineDate = string | null;

interface SupportStatus {
interface SupportDetails {
compatKey?: string;
baseline: BaselineStatus;
baseline_low_date: BaselineDate;
Expand All @@ -44,6 +44,41 @@ interface SupportStatus {
toJSON: () => string;
}

// TODO: Use a type from `web-features` directly, instead of approximating it here
interface SupportStatus {
baseline: "low" | "high" | false;
baseline_low_date: string;
baseline_high_date?: string;
support: Record<string, string>;
}

/**
* Calculate a Baseline status for specific browser compat data keys within a
* web-features feature, in the style of a web-feature's `status` key. Use this
* method to calculate fine-grained support statuses. This is the only method
* approved to compute Baseline statuses not otherwise published in the
* `web-features` package.
*
* For example, suppose you want to show a Baseline status for a specific method
* in a feature, which might've been supported earlier or later than the broader
* feature overall. Then you'd call `getStatus('example-feature',
* 'api.ExampleManager.doExample')`.
*/
export function getStatus(
featureId: string,
compatKey: string,
compat: Compat = defaultCompat,
): SupportStatus {
// TODO: actually check that featureId is a valid feature
// TODO: actually check that compatKey is tagged as featureId in BCD _or_ listed in web-features
Comment on lines +72 to +73
Copy link
Contributor

Choose a reason for hiding this comment

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

Are you planning on implementing those TODOs in this PR?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I am not. This requires some non-trivial changes to the way the repo and dependencies are set up, which would overwhelm the policy and documentation changes going on here.

return JSON.parse(
computeBaseline(
{ compatKeys: [compatKey], checkAncestors: true },
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you add a test that shows the difference between checkAncestors being true or false? Is it about flags that aren't correctly cascaded?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is already tested with

it("finds discrepancies with ancestors (checkAncestors)", function () {
const result = computeBaseline({
compatKeys: ["api.Notification.body"],
checkAncestors: false,
});
const resultExplicit = computeBaseline({
compatKeys: ["api.Notification", "api.Notification.body"],
checkAncestors: false,
});
const resultWithAncestors = computeBaseline({
compatKeys: ["api.Notification.body"],
checkAncestors: true,
});
assert.equal(resultExplicit.toJSON(), resultWithAncestors.toJSON());
assert.notEqual(result.toJSON(), resultWithAncestors.toJSON());
assert.notEqual(result.baseline, resultWithAncestors.baseline);
assert.notEqual(
result.baseline_low_date?.toString(),
resultWithAncestors.baseline_low_date?.toString(),
);
chai.expect(result).to.matchSnapshot();
chai.expect(resultExplicit).to.matchSnapshot();
chai.expect(resultWithAncestors).to.matchSnapshot();
});
. Do you want another test to confirm that getStatus does the same?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ah, existing tests are OK.

compat,
).toJSON(),
);
}

/**
* Given a set of compat keys, compute the aggregate Baseline support ("high",
* "low" or false, dates, and releases) for those keys.
Expand All @@ -54,7 +89,7 @@ export function computeBaseline(
checkAncestors?: boolean;
},
compat: Compat = defaultCompat,
): SupportStatus {
): SupportDetails {
const { compatKeys } = featureSelector;
const keys = featureSelector.checkAncestors
? compatKeys.flatMap((key) => withAncestors(key, compat))
Expand Down Expand Up @@ -88,7 +123,7 @@ export function computeBaseline(
* Compute the Baseline support ("high", "low" or false, dates, and releases)
* for a single compat key.
*/
function calculate(compatKey: string, compat: Compat): SupportStatus {
function calculate(compatKey: string, compat: Compat): SupportDetails {
const f = feature(compatKey);
const s = support(f, browsers(compat));
const keystoneDate = findKeystoneDate([...s.values()]);
Expand Down Expand Up @@ -227,7 +262,7 @@ function findKeystoneDate(
return latestDate;
}

function jsonify(status: SupportStatus): string {
function jsonify(status: SupportDetails): string {
const { baseline_low_date, baseline_high_date } = status;
const support: Record<string, string> = {};

Expand Down
Loading