Skip to content

Commit

Permalink
Update deprecations tests to use YAML list (#1996)
Browse files Browse the repository at this point in the history
* Update deprecations tests to use YAML list

* Disable deprecation type tests in the browser

We don't have a good way to make the YAML file accessible to tests
running in a browser, so we can just skip them there.

* Code review
  • Loading branch information
jathak committed May 29, 2024
1 parent dd934e0 commit bf2e3c8
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 103 deletions.
6 changes: 6 additions & 0 deletions js-api-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ if (!fs.existsSync(specIndex)) {
// `node_modules` directory.
fs.copySync(p.resolve(specPath), p.join(sassPackagePath, 'js-api'));

// Copy deprecations YAML so we can test against it.
fs.copySync(
p.resolve(p.join(argv.sassSassRepo, 'spec/deprecations.yaml')),
p.join(sassPackagePath, 'deprecations.yaml')
);

fs.writeFileSync(
p.join(sassPackagePath, 'package.json'),
JSON.stringify({
Expand Down
68 changes: 68 additions & 0 deletions js-api-spec/deprecations.node.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright 2024 Google LLC. Use of this source code is governed by an
// MIT-style license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

import fs from 'fs';
import yaml from 'js-yaml';
import {deprecations, Deprecation, Version} from 'sass';

describe('deprecation type', () => {
const deprecationsMap = deprecations as unknown as {
[key: string]: Deprecation;
};
const obsoleteDeprecations: {[key: string]: [string, string]} = {};
const activeDeprecations: {[key: string]: string} = {};
const futureDeprecations: Set<string> = new Set();
const data = yaml.load(
fs.readFileSync('js-api-spec/node_modules/sass/deprecations.yaml', 'utf8')
) as {
[key: string]: {
'dart-sass':
| {status: 'future'}
| {status: 'active'; deprecated: string}
| {status: 'obsolete'; deprecated: string; obsolete: string};
};
};
for (const [id, deprecation] of Object.entries(data)) {
const dartSass = deprecation['dart-sass'];
if (dartSass.status === 'obsolete') {
obsoleteDeprecations[id] = [dartSass.deprecated, dartSass.obsolete];
} else if (dartSass.status === 'active') {
activeDeprecations[id] = dartSass.deprecated;
} else if (dartSass.status === 'future') {
futureDeprecations.add(id);
}
}

// These tests assume that the JS API being tested is backed by Dart Sass.
// If there's a JS API implementation in the future with a different compiler,
// then these tests shouldn't be run.
for (const [id, versions] of Object.entries(obsoleteDeprecations)) {
if (!versions) continue;
const [deprecatedIn, obsoleteIn] = versions;
it(`${id} deprecated in ${deprecatedIn} and obsolete in ${obsoleteIn}`, () => {
const deprecation = deprecationsMap[id];
expect(deprecation?.id).toBe(id);
expect(deprecation?.status).toBe('obsolete');
expect(deprecation?.deprecatedIn).toEqual(Version.parse(deprecatedIn));
expect(deprecation?.obsoleteIn).toEqual(Version.parse(obsoleteIn));
});
}

for (const [id, version] of Object.entries(activeDeprecations)) {
it(`${id} deprecated in ${version}`, () => {
const deprecation = deprecationsMap[id];
expect(deprecation?.id).toBe(id);
expect(deprecation?.status).toBe('active');
expect(deprecation?.deprecatedIn).toEqual(Version.parse(version));
});
}

for (const id of futureDeprecations) {
it(`${id} is a future deprecation`, () => {
const deprecation = deprecationsMap[id];
expect(deprecation?.id).toBe(id);
expect(deprecation?.status).toBe('future');
});
}
});
103 changes: 0 additions & 103 deletions js-api-spec/deprecations.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,115 +6,12 @@ import {
compileString,
deprecations,
Deprecation,
Deprecations,
Importer,
Version,
} from 'sass';

import {captureStdio, URL} from './utils';

/**
* Map from obsolete deprecation IDs to version pairs.
*
* The first version is the version this deprecation type was deprecated in,
* while the second version is the version it was made obsolete in.
*/
const obsoleteDeprecations: {[key in keyof Deprecations]?: [string, string]} =
{};

/** Map from active deprecation IDs to the version they were deprecated in. */
const activeDeprecations: {[key in keyof Deprecations]?: string} = {
'call-string': '0.0.0',
elseif: '1.3.2',
'moz-document': '1.7.2',
'relative-canonical': '1.14.2',
'new-global': '1.17.2',
'color-module-compat': '1.23.0',
'slash-div': '1.33.0',
'bogus-combinators': '1.54.0',
'strict-unary': '1.55.0',
'function-units': '1.56.0',
'duplicate-var-flags': '1.62.0',
'null-alpha': '1.62.3',
'abs-percent': '1.65.0',
'fs-importer-cwd': '1.73.0',
'css-function-mixin': '1.76.0',
};

/**
* List of future deprecation IDs.
*
* This is only structured as an object to allow us to use a mapped object type
* to ensure that all deprecation IDs listed here are included in the JS API
* spec.
*/
const futureDeprecations: {[key in keyof Deprecations]?: true} = {import: true};

/**
* This is a temporary synchronization check to ensure that any new deprecation
* types are added to all five of these locations:
* - lib/src/deprecation.dart in sass/dart-sass
* - js-api-doc/deprecations.d.ts in sass/sass
* - spec/js-api/deprecations.d.ts.md in sass/sass
* - lib/src/deprecations.ts in sass/embedded-host-node
* - js-api-spec/deprecations.test.ts in sass/sass-spec (this file)
*
* Work to replace these manual changes with generated code from a single
* source-of-truth is tracked in sass/sass#3827
*/
it('there are no extra or missing deprecation types', () => {
const expectedDeprecations = [
...Object.keys(obsoleteDeprecations),
...Object.keys(activeDeprecations),
...Object.keys(futureDeprecations),
'user-authored',
];
const actualDeprecations = Object.keys(deprecations);
const extraDeprecations = actualDeprecations.filter(
deprecation => !expectedDeprecations.includes(deprecation)
);
expect(extraDeprecations).toBeEmptyArray();
const missingDeprecations = expectedDeprecations.filter(
deprecation => !actualDeprecations.includes(deprecation)
);
expect(missingDeprecations).toBeEmptyArray();
});

describe('deprecation type', () => {
const deprecationsMap = deprecations as unknown as {
[key: string]: Deprecation;
};

for (const [id, versions] of Object.entries(obsoleteDeprecations)) {
if (!versions) continue;
const [deprecatedIn, obsoleteIn] = versions;
it(`${id} deprecated in ${deprecatedIn} and obsolete in ${obsoleteIn}`, () => {
const deprecation = deprecationsMap[id];
expect(deprecation?.id).toBe(id);
expect(deprecation?.status).toBe('obsolete');
expect(deprecation?.deprecatedIn).toEqual(Version.parse(deprecatedIn));
expect(deprecation?.obsoleteIn).toEqual(Version.parse(obsoleteIn));
});
}

for (const [id, version] of Object.entries(activeDeprecations)) {
it(`${id} deprecated in ${version}`, () => {
const deprecation = deprecationsMap[id];
expect(deprecation?.id).toBe(id);
expect(deprecation?.status).toBe('active');
expect(deprecation?.deprecatedIn).toEqual(Version.parse(version));
});
}

for (const [id] of Object.entries(futureDeprecations)) {
it(`${id} is a future deprecation`, () => {
const deprecation = deprecationsMap[id];
expect(deprecation?.id).toBe(id);
expect(deprecation?.status).toBe('future');
});
}
});

describe('a warning', () => {
it('is emitted with no flags', done => {
compileString('a { $b: c !global; }', {
Expand Down

0 comments on commit bf2e3c8

Please sign in to comment.