Merge pull request #1188 from quantified-uncertainty/component-testing
Component testing
This commit is contained in:
		
						commit
						60f464ebac
					
				
							
								
								
									
										6
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -116,8 +116,8 @@ jobs:
 | 
			
		|||
          dry: true
 | 
			
		||||
          prettier_options: --check packages/components --ignore-path packages/components/.prettierignore
 | 
			
		||||
 | 
			
		||||
  components-bundle-build:
 | 
			
		||||
    name: Components bundle and build
 | 
			
		||||
  components-bundle-build-test:
 | 
			
		||||
    name: Components bundle, build and test
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
    needs: pre_check
 | 
			
		||||
    if: ${{ (needs.pre_check.outputs.should_skip_components != 'true') || (needs.pre_check.outputs.should_skip_lang != 'true') }}
 | 
			
		||||
| 
						 | 
				
			
			@ -135,6 +135,8 @@ jobs:
 | 
			
		|||
        run: yarn bundle
 | 
			
		||||
      - name: Build storybook
 | 
			
		||||
        run: yarn build
 | 
			
		||||
      - name: Test components 
 | 
			
		||||
        run: yarn test
 | 
			
		||||
 | 
			
		||||
  website-lint:
 | 
			
		||||
    name: Website lint
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										6
									
								
								packages/components/jest.config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								packages/components/jest.config.js
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,6 @@
 | 
			
		|||
/** @type {import('ts-jest').JestConfigWithTsJest} */
 | 
			
		||||
module.exports = {
 | 
			
		||||
  preset: "ts-jest",
 | 
			
		||||
  setupFilesAfterEnv: ["<rootDir>/test/setup.js"],
 | 
			
		||||
  testEnvironment: "jsdom",
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -43,7 +43,11 @@
 | 
			
		|||
    "@types/react": "^18.0.21",
 | 
			
		||||
    "@types/styled-components": "^5.1.26",
 | 
			
		||||
    "@types/webpack": "^5.28.0",
 | 
			
		||||
    "canvas": "^2.10.1",
 | 
			
		||||
    "cross-env": "^7.0.3",
 | 
			
		||||
    "jest": "^29.0.3",
 | 
			
		||||
    "jest-environment-jsdom": "^29.0.3",
 | 
			
		||||
    "jsdom": "^20.0.0",
 | 
			
		||||
    "mini-css-extract-plugin": "^2.6.1",
 | 
			
		||||
    "postcss-cli": "^10.0.0",
 | 
			
		||||
    "postcss-import": "^15.0.0",
 | 
			
		||||
| 
						 | 
				
			
			@ -53,6 +57,7 @@
 | 
			
		|||
    "react-scripts": "^5.0.1",
 | 
			
		||||
    "style-loader": "^3.3.1",
 | 
			
		||||
    "tailwindcss": "^3.1.8",
 | 
			
		||||
    "ts-jest": "^29.0.2",
 | 
			
		||||
    "ts-loader": "^9.4.1",
 | 
			
		||||
    "tsconfig-paths-webpack-plugin": "^4.0.0",
 | 
			
		||||
    "typescript": "^4.8.4",
 | 
			
		||||
| 
						 | 
				
			
			@ -75,7 +80,9 @@
 | 
			
		|||
    "all": "yarn bundle && yarn build",
 | 
			
		||||
    "lint": "prettier --check .",
 | 
			
		||||
    "format": "prettier --write .",
 | 
			
		||||
    "prepack": "yarn run build:cjs && yarn run bundle"
 | 
			
		||||
    "prepack": "yarn run build:cjs && yarn run bundle",
 | 
			
		||||
    "test": "jest",
 | 
			
		||||
    "test:debug": "node --inspect-brk node_modules/.bin/jest --runInBand"
 | 
			
		||||
  },
 | 
			
		||||
  "eslintConfig": {
 | 
			
		||||
    "extends": [
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -83,18 +83,32 @@ export const DistributionChart: React.FC<DistributionChartProps> = (props) => {
 | 
			
		|||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const spec = buildVegaSpec(props);
 | 
			
		||||
    const domain = shapes.value.flatMap((shape) =>
 | 
			
		||||
      shape.discrete.concat(shape.continuous)
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    let widthProp = width ? width : size.width;
 | 
			
		||||
    const spec = buildVegaSpec({
 | 
			
		||||
      ...props,
 | 
			
		||||
      minX: props.minX ?? Math.min(...domain.map((x) => x.x)),
 | 
			
		||||
      maxX: props.minX ?? Math.max(...domain.map((x) => x.x)),
 | 
			
		||||
      maxY: Math.max(...domain.map((x) => x.y)),
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // I think size.width is sometimes not finite due to the component not being in a visible context
 | 
			
		||||
    // This occurs during testing
 | 
			
		||||
    let widthProp = width
 | 
			
		||||
      ? width
 | 
			
		||||
      : Number.isFinite(size.width)
 | 
			
		||||
      ? size.width
 | 
			
		||||
      : 400;
 | 
			
		||||
    if (widthProp < 20) {
 | 
			
		||||
      console.warn(
 | 
			
		||||
        `Width of Distribution is set to ${widthProp}, which is too small`
 | 
			
		||||
      );
 | 
			
		||||
      widthProp = 20;
 | 
			
		||||
    }
 | 
			
		||||
    const domain = shapes.value.flatMap((shape) =>
 | 
			
		||||
      shape.discrete.concat(shape.continuous)
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    const vegaData = { data: shapes.value, samples };
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
      <div style={{ width: widthProp }}>
 | 
			
		||||
| 
						 | 
				
			
			@ -105,7 +119,7 @@ export const DistributionChart: React.FC<DistributionChartProps> = (props) => {
 | 
			
		|||
        ) : (
 | 
			
		||||
          <Vega
 | 
			
		||||
            spec={spec}
 | 
			
		||||
            data={{ data: shapes.value, domain, samples }}
 | 
			
		||||
            data={vegaData}
 | 
			
		||||
            width={widthProp - 10}
 | 
			
		||||
            height={height}
 | 
			
		||||
            actions={actions}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,7 +26,6 @@ export const linearXScale: LinearScale = {
 | 
			
		|||
  range: "width",
 | 
			
		||||
  zero: false,
 | 
			
		||||
  nice: false,
 | 
			
		||||
  domain: { data: "domain", field: "x" },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const logXScale: LogScale = {
 | 
			
		||||
| 
						 | 
				
			
			@ -37,7 +36,6 @@ export const logXScale: LogScale = {
 | 
			
		|||
  base: 10,
 | 
			
		||||
  nice: false,
 | 
			
		||||
  clamp: true,
 | 
			
		||||
  domain: { data: "domain", field: "x" },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const timeXScale: TimeScale = {
 | 
			
		||||
| 
						 | 
				
			
			@ -46,7 +44,6 @@ export const timeXScale: TimeScale = {
 | 
			
		|||
  type: "time",
 | 
			
		||||
  range: "width",
 | 
			
		||||
  nice: false,
 | 
			
		||||
  domain: { data: "domain", field: "x" },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/** Y Scales */
 | 
			
		||||
| 
						 | 
				
			
			@ -55,7 +52,6 @@ export const linearYScale: LinearScale = {
 | 
			
		|||
  type: "linear",
 | 
			
		||||
  range: "height",
 | 
			
		||||
  zero: true,
 | 
			
		||||
  domain: { data: "domain", field: "y" },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const expYScale: PowScale = {
 | 
			
		||||
| 
						 | 
				
			
			@ -65,7 +61,6 @@ export const expYScale: PowScale = {
 | 
			
		|||
  range: "height",
 | 
			
		||||
  zero: true,
 | 
			
		||||
  nice: false,
 | 
			
		||||
  domain: { data: "domain", field: "y" },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const defaultTickFormat = ".9~s";
 | 
			
		||||
| 
						 | 
				
			
			@ -73,9 +68,17 @@ export const timeTickFormat = "%b %d, %Y %H:%M";
 | 
			
		|||
const width = 500;
 | 
			
		||||
 | 
			
		||||
export function buildVegaSpec(
 | 
			
		||||
  specOptions: DistributionChartSpecOptions
 | 
			
		||||
  specOptions: DistributionChartSpecOptions & { maxY: number }
 | 
			
		||||
): VisualizationSpec {
 | 
			
		||||
  const { title, minX, maxX, logX, expY, xAxisType = "number" } = specOptions;
 | 
			
		||||
  const {
 | 
			
		||||
    title,
 | 
			
		||||
    minX,
 | 
			
		||||
    maxX,
 | 
			
		||||
    logX,
 | 
			
		||||
    expY,
 | 
			
		||||
    xAxisType = "number",
 | 
			
		||||
    maxY,
 | 
			
		||||
  } = specOptions;
 | 
			
		||||
 | 
			
		||||
  const dateTime = xAxisType === "dateTime";
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -88,13 +91,15 @@ export function buildVegaSpec(
 | 
			
		|||
 | 
			
		||||
  let xScale = dateTime ? timeXScale : logX ? logXScale : linearXScale;
 | 
			
		||||
 | 
			
		||||
  if (minX !== undefined && Number.isFinite(minX)) {
 | 
			
		||||
    xScale = { ...xScale, domainMin: minX };
 | 
			
		||||
  }
 | 
			
		||||
  xScale = {
 | 
			
		||||
    ...xScale,
 | 
			
		||||
    domain: [minX ?? 0, maxX ?? 1],
 | 
			
		||||
    domainMin: minX,
 | 
			
		||||
    domainMax: maxX,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  if (maxX !== undefined && Number.isFinite(maxX)) {
 | 
			
		||||
    xScale = { ...xScale, domainMax: maxX };
 | 
			
		||||
  }
 | 
			
		||||
  let yScale = expY ? expYScale : linearYScale;
 | 
			
		||||
  yScale = { ...yScale, domain: [0, maxY ?? 1], domainMin: 0, domainMax: maxY };
 | 
			
		||||
 | 
			
		||||
  const spec: VisualizationSpec = {
 | 
			
		||||
    $schema: "https://vega.github.io/schema/vega/v5.json",
 | 
			
		||||
| 
						 | 
				
			
			@ -128,7 +133,7 @@ export function buildVegaSpec(
 | 
			
		|||
    ],
 | 
			
		||||
    scales: [
 | 
			
		||||
      xScale,
 | 
			
		||||
      expY ? expYScale : linearYScale,
 | 
			
		||||
      yScale,
 | 
			
		||||
      {
 | 
			
		||||
        name: "color",
 | 
			
		||||
        type: "ordinal",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										13
									
								
								packages/components/test/basic.test.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								packages/components/test/basic.test.tsx
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,13 @@
 | 
			
		|||
import { render } from "@testing-library/react";
 | 
			
		||||
import React from "react";
 | 
			
		||||
import "@testing-library/jest-dom";
 | 
			
		||||
import { SquiggleChart } from "../src/index";
 | 
			
		||||
 | 
			
		||||
test("Logs no warnings or errors", async () => {
 | 
			
		||||
  debugger;
 | 
			
		||||
  const { unmount } = render(<SquiggleChart code={"normal(0, 1)"} />);
 | 
			
		||||
  unmount();
 | 
			
		||||
 | 
			
		||||
  expect(console.warn).not.toBeCalled();
 | 
			
		||||
  expect(console.error).not.toBeCalled();
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										8
									
								
								packages/components/test/setup.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								packages/components/test/setup.js
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,8 @@
 | 
			
		|||
global.console = {
 | 
			
		||||
  ...console,
 | 
			
		||||
  log: jest.fn(console.log),
 | 
			
		||||
  debug: jest.fn(console.debug),
 | 
			
		||||
  info: jest.fn(console.info),
 | 
			
		||||
  warn: jest.fn(console.warn),
 | 
			
		||||
  error: jest.fn(console.error),
 | 
			
		||||
};
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user