Back to Repositories

Validating Card Component Rendering and Styling in github-readme-stats

This test suite validates the Card component functionality in github-readme-stats, covering rendering, styling, and configuration options. The tests ensure proper handling of card attributes like borders, titles, dimensions, and color schemes.

Test Coverage Overview

The test suite provides comprehensive coverage of the Card component’s core functionality.

Key areas tested include:
  • Border visibility controls
  • Title management and customization
  • Dimension handling and responsive layouts
  • Color scheme implementation
  • Gradient background rendering
Edge cases cover null states, custom configurations, and various style combinations.

Implementation Analysis

The testing approach utilizes Jest and Testing Library for DOM manipulation and assertions. The implementation follows component-based testing patterns, with focused test cases for each feature. Jest-specific features like describe blocks and it statements organize the test suite logically.

The tests employ DOM querying and attribute validation to verify rendered output.

Technical Details

Testing tools and libraries:
  • @testing-library/dom for DOM queries
  • @testing-library/jest-dom for custom matchers
  • @uppercod/css-to-object for CSS parsing
  • Jest test runner and assertion library
Setup includes DOM environment configuration and custom utility imports.

Best Practices Demonstrated

The test suite exemplifies strong testing practices through isolated test cases, clear assertions, and comprehensive coverage.

Notable practices include:
  • Consistent test structure and naming
  • Focused, single-responsibility test cases
  • Proper setup and cleanup
  • Thorough attribute and style testing
  • Clear separation of concerns

anuraghazra/github-readme-stats

tests/card.test.js

            
import { queryByTestId } from "@testing-library/dom";
import "@testing-library/jest-dom";
import { cssToObject } from "@uppercod/css-to-object";
import { Card } from "../src/common/Card.js";
import { icons } from "../src/common/icons.js";
import { getCardColors } from "../src/common/utils.js";
import { expect, it, describe } from "@jest/globals";

describe("Card", () => {
  it("should hide border", () => {
    const card = new Card({});
    card.setHideBorder(true);

    document.body.innerHTML = card.render(``);
    expect(queryByTestId(document.body, "card-bg")).toHaveAttribute(
      "stroke-opacity",
      "0",
    );
  });

  it("should not hide border", () => {
    const card = new Card({});
    card.setHideBorder(false);

    document.body.innerHTML = card.render(``);
    expect(queryByTestId(document.body, "card-bg")).toHaveAttribute(
      "stroke-opacity",
      "1",
    );
  });

  it("should have a custom title", () => {
    const card = new Card({
      customTitle: "custom title",
      defaultTitle: "default title",
    });

    document.body.innerHTML = card.render(``);
    expect(queryByTestId(document.body, "card-title")).toHaveTextContent(
      "custom title",
    );
  });

  it("should set custom title", () => {
    const card = new Card({});
    card.setTitle("custom title");

    document.body.innerHTML = card.render(``);
    expect(queryByTestId(document.body, "card-title")).toHaveTextContent(
      "custom title",
    );
  });

  it("should hide title", () => {
    const card = new Card({});
    card.setHideTitle(true);

    document.body.innerHTML = card.render(``);
    expect(queryByTestId(document.body, "card-title")).toBeNull();
  });

  it("should not hide title", () => {
    const card = new Card({});
    card.setHideTitle(false);

    document.body.innerHTML = card.render(``);
    expect(queryByTestId(document.body, "card-title")).toBeInTheDocument();
  });

  it("title should have prefix icon", () => {
    const card = new Card({ title: "ok", titlePrefixIcon: icons.contribs });

    document.body.innerHTML = card.render(``);
    expect(document.getElementsByClassName("icon")[0]).toBeInTheDocument();
  });

  it("title should not have prefix icon", () => {
    const card = new Card({ title: "ok" });

    document.body.innerHTML = card.render(``);
    expect(document.getElementsByClassName("icon")[0]).toBeUndefined();
  });

  it("should have proper height, width", () => {
    const card = new Card({ height: 200, width: 200, title: "ok" });
    document.body.innerHTML = card.render(``);
    expect(document.getElementsByTagName("svg")[0]).toHaveAttribute(
      "height",
      "200",
    );
    expect(document.getElementsByTagName("svg")[0]).toHaveAttribute(
      "width",
      "200",
    );
  });

  it("should have less height after title is hidden", () => {
    const card = new Card({ height: 200, title: "ok" });
    card.setHideTitle(true);

    document.body.innerHTML = card.render(``);
    expect(document.getElementsByTagName("svg")[0]).toHaveAttribute(
      "height",
      "170",
    );
  });

  it("main-card-body should have proper when title is visible", () => {
    const card = new Card({ height: 200 });
    document.body.innerHTML = card.render(``);
    expect(queryByTestId(document.body, "main-card-body")).toHaveAttribute(
      "transform",
      "translate(0, 55)",
    );
  });

  it("main-card-body should have proper position after title is hidden", () => {
    const card = new Card({ height: 200 });
    card.setHideTitle(true);

    document.body.innerHTML = card.render(``);
    expect(queryByTestId(document.body, "main-card-body")).toHaveAttribute(
      "transform",
      "translate(0, 25)",
    );
  });

  it("should render with correct colors", () => {
    // returns theme based colors with proper overrides and defaults
    const { titleColor, textColor, iconColor, bgColor } = getCardColors({
      title_color: "f00",
      icon_color: "0f0",
      text_color: "00f",
      bg_color: "fff",
      theme: "default",
    });

    const card = new Card({
      height: 200,
      colors: {
        titleColor,
        textColor,
        iconColor,
        bgColor,
      },
    });
    document.body.innerHTML = card.render(``);

    const styleTag = document.querySelector("style");
    const stylesObject = cssToObject(styleTag.innerHTML);
    const headerClassStyles = stylesObject[":host"][".header "];

    expect(headerClassStyles["fill"].trim()).toBe("#f00");
    expect(queryByTestId(document.body, "card-bg")).toHaveAttribute(
      "fill",
      "#fff",
    );
  });
  it("should render gradient backgrounds", () => {
    const { titleColor, textColor, iconColor, bgColor } = getCardColors({
      title_color: "f00",
      icon_color: "0f0",
      text_color: "00f",
      bg_color: "90,fff,000,f00",
      theme: "default",
    });

    const card = new Card({
      height: 200,
      colors: {
        titleColor,
        textColor,
        iconColor,
        bgColor,
      },
    });
    document.body.innerHTML = card.render(``);
    expect(queryByTestId(document.body, "card-bg")).toHaveAttribute(
      "fill",
      "url(#gradient)",
    );
    expect(document.querySelector("defs #gradient")).toHaveAttribute(
      "gradientTransform",
      "rotate(90)",
    );
    expect(
      document.querySelector("defs #gradient stop:nth-child(1)"),
    ).toHaveAttribute("stop-color", "#fff");
    expect(
      document.querySelector("defs #gradient stop:nth-child(2)"),
    ).toHaveAttribute("stop-color", "#000");
    expect(
      document.querySelector("defs #gradient stop:nth-child(3)"),
    ).toHaveAttribute("stop-color", "#f00");
  });
});