Skip to content

Commit bc28ed2

Browse files
committed
fix
1 parent 34c9eb5 commit bc28ed2

3 files changed

Lines changed: 6 additions & 2 deletions

File tree

packages/postcss-tape/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changes to PostCSS Tape
22

3+
### Unreleased (patch)
4+
5+
- Ignore differences in whitespace sequences when comparing latest and oldest PostCSS versions.
6+
37
### 7.0.0
48

59
_January 14, 2026_
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
/* node:coverage disable */
2-
import e from"node:assert/strict";import t from"node:fs/promises";import s from"node:fs";import o from"node:path";import n from"postcss";import r from"postcss-8.4";import i from"node:test";import a from"node:url";const noopPlugin=()=>({postcssPlugin:"noop-plugin",Once(){}});async function fileContentsOrEmptyString(e){try{return await t.readFile(e,"utf8")}catch{return""}}function reduceInformationInCssSyntaxError(e){process.env.DEBUG||(delete e.source,e.input&&delete e.input.source,delete e.postcssNode)}function postcssTape(a,c){return async p=>{c=c??{},await i("`postcss` flag is set on exported plugin creator",()=>{e.equal(a.postcss,!0)}),await i("exported plugin creator is a function",()=>{e.equal(typeof a,"function")}),await i("`postcssPlugin` is set on a plugin instance",()=>{const t=a();e.ok(t.postcssPlugin),e.equal(typeof t.postcssPlugin,"string")}),await i("package.json",async s=>{const o=await t.readFile("./package.json","utf-8"),n=JSON.parse(o);await s.test('includes "postcss-plugin" keyword',()=>{e.ok(Array.isArray(n.keywords)&&n.keywords?.includes("postcss-plugin"),new PackageDescriptionError('Missing "postcss-plugin" keyword in package.json',"keywords"))}),await s.test('name starts with "postcss-"',{skip:c?.skipPackageNameCheck},()=>{let t="string"==typeof n.name?n.name:"";if(t.startsWith("@")){const e=t.split("/");t=e.slice(1).join("/")}e.ok(t.startsWith("postcss-"),new PackageDescriptionError(`package name "${t}" does not start with "postcss-"`,"name"))}),await s.test("`postcss` is a peer dependency and not a direct dependency",{skip:"postcssTapeSelfTest"in a},()=>{e.ok(Object.keys(Object(n.peerDependencies)).includes("postcss"),new PackageDescriptionError('"postcss" must be listed in "peerDependencies"',"peerDependencies")),e.ok(!Object.keys(Object(n.dependencies)).includes("postcss"),new PackageDescriptionError('"postcss" must not be listed in "dependencies"',"dependencies"))})});const l=a().postcssPlugin;await i(l,async i=>{for(const c in p)await i.test(c,async i=>{const l=p[c];l.before&&await l.before();const u=o.join(".","test",...c.split(":")[0].split(o.posix.sep)),d=o.join(".","test",...c.replace(/:/g,".").split(o.posix.sep)),m="css";let g=`${u}.${m}`,w=`${d}.expect.${m}`,f=`${d}.result.${m}`;l.source&&(g=o.join(".","test",l.source)),l.expect&&(w=o.join(".","test",l.expect)),l.result&&(f=o.join(".","test",l.result));const k=l.plugins??[a(l.options)],h=await fileContentsOrEmptyString(g),y=await fileContentsOrEmptyString(w);let E,x=null;const S=n([noopPlugin()]).version===r([noopPlugin()]).version;try{E=await n(k).process(h,{from:g,to:f,map:{inline:!1,annotation:!1}});try{x=S?null:await r(k).process(h,{from:g,to:f,map:{inline:!1,annotation:!1}})}catch{}}catch(e){if(!(e instanceof Error))throw e;if(reduceInformationInCssSyntaxError(e),l.exception&&l.exception.test(e.message))return;throw e}e.ok(!l.exception,new OutcomeError(`expected an exception matching "${l.exception}"`,g));const P=E.css.toString();{const e=[t.writeFile(f,P,"utf8")];process.env.REWRITE_EXPECTS&&e.push(t.writeFile(w,P,"utf8")),await Promise.all(e)}y||e.ok(s.existsSync(w),new OutcomeError(`Missing expect file: "${w}"`,g)),l.after&&await l.after();const $=await fileContentsOrEmptyString(f);let O=null;try{O=await n([noopPlugin()]).process($,{from:f,to:f,map:{inline:!1,annotation:!1}})}catch{}await i.test("has expected output",()=>{e.deepEqual(P,y),e.deepEqual(E.warnings().length,l.warnings??0,`Unexpected number warnings:\n${E.warnings().toString()}`)}),await i.test("sourcemaps",()=>{e.ok(!E.map.toJSON().sources.includes("<no source>"),'Sourcemap is broken. This is most likely a newly created PostCSS AST Node without a value for "source". See: https://github.com/postcss/postcss/blob/main/docs/guidelines/plugin.md#24-set-nodesource-for-new-nodes')}),await i.test("output is parsable with PostCSS",()=>{e.deepEqual(O?.warnings(),[],"Unexpected warnings on second pass")}),await i.test("The oldest and current PostCSS version produce the same result",{skip:S},()=>{e.deepEqual(x?.css?.toString(),P)})})})}}noopPlugin.postcss=!0;const c={postcssPlugin:"declaration-cloner",Declaration(e){"to-clone"===e.prop&&e.cloneBefore({prop:"cloned"})}},p={postcssPlugin:"rule-cloner",prepare(){const e=new WeakSet;return{postcssPlugin:"rule-cloner",RuleExit(t){e.has(t)||"to-clone"===t.selector&&(e.add(t),t.cloneBefore({selector:"cloned"}))}}}},l={postcssPlugin:"at-rule-cloner",prepare(){const e=new WeakSet;return{postcssPlugin:"at-rule-cloner",AtRuleExit(t){if(!e.has(t))return"to-clone"===t.params?(e.add(t),void t.cloneBefore({params:"cloned"})):void("to-clone"===t.name&&(e.add(t),t.cloneBefore({name:"cloned"})))}}}};class PackageDescriptionError extends Error{constructor(e,t){super(e),this.name="PackageDescriptionError",this.stack=`${this.name}: ${this.message}\n at "${t}" (${a.pathToFileURL(o.resolve("package.json")).href}:1:1)`}}class OutcomeError extends Error{constructor(e,t){super(e),this.name="OutcomeError",this.stack=`${this.name}: ${this.message}\n at ${a.pathToFileURL(o.resolve(t)).href}:1:1`}}export{l as atRuleClonerPlugin,c as declarationClonerPlugin,postcssTape,p as ruleClonerPlugin};
2+
import e from"node:assert/strict";import s from"node:fs/promises";import t from"node:fs";import o from"node:path";import n from"postcss";import r from"postcss-8.4";import i from"node:test";import a from"node:url";const noopPlugin=()=>({postcssPlugin:"noop-plugin",Once(){}});async function fileContentsOrEmptyString(e){try{return await s.readFile(e,"utf8")}catch{return""}}function reduceInformationInCssSyntaxError(e){process.env.DEBUG||(delete e.source,e.input&&delete e.input.source,delete e.postcssNode)}function postcssTape(a,c){return async p=>{c=c??{},await i("`postcss` flag is set on exported plugin creator",()=>{e.equal(a.postcss,!0)}),await i("exported plugin creator is a function",()=>{e.equal(typeof a,"function")}),await i("`postcssPlugin` is set on a plugin instance",()=>{const s=a();e.ok(s.postcssPlugin),e.equal(typeof s.postcssPlugin,"string")}),await i("package.json",async t=>{const o=await s.readFile("./package.json","utf-8"),n=JSON.parse(o);await t.test('includes "postcss-plugin" keyword',()=>{e.ok(Array.isArray(n.keywords)&&n.keywords?.includes("postcss-plugin"),new PackageDescriptionError('Missing "postcss-plugin" keyword in package.json',"keywords"))}),await t.test('name starts with "postcss-"',{skip:c?.skipPackageNameCheck},()=>{let s="string"==typeof n.name?n.name:"";if(s.startsWith("@")){const e=s.split("/");s=e.slice(1).join("/")}e.ok(s.startsWith("postcss-"),new PackageDescriptionError(`package name "${s}" does not start with "postcss-"`,"name"))}),await t.test("`postcss` is a peer dependency and not a direct dependency",{skip:"postcssTapeSelfTest"in a},()=>{e.ok(Object.keys(Object(n.peerDependencies)).includes("postcss"),new PackageDescriptionError('"postcss" must be listed in "peerDependencies"',"peerDependencies")),e.ok(!Object.keys(Object(n.dependencies)).includes("postcss"),new PackageDescriptionError('"postcss" must not be listed in "dependencies"',"dependencies"))})});const l=a().postcssPlugin;await i(l,async i=>{for(const c in p)await i.test(c,async i=>{const l=p[c];l.before&&await l.before();const u=o.join(".","test",...c.split(":")[0].split(o.posix.sep)),d=o.join(".","test",...c.replace(/:/g,".").split(o.posix.sep)),m="css";let g=`${u}.${m}`,w=`${d}.expect.${m}`,f=`${d}.result.${m}`;l.source&&(g=o.join(".","test",l.source)),l.expect&&(w=o.join(".","test",l.expect)),l.result&&(f=o.join(".","test",l.result));const k=l.plugins??[a(l.options)],h=await fileContentsOrEmptyString(g),y=await fileContentsOrEmptyString(w);let E,x=null;const S=n([noopPlugin()]).version===r([noopPlugin()]).version;try{E=await n(k).process(h,{from:g,to:f,map:{inline:!1,annotation:!1}});try{x=S?null:await r(k).process(h,{from:g,to:f,map:{inline:!1,annotation:!1}})}catch{}}catch(e){if(!(e instanceof Error))throw e;if(reduceInformationInCssSyntaxError(e),l.exception&&l.exception.test(e.message))return;throw e}e.ok(!l.exception,new OutcomeError(`expected an exception matching "${l.exception}"`,g));const P=E.css.toString();{const e=[s.writeFile(f,P,"utf8")];process.env.REWRITE_EXPECTS&&e.push(s.writeFile(w,P,"utf8")),await Promise.all(e)}y||e.ok(t.existsSync(w),new OutcomeError(`Missing expect file: "${w}"`,g)),l.after&&await l.after();const $=await fileContentsOrEmptyString(f);let O=null;try{O=await n([noopPlugin()]).process($,{from:f,to:f,map:{inline:!1,annotation:!1}})}catch{}await i.test("has expected output",()=>{e.deepEqual(P,y),e.deepEqual(E.warnings().length,l.warnings??0,`Unexpected number warnings:\n${E.warnings().toString()}`)}),await i.test("sourcemaps",()=>{e.ok(!E.map.toJSON().sources.includes("<no source>"),'Sourcemap is broken. This is most likely a newly created PostCSS AST Node without a value for "source". See: https://github.com/postcss/postcss/blob/main/docs/guidelines/plugin.md#24-set-nodesource-for-new-nodes')}),await i.test("output is parsable with PostCSS",()=>{e.deepEqual(O?.warnings(),[],"Unexpected warnings on second pass")}),await i.test("The oldest and current PostCSS version produce the same result",{skip:S},()=>{e.deepEqual(x?.css?.toString()?.replaceAll(/\s+/g," "),P.replaceAll(/\s+/g," "))})})})}}noopPlugin.postcss=!0;const c={postcssPlugin:"declaration-cloner",Declaration(e){"to-clone"===e.prop&&e.cloneBefore({prop:"cloned"})}},p={postcssPlugin:"rule-cloner",prepare(){const e=new WeakSet;return{postcssPlugin:"rule-cloner",RuleExit(s){e.has(s)||"to-clone"===s.selector&&(e.add(s),s.cloneBefore({selector:"cloned"}))}}}},l={postcssPlugin:"at-rule-cloner",prepare(){const e=new WeakSet;return{postcssPlugin:"at-rule-cloner",AtRuleExit(s){if(!e.has(s))return"to-clone"===s.params?(e.add(s),void s.cloneBefore({params:"cloned"})):void("to-clone"===s.name&&(e.add(s),s.cloneBefore({name:"cloned"})))}}}};class PackageDescriptionError extends Error{constructor(e,s){super(e),this.name="PackageDescriptionError",this.stack=`${this.name}: ${this.message}\n at "${s}" (${a.pathToFileURL(o.resolve("package.json")).href}:1:1)`}}class OutcomeError extends Error{constructor(e,s){super(e),this.name="OutcomeError",this.stack=`${this.name}: ${this.message}\n at ${a.pathToFileURL(o.resolve(s)).href}:1:1`}}export{l as atRuleClonerPlugin,c as declarationClonerPlugin,postcssTape,p as ruleClonerPlugin};
33
/* node:coverage enable */

packages/postcss-tape/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ export function postcssTape(pluginCreator: PluginCreator<unknown>, runOptions?:
281281
'The oldest and current PostCSS version produce the same result',
282282
{ skip: olderVersionAndCurrentVersionAreTheSame },
283283
() => {
284-
assert.deepEqual(resultFromOldestPostCSS?.css?.toString(), resultString);
284+
assert.deepEqual(resultFromOldestPostCSS?.css?.toString()?.replaceAll(/\s+/g, ' '), resultString.replaceAll(/\s+/g, ' '));
285285
},
286286
);
287287
});

0 commit comments

Comments
 (0)