From 1bda87944cb8922332689c374acaffddefd6c668 Mon Sep 17 00:00:00 2001 From: Eric Liu Date: Sat, 8 Feb 2025 11:29:21 -0800 Subject: [PATCH] test: add more coverage (#78) --- tests/OptimizeCssPlugin.test.ts | 138 ++++++++++++++++++++++++++++++++ tests/extract-selectors.test.ts | 73 ++++++++++------- tests/utils.test.ts | 56 +++++++++++++ 3 files changed, 240 insertions(+), 27 deletions(-) create mode 100644 tests/OptimizeCssPlugin.test.ts create mode 100644 tests/utils.test.ts diff --git a/tests/OptimizeCssPlugin.test.ts b/tests/OptimizeCssPlugin.test.ts new file mode 100644 index 0000000..fa9bca9 --- /dev/null +++ b/tests/OptimizeCssPlugin.test.ts @@ -0,0 +1,138 @@ +import { CarbonSvelte } from "../src/constants"; +import OptimizeCssPlugin from "../src/plugins/OptimizeCssPlugin"; + +// Mock webpack compiler and related types +const createMockCompiler = (options: any = {}) => { + const { assets = {}, fileDependencies = [] } = options; + + const compilation = { + hooks: { + processAssets: { + tap: jest.fn((_, callback) => { + callback(assets); + }), + }, + }, + updateAsset: jest.fn(), + }; + + const normalModuleHooks = { + beforeSnapshot: { + tap: jest.fn((_, callback) => { + callback({ buildInfo: { fileDependencies } }); + }), + }, + }; + + return { + hooks: { + thisCompilation: { + tap: jest.fn((_, callback) => callback(compilation)), + }, + }, + webpack: { + Compilation: { + PROCESS_ASSETS_STAGE_DERIVED: "PROCESS_ASSETS_STAGE_DERIVED", + }, + NormalModule: { + getCompilationHooks: () => normalModuleHooks, + }, + sources: { + RawSource: jest.fn((content) => ({ source: () => content })), + }, + }, + compilation, + normalModuleHooks, + }; +}; + +describe("OptimizeCssPlugin", () => { + test("constructor sets default options correctly", () => { + const plugin = new OptimizeCssPlugin(); + expect((plugin as any).options).toEqual({ + verbose: true, + preserveAllIBMFonts: false, + }); + }); + + test("constructor respects provided options", () => { + const plugin = new OptimizeCssPlugin({ + verbose: false, + preserveAllIBMFonts: true, + }); + expect((plugin as any).options).toEqual({ + verbose: false, + preserveAllIBMFonts: true, + }); + }); + + test("skips processing if no Carbon Svelte imports are found", () => { + const plugin = new OptimizeCssPlugin(); + const mockCompiler = createMockCompiler({ + assets: { "styles.css": { source: () => "body { color: red; }" } }, + fileDependencies: ["regular-component.svelte"], + }); + + plugin.apply(mockCompiler as any); + + expect(mockCompiler.compilation.updateAsset).not.toHaveBeenCalled(); + }); + + test("processes CSS files when Carbon Svelte imports are found", () => { + const plugin = new OptimizeCssPlugin(); + const carbonComponent = `node_modules/${CarbonSvelte.Components}/Button.svelte`; + const cssContent = ".bx--btn { color: blue; }"; + + const mockCompiler = createMockCompiler({ + assets: { + "styles.css": { source: () => cssContent }, + }, + fileDependencies: [carbonComponent], + }); + + plugin.apply(mockCompiler as any); + + expect(mockCompiler.compilation.updateAsset).toHaveBeenCalledWith( + "styles.css", + expect.any(Object), + ); + }); + + test("handles Buffer input correctly", () => { + const plugin = new OptimizeCssPlugin(); + const carbonComponent = `node_modules/${CarbonSvelte.Components}/Button.svelte`; + const cssContent = Buffer.from(".bx--btn { color: blue; }"); + + const mockCompiler = createMockCompiler({ + assets: { + "styles.css": { source: () => cssContent }, + }, + fileDependencies: [carbonComponent], + }); + + plugin.apply(mockCompiler as any); + + expect(mockCompiler.compilation.updateAsset).toHaveBeenCalledWith( + "styles.css", + expect.any(Object), + ); + }); + + test("respects verbose option for printing diff", () => { + const consoleSpy = jest.spyOn(console, "log").mockImplementation(); + const plugin = new OptimizeCssPlugin({ verbose: true }); + const carbonComponent = `node_modules/${CarbonSvelte.Components}/Button.svelte`; + + const mockCompiler = createMockCompiler({ + assets: { + "styles.css": { source: () => ".bx--btn { color: blue; }" }, + }, + fileDependencies: [carbonComponent], + }); + + plugin.apply(mockCompiler as any); + + expect(consoleSpy).toHaveBeenCalled(); + consoleSpy.mockRestore(); + }); +}); diff --git a/tests/extract-selectors.test.ts b/tests/extract-selectors.test.ts index 57c35d6..bc84cdd 100644 --- a/tests/extract-selectors.test.ts +++ b/tests/extract-selectors.test.ts @@ -1,3 +1,4 @@ +import { describe, expect, test } from "bun:test"; import { extractSelectors } from "../scripts/extract-selectors"; describe("extractSelectors", () => { @@ -7,6 +8,7 @@ describe("extractSelectors", () => { filename: "test.svelte", }); expect(result.classes).toEqual([".test-class"]); + expect(result.components).toEqual([]); }); test("extracts multiple classes from class attribute", () => { @@ -15,70 +17,87 @@ describe("extractSelectors", () => { filename: "test.svelte", }); expect(result.classes).toEqual([".class1", ".class2", ".class3"]); + expect(result.components).toEqual([]); + }); + + test("extracts Carbon classes with bx-- prefix", () => { + const result = extractSelectors({ + code: '
', + filename: "test.svelte", + }); + expect(result.classes).toEqual([".bx--btn", ".bx--modal"]); }); test("extracts class directives", () => { const result = extractSelectors({ - code: "
", + code: "
", filename: "test.svelte", }); - expect(result.classes).toEqual([".active"]); + expect(result.classes).toEqual([".active", ".bx--selected"]); }); - test("extracts global selectors", () => { + test("extracts classes from dynamic expressions", () => { const result = extractSelectors({ - code: "", + code: "
", filename: "test.svelte", }); - expect(result.classes).toEqual([".div"]); + expect(result.classes).toEqual([".static-class", ".bx--active"]); }); - test("handles Carbon prefix classes", () => { + test("extracts global selectors", () => { const result = extractSelectors({ - code: '
', + code: "", filename: "test.svelte", }); - expect(result.classes).toEqual([".bx--button", ".bx--text"]); + expect(result.classes).toEqual([".bx--global-class"]); }); - test("deduplicates repeated classes", () => { + test("extracts component references", () => { const result = extractSelectors({ - code: '
', + code: ` + +