From 4260ecf1ff4ba38f5f068c642158f4cc1a4815e5 Mon Sep 17 00:00:00 2001 From: "voxel!()" Date: Sun, 4 Feb 2024 11:58:44 -0800 Subject: [PATCH] chore(`@astrojs/rss`): Migrate tests to `node:test` (#9939) * Progressively add new tests (remove old later) * Finalize tests * Remove unused comments * Assert that errors are not present and add jsdocs to util function * Fix * Remove mocha deps --- packages/astro-rss/package.json | 15 ++--- .../test/pagesGlobToRssItems.test.js | 25 +++---- packages/astro-rss/test/rss.test.js | 55 +++++++++------- packages/astro-rss/test/test-utils.js | 19 ++++++ pnpm-lock.yaml | 66 ++++--------------- 5 files changed, 82 insertions(+), 98 deletions(-) diff --git a/packages/astro-rss/package.json b/packages/astro-rss/package.json index 2c12c75bba..d7d117be4d 100644 --- a/packages/astro-rss/package.json +++ b/packages/astro-rss/package.json @@ -17,25 +17,18 @@ ".": "./dist/index.js", "./package.json": "./package.json" }, - "files": [ - "dist" - ], + "files": ["dist"], "scripts": { "build": "astro-scripts build \"src/**/*.ts\" && tsc", "build:ci": "astro-scripts build \"src/**/*.ts\"", "dev": "astro-scripts dev \"src/**/*.ts\"", - "test": "mocha --exit --timeout 20000" + "test": "astro-scripts test \"test/**/*.test.js\"" }, "devDependencies": { - "@types/chai": "^4.3.10", - "@types/chai-as-promised": "^7.1.8", - "@types/mocha": "^10.0.4", + "@types/xml2js": "^0.4.14", "astro": "workspace:*", "astro-scripts": "workspace:*", - "chai": "^4.3.7", - "chai-as-promised": "^7.1.1", - "chai-xml": "^0.4.1", - "mocha": "^10.2.0" + "xml2js": "0.6.2" }, "dependencies": { "fast-xml-parser": "^4.2.7", diff --git a/packages/astro-rss/test/pagesGlobToRssItems.test.js b/packages/astro-rss/test/pagesGlobToRssItems.test.js index d0b944ac83..b590daa382 100644 --- a/packages/astro-rss/test/pagesGlobToRssItems.test.js +++ b/packages/astro-rss/test/pagesGlobToRssItems.test.js @@ -1,10 +1,9 @@ -import chai from 'chai'; -import chaiPromises from 'chai-as-promised'; +import assert from 'node:assert/strict'; +import { describe, it } from 'node:test'; + import { phpFeedItem, web1FeedItem } from './test-utils.js'; import { pagesGlobToRssItems } from '../dist/index.js'; -chai.use(chaiPromises); - describe('pagesGlobToRssItems', () => { it('should generate on valid result', async () => { const globResult = { @@ -33,8 +32,7 @@ describe('pagesGlobToRssItems', () => { }; const items = await pagesGlobToRssItems(globResult); - - chai.expect(items.sort((a, b) => a.pubDate - b.pubDate)).to.deep.equal([ + const expected = [ { title: phpFeedItem.title, link: phpFeedItem.link, @@ -47,7 +45,12 @@ describe('pagesGlobToRssItems', () => { pubDate: new Date(web1FeedItem.pubDate), description: web1FeedItem.description, }, - ]); + ]; + + assert.deepStrictEqual( + items.sort((a, b) => a.pubDate - b.pubDate), + expected + ); }); it('should fail on missing "url"', () => { @@ -63,7 +66,7 @@ describe('pagesGlobToRssItems', () => { }) ), }; - return chai.expect(pagesGlobToRssItems(globResult)).to.be.rejected; + return assert.rejects(pagesGlobToRssItems(globResult)); }); it('should fail on missing "title" key and "description"', () => { @@ -80,7 +83,7 @@ describe('pagesGlobToRssItems', () => { }) ), }; - return chai.expect(pagesGlobToRssItems(globResult)).to.be.rejected; + return assert.rejects(pagesGlobToRssItems(globResult)); }); it('should not fail on missing "title" key if "description" is present', () => { @@ -97,7 +100,7 @@ describe('pagesGlobToRssItems', () => { }) ), }; - return chai.expect(pagesGlobToRssItems(globResult)).to.not.be.rejected; + return assert.doesNotReject(pagesGlobToRssItems(globResult)); }); it('should not fail on missing "description" key if "title" is present', () => { @@ -114,6 +117,6 @@ describe('pagesGlobToRssItems', () => { }) ), }; - return chai.expect(pagesGlobToRssItems(globResult)).to.not.be.rejected; + return assert.doesNotReject(pagesGlobToRssItems(globResult)); }); }); diff --git a/packages/astro-rss/test/rss.test.js b/packages/astro-rss/test/rss.test.js index d32c420f16..dea3e77878 100644 --- a/packages/astro-rss/test/rss.test.js +++ b/packages/astro-rss/test/rss.test.js @@ -1,6 +1,6 @@ -import chai from 'chai'; -import chaiPromises from 'chai-as-promised'; -import chaiXml from 'chai-xml'; +import assert from 'node:assert/strict'; +import { describe, it } from 'node:test'; + import { z } from 'astro/zod'; import rss, { getRssString } from '../dist/index.js'; import { rssSchema } from '../dist/schema.js'; @@ -14,11 +14,9 @@ import { web1FeedItem, web1FeedItemWithAllData, web1FeedItemWithContent, + parseXmlString, } from './test-utils.js'; -chai.use(chaiPromises); -chai.use(chaiXml); - // note: I spent 30 minutes looking for a nice node-based snapshot tool // ...and I gave up. Enjoy big strings! // prettier-ignore @@ -34,6 +32,15 @@ const validXmlWithStylesheet = `<![CDATA[${title}]]>${site}/`; +function assertXmlDeepEqual(a, b) { + const parsedA = parseXmlString(a); + const parsedB = parseXmlString(b); + + assert.strictEqual(parsedA.err, null); + assert.strictEqual(parsedB.err, null); + assert.deepStrictEqual(parsedA.result, parsedB.result); +} + describe('rss', () => { it('should return a response', async () => { const response = await rss({ @@ -44,10 +51,14 @@ describe('rss', () => { }); const str = await response.text(); - chai.expect(str).xml.to.equal(validXmlResult); + + // NOTE: Chai used the below parser to perform the tests, but I have omitted it for now. + // parser = new xml2js.Parser({ trim: flag(this, 'deep') }); + + assertXmlDeepEqual(str, validXmlResult); const contentType = response.headers.get('Content-Type'); - chai.expect(contentType).to.equal('application/xml'); + assert.strictEqual(contentType, 'application/xml'); }); it('should be the same string as getRssString', async () => { @@ -62,7 +73,7 @@ describe('rss', () => { const str1 = await response.text(); const str2 = await getRssString(options); - chai.expect(str1).to.equal(str2); + assert.strictEqual(str1, str2); }); }); @@ -75,7 +86,7 @@ describe('getRssString', () => { site, }); - chai.expect(str).xml.to.equal(validXmlResult); + assertXmlDeepEqual(str, validXmlResult); }); it('should generate on valid RSSFeedItem array with HTML content included', async () => { @@ -86,7 +97,7 @@ describe('getRssString', () => { site, }); - chai.expect(str).xml.to.equal(validXmlWithContentResult); + assertXmlDeepEqual(str, validXmlWithContentResult); }); it('should generate on valid RSSFeedItem array with all RSS content included', async () => { @@ -97,7 +108,7 @@ describe('getRssString', () => { site, }); - chai.expect(str).xml.to.equal(validXmlResultWithAllData); + assertXmlDeepEqual(str, validXmlResultWithAllData); }); it('should generate on valid RSSFeedItem array with custom data included', async () => { @@ -111,7 +122,7 @@ describe('getRssString', () => { site, }); - chai.expect(str).xml.to.equal(validXmlWithCustomDataResult); + assertXmlDeepEqual(str, validXmlWithCustomDataResult); }); it('should include xml-stylesheet instruction when stylesheet is defined', async () => { @@ -123,7 +134,7 @@ describe('getRssString', () => { stylesheet: '/feedstylesheet.css', }); - chai.expect(str).xml.to.equal(validXmlWithStylesheet); + assertXmlDeepEqual(str, validXmlWithStylesheet); }); it('should include xml-stylesheet instruction with xsl type when stylesheet is set to xsl file', async () => { @@ -135,7 +146,7 @@ describe('getRssString', () => { stylesheet: '/feedstylesheet.xsl', }); - chai.expect(str).xml.to.equal(validXmlWithXSLStylesheet); + assertXmlDeepEqual(str, validXmlWithXSLStylesheet); }); it('should preserve self-closing tags on `customData`', async () => { @@ -152,7 +163,7 @@ describe('getRssString', () => { customData, }); - chai.expect(str).to.contain(customData); + assert.ok(str.includes(customData)); }); it('should not append trailing slash to URLs with the given option', async () => { @@ -164,8 +175,8 @@ describe('getRssString', () => { trailingSlash: false, }); - chai.expect(str).xml.to.contain('https://example.com/<'); - chai.expect(str).xml.to.contain('https://example.com/php<'); + assert.ok(str.includes('https://example.com/<')); + assert.ok(str.includes('https://example.com/php<')); }); it('Deprecated import.meta.glob mapping still works', async () => { @@ -201,7 +212,7 @@ describe('getRssString', () => { site, }); - chai.expect(str).xml.to.equal(validXmlResult); + assertXmlDeepEqual(str, validXmlResult); }); it('should fail when an invalid date string is provided', async () => { @@ -212,8 +223,8 @@ describe('getRssString', () => { link: phpFeedItem.link, }); - chai.expect(res.success).to.be.false; - chai.expect(res.error.issues[0].path[0]).to.equal('pubDate'); + assert.strictEqual(res.success, false); + assert.strictEqual(res.error.issues[0].path[0], 'pubDate'); }); it('should be extendable', () => { @@ -225,7 +236,7 @@ describe('getRssString', () => { } catch (e) { error = e.message; } - chai.expect(error).to.be.null; + assert.strictEqual(error, null); }); it('should not fail when an enclosure has a length of 0', async () => { diff --git a/packages/astro-rss/test/test-utils.js b/packages/astro-rss/test/test-utils.js index 4f03403336..dcc57df21f 100644 --- a/packages/astro-rss/test/test-utils.js +++ b/packages/astro-rss/test/test-utils.js @@ -1,3 +1,5 @@ +import xml2js from 'xml2js'; + export const title = 'My RSS feed'; export const description = 'This sure is a nice RSS feed'; export const site = 'https://example.com'; @@ -45,3 +47,20 @@ export const web1FeedItemWithAllData = { type: 'audio/mpeg', }, }; + +const parser = new xml2js.Parser({ trim: true }); + +/** + * + * Utility function to parse an XML string into an object using `xml2js`. + * + * @param {string} xmlString - Stringified XML to parse. + * @return {{ err: Error, result: any }} Represents an option containing the parsed XML string or an Error. + */ +export function parseXmlString(xmlString) { + let res; + parser.parseString(xmlString, (err, result) => { + res = { err, result }; + }); + return res; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fa60b71911..193bb1ae73 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -849,33 +849,18 @@ importers: specifier: ^4.1.5 version: 4.1.5 devDependencies: - '@types/chai': - specifier: ^4.3.10 - version: 4.3.11 - '@types/chai-as-promised': - specifier: ^7.1.8 - version: 7.1.8 - '@types/mocha': - specifier: ^10.0.4 - version: 10.0.6 + '@types/xml2js': + specifier: ^0.4.14 + version: 0.4.14 astro: specifier: workspace:* version: link:../astro astro-scripts: specifier: workspace:* version: link:../../scripts - chai: - specifier: ^4.3.7 - version: 4.3.10 - chai-as-promised: - specifier: ^7.1.1 - version: 7.1.1(chai@4.3.10) - chai-xml: - specifier: ^0.4.1 - version: 0.4.1(chai@4.3.10) - mocha: - specifier: ^10.2.0 - version: 10.2.0 + xml2js: + specifier: 0.6.2 + version: 0.6.2 packages/astro/e2e/fixtures/_deps/astro-linked-lib: dependencies: @@ -7276,12 +7261,6 @@ packages: resolution: {integrity: sha512-fNyZ/Fdw/Y92X0vv7B+BD6ysHL4xVU5dJcgzgxLdGbn8O3PezZNIJpml44lKM0nsGur+o/6+NZbZeNTt00U1uA==} dev: false - /@types/chai-as-promised@7.1.8: - resolution: {integrity: sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw==} - dependencies: - '@types/chai': 4.3.11 - dev: true - /@types/chai@4.3.11: resolution: {integrity: sha512-qQR1dr2rGIHYlJulmr8Ioq3De0Le9E4MJ5AiaeAETJJpndT1uUNHsGFK3L/UIu+rbkQSdj8J/w2bCsBZc/Y5fQ==} dev: true @@ -7570,6 +7549,12 @@ packages: resolution: {integrity: sha512-M0ZefeDApctHbjqtATOiixiwafG7pXD3exxnjku4XmX9+2DmONGghv5Z8Pnm0lNLBZKvDQyuG+4pLkH2UkP5gg==} dev: true + /@types/xml2js@0.4.14: + resolution: {integrity: sha512-4YnrRemBShWRO2QjvUin8ESA41rH+9nQGLUGZV/1IDhi3SL9OhdpNC/MrulTWuptXKwhx/aDxE7toV0f/ypIXQ==} + dependencies: + '@types/node': 18.19.4 + dev: true + /@types/yargs-parser@21.0.3: resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} dev: true @@ -8608,15 +8593,6 @@ packages: /ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} - /chai-as-promised@7.1.1(chai@4.3.10): - resolution: {integrity: sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==} - peerDependencies: - chai: '>= 2.1.2 < 5' - dependencies: - chai: 4.3.10 - check-error: 1.0.3 - dev: true - /chai-jest-snapshot@2.0.0(chai@4.3.10): resolution: {integrity: sha512-u8jZZjw/0G1t5A8wDfH6K7DAVfMg3g0dsw9wKQURNUyrZX96VojHNrFMmLirq1m0kOvC5icgL/Qh/fu1MZyvUw==} peerDependencies: @@ -8627,16 +8603,6 @@ packages: lodash.values: 4.3.0 dev: true - /chai-xml@0.4.1(chai@4.3.10): - resolution: {integrity: sha512-VUf5Ol4ifOAsgz+lN4tfWENgQtrKxHPWsmpL5wdbqQdkpblZkcDlaT2aFvsPQH219Yvl8vc4064yFErgBIn9bw==} - engines: {node: '>= 0.8.0'} - peerDependencies: - chai: '>=1.10.0 ' - dependencies: - chai: 4.3.10 - xml2js: 0.5.0 - dev: true - /chai@4.3.10: resolution: {integrity: sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==} engines: {node: '>=4'} @@ -16159,14 +16125,6 @@ packages: engines: {node: '>=12'} dev: true - /xml2js@0.5.0: - resolution: {integrity: sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==} - engines: {node: '>=4.0.0'} - dependencies: - sax: 1.3.0 - xmlbuilder: 11.0.1 - dev: true - /xml2js@0.6.2: resolution: {integrity: sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==} engines: {node: '>=4.0.0'}